Prevent unbounded listener growth on SkPixelRefs.
Use SkIDChangeListener and update GrBitmapTextureMaker to add listener
to key to deregister if texture is purged before genID changes.
Add a common listener list implementation and replace existing lists.
Change-Id: Ib0c78241eaf59b59b892d8b004b2bb095140bc6d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/274549
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp
index 1ba1779..172d34a 100644
--- a/src/gpu/GrBitmapTextureMaker.cpp
+++ b/src/gpu/GrBitmapTextureMaker.cpp
@@ -10,7 +10,7 @@
#include "include/core/SkBitmap.h"
#include "include/core/SkPixelRef.h"
#include "include/private/GrRecordingContext.h"
-#include "src/core/SkMipMap.h"
+#include "include/private/SkIDChangeListener.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
@@ -33,7 +33,7 @@
SkIPoint origin = bitmap.pixelRefOrigin();
SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(),
bitmap.height());
- GrMakeKeyFromImageID(&fOriginalKey, bitmap.pixelRef()->getGenerationID(), subset);
+ GrMakeKeyFromImageID(&fKey, bitmap.pixelRef()->getGenerationID(), subset);
}
}
@@ -42,9 +42,15 @@
sk_sp<GrTextureProxy> proxy;
GrSwizzle swizzle;
- if (fOriginalKey.isValid()) {
+ auto installKey = [&](GrTextureProxy* proxy) {
+ auto listener = GrMakeUniqueKeyInvalidationListener(&fKey, proxyProvider->contextID());
+ fBitmap.pixelRef()->addGenIDChangeListener(std::move(listener));
+ proxyProvider->assignUniqueKeyToProxy(fKey, proxy);
+ };
+
+ if (fKey.isValid()) {
auto colorType = SkColorTypeToGrColorType(fBitmap.colorType());
- proxy = proxyProvider->findOrCreateProxyByUniqueKey(fOriginalKey, colorType);
+ proxy = proxyProvider->findOrCreateProxyByUniqueKey(fKey, colorType);
if (proxy) {
swizzle = this->context()->priv().caps()->getReadSwizzle(proxy->backendFormat(),
this->colorType());
@@ -71,10 +77,8 @@
swizzle = this->context()->priv().caps()->getReadSwizzle(proxy->backendFormat(),
this->colorType());
SkASSERT(mipMapped == GrMipMapped::kNo || proxy->mipMapped() == GrMipMapped::kYes);
- if (fOriginalKey.isValid()) {
- proxyProvider->assignUniqueKeyToProxy(fOriginalKey, proxy.get());
- GrInstallBitmapUniqueKeyInvalidator(
- fOriginalKey, proxyProvider->contextID(), fBitmap.pixelRef());
+ if (fKey.isValid()) {
+ installKey(proxy.get());
}
return GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle);
}
@@ -83,7 +87,7 @@
if (proxy) {
SkASSERT(mipMapped == GrMipMapped::kYes);
SkASSERT(proxy->mipMapped() == GrMipMapped::kNo);
- SkASSERT(fOriginalKey.isValid());
+ SkASSERT(fKey.isValid());
// We need a mipped proxy, but we found a proxy earlier that wasn't mipped. Thus we generate
// a new mipped surface and copy the original proxy into the base layer. We will then let
// the gpu generate the rest of the mips.
@@ -96,13 +100,11 @@
// means that all future uses of the key will access the mipmapped version. The texture
// backing the unmipped version will remain in the resource cache until the last texture
// proxy referencing it is deleted at which time it too will be deleted or recycled.
- SkASSERT(proxy->getUniqueKey() == fOriginalKey);
+ SkASSERT(proxy->getUniqueKey() == fKey);
SkASSERT(mippedView.origin() == kTopLeft_GrSurfaceOrigin);
SkASSERT(mippedView.swizzle() == swizzle);
proxyProvider->removeUniqueKeyFromProxy(proxy.get());
- proxyProvider->assignUniqueKeyToProxy(fOriginalKey, mippedProxy);
- GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, proxyProvider->contextID(),
- fBitmap.pixelRef());
+ installKey(mippedProxy);
return mippedView;
}
// We failed to make a mipped proxy with the base copied into it. This could have