зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1022612. Part 10: Implement merging and flattening in ProcessDisplayItems. r=mattwoodrow
BuildContainerLayerFor now has to be able to mutate the passed-in display item list. --HG-- extra : rebase_source : c242006445d90372f6c7941d909f30945422321b
This commit is contained in:
Родитель
e94df3456a
Коммит
d143dbdffc
|
@ -23,6 +23,7 @@
|
|||
#include "ImageContainer.h"
|
||||
#include "ActiveLayerTracker.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
#include "mozilla/gfx/Tools.h"
|
||||
|
@ -521,7 +522,7 @@ public:
|
|||
* This is the method that actually walks a display list and builds
|
||||
* the child layers.
|
||||
*/
|
||||
void ProcessDisplayItems(const nsDisplayList& aList, uint32_t aFlags);
|
||||
void ProcessDisplayItems(nsDisplayList* aList, uint32_t aFlags);
|
||||
/**
|
||||
* This finalizes all the open ThebesLayers by popping every element off
|
||||
* mThebesLayerDataStack, then sets the children of the container layer
|
||||
|
@ -2410,6 +2411,31 @@ ContainerState::ChooseAnimatedGeometryRoot(const nsDisplayList& aList,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Checks if aPotentialScrollItem is a scroll layer item and aPotentialScrollbarItem
|
||||
* is an overlay scrollbar item for the same scroll frame.
|
||||
*/
|
||||
static bool
|
||||
IsScrollLayerItemAndOverlayScrollbarForScrollFrame(
|
||||
nsDisplayItem* aPotentialScrollItem, nsDisplayItem* aPotentialScrollbarItem)
|
||||
{
|
||||
if (aPotentialScrollItem->GetType() == nsDisplayItem::TYPE_SCROLL_LAYER &&
|
||||
aPotentialScrollbarItem &&
|
||||
aPotentialScrollbarItem->GetType() == nsDisplayItem::TYPE_OWN_LAYER &&
|
||||
LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars)) {
|
||||
nsDisplayScrollLayer* scrollItem =
|
||||
static_cast<nsDisplayScrollLayer*>(aPotentialScrollItem);
|
||||
nsDisplayOwnLayer* layerItem =
|
||||
static_cast<nsDisplayOwnLayer*>(aPotentialScrollbarItem);
|
||||
if ((layerItem->GetFlags() &
|
||||
(nsDisplayOwnLayer::VERTICAL_SCROLLBAR |
|
||||
nsDisplayOwnLayer::HORIZONTAL_SCROLLBAR)) &&
|
||||
layerItem->Frame()->GetParent() == scrollItem->GetScrollFrame()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate through the non-clip items in aList and its descendants.
|
||||
* For each item we compute the effective clip rect. Each item is assigned
|
||||
|
@ -2425,7 +2451,7 @@ ContainerState::ChooseAnimatedGeometryRoot(const nsDisplayList& aList,
|
|||
* of ContainerState::Finish.
|
||||
*/
|
||||
void
|
||||
ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
||||
ContainerState::ProcessDisplayItems(nsDisplayList* aList,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
PROFILER_LABEL("ContainerState", "ProcessDisplayItems",
|
||||
|
@ -2438,7 +2464,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
|||
// layer, so we need to choose which active scrolled root to use for all
|
||||
// items.
|
||||
if (aFlags & NO_COMPONENT_ALPHA) {
|
||||
if (ChooseAnimatedGeometryRoot(aList, &lastAnimatedGeometryRoot)) {
|
||||
if (ChooseAnimatedGeometryRoot(*aList, &lastAnimatedGeometryRoot)) {
|
||||
topLeft = lastAnimatedGeometryRoot->GetOffsetToCrossDoc(mContainerReferenceFrame);
|
||||
}
|
||||
}
|
||||
|
@ -2446,7 +2472,42 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
|||
int32_t maxLayers = nsDisplayItem::MaxActiveLayers();
|
||||
int layerCount = 0;
|
||||
|
||||
for (nsDisplayItem* item = aList.GetBottom(); item; item = item->GetAbove()) {
|
||||
nsDisplayList savedItems;
|
||||
nsDisplayItem* item;
|
||||
while ((item = aList->RemoveBottom()) != nullptr) {
|
||||
// Peek ahead to the next item and try merging with it or swapping with it
|
||||
// if necessary.
|
||||
nsDisplayItem* aboveItem;
|
||||
while ((aboveItem = aList->GetBottom()) != nullptr) {
|
||||
if (aboveItem->TryMerge(mBuilder, item)) {
|
||||
aList->RemoveBottom();
|
||||
item->~nsDisplayItem();
|
||||
item = aboveItem;
|
||||
} else if (IsScrollLayerItemAndOverlayScrollbarForScrollFrame(aboveItem, item)) {
|
||||
// If an overlay scrollbar item is between a scroll layer item and the
|
||||
// other scroll layer items that we need to merge with just move the
|
||||
// scrollbar item up, that way it will be on top of the scrolled content
|
||||
// and we can try to merge all the scroll layer items.
|
||||
aList->RemoveBottom();
|
||||
aList->AppendToBottom(item);
|
||||
item = aboveItem;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsDisplayList* itemSameCoordinateSystemChildren
|
||||
= item->GetSameCoordinateSystemChildren();
|
||||
if (itemSameCoordinateSystemChildren) {
|
||||
if (item->ShouldFlattenAway(mBuilder)) {
|
||||
aList->AppendToBottom(itemSameCoordinateSystemChildren);
|
||||
item->~nsDisplayItem();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
savedItems.AppendToTop(item);
|
||||
|
||||
NS_ASSERTION(mAppUnitsPerDevPixel == AppUnitsPerDevPixel(item),
|
||||
"items in a container layer should all have the same app units per dev pixel");
|
||||
|
||||
|
@ -2667,6 +2728,8 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
aList->AppendToTop(&savedItems);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3313,7 +3376,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
|||
LayerManager* aManager,
|
||||
nsIFrame* aContainerFrame,
|
||||
nsDisplayItem* aContainerItem,
|
||||
const nsDisplayList& aChildren,
|
||||
nsDisplayList* aChildren,
|
||||
const ContainerLayerParameters& aParameters,
|
||||
const gfx3DMatrix* aTransform,
|
||||
uint32_t aFlags)
|
||||
|
@ -3377,7 +3440,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
|||
// early exit because later, invalidation will walk up the frame tree to
|
||||
// determine which thebes layer gets invalidated. Since an empty layer
|
||||
// should never have anything to paint, it should never be invalidated.
|
||||
NS_ASSERTION(aChildren.IsEmpty(), "Should have no children");
|
||||
NS_ASSERTION(aChildren->IsEmpty(), "Should have no children");
|
||||
return containerLayer.forget();
|
||||
}
|
||||
|
||||
|
@ -3445,7 +3508,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
|||
break;
|
||||
}
|
||||
|
||||
NS_ASSERTION(bounds.IsEqualInterior(aChildren.GetBounds(aBuilder)), "Wrong bounds");
|
||||
NS_ASSERTION(bounds.IsEqualInterior(aChildren->GetBounds(aBuilder)), "Wrong bounds");
|
||||
pixBounds.MoveBy(nsIntPoint(scaleParameters.mOffset.x, scaleParameters.mOffset.y));
|
||||
if (aParameters.mAncestorClipRect && !(aFlags & CONTAINER_NOT_CLIPPED_BY_ANCESTORS)) {
|
||||
SetVisibleRegionForLayer(containerLayer, nsIntRegion(pixBounds),
|
||||
|
@ -3455,7 +3518,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
// Make sure that rounding the visible region out didn't add any area
|
||||
// we won't paint
|
||||
if (aChildren.IsOpaque() && !aChildren.NeedsTransparentSurface()) {
|
||||
if (aChildren->IsOpaque() && !aChildren->NeedsTransparentSurface()) {
|
||||
bounds.ScaleRoundIn(scaleParameters.mXScale, scaleParameters.mYScale);
|
||||
if (bounds.Contains(pixBounds.ToAppUnits(appUnitsPerDevPixel))) {
|
||||
// Clear CONTENT_COMPONENT_ALPHA
|
||||
|
|
|
@ -207,13 +207,14 @@ public:
|
|||
* is set based on what's in the layer.
|
||||
* The container layer is transformed by aTransform (if non-null), and
|
||||
* the result is transformed by the scale factors in aContainerParameters.
|
||||
* aChildren is modified due to display item merging and flattening.
|
||||
*/
|
||||
already_AddRefed<ContainerLayer>
|
||||
BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
nsIFrame* aContainerFrame,
|
||||
nsDisplayItem* aContainerItem,
|
||||
const nsDisplayList& aChildren,
|
||||
nsDisplayList* aChildren,
|
||||
const ContainerLayerParameters& aContainerParameters,
|
||||
const gfx3DMatrix* aTransform,
|
||||
uint32_t aFlags = 0);
|
||||
|
|
|
@ -1232,10 +1232,9 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
void nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx,
|
||||
uint32_t aFlags) const {
|
||||
uint32_t aFlags) {
|
||||
PROFILER_LABEL("nsDisplayList", "PaintRoot",
|
||||
js::ProfileEntry::Category::GRAPHICS);
|
||||
|
||||
PaintForFrame(aBuilder, aCtx, aBuilder->RootReferenceFrame(), aFlags);
|
||||
}
|
||||
|
||||
|
@ -1247,7 +1246,7 @@ void nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder,
|
|||
void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx,
|
||||
nsIFrame* aForFrame,
|
||||
uint32_t aFlags) const {
|
||||
uint32_t aFlags) {
|
||||
NS_ASSERTION(mDidComputeVisibility,
|
||||
"Must call ComputeVisibility before calling Paint");
|
||||
|
||||
|
@ -1319,7 +1318,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
|||
ContainerLayerParameters containerParameters
|
||||
(presShell->GetXResolution(), presShell->GetYResolution());
|
||||
nsRefPtr<ContainerLayer> root = layerBuilder->
|
||||
BuildContainerLayerFor(aBuilder, layerManager, aForFrame, nullptr, *this,
|
||||
BuildContainerLayerFor(aBuilder, layerManager, aForFrame, nullptr, this,
|
||||
containerParameters, nullptr);
|
||||
|
||||
nsIDocument* document = nullptr;
|
||||
|
@ -3288,7 +3287,7 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
return nullptr;
|
||||
}
|
||||
nsRefPtr<Layer> container = aManager->GetLayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
|
||||
aContainerParameters, nullptr);
|
||||
if (!container)
|
||||
return nullptr;
|
||||
|
@ -3451,7 +3450,7 @@ nsDisplayMixBlendMode::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true;
|
||||
|
||||
nsRefPtr<Layer> container = aManager->GetLayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
|
||||
newContainerParameters, nullptr);
|
||||
if (!container) {
|
||||
return nullptr;
|
||||
|
@ -3528,7 +3527,7 @@ nsDisplayBlendContainer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true;
|
||||
|
||||
nsRefPtr<Layer> container = aManager->GetLayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
|
||||
newContainerParameters, nullptr);
|
||||
if (!container) {
|
||||
return nullptr;
|
||||
|
@ -3573,7 +3572,7 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aContainerParameters) {
|
||||
nsRefPtr<ContainerLayer> layer = aManager->GetLayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
|
||||
aContainerParameters, nullptr);
|
||||
if (mFlags & VERTICAL_SCROLLBAR) {
|
||||
layer->SetScrollbarData(mScrollTarget, Layer::ScrollDirection::VERTICAL);
|
||||
|
@ -3896,7 +3895,7 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aContainerParameters) {
|
||||
nsRefPtr<ContainerLayer> layer = aManager->GetLayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
|
||||
aContainerParameters, nullptr);
|
||||
|
||||
nsRect viewport = mScrollFrame->GetRect() -
|
||||
|
@ -4800,7 +4799,7 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
|
|||
uint32_t flags = ShouldPrerenderTransformedContent(aBuilder, mFrame, false) ?
|
||||
FrameLayerBuilder::CONTAINER_NOT_CLIPPED_BY_ANCESTORS : 0;
|
||||
nsRefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, *mStoredList.GetChildren(),
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mStoredList.GetChildren(),
|
||||
aContainerParameters, &newTransformMatrix, flags);
|
||||
|
||||
if (!container) {
|
||||
|
@ -5324,7 +5323,7 @@ nsDisplaySVGEffects::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
|
||||
nsRefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
|
||||
newContainerParameters, nullptr);
|
||||
|
||||
return container.forget();
|
||||
|
|
|
@ -1681,13 +1681,13 @@ public:
|
|||
PAINT_COMPRESSED = 0x10
|
||||
};
|
||||
void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
|
||||
uint32_t aFlags) const;
|
||||
uint32_t aFlags);
|
||||
/**
|
||||
* Like PaintRoot, but used for internal display sublists.
|
||||
* aForFrame is the frame that the list is associated with.
|
||||
*/
|
||||
void PaintForFrame(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
|
||||
nsIFrame* aForFrame, uint32_t aFlags) const;
|
||||
nsIFrame* aForFrame, uint32_t aFlags);
|
||||
/**
|
||||
* Get the bounds. Takes the union of the bounds of all children.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче