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 : 6a9727998a5ffb01896a4a2bbdd8d30a24c89dcd
This commit is contained in:
Robert O'Callahan 2014-06-09 16:48:00 +12:00
Родитель fad84a8654
Коммит 88afa39f1c
4 изменённых файлов: 85 добавлений и 22 удалений

Просмотреть файл

@ -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);

Просмотреть файл

@ -1235,10 +1235,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);
}
@ -1250,7 +1249,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");
@ -1322,7 +1321,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;
@ -3291,7 +3290,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;
@ -3454,7 +3453,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;
@ -3531,7 +3530,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;
@ -3576,7 +3575,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);
@ -3899,7 +3898,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() -
@ -4803,7 +4802,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) {
@ -5327,7 +5326,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.
*/