Canvas image cache isn't hooked up to memory pressure purging, and needs a size limit (bug 865929, r=jlebar, a=tef+).

This commit is contained in:
Andreas Gal 2013-04-25 17:48:59 -07:00
parent 9e6b2c0f43
commit 9b21b209bb
3 changed files with 57 additions and 1 deletions

View File

@ -28,6 +28,7 @@ pref("browser.cache.memory.capacity", 1024); // kilobytes
/* image cache prefs */
pref("image.cache.size", 1048576); // bytes
pref("image.high_quality_downscaling.enabled", false);
pref("canvas.image.cache.limit", 10485760); // 10 MB
/* offline cache prefs */
pref("browser.offline-apps.notify", false);

View File

@ -13,6 +13,7 @@
#include "nsTHashtable.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
namespace mozilla {
@ -42,6 +43,8 @@ struct ImageCacheEntryData {
nsExpirationState* GetExpirationState() { return &mState; }
size_t SizeInBytes() { return mSize.width * mSize.height * 4; }
// Key
nsRefPtr<Element> mImage;
nsIImageLoadingContent* mILC;
@ -79,19 +82,43 @@ public:
nsAutoPtr<ImageCacheEntryData> mData;
};
class ImageCache MOZ_FINAL : public nsExpirationTracker<ImageCacheEntryData,4> {
static bool sPrefsInitialized = false;
static int32_t sCanvasImageCacheLimit = 0;
class ImageCache MOZ_FINAL : public nsExpirationTracker<ImageCacheEntryData,4>,
public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
// We use 3 generations of 1 second each to get a 2-3 seconds timeout.
enum { GENERATION_MS = 1000 };
ImageCache()
: nsExpirationTracker<ImageCacheEntryData,4>(GENERATION_MS)
, mSize(0)
{
if (!sPrefsInitialized) {
sPrefsInitialized = true;
Preferences::AddIntVarCache(&sCanvasImageCacheLimit, "canvas.image.cache.limit", 0);
}
mCache.Init();
}
~ImageCache() {
AgeAllGenerations();
}
void AddObject(ImageCacheEntryData* aObject)
{
nsExpirationTracker<ImageCacheEntryData,4>::AddObject(aObject);
mSize += aObject->SizeInBytes();
}
void RemoveObject(ImageCacheEntryData* aObject)
{
nsExpirationTracker<ImageCacheEntryData,4>::RemoveObject(aObject);
mSize -= aObject->SizeInBytes();
}
virtual void NotifyExpired(ImageCacheEntryData* aObject)
{
RemoveObject(aObject);
@ -100,10 +127,24 @@ public:
}
nsTHashtable<ImageCacheEntry> mCache;
size_t mSize;
};
static ImageCache* gImageCache = nullptr;
NS_IMPL_ISUPPORTS1(ImageCache, nsIObserver)
NS_IMETHODIMP
ImageCache::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
if (strcmp(aTopic, "memory-pressure") == 0) {
AgeAllGenerations();
}
return NS_OK;
}
class CanvasImageCacheShutdownObserver MOZ_FINAL : public nsIObserver
{
public:
@ -120,6 +161,9 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
{
if (!gImageCache) {
gImageCache = new ImageCache();
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os)
os->AddObserver(gImageCache, "memory-pressure", false);
nsContentUtils::RegisterShutdownObserver(new CanvasImageCacheShutdownObserver());
}
@ -140,6 +184,13 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
entry->mData->mSurface = aSurface;
entry->mData->mSize = aSize;
}
if (!sCanvasImageCacheLimit)
return;
// Expire the image cache early if its larger than we want it to be.
while (gImageCache->mSize > size_t(sCanvasImageCacheLimit))
gImageCache->AgeOneGeneration();
}
gfxASurface*

View File

@ -3921,6 +3921,10 @@ pref("image.multithreaded_decoding.enabled", true);
// automatically determined based on the system's number of cores.
pref("image.multithreaded_decoding.limit", -1);
// Limit for the canvas image cache. 0 means we don't limit the size of the
// cache.
pref("canvas.image.cache.limit", 0);
// WebGL prefs
pref("gl.msaa-level", 2);
pref("webgl.force-enabled", false);