Add option to skip intermediate release/fulfill calls for promise images.
SkiaRenderer does not delete promise image textures when they are released
but not done. Refulfilling promise image textures takes a significant amount
of CPU time. This allows us to fulfill each promise image once.
Bug: skia:8736
Change-Id: I7ad7fa9678ed0ec4bb714b71fbf920ab4a845409
Reviewed-on: https://skia-review.googlesource.com/c/188039
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index 7c731cf..e4aabb7 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -360,7 +360,8 @@
PromiseImageTextureFulfillProc fulfillProc,
PromiseImageTextureReleaseProc releaseProc,
PromiseImageTextureDoneProc doneProc,
- PromiseImageTextureContext textureContext) {
+ PromiseImageTextureContext textureContext,
+ DelayReleaseCallback delayReleaseCallback) {
SkASSERT(context);
SkASSERT(width > 0 && height > 0);
SkASSERT(doneProc);
@@ -402,9 +403,11 @@
PromiseImageTextureReleaseProc releaseProc,
PromiseImageTextureDoneProc doneProc,
PromiseImageTextureContext context,
+ DelayReleaseCallback delayReleaseCallback,
GrPixelConfig config)
: fFulfillProc(fulfillProc)
- , fConfig(config) {
+ , fConfig(config)
+ , fDelayReleaseCallback(delayReleaseCallback) {
auto doneHelper = sk_make_sp<GrReleaseProcHelper>(doneProc, context);
fReleaseContext = sk_make_sp<IdleContext::PromiseImageReleaseContext>(
releaseProc, context, std::move(doneHelper));
@@ -414,8 +417,14 @@
sk_sp<GrSurface> operator()(GrResourceProvider* resourceProvider) {
if (!resourceProvider) {
+ if (fDelayedReleaseTexture) {
+ fDelayedReleaseTexture.reset();
+ }
return nullptr;
}
+ if (fDelayedReleaseTexture) {
+ return fDelayedReleaseTexture;
+ }
sk_sp<GrTexture> cachedTexture;
SkASSERT(fLastFulfilledKey.isValid() == (fLastFulfillID > 0));
@@ -459,6 +468,7 @@
return sk_sp<GrTexture>();
}
+ sk_sp<GrTexture> tex;
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey::Builder builder(&fLastFulfilledKey, kDomain, 2, "promise");
builder[0] = promiseTexture->uniqueID();
@@ -467,7 +477,6 @@
// A texture with this key may already exist from a different instance of this lazy
// callback. This could happen if the client fulfills a promise image with a texture
// that was previously used to fulfill a different promise image.
- sk_sp<GrTexture> tex;
if (auto surf = resourceProvider->findByUniqueKey<GrSurface>(fLastFulfilledKey)) {
tex = sk_ref_sp(surf->asTexture());
SkASSERT(tex);
@@ -484,6 +493,9 @@
}
}
this->addToIdleContext(tex.get());
+ if (fDelayReleaseCallback == DelayReleaseCallback::kYes) {
+ fDelayedReleaseTexture = tex;
+ }
tex->resourcePriv().setUniqueKey(fLastFulfilledKey);
SkASSERT(fContextID == SK_InvalidUniqueID ||
fContextID == tex->getContext()->uniqueID());
@@ -567,15 +579,17 @@
}
sk_sp<IdleContext::PromiseImageReleaseContext> fReleaseContext;
+ sk_sp<GrTexture> fDelayedReleaseTexture;
PromiseImageTextureFulfillProc fFulfillProc;
GrPixelConfig fConfig;
+ DelayReleaseCallback fDelayReleaseCallback;
// ID of the last SkPromiseImageTexture given to us by the client.
uint32_t fLastFulfillID = 0;
// ID of the GrContext that we are interacting with.
uint32_t fContextID = SK_InvalidUniqueID;
GrUniqueKey fLastFulfilledKey;
- } callback(fulfillProc, releaseProc, doneProc, textureContext, config);
+ } callback(fulfillProc, releaseProc, doneProc, textureContext, delayReleaseCallback, config);
GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();