Bug 1298218 - Save and restore the combined clip for the "top layer". r?tnikkel draft
authorMarkus Stange <mstange@themasta.com>
Fri, 27 Jan 2017 17:33:53 +0100
changeset 469206 a5e52ee4e4a2d6401dc98d958d40de9465f4b3ee
parent 469205 2369451d7c77c36339b9e5a3c42713d3c730ddae
child 469207 8df89a7bc06b3cec0dc0668e1a2b40acd86019a5
push id43652
push userbmo:mstange@themasta.com
push dateWed, 01 Feb 2017 21:18:30 +0000
reviewerstnikkel
bugs1298218
milestone54.0a1
Bug 1298218 - Save and restore the combined clip for the "top layer". r?tnikkel MozReview-Commit-ID: IRfB85gVyWB
layout/generic/ViewportFrame.cpp
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/layout/generic/ViewportFrame.cpp
+++ b/layout/generic/ViewportFrame.cpp
@@ -102,18 +102,25 @@ BuildDisplayListForTopLayerFrame(nsDispl
 {
   nsRect dirty;
   DisplayListClipState::AutoClipMultiple clipState(aBuilder);
   nsDisplayListBuilder::AutoCurrentActiveScrolledRootSetter asrSetter(aBuilder);
   nsDisplayListBuilder::OutOfFlowDisplayData*
     savedOutOfFlowData = nsDisplayListBuilder::GetOutOfFlowData(aFrame);
   if (savedOutOfFlowData) {
     dirty = savedOutOfFlowData->mDirtyRect;
+    // This function is called after we've finished building display items for
+    // the root scroll frame. That means that the content clip from the root
+    // scroll frame is no longer on aBuilder. However, we need to make sure
+    // that the display items we build in this function have finite clipped
+    // bounds with respect to the root ASR, so we restore the *combined clip*
+    // that we saved earlier. The combined clip will include the clip from the
+    // root scroll frame.
     clipState.SetClipChainForContainingBlockDescendants(
-      savedOutOfFlowData->mContainingBlockClipChain);
+      savedOutOfFlowData->mCombinedClipChain);
     clipState.ClipContainingBlockDescendantsExtra(
       dirty + aBuilder->ToReferenceFrame(aFrame), nullptr);
     asrSetter.SetCurrentActiveScrolledRoot(
       savedOutOfFlowData->mContainingBlockActiveScrolledRoot);
   }
   nsDisplayList list;
   aFrame->BuildDisplayListForStackingContext(aBuilder, dirty, &list);
   aList->AppendToTop(&list);
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -1046,18 +1046,19 @@ void nsDisplayListBuilder::MarkOutOfFlow
       !(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
     return;
   }
 
   // mClipState.GetClipChainForContainingBlockDescendants can return pointers
   // to objects on the stack, so we need to clone the chain.
   const DisplayItemClipChain* clipChain =
     CopyWholeChain(mClipState.GetClipChainForContainingBlockDescendants());
+  const DisplayItemClipChain* combinedClipChain = mClipState.GetCurrentCombinedClipChain(this);
   const ActiveScrolledRoot* asr = mCurrentActiveScrolledRoot;
-  OutOfFlowDisplayData* data = new OutOfFlowDisplayData(clipChain, asr, dirty);
+  OutOfFlowDisplayData* data = new OutOfFlowDisplayData(clipChain, combinedClipChain, asr, dirty);
   aFrame->Properties().Set(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data);
 
   MarkFrameForDisplay(aFrame, aDirtyFrame);
 }
 
 static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
   nsPresContext* presContext = aFrame->PresContext();
   presContext->PropertyTable()->
@@ -1270,19 +1271,20 @@ nsDisplayListBuilder::MarkFramesForDispl
     NS_ASSERTION(CurrentPresShellState()->mPresShell ==
         aDirtyFrame->PresContext()->PresShell(),
         "Presshell mismatch");
     MOZ_ASSERT(!CurrentPresShellState()->mFixedBackgroundDisplayData,
                "already traversed this presshell's root frame?");
 
     const DisplayItemClipChain* clipChain =
       CopyWholeChain(mClipState.GetClipChainForContainingBlockDescendants());
+    const DisplayItemClipChain* combinedClipChain = mClipState.GetCurrentCombinedClipChain(this);
     const ActiveScrolledRoot* asr = mCurrentActiveScrolledRoot;
     CurrentPresShellState()->mFixedBackgroundDisplayData.emplace(
-      clipChain, asr, aDirtyRect);
+      clipChain, combinedClipChain, asr, aDirtyRect);
   }
 }
 
 /**
  * Mark all preserve-3d children with
  * NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO to make sure
  * nsFrame::BuildDisplayListForChild() would visit them.  Also compute
  * dirty rect for preserve-3d children.
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -1206,23 +1206,26 @@ public:
   }
 
   // Helpers for tables
   nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
   void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
 
   struct OutOfFlowDisplayData {
     OutOfFlowDisplayData(const DisplayItemClipChain* aContainingBlockClipChain,
+                         const DisplayItemClipChain* aCombinedClipChain,
                          const ActiveScrolledRoot* aContainingBlockActiveScrolledRoot,
                          const nsRect &aDirtyRect)
       : mContainingBlockClipChain(aContainingBlockClipChain)
+      , mCombinedClipChain(aCombinedClipChain)
       , mContainingBlockActiveScrolledRoot(aContainingBlockActiveScrolledRoot)
       , mDirtyRect(aDirtyRect)
     {}
     const DisplayItemClipChain* mContainingBlockClipChain;
+    const DisplayItemClipChain* mCombinedClipChain; // only necessary for the special case of top layer
     const ActiveScrolledRoot* mContainingBlockActiveScrolledRoot;
     nsRect mDirtyRect;
   };
 
   NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty,
                                       OutOfFlowDisplayData)
 
   static OutOfFlowDisplayData* GetOutOfFlowData(nsIFrame* aFrame)