summaryrefslogtreecommitdiffstats
path: root/dom/canvas
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas')
-rw-r--r--dom/canvas/CanvasImageCache.cpp62
-rw-r--r--dom/canvas/CanvasImageCache.h15
-rw-r--r--dom/canvas/CanvasRenderingContext2D.cpp7
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);
}