Bug 1331342 - Cache and reuse the result of GetDisplayPort. r=mattwoodrow
authorThinker K.F. Li <thinker@codemud.net>
Sat, 04 Mar 2017 10:18:00 -0500
changeset 346034 8cf1aa220fc1
parent 346033 3f78543493a2
child 346035 75e73a2476b8
push id31452
push usercbook@mozilla.com
push date2017-03-06 09:54 +0000
treeherdermozilla-central@966464a68a2c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1331342
milestone54.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 1331342 - Cache and reuse the result of GetDisplayPort. r=mattwoodrow
layout/painting/FrameLayerBuilder.cpp
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -1058,17 +1058,18 @@ public:
     mContainerFrame(aContainerFrame),
     mContainerLayer(aContainerLayer),
     mContainerBounds(aContainerBounds),
     mContainerASR(aContainerASR),
     mContainerScrollMetadataASR(aContainerScrollMetadataASR),
     mContainerCompositorASR(aContainerCompositorASR),
     mParameters(aParameters),
     mPaintedLayerDataTree(*this, aBackgroundColor),
-    mFlattenToSingleLayer(aFlattenToSingleLayer)
+    mFlattenToSingleLayer(aFlattenToSingleLayer),
+    mLastDisplayPortAGR(nullptr)
   {
     nsPresContext* presContext = aContainerFrame->PresContext();
     mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
     mContainerReferenceFrame =
       const_cast<nsIFrame*>(aContainerItem ? aContainerItem->ReferenceFrameForChildren() :
                                              mBuilder->FindReferenceFrameFor(mContainerFrame));
     bool isAtRoot = !aContainerItem || (aContainerItem->Frame() == mBuilder->RootReferenceFrame());
     MOZ_ASSERT_IF(isAtRoot, mContainerReferenceFrame == mBuilder->RootReferenceFrame());
@@ -1379,16 +1380,22 @@ protected:
     Layer *aLayer, const DisplayItemClip& aClip,
     const Maybe<size_t>& aForAncestorMaskLayer,
     uint32_t aRoundedRectClipCount = UINT32_MAX);
 
   bool ChooseAnimatedGeometryRoot(const nsDisplayList& aList,
                                   AnimatedGeometryRoot** aAnimatedGeometryRoot,
                                   const ActiveScrolledRoot** aASR);
 
+  /**
+   * Get the display port for an AGR.
+   * The result would be cached for later reusing.
+   */
+  nsRect GetDisplayPortForAnimatedGeometryRoot(AnimatedGeometryRoot* aAnimatedGeometryRoot);
+
   nsDisplayListBuilder*            mBuilder;
   LayerManager*                    mManager;
   FrameLayerBuilder*               mLayerBuilder;
   nsIFrame*                        mContainerFrame;
   nsIFrame*                        mContainerReferenceFrame;
   AnimatedGeometryRoot*            mContainerAnimatedGeometryRoot;
   ContainerLayer*                  mContainerLayer;
   nsRect                           mContainerBounds;
@@ -1449,16 +1456,20 @@ protected:
     }
 
     Layer* mLayer;
     Maybe<size_t> mAncestorIndex;
   };
 
   nsDataHashtable<nsGenericHashKey<MaskLayerKey>, RefPtr<ImageLayer>>
     mRecycledMaskImageLayers;
+  // Keep display port of AGR to avoid wasting time on doing the same
+  // thing repeatly.
+  AnimatedGeometryRoot* mLastDisplayPortAGR;
+  nsRect mLastDisplayPortRect;
 };
 
 class PaintedDisplayItemLayerUserData : public LayerUserData
 {
 public:
   PaintedDisplayItemLayerUserData() :
     mMaskClipCount(0),
     mForcedBackgroundColor(NS_RGBA(0,0,0,0)),
@@ -3758,16 +3769,43 @@ ContainerState::ChooseAnimatedGeometryRo
     // should result in the least invalidation when scrolling.
     *aAnimatedGeometryRoot = item->GetAnimatedGeometryRoot();
     *aASR = item->GetActiveScrolledRoot();
     return true;
   }
   return false;
 }
 
+nsRect
+ContainerState::GetDisplayPortForAnimatedGeometryRoot(AnimatedGeometryRoot* aAnimatedGeometryRoot)
+{
+  if (mLastDisplayPortAGR == aAnimatedGeometryRoot) {
+    return mLastDisplayPortRect;
+  }
+
+  nsIScrollableFrame* sf = nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot);
+  if (sf == nullptr) {
+    return nsRect();
+  }
+
+  mLastDisplayPortAGR = aAnimatedGeometryRoot;
+  nsRect& displayport = mLastDisplayPortRect;;
+  bool usingDisplayport =
+    nsLayoutUtils::GetDisplayPort((*aAnimatedGeometryRoot)->GetContent(), &displayport,
+                                  RelativeTo::ScrollFrame);
+  if (!usingDisplayport) {
+    // No async scrolling, so all that matters is that the layer contents
+    // cover the scrollport.
+    displayport = sf->GetScrollPortRect();
+  }
+  nsIFrame* scrollFrame = do_QueryFrame(sf);
+  displayport += scrollFrame->GetOffsetToCrossDoc(mContainerReferenceFrame);
+  return displayport;
+}
+
 nsIntRegion
 ContainerState::ComputeOpaqueRect(nsDisplayItem* aItem,
                                   AnimatedGeometryRoot* aAnimatedGeometryRoot,
                                   const DisplayItemClip& aClip,
                                   nsDisplayList* aList,
                                   bool* aHideAllLayersBelow,
                                   bool* aOpaqueForAnimatedGeometryRootParent)
 {
@@ -3796,32 +3834,21 @@ ContainerState::ComputeOpaqueRect(nsDisp
     mBuilder->AddWindowOpaqueRegion(opaqueClipped);
   }
   opaquePixels = ScaleRegionToInsidePixels(opaqueClipped, snapOpaque);
 
   if (IsInInactiveLayer()) {
     return opaquePixels;
   }
 
-  nsIScrollableFrame* sf = nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot);
-  if (sf) {
-    nsRect displayport;
-    bool usingDisplayport =
-      nsLayoutUtils::GetDisplayPort((*aAnimatedGeometryRoot)->GetContent(), &displayport,
-        RelativeTo::ScrollFrame);
-    if (!usingDisplayport) {
-      // No async scrolling, so all that matters is that the layer contents
-      // cover the scrollport.
-      displayport = sf->GetScrollPortRect();
-    }
-    nsIFrame* scrollFrame = do_QueryFrame(sf);
-    displayport += scrollFrame->GetOffsetToCrossDoc(mContainerReferenceFrame);
-    if (opaquePixels.Contains(ScaleRegionToNearestPixels(displayport))) {
-      *aOpaqueForAnimatedGeometryRootParent = true;
-    }
+  const nsRect& displayport =
+    GetDisplayPortForAnimatedGeometryRoot(aAnimatedGeometryRoot);
+  if (!displayport.IsEmpty() &&
+      opaquePixels.Contains(ScaleRegionToNearestPixels(displayport))) {
+    *aOpaqueForAnimatedGeometryRootParent = true;
   }
   return opaquePixels;
 }
 
 Maybe<size_t>
 ContainerState::SetupMaskLayerForScrolledClip(Layer* aLayer,
                                               const DisplayItemClip& aClip)
 {