Bug 1407815 - Allow merging of items that are in different wrap lists. r=miko

This commit is contained in:
Matt Woodrow 2017-10-17 15:16:28 +13:00
Родитель 71d7fc5d25
Коммит 8b1212fa67
5 изменённых файлов: 102 добавлений и 64 удалений

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

@ -114,7 +114,8 @@ WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList* a
bool apzEnabled = mManager->AsyncPanZoomEnabled();
EventRegions eventRegions;
for (nsDisplayItem* i = aDisplayList->GetBottom(); i; i = i->GetAbove()) {
FlattenedDisplayItemIterator iter(aDisplayListBuilder, aDisplayList);
while (nsDisplayItem* i = iter.GetNext()) {
nsDisplayItem* item = i;
DisplayItemType itemType = item->GetType();
@ -132,7 +133,7 @@ WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList* a
// if necessary.
AutoTArray<nsDisplayItem*, 1> mergedItems;
mergedItems.AppendElement(item);
for (nsDisplayItem* peek = item->GetAbove(); peek; peek = peek->GetAbove()) {
while (nsDisplayItem* peek = iter.PeekNext()) {
if (!item->CanMerge(peek)) {
break;
}
@ -140,7 +141,7 @@ WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList* a
mergedItems.AppendElement(peek);
// Move the iterator forward since we will merge this item.
i = peek;
i = iter.GetNext();
}
if (mergedItems.Length() > 1) {
@ -212,21 +213,14 @@ WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList* a
}
}
nsDisplayList* childItems = item->GetSameCoordinateSystemChildren();
if (item->ShouldFlattenAway(aDisplayListBuilder)) {
MOZ_ASSERT(childItems);
CreateWebRenderCommandsFromDisplayList(childItems, aDisplayListBuilder, aSc,
aBuilder, aResources);
} else {
// ensure the scope of ScrollingLayersHelper is maintained
ScrollingLayersHelper clip(item, aBuilder, aSc, mClipIdCache, apzEnabled);
// ensure the scope of ScrollingLayersHelper is maintained
ScrollingLayersHelper clip(item, aBuilder, aSc, mClipIdCache, apzEnabled);
// Note: this call to CreateWebRenderCommands can recurse back into
// this function if the |item| is a wrapper for a sublist.
if (!item->CreateWebRenderCommands(aBuilder, aResources, aSc, mManager,
aDisplayListBuilder)) {
PushItemAsImage(item, aBuilder, aResources, aSc, aDisplayListBuilder);
}
// Note: this call to CreateWebRenderCommands can recurse back into
// this function if the |item| is a wrapper for a sublist.
if (!item->CreateWebRenderCommands(aBuilder, aResources, aSc, mManager,
aDisplayListBuilder)) {
PushItemAsImage(item, aBuilder, aResources, aSc, aDisplayListBuilder);
}
if (apzEnabled) {

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

@ -1101,13 +1101,6 @@ public:
* the child layers.
*/
void ProcessDisplayItems(nsDisplayList* aList);
void ProcessDisplayItems(nsDisplayList* aList,
AnimatedGeometryRoot* aLastAnimatedGeometryRoot,
const ActiveScrolledRoot* aLastASR,
const nsPoint& aLastAGRTopLeft,
nsPoint& aTopLeft,
int32_t aMaxLayers,
int& aLayerCount);
/**
* This finalizes all the open PaintedLayers by popping every element off
* mPaintedLayerDataStack, then sets the children of the container layer
@ -3983,20 +3976,8 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
int32_t maxLayers = gfxPrefs::MaxActiveLayers();
int layerCount = 0;
ProcessDisplayItems(aList, lastAnimatedGeometryRoot, lastASR,
lastAGRTopLeft, topLeft, maxLayers, layerCount);
}
void
ContainerState::ProcessDisplayItems(nsDisplayList* aList,
AnimatedGeometryRoot* aLastAnimatedGeometryRoot,
const ActiveScrolledRoot* aLastASR,
const nsPoint& aLastAGRTopLeft,
nsPoint& aTopLeft,
int32_t aMaxLayers,
int& aLayerCount)
{
for (nsDisplayItem* i = aList->GetBottom(); i; i = i->GetAbove()) {
FlattenedDisplayItemIterator iter(mBuilder, aList);
while (nsDisplayItem* i = iter.GetNext()) {
nsDisplayItem* item = i;
MOZ_ASSERT(item);
@ -4017,7 +3998,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
// item. We create a list of consecutive items that can be merged together.
AutoTArray<nsDisplayItem*, 1> mergedItems;
mergedItems.AppendElement(item);
for (nsDisplayItem* peek = item->GetAbove(); peek; peek = peek->GetAbove()) {
while (nsDisplayItem* peek = iter.PeekNext()) {
if (!item->CanMerge(peek)) {
break;
}
@ -4025,7 +4006,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
mergedItems.AppendElement(peek);
// Move the iterator forward since we will merge this item.
i = peek;
i = iter.GetNext();
}
if (mergedItems.Length() > 1) {
@ -4035,18 +4016,6 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
MOZ_ASSERT(item && itemType == item->GetType());
}
nsDisplayList* childItems = item->GetSameCoordinateSystemChildren();
if (item->ShouldFlattenAway(mBuilder)) {
MOZ_ASSERT(childItems);
ProcessDisplayItems(childItems, aLastAnimatedGeometryRoot, aLastASR,
aLastAGRTopLeft, aTopLeft, aMaxLayers, aLayerCount);
if (childItems->NeedsTransparentSurface()) {
aList->SetNeedsTransparentSurface();
}
continue;
}
MOZ_ASSERT(item->GetType() != DisplayItemType::TYPE_WRAP_LIST);
NS_ASSERTION(mAppUnitsPerDevPixel == AppUnitsPerDevPixel(item),
@ -4074,9 +4043,9 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
const DisplayItemClipChain* layerClipChain = nullptr;
if (mFlattenToSingleLayer && layerState != LAYER_ACTIVE_FORCE) {
forceInactive = true;
animatedGeometryRoot = aLastAnimatedGeometryRoot;
itemASR = aLastASR;
aTopLeft = aLastAGRTopLeft;
animatedGeometryRoot = lastAnimatedGeometryRoot;
itemASR = lastASR;
topLeft = lastAGRTopLeft;
item->FuseClipChainUpTo(mBuilder, mContainerASR);
} else {
forceInactive = false;
@ -4098,7 +4067,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
itemASR = mContainerASR;
item->FuseClipChainUpTo(mBuilder, mContainerASR);
}
aTopLeft = (*animatedGeometryRoot)->GetOffsetToCrossDoc(mContainerReferenceFrame);
topLeft = (*animatedGeometryRoot)->GetOffsetToCrossDoc(mContainerReferenceFrame);
}
const ActiveScrolledRoot* scrollMetadataASR =
@ -4155,7 +4124,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
ScaleToOutsidePixels(item->GetVisibleRect(), false));
}
if (aMaxLayers != -1 && aLayerCount >= aMaxLayers) {
if (maxLayers != -1 && layerCount >= maxLayers) {
forceInactive = true;
}
@ -4166,7 +4135,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
(layerState == LAYER_ACTIVE_EMPTY ||
layerState == LAYER_ACTIVE))) {
aLayerCount++;
layerCount++;
// LAYER_ACTIVE_EMPTY means the layer is created just for its metadata.
// We should never see an empty layer with any visible content!
@ -4371,11 +4340,11 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
nsDisplayMask* maskItem = static_cast<nsDisplayMask*>(item);
SetupMaskLayerForCSSMask(ownLayer, maskItem);
if (i->GetAbove() &&
i->GetAbove()->GetType() == DisplayItemType::TYPE_SCROLL_INFO_LAYER) {
if (iter.PeekNext() &&
iter.PeekNext()->GetType() == DisplayItemType::TYPE_SCROLL_INFO_LAYER) {
// Since we do build a layer for mask, there is no need for this
// scroll info layer anymore.
i = i->GetAbove();
i = iter.GetNext();
}
}
@ -4484,7 +4453,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
item->Frame()->In3DContextAndBackfaceIsHidden(),
[&]() {
return NewPaintedLayerData(item, animatedGeometryRoot, itemASR, layerClipChain, scrollMetadataASR,
aTopLeft);
topLeft);
});
if (itemType == DisplayItemType::TYPE_LAYER_EVENT_REGIONS) {
@ -4502,7 +4471,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
if (!paintedLayerData->mLayer) {
// Try to recycle the old layer of this display item.
RefPtr<PaintedLayer> layer =
AttemptToRecyclePaintedLayer(animatedGeometryRoot, item, aTopLeft);
AttemptToRecyclePaintedLayer(animatedGeometryRoot, item, topLeft);
if (layer) {
paintedLayerData->mLayer = layer;
@ -4514,6 +4483,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
}
}
nsDisplayList* childItems = item->GetSameCoordinateSystemChildren();
if (childItems && childItems->NeedsTransparentSurface()) {
aList->SetNeedsTransparentSurface();
}

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

@ -6155,6 +6155,13 @@ CollectItemsWithOpacity(nsDisplayList* aList,
bool
nsDisplayOpacity::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
{
if (mFrame->GetPrevContinuation() ||
mFrame->GetNextContinuation()) {
// If we've been split, then we might need to merge, so
// don't flatten us away.
return false;
}
if (NeedsActiveLayer(aBuilder, mFrame) || mOpacity == 0.0) {
// If our opacity is zero then we'll discard all descendant display items
// except for layer event regions, so there's no point in doing this

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

@ -5588,6 +5588,73 @@ public:
mutable mozilla::Maybe<bool> mIsFrameSelected;
};
class FlattenedDisplayItemIterator
{
public:
FlattenedDisplayItemIterator(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList)
: mBuilder(aBuilder)
, mNext(aList->GetBottom())
{
ResolveFlattening();
}
nsDisplayItem* GetNext()
{
nsDisplayItem* next = mNext;
// Advance mNext to the following item
if (next) {
mNext = mNext->GetAbove();
ResolveFlattening();
}
return next;
}
nsDisplayItem* PeekNext()
{
return mNext;
}
private:
bool AtEndOfNestedList()
{
return !mNext && mStack.Length() > 0;
}
bool ShouldFlattenNextItem()
{
return mNext && mNext->ShouldFlattenAway(mBuilder);
}
void ResolveFlattening()
{
// Handle the case where we reach the end of a nested list, or the current
// item should start a new nested list. Repeat this until we find an actual
// item, or the very end of the outer list.
while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
if (AtEndOfNestedList()) {
// Pop the last item off the stack.
mNext = mStack.LastElement();
mStack.RemoveElementAt(mStack.Length() - 1);
// We stored the item that was flattened, so advance to the next.
mNext = mNext->GetAbove();
} else {
// This item wants to be flattened. Store the current item on the stack,
// and use the first item in the child list instead.
mStack.AppendElement(mNext);
nsDisplayList* childItems = mNext->GetSameCoordinateSystemChildren();
mNext = childItems->GetBottom();
}
}
}
nsDisplayListBuilder* mBuilder;
nsDisplayItem* mNext;
AutoTArray<nsDisplayItem*, 10> mStack;
};
namespace mozilla {
class PaintTelemetry

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

@ -1687,7 +1687,7 @@ fuzzy-if(skiaContent,1,4500) == 654950-1.html 654950-1-ref.html # Quartz alpha b
== 655836-1.html 655836-1-ref.html
!= 656875.html about:blank
== 658952.html 658952-ref.html
fuzzy-if(skiaContent,1,3500) == 660682-1.html 660682-1-ref.html
fuzzy-if(skiaContent,7,3500) fails-if(webrender) == 660682-1.html 660682-1-ref.html
fuzzy-if(d2d,1,256) skip-if(Android) fuzzy-if(skiaContent,1,68000) fails-if(styloVsGecko) asserts-if(stylo,16-18) == 664127-1.xul 664127-1-ref.xul # Android: Intermittent failures - bug 1019131, stylo: bug 1397644
== 665597-1.html 665597-1-ref.html
== 665597-2.html 665597-2-ref.html