Bug 1022612. Part 30: Expose IsConstructingScrollLayerForScrolledFrame and IsDisplayPortOpaque on nsDisplayScrollLayer. r=mattwoodrow
☠☠ backed out by 2bcded4e3b4a ☠ ☠
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 23 Jun 2014 16:23:58 +1200
changeset 215504 b72413ecc3851b5e550eec4e4f169f7ebd3d0b4b
parent 215503 b23f1081afb8a72b2dce03fb279695294b489864
child 215505 2763c4878de50e4b5078820ed7580312d46d3bfb
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1022612
milestone33.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 1022612. Part 30: Expose IsConstructingScrollLayerForScrolledFrame and IsDisplayPortOpaque on nsDisplayScrollLayer. r=mattwoodrow
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -3703,16 +3703,17 @@ nsDisplayScrollLayer::nsDisplayScrollLay
                                            nsDisplayList* aList,
                                            nsIFrame* aForFrame,
                                            nsIFrame* aScrolledFrame,
                                            nsIFrame* aScrollFrame)
   : nsDisplayWrapList(aBuilder, aForFrame, aList)
   , mScrollFrame(aScrollFrame)
   , mScrolledFrame(aScrolledFrame)
   , mScrollParentId(aBuilder->GetCurrentScrollParentId())
+  , mDisplayPortContentsOpaque(false)
 {
 #ifdef NS_BUILD_REFCNT_LOGGING
   MOZ_COUNT_CTOR(nsDisplayScrollLayer);
 #endif
 
   NS_ASSERTION(mScrolledFrame && mScrolledFrame->GetContent(),
                "Need a child frame with content");
 }
@@ -3721,16 +3722,17 @@ nsDisplayScrollLayer::nsDisplayScrollLay
                                            nsDisplayItem* aItem,
                                            nsIFrame* aForFrame,
                                            nsIFrame* aScrolledFrame,
                                            nsIFrame* aScrollFrame)
   : nsDisplayWrapList(aBuilder, aForFrame, aItem)
   , mScrollFrame(aScrollFrame)
   , mScrolledFrame(aScrolledFrame)
   , mScrollParentId(aBuilder->GetCurrentScrollParentId())
+  , mDisplayPortContentsOpaque(false)
 {
 #ifdef NS_BUILD_REFCNT_LOGGING
   MOZ_COUNT_CTOR(nsDisplayScrollLayer);
 #endif
 
   NS_ASSERTION(mScrolledFrame && mScrolledFrame->GetContent(),
                "Need a child frame with content");
 }
@@ -3738,16 +3740,17 @@ nsDisplayScrollLayer::nsDisplayScrollLay
 nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
                                            nsIFrame* aForFrame,
                                            nsIFrame* aScrolledFrame,
                                            nsIFrame* aScrollFrame)
   : nsDisplayWrapList(aBuilder, aForFrame)
   , mScrollFrame(aScrollFrame)
   , mScrolledFrame(aScrolledFrame)
   , mScrollParentId(aBuilder->GetCurrentScrollParentId())
+  , mDisplayPortContentsOpaque(false)
 {
 #ifdef NS_BUILD_REFCNT_LOGGING
   MOZ_COUNT_CTOR(nsDisplayScrollLayer);
 #endif
 
   NS_ASSERTION(mScrolledFrame && mScrolledFrame->GetContent(),
                "Need a child frame with content");
 }
@@ -3765,36 +3768,69 @@ nsDisplayScrollLayer::GetBounds(nsDispla
   nsIScrollableFrame* sf = do_QueryFrame(mScrollFrame);
   if (sf) {
     *aSnap = false;
     return sf->GetScrollPortRect() + aBuilder->ToReferenceFrame(mScrollFrame);
   }
   return nsDisplayWrapList::GetBounds(aBuilder, aSnap);
 }
 
+nsRect
+nsDisplayScrollLayer::GetScrolledContentRectToDraw(nsDisplayListBuilder* aBuilder,
+                                                   nsRect* aDisplayPort)
+{
+  if (aDisplayPort) {
+    // The visible region for the children may be much bigger than the hole we
+    // are viewing the children from, so that the compositor process has enough
+    // content to asynchronously pan while content is being refreshed.
+    // XXX mScrollFrame seems wrong here; we should add the offset of the
+    // scrollport
+    return *aDisplayPort + mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
+  }
+  bool snap;
+  return GetBounds(aBuilder, &snap);
+}
+
 already_AddRefed<Layer>
 nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
                                  LayerManager* aManager,
                                  const ContainerLayerParameters& aContainerParameters) {
   nsRefPtr<ContainerLayer> layer = aManager->GetLayerBuilder()->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
                            aContainerParameters, nullptr);
 
   nsRect viewport = mScrollFrame->GetRect() -
                     mScrollFrame->GetPosition() +
                     mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
 
   layer->SetScrollHandoffParentId(mScrollParentId);
   RecordFrameMetrics(mScrolledFrame, mScrollFrame, ReferenceFrame(), layer,
                      viewport, false, false, aContainerParameters);
 
+  if (mList.IsOpaque()) {
+    nsRect displayport;
+    bool usingDisplayport =
+      nsLayoutUtils::GetDisplayPort(mScrolledFrame->GetContent(), &displayport);
+    mDisplayPortContentsOpaque = mList.GetBounds(aBuilder).Contains(
+        GetScrolledContentRectToDraw(aBuilder, usingDisplayport ? &displayport : nullptr));
+  } else {
+    mDisplayPortContentsOpaque = false;
+  }
+
   return layer.forget();
 }
 
 bool
+nsDisplayScrollLayer::IsConstructingScrollLayerForScrolledFrame(const nsIFrame* aScrolledFrame)
+{
+  FrameProperties props = aScrolledFrame->Properties();
+  return reinterpret_cast<intptr_t>(props.Get(nsIFrame::ScrollLayerCount())) != 0;
+}
+
+bool
 nsDisplayScrollLayer::ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder)
 {
   if (nsLayoutUtils::GetDisplayPort(mScrolledFrame->GetContent(), nullptr)) {
     return true;
   }
 
   return nsDisplayWrapList::ShouldBuildLayerEvenIfInvisible(aBuilder);
 }
@@ -3802,30 +3838,22 @@ nsDisplayScrollLayer::ShouldBuildLayerEv
 bool
 nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                         nsRegion* aVisibleRegion,
                                         const nsRect& aAllowVisibleRegionExpansion)
 {
   nsRect displayport;
   bool usingDisplayPort =
     nsLayoutUtils::GetDisplayPort(mScrolledFrame->GetContent(), &displayport);
-  nsRegion childVisibleRegion;
-  if (usingDisplayPort) {
-    // The visible region for the children may be much bigger than the hole we
-    // are viewing the children from, so that the compositor process has enough
-    // content to asynchronously pan while content is being refreshed.
-    childVisibleRegion = displayport + mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
-  } else {
-    bool snap;
-    childVisibleRegion = GetBounds(aBuilder, &snap);
-  }
-
-  nsRect boundedRect =
-    childVisibleRegion.GetBounds().Intersect(mList.GetBounds(aBuilder));
+  nsRect scrolledContentRect = GetScrolledContentRectToDraw(aBuilder,
+      usingDisplayPort ? &displayport : nullptr);
+
+  nsRect boundedRect = scrolledContentRect.Intersect(mList.GetBounds(aBuilder));
   nsRect allowExpansion = boundedRect.Intersect(aAllowVisibleRegionExpansion);
+  nsRegion childVisibleRegion = scrolledContentRect;
   bool visible = mList.ComputeVisibilityForSublist(
     aBuilder, &childVisibleRegion, boundedRect, allowExpansion,
     usingDisplayPort ? mScrollFrame : nullptr);
   // We don't allow this computation to influence aVisibleRegion, on the
   // assumption that the layer can be asynchronously scrolled so we'll
   // definitely need all the content under it.
 
   return visible;
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -3036,27 +3036,35 @@ public:
 
   virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
 
   // Get the number of nsDisplayScrollLayers for a scroll frame. Note that this
   // number does not include nsDisplayScrollInfoLayers. If this number is not 1
   // after merging, all the nsDisplayScrollLayers should flatten away.
   intptr_t GetScrollLayerCount();
 
+  static bool IsConstructingScrollLayerForScrolledFrame(const nsIFrame* aScrolledFrame);
+
   virtual nsIFrame* GetScrollFrame() { return mScrollFrame; }
   virtual nsIFrame* GetScrolledFrame() { return mScrolledFrame; }
 
 #ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE;
 #endif
 
+  bool IsDisplayPortOpaque() { return mDisplayPortContentsOpaque; }
+
 protected:
+  nsRect GetScrolledContentRectToDraw(nsDisplayListBuilder* aBuilder,
+                                      nsRect* aDisplayPort);
+
   nsIFrame* mScrollFrame;
   nsIFrame* mScrolledFrame;
   ViewID mScrollParentId;
+  bool mDisplayPortContentsOpaque;
 };
 
 /**
  * Like nsDisplayScrollLayer, but only has metadata on the scroll frame. This
  * creates a layer that has no Thebes child layer, but still allows the
  * compositor process to know of the scroll frame's existence.
  *
  * After visibility computation, nsDisplayScrollInfoLayers should only exist if