Bug 1459441 - Make sure we build the full display list when we have blend containers in order to get the correct sorting for them. r=mstange

MozReview-Commit-ID: ECTU7enMb1r

--HG--
extra : rebase_source : 70f1b6187c152e770c4e19539645174c62198dc0
This commit is contained in:
Matt Woodrow 2018-05-10 11:39:12 +12:00
Родитель 1044f75cf5
Коммит 085d0bbe3b
8 изменённых файлов: 93 добавлений и 53 удалений

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

@ -2939,13 +2939,6 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
hasOverrideDirtyRect = true; hasOverrideDirtyRect = true;
} }
} }
// Always build the entire display list if we previously had a blend
// container since a partial build might make us think we no longer
// need the container even though the merged result will.
if (aBuilder->IsRetainingDisplayList() && BuiltBlendContainer()) {
dirtyRect = visibleRect;
aBuilder->MarkFrameModifiedDuringBuilding(this);
}
bool usingFilter = StyleEffects()->HasFilters(); bool usingFilter = StyleEffects()->HasFilters();
bool usingMask = nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(this); bool usingMask = nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(this);
@ -3107,42 +3100,17 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
// is complex and likely to be buggy. // is complex and likely to be buggy.
// Instead we're doing the sad thing, detecting it afterwards, and just // Instead we're doing the sad thing, detecting it afterwards, and just
// repeating display list building if it changed. // repeating display list building if it changed.
// We have to repeat building for the entire display list (or at least
// If we changed whether we're going to build a blend mode item, // the outer stacking context), since we need to mark this frame as invalid
// then we need to make sure we're marked as invalid and we've built // to remove any existing content that isn't wrapped in the blend container,
// the full display list. // and then we need to build content infront/behind the blend container
if (aBuilder->ContainsBlendMode() != BuiltBlendContainer() && // to get correct positioning during merging.
if (aBuilder->ContainsBlendMode() &&
aBuilder->IsRetainingDisplayList()) { aBuilder->IsRetainingDisplayList()) {
SetBuiltBlendContainer(aBuilder->ContainsBlendMode());
// If we did a partial build then delete all the items we just built
// and repeat building with the full area.
if (!aBuilder->GetDirtyRect().Contains(aBuilder->GetVisibleRect())) { if (!aBuilder->GetDirtyRect().Contains(aBuilder->GetVisibleRect())) {
aBuilder->MarkCurrentFrameModifiedDuringBuilding(); aBuilder->SetPartialBuildFailed(true);
set.DeleteAll(aBuilder); } else {
aBuilder->SetDisablePartialUpdates(true);
if (eventRegions) {
eventRegions->Destroy(aBuilder);
eventRegions = MakeDisplayItem<nsDisplayLayerEventRegions>(aBuilder, this);
eventRegions->AddFrame(aBuilder, this);
aBuilder->SetLayerEventRegions(eventRegions);
}
aBuilder->BuildCompositorHitTestInfoIfNeeded(this,
set.BorderBackground(),
true);
// If this is the root frame, then the previous call to
// MarkAbsoluteFramesForDisplayList might have stored some fixed
// background data. Clear that now.
if (!GetParent()) {
aBuilder->ClearFixedBackgroundDisplayData();
}
MarkAbsoluteFramesForDisplayList(aBuilder);
aBuilder->Check();
BuildDisplayList(aBuilder, set);
aBuilder->Check();
} }
} }

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

@ -612,7 +612,6 @@ public:
, mFrameIsModified(false) , mFrameIsModified(false)
, mHasOverrideDirtyRegion(false) , mHasOverrideDirtyRegion(false)
, mMayHaveWillChangeBudget(false) , mMayHaveWillChangeBudget(false)
, mBuiltBlendContainer(false)
, mIsPrimaryFrame(false) , mIsPrimaryFrame(false)
, mMayHaveTransformAnimation(false) , mMayHaveTransformAnimation(false)
, mMayHaveOpacityAnimation(false) , mMayHaveOpacityAnimation(false)
@ -4145,9 +4144,6 @@ public:
bool MayHaveWillChangeBudget() { return mMayHaveWillChangeBudget; } bool MayHaveWillChangeBudget() { return mMayHaveWillChangeBudget; }
void SetMayHaveWillChangeBudget(bool aHasBudget) { mMayHaveWillChangeBudget = aHasBudget; } void SetMayHaveWillChangeBudget(bool aHasBudget) { mMayHaveWillChangeBudget = aHasBudget; }
bool BuiltBlendContainer() { return mBuiltBlendContainer; }
void SetBuiltBlendContainer(bool aBuilt) { mBuiltBlendContainer = aBuilt; }
/** /**
* Returns the set of flags indicating the properties of the frame that the * Returns the set of flags indicating the properties of the frame that the
* compositor might care about for hit-testing purposes. Note that this function * compositor might care about for hit-testing purposes. Note that this function
@ -4345,12 +4341,6 @@ protected:
*/ */
bool mMayHaveWillChangeBudget : 1; bool mMayHaveWillChangeBudget : 1;
/**
* True if we built an nsDisplayBlendContainer last time
* we did retained display list building for this frame.
*/
bool mBuiltBlendContainer : 1;
private: private:
/** /**
* True if this is the primary frame for mContent. * True if this is the primary frame for mContent.
@ -4372,7 +4362,7 @@ private:
protected: protected:
// There is no gap left here. // There is a 1-bit gap left here.
// Helpers // Helpers
/** /**

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

@ -1151,6 +1151,13 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(
} }
mBuilder.SetPartialUpdate(false); mBuilder.SetPartialUpdate(false);
if (mBuilder.PartialBuildFailed()) {
mBuilder.SetPartialBuildFailed(false);
mBuilder.LeavePresShell(mBuilder.RootReferenceFrame(), List());
mList.ClearDAG();
return PartialUpdateResult::Failed;
}
if (aChecker) { if (aChecker) {
aChecker->Set(&modifiedDL, "TM"); aChecker->Set(&modifiedDL, "TM");
} }

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

@ -1011,7 +1011,8 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mHitTestIsForVisibility(false), mHitTestIsForVisibility(false),
mIsBuilding(false), mIsBuilding(false),
mInInvalidSubtree(false), mInInvalidSubtree(false),
mDisablePartialUpdates(false) mDisablePartialUpdates(false),
mPartialBuildFailed(false)
{ {
MOZ_COUNT_CTOR(nsDisplayListBuilder); MOZ_COUNT_CTOR(nsDisplayListBuilder);

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

@ -844,6 +844,9 @@ public:
void SetDisablePartialUpdates(bool aDisable) { mDisablePartialUpdates = aDisable; } void SetDisablePartialUpdates(bool aDisable) { mDisablePartialUpdates = aDisable; }
bool DisablePartialUpdates() { return mDisablePartialUpdates; } bool DisablePartialUpdates() { return mDisablePartialUpdates; }
void SetPartialBuildFailed(bool aFailed) { mPartialBuildFailed = aFailed; }
bool PartialBuildFailed() { return mPartialBuildFailed; }
/** /**
* Return true if we're currently building a display list for the presshell * Return true if we're currently building a display list for the presshell
* of a chrome document, or if we're building the display list for a popup. * of a chrome document, or if we're building the display list for a popup.
@ -1997,6 +2000,7 @@ private:
bool mBuildCompositorHitTestInfo; bool mBuildCompositorHitTestInfo;
bool mLessEventRegionItems; bool mLessEventRegionItems;
bool mDisablePartialUpdates; bool mDisablePartialUpdates;
bool mPartialBuildFailed;
}; };
class nsDisplayItem; class nsDisplayItem;

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

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 200px;
height: 200px;
}
.sort-marker {
position: fixed;
background-color: green;
}
.wrapper {
position: absolute;
isolation: isolate;
}
.inner {
position: absolute;
background-color: blue;
}
</style>
</head>
<body>
<div class="sort-marker"></div>
<div class="wrapper">
<div class="inner" style="left: 5px; top: 5px; mix-blend-mode:screen"></div>
<div class="inner" id="move" style="left: 221px;"></div>
</div>
<div class="sort-marker" style="left: 20px; top: 20px;"></div>
</body>
</html>

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

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<style>
div {
width: 200px;
height: 200px;
}
.sort-marker {
position: fixed;
background-color: green;
}
.wrapper {
position: absolute;
isolation: isolate;
}
.inner {
position: absolute;
background-color: blue;
}
</style>
</head>
<body>
<div class="sort-marker"></div>
<div class="wrapper">
<div class="inner" style="left: 5px; top: 5px; mix-blend-mode:screen"></div>
<div class="inner" id="move" style="left: 220px;"></div>
</div>
<div class="sort-marker" style="left: 20px; top: 20px;"></div>
</body>
<script>
function doTest() {
document.getElementById("move").style.left = "221px";
document.documentElement.removeAttribute("class");
}
document.addEventListener("MozReftestInvalidate", doTest);
</script>
</html>

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

@ -11,6 +11,7 @@ skip-if(!retainedDisplayList) == retained-dl-animation-on-pseudo.html retained-d
== retained-dl-wrap-list.html retained-dl-wrap-list-ref.html == retained-dl-wrap-list.html retained-dl-wrap-list-ref.html
== retained-dl-zindex-1.html retained-dl-zindex-1-ref.html == retained-dl-zindex-1.html retained-dl-zindex-1-ref.html
== retained-dl-zindex-2.html retained-dl-zindex-2-ref.html == retained-dl-zindex-2.html retained-dl-zindex-2-ref.html
== invalidated-blendmode-sorting.html invalidated-blendmode-sorting-ref.html
fuzzy(1,235200) == 1413073.html 1413073-ref.html fuzzy(1,235200) == 1413073.html 1413073-ref.html
== 1416291.html 1416291-ref.html == 1416291.html 1416291-ref.html
== 1417601-1.html 1417601-1-ref.html == 1417601-1.html 1417601-1-ref.html