Bug 933264 - If we have to flatten scroll layer items make sure to clip their child items properly. r=roc, a=1.3+
authorTimothy Nikkel <tnikkel@gmail.com>
Tue, 10 Dec 2013 12:05:18 -0600
changeset 175229 5d3986855f3feae34f71e44c72a10825b1261918
parent 175228 b0b118d4ec72c1c3a00e4920d0bd989a8ff567f7
child 175230 b88814af4d301b7261db870198deddefe30b8a9a
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, 1
bugs933264
milestone28.0a2
Bug 933264 - If we have to flatten scroll layer items make sure to clip their child items properly. r=roc, a=1.3+ The scroll layer item has the clip induced by the scroll frame, but the scrolled items are only clipped to the (larger) display port so we can async scroll the display port area. But if we can't merge all the scroll layer items then we can't render the expanded display port content so we have to clip the scrolled items to the scroll frame by propagating the clip on the scroll layer item to its children.
layout/base/nsDisplayList.cpp
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -3562,20 +3562,43 @@ nsDisplayScrollLayer::TryMerge(nsDisplay
   // See Bug 729534 and Bug 731641.
   nsIFrame* tmp = mFrame;
   mFrame = other->mFrame;
   other->mFrame = tmp;
   MergeFromTrackingMergedFrames(other);
   return true;
 }
 
+void
+PropagateClip(nsDisplayListBuilder* aBuilder, const DisplayItemClip& aClip,
+              nsDisplayList* aList)
+{
+  for (nsDisplayItem* i = aList->GetBottom(); i != nullptr; i = i->GetAbove()) {
+    DisplayItemClip clip(i->GetClip());
+    clip.IntersectWith(aClip);
+    i->SetClip(aBuilder, clip);
+    nsDisplayList* list = i->GetSameCoordinateSystemChildren();
+    if (list) {
+      PropagateClip(aBuilder, aClip, list);
+    }
+  }
+}
+
 bool
 nsDisplayScrollLayer::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
 {
-  return GetScrollLayerCount() > 1;
+  if (GetScrollLayerCount() > 1) {
+    // Propagate our clip to our children. The clip for the scroll frame is
+    // on this item, but not our child items so that they can draw non-visible
+    // parts of the display port. But if we are flattening we failed and can't
+    // draw the extra content, so it needs to be clipped.
+    PropagateClip(aBuilder, GetClip(), &mList);
+    return true;
+  }
+  return false;
 }
 
 intptr_t
 nsDisplayScrollLayer::GetScrollLayerCount()
 {
   FrameProperties props = mScrolledFrame->Properties();
 #ifdef DEBUG
   bool hasCount = false;