Avoid unbounded listener growth on SkImage_Lazy when textures are purged
Generalizes the system used on SkPathRef where a GrTexture's key
destructor signals that a listener on the image can be removed via
the unique key custom data.
Removes texturesAreCacheable() from SkImageGenerator. This was used to
prevent unbounded growth in a narrow situation related to
GrBackendTextureImageGenerator.
Change-Id: I3c605da099acfac94751e793331e356a0979d359
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/274038
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 7222dcf..9217085 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -20,6 +20,7 @@
#include "src/core/SkAutoMalloc.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkColorSpacePriv.h"
+#include "src/core/SkIDChangeListener.h"
#include "src/core/SkImagePriv.h"
#include "src/core/SkMaskFilterBase.h"
#include "src/core/SkMessageBus.h"
@@ -117,6 +118,35 @@
pixelRef->addGenIDChangeListener(new Invalidator(key, contextUniqueID));
}
+sk_sp<SkIDChangeListener> GrMakeUniqueKeyInvalidationListener(GrUniqueKey* key,
+ uint32_t contextID) {
+ class Listener : public SkIDChangeListener {
+ public:
+ Listener(const GrUniqueKey& key, uint32_t contextUniqueID) : fMsg(key, contextUniqueID) {}
+
+ void changed() override { SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); }
+
+ private:
+ GrUniqueKeyInvalidatedMessage fMsg;
+ };
+
+ auto listener = sk_make_sp<Listener>(*key, contextID);
+
+ // We stick a SkData on the key that calls invalidateListener in its destructor.
+ auto invalidateListener = [](const void* ptr, void* /*context*/) {
+ auto listener = reinterpret_cast<const sk_sp<Listener>*>(ptr);
+ (*listener)->markShouldDeregister();
+ delete listener;
+ };
+ auto data = SkData::MakeWithProc(new sk_sp<Listener>(listener),
+ sizeof(sk_sp<Listener>),
+ invalidateListener,
+ nullptr);
+ SkASSERT(!key->getCustomData());
+ key->setCustomData(std::move(data));
+ return std::move(listener);
+}
+
GrSurfaceProxyView GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx,
GrSurfaceProxy* baseProxy,
GrSurfaceOrigin origin,