Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 39b7095

Browse files
committed
Bug 1380649 - Part 1. Ensure SurfaceCache::CollectSizeOfSurfaces removes purged volatile buffer-backed surfaces. r=tnikkel
When we lookup a surface in the cache, we are careful to remove any surfaces which were backed by volatile memory and got purged before we could reacquire the buffer. We were not so careful in doing that when generating memory reports. ISurfaceProvider::AddSizeOfExcludingThis will cause us to acquire the buffer, and if it was purged, forget about its purged status. Later when we performed a lookup, we would forget the purged status, and assume we have the right data. This would appear as completely transparent for BGRA surfaces, and completely black for BGRX surfaces. With this patch, we now properly remove purged surfaces instead of including them in the report. This ensures that the cache state is consistent. This also resolves memory reports of surfaces which reported using no data -- they were purged when the report was generated. Additionally, there was a bug in SurfaceCache::PruneImage where we did not discard surfaces outside the module lock. Both PruneImage and CollectSizeOfSurfaces now free any discarded surfaces outside the lock.
1 parent ae25105 commit 39b7095

1 file changed

Lines changed: 45 additions & 12 deletions

File tree

image/SurfaceCache.cpp

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -614,12 +614,29 @@ class ImageSurfaceCache
614614
return false;
615615
}
616616

617+
template<typename Function>
617618
void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
618-
MallocSizeOf aMallocSizeOf)
619+
MallocSizeOf aMallocSizeOf,
620+
Function&& aRemoveCallback)
619621
{
620622
CachedSurface::SurfaceMemoryReport report(aCounters, aMallocSizeOf);
621-
for (auto iter = ConstIter(); !iter.Done(); iter.Next()) {
623+
for (auto iter = mSurfaces.Iter(); !iter.Done(); iter.Next()) {
622624
NotNull<CachedSurface*> surface = WrapNotNull(iter.UserData());
625+
626+
// We don't need the drawable surface for ourselves, but adding a surface
627+
// to the report will trigger this indirectly. If the surface was
628+
// discarded by the OS because it was in volatile memory, we should remove
629+
// it from the cache immediately rather than include it in the report.
630+
DrawableSurface drawableSurface;
631+
if (!surface->IsPlaceholder()) {
632+
drawableSurface = surface->GetDrawableSurface();
633+
if (!drawableSurface) {
634+
aRemoveCallback(surface);
635+
iter.Remove();
636+
continue;
637+
}
638+
}
639+
623640
const IntSize& size = surface->GetSurfaceKey().Size();
624641
bool factor2Size = false;
625642
if (mFactor2Mode) {
@@ -1073,6 +1090,8 @@ class SurfaceCacheImpl final : public nsIMemoryReporter
10731090

10741091
cache->Prune([this, &aAutoLock](NotNull<CachedSurface*> aSurface) -> void {
10751092
StopTracking(aSurface, /* aIsTracked */ true, aAutoLock);
1093+
// Individual surfaces must be freed outside the lock.
1094+
mCachedSurfacesDiscard.AppendElement(aSurface);
10761095
});
10771096
}
10781097

@@ -1165,15 +1184,21 @@ class SurfaceCacheImpl final : public nsIMemoryReporter
11651184

11661185
void CollectSizeOfSurfaces(const ImageKey aImageKey,
11671186
nsTArray<SurfaceMemoryCounter>& aCounters,
1168-
MallocSizeOf aMallocSizeOf)
1187+
MallocSizeOf aMallocSizeOf,
1188+
const StaticMutexAutoLock& aAutoLock)
11691189
{
11701190
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
11711191
if (!cache) {
11721192
return; // No surfaces for this image.
11731193
}
11741194

11751195
// Report all surfaces in the per-image cache.
1176-
cache->CollectSizeOfSurfaces(aCounters, aMallocSizeOf);
1196+
cache->CollectSizeOfSurfaces(aCounters, aMallocSizeOf,
1197+
[this, &aAutoLock](NotNull<CachedSurface*> aSurface) -> void {
1198+
StopTracking(aSurface, /* aIsTracked */ true, aAutoLock);
1199+
// Individual surfaces must be freed outside the lock.
1200+
mCachedSurfacesDiscard.AppendElement(aSurface);
1201+
});
11771202
}
11781203

11791204
private:
@@ -1544,9 +1569,13 @@ SurfaceCache::RemoveImage(const ImageKey aImageKey)
15441569
/* static */ void
15451570
SurfaceCache::PruneImage(const ImageKey aImageKey)
15461571
{
1547-
StaticMutexAutoLock lock(sInstanceMutex);
1548-
if (sInstance) {
1549-
sInstance->PruneImage(aImageKey, lock);
1572+
nsTArray<RefPtr<CachedSurface>> discard;
1573+
{
1574+
StaticMutexAutoLock lock(sInstanceMutex);
1575+
if (sInstance) {
1576+
sInstance->PruneImage(aImageKey, lock);
1577+
sInstance->TakeDiscard(discard, lock);
1578+
}
15501579
}
15511580
}
15521581

@@ -1568,12 +1597,16 @@ SurfaceCache::CollectSizeOfSurfaces(const ImageKey aImageKey,
15681597
nsTArray<SurfaceMemoryCounter>& aCounters,
15691598
MallocSizeOf aMallocSizeOf)
15701599
{
1571-
StaticMutexAutoLock lock(sInstanceMutex);
1572-
if (!sInstance) {
1573-
return;
1574-
}
1600+
nsTArray<RefPtr<CachedSurface>> discard;
1601+
{
1602+
StaticMutexAutoLock lock(sInstanceMutex);
1603+
if (!sInstance) {
1604+
return;
1605+
}
15751606

1576-
return sInstance->CollectSizeOfSurfaces(aImageKey, aCounters, aMallocSizeOf);
1607+
sInstance->CollectSizeOfSurfaces(aImageKey, aCounters, aMallocSizeOf, lock);
1608+
sInstance->TakeDiscard(discard, lock);
1609+
}
15771610
}
15781611

15791612
/* static */ size_t

0 commit comments

Comments
 (0)