mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-04 22:37:29 +09:00
Issue #2218 - Part 2: Make SurfaceCache free ImageSurfaceCache objects outside of the lock
Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1389479
This commit is contained in:
parent
fa787f4a6a
commit
93644fd33e
1 changed files with 108 additions and 36 deletions
|
|
@ -251,12 +251,14 @@ public:
|
||||||
mSurfaces.Put(aSurface->GetSurfaceKey(), aSurface);
|
mSurfaces.Put(aSurface->GetSurfaceKey(), aSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Remove(NotNull<CachedSurface*> aSurface)
|
already_AddRefed<CachedSurface> Remove(NotNull<CachedSurface*> aSurface)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mSurfaces.GetWeak(aSurface->GetSurfaceKey()),
|
MOZ_ASSERT(mSurfaces.GetWeak(aSurface->GetSurfaceKey()),
|
||||||
"Should not be removing a surface we don't have");
|
"Should not be removing a surface we don't have");
|
||||||
|
|
||||||
mSurfaces.Remove(aSurface->GetSurfaceKey());
|
RefPtr<CachedSurface> surface;
|
||||||
|
mSurfaces.Remove(aSurface->GetSurfaceKey(), getter_AddRefs(surface));
|
||||||
|
return surface.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<CachedSurface> Lookup(const SurfaceKey& aSurfaceKey)
|
already_AddRefed<CachedSurface> Lookup(const SurfaceKey& aSurfaceKey)
|
||||||
|
|
@ -507,10 +509,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
StopTracking(aSurface, aAutoLock);
|
StopTracking(aSurface, aAutoLock);
|
||||||
cache->Remove(aSurface);
|
|
||||||
|
|
||||||
// Remove the per-image cache if it's unneeded now. (Keep it if the image is
|
// Individual surfaces must be freed outside the lock.
|
||||||
// locked, since the per-image cache is where we store that state.)
|
mCachedSurfacesDiscard.AppendElement(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. Note that
|
||||||
|
// we don't push it into mImageCachesDiscard because all of its surfaces
|
||||||
|
// have been removed, so it is safe to free while holding the lock.
|
||||||
if (cache->IsEmpty() && !cache->IsLocked()) {
|
if (cache->IsEmpty() && !cache->IsLocked()) {
|
||||||
mImageCaches.Remove(imageKey);
|
mImageCaches.Remove(imageKey);
|
||||||
}
|
}
|
||||||
|
|
@ -719,11 +725,12 @@ public:
|
||||||
DoUnlockSurfaces(WrapNotNull(cache), aAutoLock);
|
DoUnlockSurfaces(WrapNotNull(cache), aAutoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveImage(const ImageKey aImageKey, const StaticMutexAutoLock& aAutoLock)
|
already_AddRefed<ImageSurfaceCache>
|
||||||
|
RemoveImage(const ImageKey aImageKey, const StaticMutexAutoLock& aAutoLock)
|
||||||
{
|
{
|
||||||
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||||
if (!cache) {
|
if (!cache) {
|
||||||
return; // No cached surfaces for this image, so nothing to do.
|
return nullptr; // No cached surfaces for this image, so nothing to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard all of the cached surfaces for this image.
|
// Discard all of the cached surfaces for this image.
|
||||||
|
|
@ -738,6 +745,10 @@ public:
|
||||||
// The per-image cache isn't needed anymore, so remove it as well.
|
// The per-image cache isn't needed anymore, so remove it as well.
|
||||||
// This implicitly unlocks the image if it was locked.
|
// This implicitly unlocks the image if it was locked.
|
||||||
mImageCaches.Remove(aImageKey);
|
mImageCaches.Remove(aImageKey);
|
||||||
|
|
||||||
|
// Since we did not actually remove any of the surfaces from the cache
|
||||||
|
// itself, only stopped tracking them, we should free it outside the lock.
|
||||||
|
return cache.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiscardAll(const StaticMutexAutoLock& aAutoLock)
|
void DiscardAll(const StaticMutexAutoLock& aAutoLock)
|
||||||
|
|
@ -776,6 +787,13 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TakeDiscard(nsTArray<RefPtr<CachedSurface>>& aDiscard,
|
||||||
|
const StaticMutexAutoLock& aAutoLock)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aDiscard.IsEmpty());
|
||||||
|
aDiscard = Move(mCachedSurfacesDiscard);
|
||||||
|
}
|
||||||
|
|
||||||
void LockSurface(NotNull<CachedSurface*> aSurface,
|
void LockSurface(NotNull<CachedSurface*> aSurface,
|
||||||
const StaticMutexAutoLock& aAutoLock)
|
const StaticMutexAutoLock& aAutoLock)
|
||||||
{
|
{
|
||||||
|
|
@ -922,10 +940,12 @@ private:
|
||||||
Remove(WrapNotNull(surface), aAutoLock);
|
Remove(WrapNotNull(surface), aAutoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SurfaceTracker : public ExpirationTrackerImpl<CachedSurface, 2,
|
class SurfaceTracker final :
|
||||||
StaticMutex,
|
public ExpirationTrackerImpl<CachedSurface, 2,
|
||||||
StaticMutexAutoLock>
|
StaticMutex,
|
||||||
|
StaticMutexAutoLock>
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
explicit SurfaceTracker(uint32_t aSurfaceCacheExpirationTimeMS)
|
explicit SurfaceTracker(uint32_t aSurfaceCacheExpirationTimeMS)
|
||||||
: ExpirationTrackerImpl<CachedSurface, 2,
|
: ExpirationTrackerImpl<CachedSurface, 2,
|
||||||
StaticMutex, StaticMutexAutoLock>(
|
StaticMutex, StaticMutexAutoLock>(
|
||||||
|
|
@ -939,23 +959,40 @@ private:
|
||||||
sInstance->Remove(WrapNotNull(aSurface), aAutoLock);
|
sInstance->Remove(WrapNotNull(aSurface), aAutoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NotifyHandlerEndLocked(const StaticMutexAutoLock& aAutoLock) override
|
||||||
|
{
|
||||||
|
sInstance->TakeDiscard(mDiscard, aAutoLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotifyHandlerEnd() override
|
||||||
|
{
|
||||||
|
nsTArray<RefPtr<CachedSurface>> discard(Move(mDiscard));
|
||||||
|
}
|
||||||
|
|
||||||
StaticMutex& GetMutex() override
|
StaticMutex& GetMutex() override
|
||||||
{
|
{
|
||||||
return sInstanceMutex;
|
return sInstanceMutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsTArray<RefPtr<CachedSurface>> mDiscard;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MemoryPressureObserver : public nsIObserver
|
class MemoryPressureObserver final : public nsIObserver
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
NS_IMETHOD Observe(nsISupports*,
|
NS_IMETHOD Observe(nsISupports*,
|
||||||
const char* aTopic,
|
const char* aTopic,
|
||||||
const char16_t*) override
|
const char16_t*) override
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock lock(sInstanceMutex);
|
nsTArray<RefPtr<CachedSurface>> discard;
|
||||||
if (sInstance && strcmp(aTopic, "memory-pressure") == 0) {
|
{
|
||||||
sInstance->DiscardForMemoryPressure(lock);
|
StaticMutexAutoLock lock(sInstanceMutex);
|
||||||
|
if (sInstance && strcmp(aTopic, "memory-pressure") == 0) {
|
||||||
|
sInstance->DiscardForMemoryPressure(lock);
|
||||||
|
sInstance->TakeDiscard(discard, lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -967,6 +1004,7 @@ private:
|
||||||
nsTArray<CostEntry> mCosts;
|
nsTArray<CostEntry> mCosts;
|
||||||
nsRefPtrHashtable<nsPtrHashKey<Image>,
|
nsRefPtrHashtable<nsPtrHashKey<Image>,
|
||||||
ImageSurfaceCache> mImageCaches;
|
ImageSurfaceCache> mImageCaches;
|
||||||
|
nsTArray<RefPtr<CachedSurface>> mCachedSurfacesDiscard;
|
||||||
SurfaceTracker mExpirationTracker;
|
SurfaceTracker mExpirationTracker;
|
||||||
RefPtr<MemoryPressureObserver> mMemoryPressureObserver;
|
RefPtr<MemoryPressureObserver> mMemoryPressureObserver;
|
||||||
nsTArray<RefPtr<image::Image>> mReleasingImagesOnMainThread;
|
nsTArray<RefPtr<image::Image>> mReleasingImagesOnMainThread;
|
||||||
|
|
@ -1043,45 +1081,72 @@ SurfaceCache::Initialize()
|
||||||
/* static */ void
|
/* static */ void
|
||||||
SurfaceCache::Shutdown()
|
SurfaceCache::Shutdown()
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock lock(sInstanceMutex);
|
RefPtr<SurfaceCacheImpl> cache;
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
{
|
||||||
MOZ_ASSERT(sInstance, "No singleton - was Shutdown() called twice?");
|
StaticMutexAutoLock lock(sInstanceMutex);
|
||||||
sInstance = nullptr;
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(sInstance, "No singleton - was Shutdown() called twice?");
|
||||||
|
cache = sInstance.forget();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ LookupResult
|
/* static */ LookupResult
|
||||||
SurfaceCache::Lookup(const ImageKey aImageKey,
|
SurfaceCache::Lookup(const ImageKey aImageKey,
|
||||||
const SurfaceKey& aSurfaceKey)
|
const SurfaceKey& aSurfaceKey)
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock lock(sInstanceMutex);
|
nsTArray<RefPtr<CachedSurface>> discard;
|
||||||
if (!sInstance) {
|
LookupResult rv(MatchType::NOT_FOUND);
|
||||||
return LookupResult(MatchType::NOT_FOUND);
|
|
||||||
|
{
|
||||||
|
StaticMutexAutoLock lock(sInstanceMutex);
|
||||||
|
if (!sInstance) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = sInstance->Lookup(aImageKey, aSurfaceKey, lock);
|
||||||
|
sInstance->TakeDiscard(discard, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sInstance->Lookup(aImageKey, aSurfaceKey, lock);
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ LookupResult
|
/* static */ LookupResult
|
||||||
SurfaceCache::LookupBestMatch(const ImageKey aImageKey,
|
SurfaceCache::LookupBestMatch(const ImageKey aImageKey,
|
||||||
const SurfaceKey& aSurfaceKey)
|
const SurfaceKey& aSurfaceKey)
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock lock(sInstanceMutex);
|
nsTArray<RefPtr<CachedSurface>> discard;
|
||||||
if (!sInstance) {
|
LookupResult rv(MatchType::NOT_FOUND);
|
||||||
return LookupResult(MatchType::NOT_FOUND);
|
|
||||||
|
{
|
||||||
|
StaticMutexAutoLock lock(sInstanceMutex);
|
||||||
|
if (!sInstance) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = sInstance->LookupBestMatch(aImageKey, aSurfaceKey, lock);
|
||||||
|
sInstance->TakeDiscard(discard, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sInstance->LookupBestMatch(aImageKey, aSurfaceKey, lock);
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ InsertOutcome
|
/* static */ InsertOutcome
|
||||||
SurfaceCache::Insert(NotNull<ISurfaceProvider*> aProvider)
|
SurfaceCache::Insert(NotNull<ISurfaceProvider*> aProvider)
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock lock(sInstanceMutex);
|
nsTArray<RefPtr<CachedSurface>> discard;
|
||||||
if (!sInstance) {
|
InsertOutcome rv(InsertOutcome::FAILURE);
|
||||||
return InsertOutcome::FAILURE;
|
|
||||||
|
{
|
||||||
|
StaticMutexAutoLock lock(sInstanceMutex);
|
||||||
|
if (!sInstance) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = sInstance->Insert(aProvider, /* aSetAvailable = */ false, lock);
|
||||||
|
sInstance->TakeDiscard(discard, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sInstance->Insert(aProvider, /* aSetAvailable = */ false, lock);
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
|
|
@ -1148,18 +1213,25 @@ SurfaceCache::UnlockEntries(const ImageKey aImageKey)
|
||||||
/* static */ void
|
/* static */ void
|
||||||
SurfaceCache::RemoveImage(const ImageKey aImageKey)
|
SurfaceCache::RemoveImage(const ImageKey aImageKey)
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock lock(sInstanceMutex);
|
RefPtr<ImageSurfaceCache> discard;
|
||||||
if (sInstance) {
|
{
|
||||||
sInstance->RemoveImage(aImageKey, lock);
|
StaticMutexAutoLock lock(sInstanceMutex);
|
||||||
|
if (sInstance) {
|
||||||
|
discard = sInstance->RemoveImage(aImageKey, lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
SurfaceCache::DiscardAll()
|
SurfaceCache::DiscardAll()
|
||||||
{
|
{
|
||||||
StaticMutexAutoLock lock(sInstanceMutex);
|
nsTArray<RefPtr<CachedSurface>> discard;
|
||||||
if (sInstance) {
|
{
|
||||||
sInstance->DiscardAll(lock);
|
StaticMutexAutoLock lock(sInstanceMutex);
|
||||||
|
if (sInstance) {
|
||||||
|
sInstance->DiscardAll(lock);
|
||||||
|
sInstance->TakeDiscard(discard, lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue