Bug 1313898 - Part 4. Cache svg mask property in CSSMaskLayerUserData.
MozReview-Commit-ID: 2X90LyY3IJz
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1577,17 +1577,42 @@ struct CSSMaskLayerUserData : public Lay
private:
virtual void DoUpdate() override {
mHost->mCorrupt = true;
}
CSSMaskLayerUserData* mHost;
};
+ class nsSVGMaskChainProp final : public nsISupports
+ {
+ public:
+ explicit nsSVGMaskChainProp(nsIFrame* aFrame,
+ bool aReferenceImage, CSSMaskLayerUserData* aUserData)
+ {
+ const nsStyleSVGReset *svgReset = aFrame->StyleSVGReset();
+
+ for (uint32_t i = 0; i < svgReset->mMask.mImageCount; i++) {
+ nsCOMPtr<nsIURI> maskUri = nsSVGEffects::GetMaskURI(aFrame, i);
+ UDRenderObserver* prop =
+ new UDRenderObserver(maskUri, aFrame, aReferenceImage, aUserData);
+ mProperties.AppendElement(prop);
+ prop->GetReferencedElement();
+ }
+ }
+
+ NS_DECL_ISUPPORTS
+
+ private:
+ virtual ~nsSVGMaskChainProp() {}
+ nsTArray<RefPtr<UDRenderObserver>> mProperties;
+ };
+
NS_DECLARE_FRAME_PROPERTY_RELEASABLE(ClipPathProperty, UDRenderObserver)
+ NS_DECLARE_FRAME_PROPERTY_RELEASABLE(MaskProperty, nsSVGMaskChainProp)
CSSMaskLayerUserData()
: mFrame(nullptr),
mImageLayers(nsStyleImageLayers::LayerType::Mask),
mCorrupt(false)
{ }
CSSMaskLayerUserData(nsIFrame* aFrame, const nsRect& aBound)
@@ -1595,56 +1620,66 @@ struct CSSMaskLayerUserData : public Lay
mImageLayers(aFrame->StyleSVGReset()->mMask),
mContentRect(aFrame->GetContentRectRelativeToSelf()),
mPaddingRect(aFrame->GetPaddingRectRelativeToSelf()),
mBorderRect(aFrame->GetRectRelativeToSelf()),
mMarginRect(aFrame->GetMarginRectRelativeToSelf()),
mBounds(aBound),
mCorrupt(false)
{
- // Once clip-path value changed, nsChangeHint_UpdateEffects is pass to
- // RestyleManager, ClipPathProperty in mFrame will be clean out then. By
- // keeping the pointer value of ClipPathProperty, we are able to know
- // whether clip-path of mFrame change or not.
+ // Once clip-path/mask value changed, nsChangeHint_UpdateEffects is pass
+ // to RestyleManager, ClipPathProperty/MaskProperty in mFrame will be
+ // clean out then. By keeping the pointer value of ClipPathProperty/
+ // MaskProperty, we are able to know whether clip-path/mask of mFrame
+ // change or not.
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(mFrame);
mClipPathPropCache =
reinterpret_cast<uintptr_t>(effectProperties.mClipPath);
+ mSVGMaskPropCache =
+ reinterpret_cast<uintptr_t>(effectProperties.mMask);
Hash();
}
void StartListen()
{
FrameProperties props = mFrame->Properties();
props.Delete(CSSMaskLayerUserData::ClipPathProperty());
+ props.Delete(CSSMaskLayerUserData::MaskProperty());
if (mFrame->StyleSVGReset()->mClipPath.GetType() ==
StyleShapeSourceType::URL) {
nsCOMPtr<nsIURI> pathURI = nsSVGEffects::GetClipPathURI(mFrame);
if (pathURI) {
UDRenderObserver* prop = new UDRenderObserver(pathURI, mFrame, false, this);
NS_ADDREF(prop);
props.Set(CSSMaskLayerUserData::ClipPathProperty(), prop);
prop->GetReferencedElement();
}
}
+
+ nsSVGMaskChainProp* prop =
+ new nsSVGMaskChainProp(mFrame, false, this);
+ NS_ADDREF(prop);
+ props.Set(CSSMaskLayerUserData::MaskProperty(), prop);
}
CSSMaskLayerUserData& operator=(const CSSMaskLayerUserData& aOther)
{
mImageLayers = aOther.mImageLayers;
mContentRect = aOther.mContentRect;
mPaddingRect = aOther.mPaddingRect;
mBorderRect = aOther.mBorderRect;
mMarginRect = aOther.mMarginRect;
mBounds = aOther.mBounds;
mClipPathPropCache = aOther.mClipPathPropCache;
+ mSVGMaskPropCache = aOther.mSVGMaskPropCache;
mFrame = aOther.mFrame;
mHash = aOther.mHash;
return *this;
}
@@ -1666,16 +1701,19 @@ struct CSSMaskLayerUserData : public Lay
!mBorderRect.IsEqualEdges(aOther.mBorderRect) ||
!mMarginRect.IsEqualEdges(aOther.mMarginRect)) {
return false;
}
if (mClipPathPropCache != aOther.mClipPathPropCache) {
return false;
}
+ if (mSVGMaskPropCache != aOther.mSVGMaskPropCache) {
+ return false;
+ }
if (!mBounds.IsEqualEdges(aOther.mBounds)) {
return false;
}
return true;
}
@@ -1689,36 +1727,40 @@ private:
// Hash css-position-mask props.
const nsStyleImageLayers& imageLayers = aSVGReset->mMask;
for (uint32_t i = 0; i < imageLayers.mLayers.Length(); i++) {
const nsStyleImageLayers::Layer& newLayer = imageLayers.mLayers[i];
hash = AddToHash(hash, HashBytes(&newLayer, sizeof(newLayer)));
}
hash = AddToHash(hash, mClipPathPropCache);
+ hash = AddToHash(hash, mSVGMaskPropCache);
hash = AddToHash(hash, HashBytes(&mBounds, sizeof(mBounds)));
mHash = hash;
}
nsIFrame* mFrame;
nsStyleImageLayers mImageLayers;
nsRect mContentRect;
nsRect mPaddingRect;
nsRect mBorderRect;
nsRect mMarginRect;
nsRect mBounds;
uintptr_t mClipPathPropCache;
+ uintptr_t mSVGMaskPropCache;
bool mCorrupt;
uint32_t mHash;
};
+NS_IMPL_ISUPPORTS(CSSMaskLayerUserData::nsSVGMaskChainProp, nsISupports)
+
/*
* A helper object to create a draw target for painting mask and create a
* image container to hold the drawing result. The caller can then bind this
* image container with a image mask layer via ImageLayer::SetContainer.
*/
class MaskImageData
{
public:
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -7101,30 +7101,16 @@ bool nsDisplayMask::ShouldPaintOnMaskLay
if (maskUsage.opacity != 1.0 || maskUsage.shouldApplyBasicShape) {
return false;
}
if (!nsSVGIntegrationUtils::IsMaskResourceReady(mFrame)) {
return false;
}
- // XXX temporary disable drawing SVG mask onto mask layer before bug 1313877
- // been fixed.
- nsIFrame* firstFrame =
- nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
- nsSVGEffects::EffectProperties effectProperties =
- nsSVGEffects::GetEffectProperties(firstFrame);
- nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
- for (size_t i = 0; i < maskFrames.Length() ; i++) {
- nsSVGMaskFrame *maskFrame = maskFrames[i];
- if (maskFrame) {
- return false; // Found SVG mask.
- }
- }
-
if (gfxPrefs::DrawMaskLayer()) {
return false;
}
return true;
}
bool nsDisplayMask::ComputeVisibility(nsDisplayListBuilder* aBuilder,