Bug 1382534 - Relax the requirement of having a clip with respect to an ASR for nsDisplayMask items. r=mstange draft
authorBotond Ballo <botond@mozilla.com>
Mon, 25 Sep 2017 19:15:23 -0400
changeset 690309 74baaea2647708d1cd024f9e6afd82508e95c74a
parent 690308 b4e868a89408e31aef1f26c3f701e1fb2daa2477
child 690310 ec188650070d4e8de1b19395c3ed6f31e7d0e04f
push id87277
push userbballo@mozilla.com
push dateWed, 01 Nov 2017 21:17:50 +0000
reviewersmstange
bugs1382534
milestone58.0a1
Bug 1382534 - Relax the requirement of having a clip with respect to an ASR for nsDisplayMask items. r=mstange We allow an nsDisplayMask item to satisfy the requirement even it does not itself have a clip, as long as its children have finite bounds with respect to the ASR. MozReview-Commit-ID: 8zKE0bguY38
layout/painting/FrameLayerBuilder.cpp
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -4098,21 +4098,18 @@ ContainerState::ProcessDisplayItems(nsDi
     if (itemType == DisplayItemType::TYPE_LAYER_EVENT_REGIONS) {
       bounds = item->GetBounds(mBuilder, &dummy);
       if (itemClip.HasClip()) {
         bounds.IntersectRect(bounds, itemClip.GetClipRect());
       }
     }
     if (!bounds.IsEmpty()) {
       if (itemASR != mContainerASR) {
-        const DisplayItemClip* clip = DisplayItemClipChain::ClipForASR(item->GetClipChain(), mContainerASR);
-        MOZ_ASSERT(clip || gfxPrefs::LayoutUseContainersForRootFrames(),
-                   "the item should have finite bounds with respect to mContainerASR.");
-        if (clip) {
-          bounds = clip->GetClipRect();
+        if (Maybe<nsRect> clip = item->GetClipWithRespectToASR(mBuilder, mContainerASR)) {
+          bounds = clip.ref();
         }
       }
     }
     ((nsRect&)mAccumulatedChildBounds).UnionRect(mAccumulatedChildBounds, bounds);
 #endif
 
     nsIntRect itemVisibleRect = itemDrawRect;
     // We haven't computed visibility at this point, so item->GetVisibleRect()
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -2152,25 +2152,18 @@ nsDisplayList::GetBounds(nsDisplayListBu
 nsRect
 nsDisplayList::GetClippedBoundsWithRespectToASR(nsDisplayListBuilder* aBuilder,
                                                 const ActiveScrolledRoot* aASR,
                                                 nsRect* aVisibleRect) const {
   nsRect bounds;
   for (nsDisplayItem* i = GetBottom(); i != nullptr; i = i->GetAbove()) {
     nsRect r = i->GetClippedBounds(aBuilder);
     if (aASR != i->GetActiveScrolledRoot() && !r.IsEmpty()) {
-      const DisplayItemClip* clip = DisplayItemClipChain::ClipForASR(i->GetClipChain(), aASR);
-#ifdef DEBUG
-      if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
-        MOZ_ASSERT(clip,
-                   "Need to be clipped wrt aASR. Do not call this function with an ASR that our child items don't have finite bounds wrt.");
-      }
-#endif
-      if (clip) {
-        r = clip->GetClipRect();
+      if (Maybe<nsRect> clip = i->GetClipWithRespectToASR(aBuilder, aASR)) {
+        r = clip.ref();
       }
     }
     if (aVisibleRect) {
       aVisibleRect->UnionRect(*aVisibleRect, i->GetVisibleRect());
     }
     bounds.UnionRect(bounds, r);
   }
   return bounds;
@@ -2971,16 +2964,31 @@ nsDisplayItem::SetClipChain(const Displa
   mClip = DisplayItemClipChain::ClipForASR(aClipChain, mActiveScrolledRoot);
 
   if (aStore) {
     mState.mClipChain = mClipChain;
     mState.mClip = mClip;
   }
 }
 
+Maybe<nsRect>
+nsDisplayItem::GetClipWithRespectToASR(nsDisplayListBuilder* aBuilder,
+                                       const ActiveScrolledRoot* aASR) const
+{
+  if (const DisplayItemClip* clip = DisplayItemClipChain::ClipForASR(GetClipChain(), aASR)) {
+    return Some(clip->GetClipRect());
+  }
+#ifdef DEBUG
+  if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
+    MOZ_ASSERT(false, "item should have finite clip with respect to aASR");
+  }
+#endif
+  return Nothing();
+}
+
 void
 nsDisplayItem::FuseClipChainUpTo(nsDisplayListBuilder* aBuilder,
                                  const ActiveScrolledRoot* aASR)
 {
   const DisplayItemClipChain* sc = mClipChain;
   DisplayItemClip mergedClip;
   while (sc && ActiveScrolledRoot::PickDescendant(aASR, sc->mASR) == sc->mASR) {
     mergedClip.IntersectWith(sc->mClip);
@@ -9395,16 +9403,40 @@ nsDisplayMask::CreateWebRenderCommands(m
 
   if (mask) {
     aBuilder.PopClip(GetClipChain());
   }
 
   return true;
 }
 
+Maybe<nsRect>
+nsDisplayMask::GetClipWithRespectToASR(nsDisplayListBuilder* aBuilder,
+                                       const ActiveScrolledRoot* aASR) const
+{
+  if (const DisplayItemClip* clip = DisplayItemClipChain::ClipForASR(GetClipChain(), aASR)) {
+    return Some(clip->GetClipRect());
+  }
+  // This item does not have a clip with respect to |aASR|. However, we
+  // might still have finite bounds with respect to |aASR|. Check our
+  // children.
+  nsDisplayList* childList = GetSameCoordinateSystemChildren();
+  if (childList) {
+    return Some(childList->GetClippedBoundsWithRespectToASR(aBuilder, aASR));
+  }
+#ifdef DEBUG
+  if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
+    MOZ_ASSERT(false, "item should have finite clip with respect to aASR");
+  }
+#endif
+  return Nothing();
+}
+
+
+
 #ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayMask::PrintEffects(nsACString& aTo)
 {
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
   SVGObserverUtils::EffectProperties effectProperties =
     SVGObserverUtils::GetEffectProperties(firstFrame);
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -2622,16 +2622,20 @@ public:
 
   virtual bool CanBeReused() const { return true; }
 
   virtual nsIFrame* GetDependentFrame()
   {
     return nullptr;
   }
 
+  virtual mozilla::Maybe<nsRect> GetClipWithRespectToASR(
+      nsDisplayListBuilder* aBuilder,
+      const ActiveScrolledRoot* aASR) const;
+
 protected:
   nsDisplayItem() = delete;
 
   typedef bool (*PrefFunc)(void);
   bool ShouldUseAdvancedLayer(LayerManager* aManager, PrefFunc aFunc) const;
   bool CanUseAdvancedLayer(LayerManager* aManager) const;
 
   nsIFrame* mFrame;
@@ -5534,16 +5538,20 @@ public:
     return mDestRects;
   }
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                        mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
+
+  virtual mozilla::Maybe<nsRect> GetClipWithRespectToASR(
+      nsDisplayListBuilder* aBuilder,
+      const ActiveScrolledRoot* aASR) const override;
 private:
   // According to mask property and the capability of aManager, determine
   // whether we can paint the mask onto a dedicate mask layer.
   bool CanPaintOnMaskLayer(LayerManager* aManager);
 
   nsTArray<nsRect> mDestRects;
 };