Bug 1526972 - P8: Reset InInvalidSubtree when processing unrelated frames. r=mattwoodrow
authorDan Glastonbury <dan.glastonbury@gmail.com>
Thu, 18 Apr 2019 02:41:33 +0000
changeset 470027 817642dc917c886910c8fb9ad856ec153c2655c3
parent 470026 069c60c771c69da58dc3bf54e7e42ec755c17c00
child 470028 a9c6ef836b4a926513a711312a45fc95dca53731
push id112839
push userapavel@mozilla.com
push dateThu, 18 Apr 2019 21:50:57 +0000
treeherdermozilla-inbound@e0a826fcd85b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1526972
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1526972 - P8: Reset InInvalidSubtree when processing unrelated frames. r=mattwoodrow Differential Revision: https://phabricator.services.mozilla.com/D26141
layout/generic/nsGfxScrollFrame.cpp
layout/painting/RetainedDisplayListBuilder.cpp
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -3741,16 +3741,19 @@ void ScrollFrameHelper::BuildDisplayList
 
 void ScrollFrameHelper::MaybeAddTopLayerItems(nsDisplayListBuilder* aBuilder,
                                               const nsDisplayListSet& aLists) {
   if (mIsRoot) {
     if (ViewportFrame* viewportFrame = do_QueryFrame(mOuter->GetParent())) {
       nsDisplayList topLayerList;
       viewportFrame->BuildDisplayListForTopLayer(aBuilder, &topLayerList);
       if (!topLayerList.IsEmpty()) {
+        nsDisplayListBuilder::AutoBuildingDisplayList buildingDisplayList(
+            aBuilder, viewportFrame);
+
         // Wrap the whole top layer in a single item with maximum z-index,
         // and append it at the very end, so that it stays at the topmost.
         nsDisplayWrapList* wrapList = MakeDisplayItem<nsDisplayWrapList>(
             aBuilder, viewportFrame, &topLayerList,
             aBuilder->CurrentActiveScrolledRoot(), false, 2);
         if (wrapList) {
           wrapList->SetOverrideZIndex(
               std::numeric_limits<decltype(wrapList->ZIndex())>::max());
--- a/layout/painting/RetainedDisplayListBuilder.cpp
+++ b/layout/painting/RetainedDisplayListBuilder.cpp
@@ -209,25 +209,31 @@ void RetainedDisplayListBuilder::Increme
 
   PresShell* presShell = subDocFrame->GetSubdocumentPresShellForPainting(0);
   MOZ_ASSERT(presShell);
 
   mBuilder.IncrementPresShellPaintCount(presShell);
 }
 
 bool AnyContentAncestorModified(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
-  for (nsIFrame* f = aFrame; f;
-       f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
+  nsIFrame* f = aFrame;
+  while (f) {
     if (f->IsFrameModified()) {
       return true;
     }
 
     if (aStopAtFrame && f == aStopAtFrame) {
       break;
     }
+
+    if (f->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT) {
+      f = f->GetParent();
+    } else {
+      f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f);
+    }
   }
 
   return false;
 }
 
 static Maybe<const ActiveScrolledRoot*> SelectContainerASR(
     const DisplayItemClipChain* aClipChain, const ActiveScrolledRoot* aItemASR,
     Maybe<const ActiveScrolledRoot*>& aContainerASR) {
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -10285,16 +10285,35 @@ PaintTelemetry::AutoRecord::~AutoRecord(
     return;
   }
 
   sMetrics[mMetric] += (TimeStamp::Now() - mStart).ToMilliseconds();
 }
 
 }  // namespace mozilla
 
+static nsIFrame* GetSelfOrPlaceholderFor(nsIFrame* aFrame) {
+  if (aFrame->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT) {
+    return aFrame;
+  }
+
+  if ((aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
+      !aFrame->GetPrevInFlow()) {
+    return aFrame->GetPlaceholderFrame();
+  }
+
+  return aFrame;
+}
+
+static nsIFrame* GetAncestorFor(nsIFrame* aFrame) {
+  nsIFrame* f = GetSelfOrPlaceholderFor(aFrame);
+  MOZ_ASSERT(f);
+  return nsLayoutUtils::GetCrossDocParentFrame(f);
+}
+
 nsDisplayListBuilder::AutoBuildingDisplayList::AutoBuildingDisplayList(
     nsDisplayListBuilder* aBuilder, nsIFrame* aForChild,
     const nsRect& aVisibleRect, const nsRect& aDirtyRect,
     const bool aIsTransformed)
     : mBuilder(aBuilder),
       mPrevFrame(aBuilder->mCurrentFrame),
       mPrevReferenceFrame(aBuilder->mCurrentReferenceFrame),
       mPrevHitTestArea(aBuilder->mHitTestArea),
@@ -10326,15 +10345,23 @@ nsDisplayListBuilder::AutoBuildingDispla
           aBuilder->WrapAGRForFrame(aForChild, isAsync, aBuilder->mCurrentAGR);
     }
   } else if (aBuilder->mCurrentFrame != aForChild) {
     aBuilder->mCurrentAGR = aBuilder->FindAnimatedGeometryRootFor(aForChild);
   }
 
   MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(
       aBuilder->RootReferenceFrame(), *aBuilder->mCurrentAGR));
-  aBuilder->mInInvalidSubtree =
-      aBuilder->mInInvalidSubtree || aForChild->IsFrameModified();
+
+  // If aForChild is being visited from a frame other than it's ancestor frame,
+  // mInInvalidSubtree will need to be recalculated the slow way.
+  if (aForChild == mPrevFrame || GetAncestorFor(aForChild) == mPrevFrame) {
+    aBuilder->mInInvalidSubtree =
+        aBuilder->mInInvalidSubtree || aForChild->IsFrameModified();
+  } else {
+    aBuilder->mInInvalidSubtree = AnyContentAncestorModified(aForChild);
+  }
+
   aBuilder->mCurrentFrame = aForChild;
   aBuilder->mVisibleRect = aVisibleRect;
   aBuilder->mDirtyRect =
       aBuilder->mInInvalidSubtree ? aVisibleRect : aDirtyRect;
 }
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -1127,16 +1127,21 @@ class nsDisplayListBuilder {
 
   /**
    * A helper class used to temporarily set nsDisplayListBuilder properties for
    * building display items.
    * aVisibleRect and aDirtyRect are relative to aForChild.
    */
   class AutoBuildingDisplayList {
    public:
+    AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild)
+        : AutoBuildingDisplayList(
+              aBuilder, aForChild, aBuilder->GetVisibleRect(),
+              aBuilder->GetDirtyRect(), aForChild->IsTransformed()) {}
+
     AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild,
                             const nsRect& aVisibleRect,
                             const nsRect& aDirtyRect)
         : AutoBuildingDisplayList(aBuilder, aForChild, aVisibleRect, aDirtyRect,
                                   aForChild->IsTransformed()) {}
 
     AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild,
                             const nsRect& aVisibleRect,