diff --git a/dom/canvas/DrawTargetWebgl.cpp b/dom/canvas/DrawTargetWebgl.cpp index bc33f4a6e9d2..5d026db2bfb7 100644 --- a/dom/canvas/DrawTargetWebgl.cpp +++ b/dom/canvas/DrawTargetWebgl.cpp @@ -1807,7 +1807,7 @@ already_AddRefed PathCache::FindOrInsertEntry( } Pattern* pattern = nullptr; if (aPattern) { - pattern = aPattern->Clone(); + pattern = aPattern->CloneWeak(); if (!pattern) { return nullptr; } diff --git a/dom/canvas/DrawTargetWebglInternal.h b/dom/canvas/DrawTargetWebglInternal.h index 4d8272550e42..a7cb61e6c48f 100644 --- a/dom/canvas/DrawTargetWebglInternal.h +++ b/dom/canvas/DrawTargetWebglInternal.h @@ -72,6 +72,8 @@ class CacheEntry : public RefCounted { const IntRect& GetBounds() const { return mBounds; } HashNumber GetHash() const { return mHash; } + virtual bool IsValid() const { return true; } + protected: virtual void RemoveFromList() = 0; @@ -173,7 +175,9 @@ class TextureHandle : public RefCounted, void SetCacheEntry(const RefPtr& aEntry) { mCacheEntry = aEntry; } // Note as used if there is corresponding surface or cache entry. - bool IsUsed() const { return mSurface || mCacheEntry; } + bool IsUsed() const { + return mSurface || (mCacheEntry && mCacheEntry->IsValid()); + } private: bool mValid = true; @@ -360,6 +364,9 @@ class PathCacheEntry : public CacheEntryImpl { const Point& GetOrigin() const { return mOrigin; } + // Valid if either a mask (no pattern) or there is valid pattern. + bool IsValid() const override { return !mPattern || mPattern->IsValid(); } + private: // The actual path geometry supplied SkPath mPath; diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 0565c6971be0..b637294991e8 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -251,7 +251,7 @@ struct ShadowOptions { * matching DrawTarget. Not adhering to this condition will make a draw call * fail. */ -class GradientStops : public external::AtomicRefCounted { +class GradientStops : public SupportsThreadSafeWeakPtr { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStops) virtual ~GradientStops() = default; @@ -275,8 +275,15 @@ class Pattern { virtual PatternType GetType() const = 0; - /** Instantiate a new clone with the same pattern type and values. */ - virtual Pattern* Clone() const { return nullptr; } + /** Instantiate a new clone with the same pattern type and values. Any + * internal strong references will be converted to weak references. */ + virtual Pattern* CloneWeak() const { return nullptr; } + + /** Whether the pattern holds an internal weak reference. */ + virtual bool IsWeak() const { return false; } + + /** Whether any internal weak references still point to a target. */ + virtual bool IsValid() const { return true; } /** Determine if the pattern type and values exactly match. */ virtual bool operator==(const Pattern& aOther) const = 0; @@ -285,6 +292,19 @@ class Pattern { protected: Pattern() = default; + + // Utility functions to check if a weak reference is still valid. + template + static inline bool IsRefValid(const RefPtr& aPtr) { + // RefPtrs are always valid. + return true; + } + + template + static inline bool IsRefValid(const ThreadSafeWeakPtr& aPtr) { + // Weak refs are only valid if they aren't dead. + return !aPtr.IsDead(); + } }; class ColorPattern : public Pattern { @@ -295,7 +315,7 @@ class ColorPattern : public Pattern { PatternType GetType() const override { return PatternType::COLOR; } - Pattern* Clone() const override { return new ColorPattern(mColor); } + Pattern* CloneWeak() const override { return new ColorPattern(mColor); } bool operator==(const Pattern& aOther) const override { if (aOther.GetType() != PatternType::COLOR) { @@ -313,150 +333,201 @@ class ColorPattern : public Pattern { * stored in a separate object and are backend dependent. This class itself * may be used on the stack. */ -class LinearGradientPattern : public Pattern { +template