diff options
Diffstat (limited to 'dom/canvas')
-rw-r--r-- | dom/canvas/CanvasImageCache.cpp | 62 | ||||
-rw-r--r-- | dom/canvas/CanvasImageCache.h | 15 | ||||
-rw-r--r-- | dom/canvas/CanvasRenderingContext2D.cpp | 7 |
3 files changed, 57 insertions, 27 deletions
diff --git a/dom/canvas/CanvasImageCache.cpp b/dom/canvas/CanvasImageCache.cpp index 96a1505a40..62fe40dfb7 100644 --- a/dom/canvas/CanvasImageCache.cpp +++ b/dom/canvas/CanvasImageCache.cpp @@ -9,7 +9,6 @@ #include "imgIRequest.h" #include "mozilla/dom/Element.h" #include "nsTHashtable.h" -#include "mozilla/dom/HTMLCanvasElement.h" #include "nsContentUtils.h" #include "mozilla/Preferences.h" #include "mozilla/StaticPrefs_canvas.h" @@ -27,11 +26,11 @@ using namespace gfx; * due to CORS security. */ struct ImageCacheKey { - ImageCacheKey(imgIContainer* aImage, HTMLCanvasElement* aCanvas, + ImageCacheKey(imgIContainer* aImage, CanvasRenderingContext2D* aContext, BackendType aBackendType) - : mImage(aImage), mCanvas(aCanvas), mBackendType(aBackendType) {} + : mImage(aImage), mContext(aContext), mBackendType(aBackendType) {} nsCOMPtr<imgIContainer> mImage; - HTMLCanvasElement* mCanvas; + CanvasRenderingContext2D* mContext; BackendType mBackendType; }; @@ -42,14 +41,14 @@ struct ImageCacheKey { struct ImageCacheEntryData { ImageCacheEntryData(const ImageCacheEntryData& aOther) : mImage(aOther.mImage), - mCanvas(aOther.mCanvas), + mContext(aOther.mContext), mBackendType(aOther.mBackendType), mSourceSurface(aOther.mSourceSurface), mSize(aOther.mSize), mIntrinsicSize(aOther.mIntrinsicSize) {} explicit ImageCacheEntryData(const ImageCacheKey& aKey) : mImage(aKey.mImage), - mCanvas(aKey.mCanvas), + mContext(aKey.mContext), mBackendType(aKey.mBackendType) {} nsExpirationState* GetExpirationState() { return &mState; } @@ -57,7 +56,7 @@ struct ImageCacheEntryData { // Key nsCOMPtr<imgIContainer> mImage; - HTMLCanvasElement* mCanvas; + CanvasRenderingContext2D* mContext; BackendType mBackendType; // Value RefPtr<SourceSurface> mSourceSurface; @@ -78,13 +77,13 @@ class ImageCacheEntry : public PLDHashEntryHdr { ~ImageCacheEntry() = default; bool KeyEquals(KeyTypePointer key) const { - return mData->mImage == key->mImage && mData->mCanvas == key->mCanvas && + return mData->mImage == key->mImage && mData->mContext == key->mContext && mData->mBackendType == key->mBackendType; } static KeyTypePointer KeyToPointer(KeyType& key) { return &key; } static PLDHashNumber HashKey(KeyTypePointer key) { - return HashGeneric(key->mImage.get(), key->mCanvas, key->mBackendType); + return HashGeneric(key->mImage.get(), key->mContext, key->mBackendType); } enum { ALLOW_MEMMOVE = true }; @@ -152,7 +151,7 @@ class ImageCache final : public nsExpirationTracker<ImageCacheEntryData, 4> { AllCanvasImageCacheKey(aObject->mImage, aObject->mBackendType)); // Deleting the entry will delete aObject since the entry owns aObject. - mCache.RemoveEntry(ImageCacheKey(aObject->mImage, aObject->mCanvas, + mCache.RemoveEntry(ImageCacheKey(aObject->mImage, aObject->mContext, aObject->mBackendType)); } @@ -266,13 +265,35 @@ static already_AddRefed<imgIContainer> GetImageContainer(dom::Element* aImage) { return imgContainer.forget(); } +void CanvasImageCache::NotifyCanvasDestroyed( + CanvasRenderingContext2D* aContext) { + MOZ_ASSERT(aContext); + + if (!NS_IsMainThread() || !gImageCache) { + return; + } + + for (auto i = gImageCache->mCache.Iter(); !i.Done(); i.Next()) { + ImageCacheEntryData* data = i.Get()->mData.get(); + if (data->mContext == aContext) { + gImageCache->RemoveObject(data); + gImageCache->mAllCanvasCache.RemoveEntry( + AllCanvasImageCacheKey(data->mImage, data->mBackendType)); + i.Remove(); + } + } +} + void CanvasImageCache::NotifyDrawImage(Element* aImage, - HTMLCanvasElement* aCanvas, + CanvasRenderingContext2D* aContext, DrawTarget* aTarget, SourceSurface* aSource, const IntSize& aSize, const IntSize& aIntrinsicSize) { - if (!aTarget) { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aContext); + + if (!aTarget || !aContext) { return; } @@ -289,7 +310,7 @@ void CanvasImageCache::NotifyDrawImage(Element* aImage, BackendType backendType = aTarget->GetBackendType(); AllCanvasImageCacheKey allCanvasCacheKey(imgContainer, backendType); - ImageCacheKey canvasCacheKey(imgContainer, aCanvas, backendType); + ImageCacheKey canvasCacheKey(imgContainer, aContext, backendType); ImageCacheEntry* entry = gImageCache->mCache.PutEntry(canvasCacheKey); if (entry) { @@ -326,6 +347,8 @@ void CanvasImageCache::NotifyDrawImage(Element* aImage, SourceSurface* CanvasImageCache::LookupAllCanvas(Element* aImage, DrawTarget* aTarget) { + MOZ_ASSERT(NS_IsMainThread()); + if (!gImageCache || !aTarget) { return nullptr; } @@ -344,11 +367,12 @@ SourceSurface* CanvasImageCache::LookupAllCanvas(Element* aImage, return entry->mSourceSurface; } -SourceSurface* CanvasImageCache::LookupCanvas(Element* aImage, - HTMLCanvasElement* aCanvas, - DrawTarget* aTarget, - IntSize* aSizeOut, - IntSize* aIntrinsicSizeOut) { +SourceSurface* CanvasImageCache::LookupCanvas( + Element* aImage, CanvasRenderingContext2D* aContext, DrawTarget* aTarget, + IntSize* aSizeOut, IntSize* aIntrinsicSizeOut) { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aContext); + if (!gImageCache || !aTarget) { return nullptr; } @@ -365,7 +389,7 @@ SourceSurface* CanvasImageCache::LookupCanvas(Element* aImage, // optimized surface given to a Skia backend would cause a readback. For // details, see bug 1794442. ImageCacheEntry* entry = gImageCache->mCache.GetEntry( - ImageCacheKey(imgContainer, aCanvas, aTarget->GetBackendType())); + ImageCacheKey(imgContainer, aContext, aTarget->GetBackendType())); if (!entry) { return nullptr; } diff --git a/dom/canvas/CanvasImageCache.h b/dom/canvas/CanvasImageCache.h index 58486c5a8d..c860951fb7 100644 --- a/dom/canvas/CanvasImageCache.h +++ b/dom/canvas/CanvasImageCache.h @@ -12,7 +12,7 @@ namespace mozilla { namespace dom { class Element; -class HTMLCanvasElement; +class CanvasRenderingContext2D; } // namespace dom namespace gfx { class DrawTarget; @@ -28,18 +28,23 @@ class CanvasImageCache { public: /** - * Notify that image element aImage was drawn to aCanvas element + * Notify that image element aImage was drawn to aContext canvas * using the first frame of aRequest's image. The data for the surface is * in aSurface, and the image size is in aSize. aIntrinsicSize is the size * the surface is intended to be rendered at. */ static void NotifyDrawImage(dom::Element* aImage, - dom::HTMLCanvasElement* aCanvas, + dom::CanvasRenderingContext2D* aContext, gfx::DrawTarget* aTarget, SourceSurface* aSource, const gfx::IntSize& aSize, const gfx::IntSize& aIntrinsicSize); /** + * Notify that aContext is being destroyed. + */ + static void NotifyCanvasDestroyed(dom::CanvasRenderingContext2D* aContext); + + /** * Check whether aImage has recently been drawn any canvas. If we return * a non-null surface, then the same image was recently drawn into a canvas. */ @@ -47,11 +52,11 @@ class CanvasImageCache { gfx::DrawTarget* aTarget); /** - * Like the top above, but restricts the lookup to only aCanvas. This is + * Like the top above, but restricts the lookup to only aContext. This is * required for CORS security. */ static SourceSurface* LookupCanvas(dom::Element* aImage, - dom::HTMLCanvasElement* aCanvas, + dom::CanvasRenderingContext2D* aContext, gfx::DrawTarget* aTarget, gfx::IntSize* aSizeOut, gfx::IntSize* aIntrinsicSizeOut); diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 83fe205e35..cf20f4f7c3 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -1074,6 +1074,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D( } CanvasRenderingContext2D::~CanvasRenderingContext2D() { + CanvasImageCache::NotifyCanvasDestroyed(this); RemovePostRefreshObserver(); RemoveShutdownObserver(); ResetBitmap(); @@ -5221,8 +5222,8 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage, element = video; } - srcSurf = CanvasImageCache::LookupCanvas(element, mCanvasElement, mTarget, - &imgSize, &intrinsicImgSize); + srcSurf = CanvasImageCache::LookupCanvas(element, this, mTarget, &imgSize, + &intrinsicImgSize); } DirectDrawInfo drawInfo; @@ -5267,7 +5268,7 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage, if (res.mSourceSurface) { if (res.mImageRequest) { - CanvasImageCache::NotifyDrawImage(element, mCanvasElement, mTarget, + CanvasImageCache::NotifyDrawImage(element, this, mTarget, res.mSourceSurface, imgSize, intrinsicImgSize); } |