diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 1e80e667db26..8c331c3866d6 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -205,8 +205,7 @@ public: // Insert the new surface into the cache immediately. We need to do this so // that we won't start multiple scaling jobs for the same size. SurfaceCache::Insert(mDstRef.get(), ImageKey(mImage.get()), - RasterSurfaceKey(mDstSize.ToIntSize(), mImageFlags), - Lifetime::Transient); + RasterSurfaceKey(mDstSize.ToIntSize(), mImageFlags)); return true; } @@ -260,9 +259,9 @@ public: NS_WARNING("HQ scaling failed"); // Remove the frame from the cache since we know we don't need it. - SurfaceCache::RemoveSurface(ImageKey(mImage.get()), - RasterSurfaceKey(mDstSize.ToIntSize(), - mImageFlags)); + SurfaceCache::RemoveIfPresent(ImageKey(mImage.get()), + RasterSurfaceKey(mDstSize.ToIntSize(), + mImageFlags)); // Release everything we're holding, too. mSrcRef.reset(); @@ -365,7 +364,7 @@ RasterImage::~RasterImage() } // Release any HQ scaled frames from the surface cache. - SurfaceCache::RemoveImage(ImageKey(this)); + SurfaceCache::Discard(this); mAnim = nullptr; diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index f6e4914fdade..565fc2a99afb 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -118,18 +118,18 @@ class CachedSurface public: NS_INLINE_DECL_REFCOUNTING(CachedSurface) - CachedSurface(imgFrame* aSurface, - const Cost aCost, - const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey, - const Lifetime aLifetime) + CachedSurface(imgFrame* aSurface, + const IntSize aTargetSize, + const Cost aCost, + const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey) : mSurface(aSurface) + , mTargetSize(aTargetSize) , mCost(aCost) , mImageKey(aImageKey) , mSurfaceKey(aSurfaceKey) - , mLifetime(aLifetime) { - MOZ_ASSERT(mSurface, "Must have a valid surface"); + MOZ_ASSERT(mSurface, "Must have a valid SourceSurface"); MOZ_ASSERT(mImageKey, "Must have a valid image key"); } @@ -138,34 +138,18 @@ public: return mSurface->DrawableRef(); } - void SetLocked(bool aLocked) - { - if (aLocked && mLifetime == Lifetime::Persistent) { - // This may fail, and that's OK. We make no guarantees about whether - // locking is successful if you call SurfaceCache::LockImage() after - // SurfaceCache::Insert(). - mDrawableRef = mSurface->DrawableRef(); - } else { - mDrawableRef.reset(); - } - } - - bool IsLocked() const { return bool(mDrawableRef); } - ImageKey GetImageKey() const { return mImageKey; } SurfaceKey GetSurfaceKey() const { return mSurfaceKey; } CostEntry GetCostEntry() { return image::CostEntry(this, mCost); } nsExpirationState* GetExpirationState() { return &mExpirationState; } - Lifetime GetLifetime() const { return mLifetime; } private: nsExpirationState mExpirationState; nsRefPtr mSurface; - DrawableFrameRef mDrawableRef; + const IntSize mTargetSize; const Cost mCost; const ImageKey mImageKey; const SurfaceKey mSurfaceKey; - const Lifetime mLifetime; }; /* @@ -173,16 +157,11 @@ private: * able to remove all surfaces associated with an image when the image is * destroyed or invalidated. Since this will happen frequently, it makes sense * to make it cheap by storing the surfaces for each image separately. - * - * ImageSurfaceCache also keeps track of whether its associated image is locked - * or unlocked. */ class ImageSurfaceCache { - ~ImageSurfaceCache() { } + ~ImageSurfaceCache() {} public: - ImageSurfaceCache() : mLocked(false) { } - NS_INLINE_DECL_REFCOUNTING(ImageSurfaceCache) typedef nsRefPtrHashtable, CachedSurface> SurfaceTable; @@ -192,9 +171,6 @@ public: void Insert(const SurfaceKey& aKey, CachedSurface* aSurface) { MOZ_ASSERT(aSurface, "Should have a surface"); - MOZ_ASSERT(!mLocked || aSurface->GetLifetime() != Lifetime::Persistent || - aSurface->IsLocked(), - "Inserting an unlocked persistent surface for a locked image"); mSurfaces.Put(aKey, aSurface); } @@ -219,12 +195,8 @@ public: mSurfaces.EnumerateRead(aFunction, aData); } - void SetLocked(bool aLocked) { mLocked = aLocked; } - bool IsLocked() const { return mLocked; } - private: SurfaceTable mSurfaces; - bool mLocked; }; /* @@ -246,7 +218,6 @@ public: , mMemoryPressureObserver(new MemoryPressureObserver) , mMaxCost(aSurfaceCacheSize) , mAvailableCost(aSurfaceCacheSize) - , mLockedCost(0) { nsCOMPtr os = services::GetObserverService(); if (os) @@ -268,22 +239,23 @@ public: RegisterWeakMemoryReporter(this); } - bool Insert(imgFrame* aSurface, + void Insert(imgFrame* aSurface, + IntSize aTargetSize, const Cost aCost, const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey, - Lifetime aLifetime) + const SurfaceKey& aSurfaceKey) { MOZ_ASSERT(!Lookup(aImageKey, aSurfaceKey), "Inserting a duplicate surface into the SurfaceCache"); - // If this is bigger than we can hold after discarding everything we can, - // refuse to cache it. - if (!CanHoldAfterDiscarding(aCost)) - return false; + // If this is bigger than the maximum cache size, refuse to cache it. + if (!CanHold(aCost)) + return; - // Remove elements in order of cost until we can fit this in the cache. Note - // that locked surfaces aren't in mCosts, so we never remove them here. + nsRefPtr surface = + new CachedSurface(aSurface, aTargetSize, aCost, aImageKey, aSurfaceKey); + + // Remove elements in order of cost until we can fit this in the cache. while (aCost > mAvailableCost) { MOZ_ASSERT(!mCosts.IsEmpty(), "Removed everything and it still won't fit"); Remove(mCosts.LastElement().GetSurface()); @@ -297,24 +269,10 @@ public: mImageCaches.Put(aImageKey, cache); } - nsRefPtr surface = - new CachedSurface(aSurface, aCost, aImageKey, aSurfaceKey, aLifetime); - - // We require that locking succeed if the image is locked and the surface is - // persistent; the caller may need to know this to handle errors correctly. - if (cache->IsLocked() && aLifetime == Lifetime::Persistent) { - surface->SetLocked(true); - if (!surface->IsLocked()) { - return false; - } - } - // Insert. MOZ_ASSERT(aCost <= mAvailableCost, "Inserting despite too large a cost"); cache->Insert(aSurfaceKey, surface); StartTracking(surface); - - return true; } void Remove(CachedSurface* aSurface) @@ -328,9 +286,8 @@ public: StopTracking(aSurface); cache->Remove(aSurface); - // Remove the per-image cache if it's unneeded now. (Keep it if the image is - // locked, since the per-image cache is where we store that state.) - if (cache->IsEmpty() && !cache->IsLocked()) { + // Remove the per-image cache if it's unneeded now. + if (cache->IsEmpty()) { mImageCaches.Remove(imageKey); } } @@ -342,14 +299,8 @@ public: "Cost too large and the caller didn't catch it"); mAvailableCost -= costEntry.GetCost(); - - if (aSurface->IsLocked()) { - mLockedCost += costEntry.GetCost(); - MOZ_ASSERT(mLockedCost <= mMaxCost, "Locked more than we can hold?"); - } else { - mCosts.InsertElementSorted(costEntry); - mExpirationTracker.AddObject(aSurface); - } + mCosts.InsertElementSorted(costEntry); + mExpirationTracker.AddObject(aSurface); } void StopTracking(CachedSurface* aSurface) @@ -357,21 +308,12 @@ public: MOZ_ASSERT(aSurface, "Should have a surface"); CostEntry costEntry = aSurface->GetCostEntry(); - if (aSurface->IsLocked()) { - MOZ_ASSERT(mLockedCost >= costEntry.GetCost(), "Costs don't balance"); - mLockedCost -= costEntry.GetCost(); - // XXX(seth): It'd be nice to use an O(log n) lookup here. This is O(n). - MOZ_ASSERT(!mCosts.Contains(costEntry), - "Shouldn't have a cost entry for a locked surface"); - } else { - mExpirationTracker.RemoveObject(aSurface); - DebugOnly foundInCosts = mCosts.RemoveElementSorted(costEntry); - MOZ_ASSERT(foundInCosts, "Lost track of costs for this surface"); - } - + mExpirationTracker.RemoveObject(aSurface); + DebugOnly foundInCosts = mCosts.RemoveElementSorted(costEntry); mAvailableCost += costEntry.GetCost(); - MOZ_ASSERT(mAvailableCost <= mMaxCost, - "More available cost than we started with"); + + MOZ_ASSERT(foundInCosts, "Lost track of costs for this surface"); + MOZ_ASSERT(mAvailableCost <= mMaxCost, "More available cost than we started with"); } DrawableFrameRef Lookup(const ImageKey aImageKey, @@ -393,15 +335,12 @@ public: return DrawableFrameRef(); } - if (!surface->IsLocked()) { - mExpirationTracker.MarkUsed(surface); - } - + mExpirationTracker.MarkUsed(surface); return ref; } - void RemoveSurface(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey) + void RemoveIfPresent(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey) { nsRefPtr cache = GetImageCache(aImageKey); if (!cache) @@ -419,33 +358,7 @@ public: return aCost <= mMaxCost; } - void LockImage(const ImageKey aImageKey) - { - nsRefPtr cache = GetImageCache(aImageKey); - if (!cache) { - cache = new ImageSurfaceCache; - mImageCaches.Put(aImageKey, cache); - } - - cache->SetLocked(true); - - // Try to lock all the surfaces the per-image cache is holding. - cache->ForEach(DoLockSurface, this); - } - - void UnlockImage(const ImageKey aImageKey) - { - nsRefPtr cache = GetImageCache(aImageKey); - if (!cache) - return; // Already unlocked and removed. - - cache->SetLocked(false); - - // Unlock all the surfaces the per-image cache is holding. - cache->ForEach(DoUnlockSurface, this); - } - - void RemoveImage(const ImageKey aImageKey) + void Discard(const ImageKey aImageKey) { nsRefPtr cache = GetImageCache(aImageKey); if (!cache) @@ -459,16 +372,13 @@ public: cache->ForEach(DoStopTracking, this); // The per-image cache isn't needed anymore, so remove it as well. - // This implicitly unlocks the image if it was locked. mImageCaches.Remove(aImageKey); } void DiscardAll() { // Remove in order of cost because mCosts is an array and the other data - // structures are all hash tables. Note that locked surfaces (persistent - // surfaces belonging to locked images) are not removed, since they aren't - // present in mCosts. + // structures are all hash tables. while (!mCosts.IsEmpty()) { Remove(mCosts.LastElement().GetSurface()); } @@ -482,64 +392,14 @@ public: return PL_DHASH_NEXT; } - static PLDHashOperator DoLockSurface(const SurfaceKey&, - CachedSurface* aSurface, - void* aCache) - { - if (aSurface->GetLifetime() == Lifetime::Transient || - aSurface->IsLocked()) { - return PL_DHASH_NEXT; - } - - auto cache = static_cast(aCache); - cache->StopTracking(aSurface); - - // Lock the surface. This can fail. - aSurface->SetLocked(true); - cache->StartTracking(aSurface); - - return PL_DHASH_NEXT; - } - - static PLDHashOperator DoUnlockSurface(const SurfaceKey&, - CachedSurface* aSurface, - void* aCache) - { - if (aSurface->GetLifetime() == Lifetime::Transient || - !aSurface->IsLocked()) { - return PL_DHASH_NEXT; - } - - auto cache = static_cast(aCache); - cache->StopTracking(aSurface); - - aSurface->SetLocked(false); - cache->StartTracking(aSurface); - - return PL_DHASH_NEXT; - } - NS_IMETHOD - CollectReports(nsIHandleReportCallback* aHandleReport, - nsISupports* aData, - bool aAnonymize) + CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData, + bool aAnonymize) { - nsresult rv; - - rv = MOZ_COLLECT_REPORT("imagelib-surface-cache-total", - KIND_OTHER, UNITS_BYTES, - SizeOfSurfacesEstimate(), - "Total memory used by the imagelib surface cache."); - NS_ENSURE_SUCCESS(rv, rv); - - rv = MOZ_COLLECT_REPORT("imagelib-surface-cache-locked", - KIND_OTHER, UNITS_BYTES, - SizeOfLockedSurfacesEstimate(), - "Memory used by locked surfaces in the imagelib " - "surface cache."); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; + return MOZ_COLLECT_REPORT( + "imagelib-surface-cache", KIND_OTHER, UNITS_BYTES, + SizeOfSurfacesEstimate(), + "Memory used by the imagelib temporary surface cache."); } // XXX(seth): This is currently only an estimate and, since we don't know @@ -551,11 +411,6 @@ public: return mMaxCost - mAvailableCost; } - Cost SizeOfLockedSurfacesEstimate() const - { - return mLockedCost; - } - private: already_AddRefed GetImageCache(const ImageKey aImageKey) { @@ -564,16 +419,6 @@ private: return imageCache.forget(); } - // This is similar to CanHold() except that it takes into account the costs of - // locked surfaces. It's used internally in Insert(), but it's not exposed - // publicly because if we start permitting multithreaded access to the surface - // cache, which seems likely, then the result would be meaningless: another - // thread could insert a persistent surface or lock an image at any time. - bool CanHoldAfterDiscarding(const Cost aCost) const - { - return aCost <= mMaxCost - mLockedCost; - } - struct SurfaceTracker : public nsExpirationTracker { SurfaceTracker(SurfaceCacheImpl* aCache, uint32_t aSurfaceCacheExpirationTimeMS) @@ -616,7 +461,6 @@ private: nsRefPtr mMemoryPressureObserver; const Cost mMaxCost; Cost mAvailableCost; - Cost mLockedCost; }; NS_IMPL_ISUPPORTS(SurfaceCacheImpl, nsIMemoryReporter) @@ -632,39 +476,35 @@ SurfaceCache::Initialize() // Initialize preferences. MOZ_ASSERT(!sInstance, "Shouldn't initialize more than once"); - // See gfxPrefs for the default values of these preferences. + // See gfxPrefs for the default values - // Length of time before an unused surface is removed from the cache, in - // milliseconds. - uint32_t surfaceCacheExpirationTimeMS = - gfxPrefs::ImageMemSurfaceCacheMinExpirationMS(); + // Length of time before an unused surface is removed from the cache, in milliseconds. + uint32_t surfaceCacheExpirationTimeMS = gfxPrefs::ImageMemSurfaceCacheMinExpirationMS(); // Maximum size of the surface cache, in kilobytes. - uint64_t surfaceCacheMaxSizeKB = gfxPrefs::ImageMemSurfaceCacheMaxSizeKB(); + uint32_t surfaceCacheMaxSizeKB = gfxPrefs::ImageMemSurfaceCacheMaxSizeKB(); // A knob determining the actual size of the surface cache. Currently the // cache is (size of main memory) / (surface cache size factor) KB // or (surface cache max size) KB, whichever is smaller. The formula // may change in the future, though. - // For example, a value of 4 would yield a 256MB cache on a 1GB machine. + // For example, a value of 64 would yield a 64MB cache on a 4GB machine. // The smallest machines we are likely to run this code on have 256MB - // of memory, which would yield a 64MB cache on this setting. + // of memory, which would yield a 4MB cache on the default setting. uint32_t surfaceCacheSizeFactor = gfxPrefs::ImageMemSurfaceCacheSizeFactor(); // Clamp to avoid division by zero below. surfaceCacheSizeFactor = max(surfaceCacheSizeFactor, 1u); // Compute the size of the surface cache. - uint64_t proposedSize = PR_GetPhysicalMemorySize() / surfaceCacheSizeFactor; - uint64_t surfaceCacheSizeBytes = min(proposedSize, surfaceCacheMaxSizeKB * 1024); - uint32_t finalSurfaceCacheSizeBytes = - min(surfaceCacheSizeBytes, uint64_t(UINT32_MAX)); + uint32_t proposedSize = PR_GetPhysicalMemorySize() / surfaceCacheSizeFactor; + uint32_t surfaceCacheSizeBytes = min(proposedSize, surfaceCacheMaxSizeKB * 1024); // Create the surface cache singleton with the requested expiration time and // size. Note that the size is a limit that the cache may not grow beyond, but // we do not actually allocate any storage for surfaces at this time. sInstance = new SurfaceCacheImpl(surfaceCacheExpirationTimeMS, - finalSurfaceCacheSizeBytes); + surfaceCacheSizeBytes); sInstance->InitMemoryReporter(); } @@ -687,19 +527,17 @@ SurfaceCache::Lookup(const ImageKey aImageKey, return sInstance->Lookup(aImageKey, aSurfaceKey); } -/* static */ bool +/* static */ void SurfaceCache::Insert(imgFrame* aSurface, const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey, - Lifetime aLifetime) + const SurfaceKey& aSurfaceKey) { MOZ_ASSERT(NS_IsMainThread()); - if (!sInstance) { - return false; + if (sInstance) { + Cost cost = ComputeCost(aSurfaceKey.Size()); + sInstance->Insert(aSurface, aSurfaceKey.Size(), cost, aImageKey, + aSurfaceKey); } - - Cost cost = ComputeCost(aSurfaceKey.Size()); - return sInstance->Insert(aSurface, cost, aImageKey, aSurfaceKey, aLifetime); } /* static */ bool @@ -715,39 +553,21 @@ SurfaceCache::CanHold(const IntSize& aSize) } /* static */ void -SurfaceCache::LockImage(Image* aImageKey) +SurfaceCache::RemoveIfPresent(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey) { MOZ_ASSERT(NS_IsMainThread()); if (sInstance) { - return sInstance->LockImage(aImageKey); + sInstance->RemoveIfPresent(aImageKey, aSurfaceKey); } } /* static */ void -SurfaceCache::UnlockImage(Image* aImageKey) +SurfaceCache::Discard(Image* aImageKey) { MOZ_ASSERT(NS_IsMainThread()); if (sInstance) { - return sInstance->UnlockImage(aImageKey); - } -} - -/* static */ void -SurfaceCache::RemoveSurface(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (sInstance) { - sInstance->RemoveSurface(aImageKey, aSurfaceKey); - } -} - -/* static */ void -SurfaceCache::RemoveImage(Image* aImageKey) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (sInstance) { - sInstance->RemoveImage(aImageKey); + sInstance->Discard(aImageKey); } } diff --git a/image/src/SurfaceCache.h b/image/src/SurfaceCache.h index 3a2a54b66ec8..29231a97d901 100644 --- a/image/src/SurfaceCache.h +++ b/image/src/SurfaceCache.h @@ -109,33 +109,16 @@ VectorSurfaceKey(const gfx::IntSize& aSize, return SurfaceKey(aSize, aSVGContext, aAnimationTime, 0); } -MOZ_BEGIN_ENUM_CLASS(Lifetime, uint8_t) - Transient, - Persistent -MOZ_END_ENUM_CLASS(Lifetime) - /** * SurfaceCache is an imagelib-global service that allows caching of temporary - * surfaces. Surfaces normally expire from the cache automatically if they go - * too long without being accessed. + * surfaces. Surfaces expire from the cache automatically if they go too long + * without being accessed. * * SurfaceCache does not hold surfaces directly; instead, it holds imgFrame * objects, which hold surfaces but also layer on additional features specific * to imagelib's needs like animation, padding support, and transparent support * for volatile buffers. * - * Sometime it's useful to temporarily prevent surfaces from expiring from the - * cache. This is most often because losing the data could harm the user - * experience (for example, we often don't want to allow surfaces that are - * currently visible to expire) or because it's not possible to rematerialize - * the surface. SurfaceCache supports this through the use of image locking and - * surface lifetimes; see the comments for Insert() and LockImage() for more - * details. - * - * Any image which stores surfaces in the SurfaceCache *must* ensure that it - * calls RemoveImage() before it is destroyed. See the comments for - * RemoveImage() for more details. - * * SurfaceCache is not thread-safe; it should only be accessed from the main * thread. */ @@ -143,25 +126,23 @@ struct SurfaceCache { typedef gfx::IntSize IntSize; - /** + /* * Initialize static data. Called during imagelib module initialization. */ static void Initialize(); - /** + /* * Release static data. Called during imagelib module shutdown. */ static void Shutdown(); - /** + /* * Look up the imgFrame containing a surface in the cache and returns a * drawable reference to that imgFrame. * * If the imgFrame was found in the cache, but had stored its surface in a * volatile buffer which was discarded by the OS, then it is automatically - * removed from the cache and an empty DrawableFrameRef is returned. Note that - * this will never happen to persistent surfaces associated with a locked - * image; the cache keeps a strong reference to such surfaces internally. + * removed from the cache and an empty DrawableFrameRef is returned. * * @param aImageKey Key data identifying which image the surface belongs to. * @param aSurfaceKey Key data which uniquely identifies the requested surface. @@ -172,46 +153,21 @@ struct SurfaceCache static DrawableFrameRef Lookup(const ImageKey aImageKey, const SurfaceKey& aSurfaceKey); - /** + /* * Insert a surface into the cache. It is an error to call this function * without first calling Lookup to verify that the surface is not already in * the cache. * - * Each surface in the cache has a lifetime, either Transient or Persistent. - * Transient surfaces can expire from the cache at any time. Persistent - * surfaces can ordinarily also expire from the cache at any time, but if the - * image they're associated with is locked, then these surfaces will never - * expire. This means that surfaces which cannot be rematerialized should be - * inserted with a persistent lifetime *after* the image is locked with - * LockImage(); if you use the other order, the surfaces might expire before - * LockImage() gets called. - * - * If a surface cannot be rematerialized, it may be important to know whether - * it was inserted into the cache successfully. Insert() returns false if it - * failed to insert the surface, which could happen because of capacity - * reasons, or because it was already freed by the OS. If you aren't inserting - * a surface with persistent lifetime, or if the surface isn't associated with - * a locked image, the return value is useless: the surface might expire - * immediately after being inserted, even though Insert() returned true. Thus, - * most callers do not need to check the return value. - * * @param aTarget The new surface (wrapped in an imgFrame) to insert into * the cache. * @param aImageKey Key data identifying which image the surface belongs to. * @param aSurfaceKey Key data which uniquely identifies the requested surface. - * @param aLifetime Whether this is a transient surface that can always be - * allowed to expire, or a persistent surface that - * shouldn't expire if the image is locked. - * @return false if the surface could not be inserted. Only check this if - * inserting a persistent surface associated with a locked image (see - * above for more information). */ - static bool Insert(imgFrame* aSurface, + static void Insert(imgFrame* aSurface, const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey, - Lifetime aLifetime); + const SurfaceKey& aSurfaceKey); - /** + /* * Checks if a surface of a given size could possibly be stored in the cache. * If CanHold() returns false, Insert() will always fail to insert the * surface, but the inverse is not true: Insert() may take more information @@ -227,69 +183,30 @@ struct SurfaceCache */ static bool CanHold(const IntSize& aSize); - /** - * Locks an image, preventing any of that image's surfaces from expiring - * unless they have a transient lifetime. - * - * Regardless of locking, any of an image's surfaces may be removed using - * RemoveSurface(), and all of an image's surfaces are removed by - * RemoveImage(), whether the image is locked or not. - * - * It's safe to call LockImage() on an image that's already locked; this has - * no effect. - * - * You must always unlock any image you lock. You may do this explicitly by - * calling UnlockImage(), or implicitly by calling RemoveImage(). Since you're - * required to call RemoveImage() when you destroy an image, this doesn't - * impose any additional requirements, but it's preferable to call - * UnlockImage() earlier if it's possible. - * - * @param aImageKey The image to lock. - */ - static void LockImage(const ImageKey aImageKey); - - /** - * Unlocks an image, allowing any of its surfaces to expire at any time. - * - * It's OK to call UnlockImage() on an image that's already unlocked; this has - * no effect. - * - * @param aImageKey The image to lock. - */ - static void UnlockImage(const ImageKey aImageKey); - - /** - * Removes a surface from the cache, if it's present. If it's not present, - * RemoveSurface() has no effect. + /* + * Removes a surface from the cache, if it's present. * * Use this function to remove individual surfaces that have become invalid. - * Prefer RemoveImage() or DiscardAll() when they're applicable, as they have - * much better performance than calling this function repeatedly. + * Prefer Discard() or DiscardAll() when they're applicable, as they have much + * better performance than calling this function repeatedly. * * @param aImageKey Key data identifying which image the surface belongs to. * @param aSurfaceKey Key data which uniquely identifies the requested surface. */ - static void RemoveSurface(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey); - - /** - * Removes all cached surfaces associated with the given image from the cache. - * If the image is locked, it is automatically unlocked. - * - * This MUST be called, at a minimum, when an Image which could be storing - * surfaces in the surface cache is destroyed. If another image were allocated - * at the same address it could result in subtle, difficult-to-reproduce bugs. + static void RemoveIfPresent(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey); + /* + * Evicts any cached surfaces associated with the given image from the cache. + * This MUST be called, at a minimum, when the image is destroyed. If + * another image were allocated at the same address it could result in + * subtle, difficult-to-reproduce bugs. * * @param aImageKey The image which should be removed from the cache. */ - static void RemoveImage(const ImageKey aImageKey); + static void Discard(const ImageKey aImageKey); - /** - * Evicts all evictable surfaces from the cache. - * - * All surfaces are evictable except for persistent surfaces associated with - * locked images. Non-evictable surfaces can only be removed by - * RemoveSurface() or RemoveImage(). + /* + * Evicts all caches surfaces from ths cache. */ static void DiscardAll(); diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 81f5475ed101..42fb26a7e057 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -337,7 +337,7 @@ VectorImage::VectorImage(ProgressTracker* aProgressTracker, VectorImage::~VectorImage() { CancelAllListeners(); - SurfaceCache::RemoveImage(ImageKey(this)); + SurfaceCache::Discard(this); } //------------------------------------------------------------------------------ @@ -565,7 +565,7 @@ VectorImage::SendInvalidationNotifications() // notifications directly in |InvalidateObservers...|. if (mProgressTracker) { - SurfaceCache::RemoveImage(ImageKey(this)); + SurfaceCache::Discard(this); mProgressTracker->SyncNotifyProgress(FLAG_FRAME_COMPLETE, nsIntRect::GetMaxSizedIntRect()); } @@ -903,8 +903,7 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams) SurfaceCache::Insert(frame, ImageKey(this), VectorSurfaceKey(aParams.size, aParams.svgContext, - aParams.animationTime), - Lifetime::Transient); + aParams.animationTime)); // Draw. nsRefPtr drawable = @@ -972,7 +971,7 @@ VectorImage::UnlockImage() NS_IMETHODIMP VectorImage::RequestDiscard() { - SurfaceCache::RemoveImage(ImageKey(this)); + SurfaceCache::Discard(this); return NS_OK; }