Bug 1386483 - Set clip for each item in layers-free mode. r=kats draft
authorMorris Tseng <mtseng@mozilla.com>
Thu, 03 Aug 2017 17:19:03 +0800
changeset 620288 8b085fbcfa43f8b11d6964985f4208801f313617
parent 620112 d942ef54fdf726840a698d2ddcaf989d2c00edbc
child 640651 33ed637fdcaccd3e1c0af9a30a4b9b3d2a21ca18
push id71987
push userbmo:mtseng@mozilla.com
push dateThu, 03 Aug 2017 09:27:51 +0000
reviewerskats
bugs1386483
milestone57.0a1
Bug 1386483 - Set clip for each item in layers-free mode. r=kats MozReview-Commit-ID: 3rYKLTyHAlM
gfx/layers/wr/ScrollingLayersHelper.cpp
gfx/layers/wr/ScrollingLayersHelper.h
gfx/layers/wr/WebRenderLayerManager.cpp
--- a/gfx/layers/wr/ScrollingLayersHelper.cpp
+++ b/gfx/layers/wr/ScrollingLayersHelper.cpp
@@ -16,16 +16,17 @@ namespace mozilla {
 namespace layers {
 
 ScrollingLayersHelper::ScrollingLayersHelper(WebRenderLayer* aLayer,
                                              wr::DisplayListBuilder& aBuilder,
                                              const StackingContextHelper& aStackingContext)
   : mLayer(aLayer)
   , mBuilder(&aBuilder)
   , mPushedLayerLocalClip(false)
+  , mItem(nullptr)
 {
   if (!mLayer->WrManager()->AsyncPanZoomEnabled()) {
     // If APZ is disabled then we don't need to push the scrolling clips. We
     // still want to push the layer's local clip though.
     PushLayerLocalClip(aStackingContext);
     return;
   }
 
@@ -102,16 +103,34 @@ ScrollingLayersHelper::ScrollingLayersHe
     Maybe<wr::WrClipId> clipId = mBuilder->TopmostClipId();
     // Default to 0 if there is no ancestor, because 0 refers to the root scrollframe.
     mBuilder->PushClipAndScrollInfo(scrollsWith.valueOr(0), clipId.ptrOr(nullptr));
   } else {
     PushLayerLocalClip(aStackingContext);
   }
 }
 
+ScrollingLayersHelper::ScrollingLayersHelper(nsDisplayItem* aItem,
+                                             wr::DisplayListBuilder& aBuilder,
+                                             const StackingContextHelper& aStackingContext)
+  : mLayer(nullptr)
+  , mBuilder(&aBuilder)
+  , mPushedLayerLocalClip(false)
+  , mItem(aItem)
+{
+  const DisplayItemClip& itemClip = aItem->GetClip();
+  if (itemClip.HasClip()) {
+    int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
+    LayerRect clip = ViewAs<LayerPixel>(
+      LayoutDeviceRect::FromAppUnits(itemClip.GetClipRect(), appUnitsPerDevPixel),
+      PixelCastJustification::MovingDownToChildren);
+    aBuilder.PushClip(aStackingContext.ToRelativeLayoutRect(clip), nullptr);
+  }
+}
+
 void
 ScrollingLayersHelper::PushLayerLocalClip(const StackingContextHelper& aStackingContext)
 {
   Layer* layer = mLayer->GetLayer();
   Maybe<ParentLayerRect> clip;
   if (const Maybe<ParentLayerIntRect>& rect = layer->GetClipRect()) {
     clip = Some(IntRectToRect(rect.ref()));
   } else if (layer->GetMaskLayer()) {
@@ -141,16 +160,25 @@ ScrollingLayersHelper::PushLayerClip(con
     // TODO: check this transform is correct in all cases
     mask = maskWrLayer->RenderMaskLayer(aSc, maskLayer->GetTransform());
   }
   mBuilder->PushClip(aSc.ToRelativeLayoutRect(clipRect), mask.ptrOr(nullptr));
 }
 
 ScrollingLayersHelper::~ScrollingLayersHelper()
 {
+  if (mItem) {
+    // For layers-free mode;
+    const DisplayItemClip& itemClip = mItem->GetClip();
+    if (itemClip.HasClip()) {
+      mBuilder->PopClip();
+    }
+    return;
+  }
+
   Layer* layer = mLayer->GetLayer();
   if (!mLayer->WrManager()->AsyncPanZoomEnabled()) {
     if (mPushedLayerLocalClip) {
       mBuilder->PopClip();
     }
     return;
   }
 
--- a/gfx/layers/wr/ScrollingLayersHelper.h
+++ b/gfx/layers/wr/ScrollingLayersHelper.h
@@ -21,24 +21,28 @@ class StackingContextHelper;
 class WebRenderLayer;
 
 class MOZ_RAII ScrollingLayersHelper
 {
 public:
   ScrollingLayersHelper(WebRenderLayer* aLayer,
                         wr::DisplayListBuilder& aBuilder,
                         const StackingContextHelper& aSc);
+  ScrollingLayersHelper(nsDisplayItem* aItem,
+                        wr::DisplayListBuilder& aBuilder,
+                        const StackingContextHelper& aStackingContext);
   ~ScrollingLayersHelper();
 
 private:
   void PushLayerLocalClip(const StackingContextHelper& aStackingContext);
   void PushLayerClip(const LayerClip& aClip,
                      const StackingContextHelper& aSc);
 
   WebRenderLayer* mLayer;
   wr::DisplayListBuilder* mBuilder;
   bool mPushedLayerLocalClip;
+  nsDisplayItem* mItem;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -260,19 +260,22 @@ WebRenderLayerManager::CreateWebRenderCo
       // walking up their ASR chain when building scroll metadata.
       if (forceNewLayerData) {
         mAsrStack.push_back(asr);
       }
     }
 
     // Note: this call to CreateWebRenderCommands can recurse back into
     // this function if the |item| is a wrapper for a sublist.
-    if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
-                                       aDisplayListBuilder)) {
-      PushItemAsImage(item, aBuilder, aSc, aDisplayListBuilder);
+    {
+      ScrollingLayersHelper clip(item, aBuilder, aSc);
+      if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
+                                         aDisplayListBuilder)) {
+        PushItemAsImage(item, aBuilder, aSc, aDisplayListBuilder);
+      }
     }
 
     if (apzEnabled && forceNewLayerData) {
       // Pop the thing we pushed before the recursion, so the topmost item on
       // the stack is enclosing display item's ASR (or the stack is empty)
       mAsrStack.pop_back();
       const ActiveScrolledRoot* stopAtAsr =
           mAsrStack.empty() ? nullptr : mAsrStack.back();