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
--- 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;
};