Add release proc apis to SkSurface::MakeFromBackend* calls.
Bug: skia:
Change-Id: I0e6cd8895c328a89cd0fa50260fe4e8adbff5990
Reviewed-on: https://skia-review.googlesource.com/c/188634
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h
index 23c3b6a..525cdad 100644
--- a/include/core/SkSurface.h
+++ b/include/core/SkSurface.h
@@ -167,6 +167,15 @@
return MakeRaster(SkImageInfo::MakeN32Premul(width, height), surfaceProps);
}
+ /** Caller data passed to RenderTarget/TextureReleaseProc; may be nullptr. */
+ typedef void* ReleaseContext;
+
+ /** User function called when supplied render target may be deleted. */
+ typedef void (*RenderTargetReleaseProc)(ReleaseContext releaseContext);
+
+ /** User function called when supplied texture may be deleted. */
+ typedef void (*TextureReleaseProc)(ReleaseContext releaseContext);
+
/** Wraps a GPU-backed texture into SkSurface. Caller must ensure the texture is
valid for the lifetime of returned SkSurface. If sampleCnt greater than zero,
creates an intermediate MSAA SkSurface which is used for drawing backendTexture.
@@ -180,27 +189,31 @@
If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.
- @param context GPU context
- @param backendTexture texture residing on GPU
- @param origin one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
- @param sampleCnt samples per pixel, or 0 to disable full scene anti-aliasing
- @param colorType one of:
- kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
- kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
- kRGB_888x_SkColorType, kBGRA_8888_SkColorType,
- kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
- kGray_8_SkColorType, kRGBA_F16_SkColorType
- @param colorSpace range of colors; may be nullptr
- @param surfaceProps LCD striping orientation and setting for device independent
- fonts; may be nullptr
- @return SkSurface if all parameters are valid; otherwise, nullptr
+ @param context GPU context
+ @param backendTexture texture residing on GPU
+ @param origin one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+ @param sampleCnt samples per pixel, or 0 to disable full scene anti-aliasing
+ @param colorType one of:
+ kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
+ kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
+ kRGB_888x_SkColorType, kBGRA_8888_SkColorType,
+ kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+ kGray_8_SkColorType, kRGBA_F16_SkColorType
+ @param colorSpace range of colors; may be nullptr
+ @param surfaceProps LCD striping orientation and setting for device independent
+ fonts; may be nullptr
+ @param textureReleaseProc function called when texture can be released
+ @param releaseContext state passed to textureReleaseProc
+ @return SkSurface if all parameters are valid; otherwise, nullptr
*/
static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* context,
const GrBackendTexture& backendTexture,
GrSurfaceOrigin origin, int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
- const SkSurfaceProps* surfaceProps);
+ const SkSurfaceProps* surfaceProps,
+ TextureReleaseProc textureReleaseProc = nullptr,
+ ReleaseContext releaseContext = nullptr);
/** Wraps a GPU-backed buffer into SkSurface. Caller must ensure backendRenderTarget
is valid for the lifetime of returned SkSurface.
@@ -214,27 +227,32 @@
If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.
- @param context GPU context
- @param backendRenderTarget GPU intermediate memory buffer
- @param origin one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
- @param colorType one of:
- kUnknown_SkColorType, kAlpha_8_SkColorType,
- kRGB_565_SkColorType,
- kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
- kRGB_888x_SkColorType, kBGRA_8888_SkColorType,
- kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
- kGray_8_SkColorType, kRGBA_F16_SkColorType
- @param colorSpace range of colors
- @param surfaceProps LCD striping orientation and setting for device independent
- fonts; may be nullptr
- @return SkSurface if all parameters are valid; otherwise, nullptr
+ @param context GPU context
+ @param backendRenderTarget GPU intermediate memory buffer
+ @param origin one of:
+ kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+ @param colorType one of:
+ kUnknown_SkColorType, kAlpha_8_SkColorType,
+ kRGB_565_SkColorType,
+ kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
+ kRGB_888x_SkColorType, kBGRA_8888_SkColorType,
+ kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+ kGray_8_SkColorType, kRGBA_F16_SkColorType
+ @param colorSpace range of colors
+ @param surfaceProps LCD striping orientation and setting for device independent
+ fonts; may be nullptr
+ @param renderTargetReleaseProc function called when texture can be released
+ @param releaseContext state passed to textureReleaseProc
+ @return SkSurface if all parameters are valid; otherwise, nullptr
*/
static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext* context,
const GrBackendRenderTarget& backendRenderTarget,
GrSurfaceOrigin origin,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
- const SkSurfaceProps* surfaceProps);
+ const SkSurfaceProps* surfaceProps,
+ TextureReleaseProc textureReleaseProc = nullptr,
+ ReleaseContext releaseContext = nullptr);
/** Wraps a GPU-backed texture into SkSurface. Caller must ensure backendTexture is
valid for the lifetime of returned SkSurface. If sampleCnt greater than zero,
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index e1588ae..7701011 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -886,12 +886,15 @@
GrSurfaceOrigin origin,
int sampleCnt,
sk_sp<SkColorSpace> colorSpace,
- const SkSurfaceProps* props) {
+ const SkSurfaceProps* props,
+ ReleaseProc releaseProc,
+ ReleaseContext releaseCtx) {
ASSERT_SINGLE_OWNER_PRIV
SkASSERT(sampleCnt > 0);
sk_sp<GrTextureProxy> proxy(this->proxyProvider()->wrapRenderableBackendTexture(
- tex, origin, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo));
+ tex, origin, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, releaseProc,
+ releaseCtx));
if (!proxy) {
return nullptr;
}
@@ -904,10 +907,13 @@
const GrBackendRenderTarget& backendRT,
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> colorSpace,
- const SkSurfaceProps* surfaceProps) {
+ const SkSurfaceProps* surfaceProps,
+ ReleaseProc releaseProc,
+ ReleaseContext releaseCtx) {
ASSERT_SINGLE_OWNER_PRIV
- sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendRenderTarget(backendRT, origin);
+ sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendRenderTarget(
+ backendRT, origin, releaseProc, releaseCtx);
if (!proxy) {
return nullptr;
}
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index 02dc7a3..5b36351 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -70,18 +70,26 @@
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> colorSpace);
+ // These match the definitions in SkSurface & GrSurface.h, for whence they came
+ typedef void* ReleaseContext;
+ typedef void (*ReleaseProc)(ReleaseContext);
+
sk_sp<GrRenderTargetContext> makeBackendTextureRenderTargetContext(
const GrBackendTexture& tex,
GrSurfaceOrigin origin,
int sampleCnt,
sk_sp<SkColorSpace> colorSpace,
- const SkSurfaceProps* = nullptr);
+ const SkSurfaceProps* = nullptr,
+ ReleaseProc = nullptr,
+ ReleaseContext = nullptr);
sk_sp<GrRenderTargetContext> makeBackendRenderTargetRenderTargetContext(
const GrBackendRenderTarget&,
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> colorSpace,
- const SkSurfaceProps* = nullptr);
+ const SkSurfaceProps* = nullptr,
+ ReleaseProc = nullptr,
+ ReleaseContext = nullptr);
sk_sp<GrRenderTargetContext> makeBackendTextureAsRenderTargetRenderTargetContext(
const GrBackendTexture& tex,
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index f13cf7c..46f2709 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -475,7 +475,7 @@
if (releaseProc) {
releaseHelper.reset(new GrReleaseProcHelper(releaseProc, releaseCtx));
// This gives the texture a ref on the releaseHelper
- tex->setRelease(releaseHelper);
+ tex->setRelease(std::move(releaseHelper));
}
SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
@@ -487,7 +487,8 @@
sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture(
const GrBackendTexture& backendTex, GrSurfaceOrigin origin, int sampleCnt,
- GrWrapOwnership ownership, GrWrapCacheable cacheable) {
+ GrWrapOwnership ownership, GrWrapCacheable cacheable, ReleaseProc releaseProc,
+ ReleaseContext releaseCtx) {
if (this->isAbandoned()) {
return nullptr;
}
@@ -508,6 +509,13 @@
return nullptr;
}
+ sk_sp<GrReleaseProcHelper> releaseHelper;
+ if (releaseProc) {
+ releaseHelper.reset(new GrReleaseProcHelper(releaseProc, releaseCtx));
+ // This gives the texture a ref on the releaseHelper
+ tex->setRelease(std::move(releaseHelper));
+ }
+
SkASSERT(tex->asRenderTarget()); // A GrTextureRenderTarget
// Make sure we match how we created the proxy with SkBudgeted::kNo
SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
@@ -516,7 +524,8 @@
}
sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendRenderTarget(
- const GrBackendRenderTarget& backendRT, GrSurfaceOrigin origin) {
+ const GrBackendRenderTarget& backendRT, GrSurfaceOrigin origin, ReleaseProc releaseProc,
+ ReleaseContext releaseCtx) {
if (this->isAbandoned()) {
return nullptr;
}
@@ -530,6 +539,14 @@
if (!rt) {
return nullptr;
}
+
+ sk_sp<GrReleaseProcHelper> releaseHelper;
+ if (releaseProc) {
+ releaseHelper.reset(new GrReleaseProcHelper(releaseProc, releaseCtx));
+ // This gives the render target a ref on the releaseHelper
+ rt->setRelease(std::move(releaseHelper));
+ }
+
SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
SkASSERT(!rt->getUniqueKey().isValid());
// Make sure we match how we created the proxy with SkBudgeted::kNo
diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h
index f093416..f7481e5 100644
--- a/src/gpu/GrProxyProvider.h
+++ b/src/gpu/GrProxyProvider.h
@@ -121,12 +121,14 @@
*/
sk_sp<GrTextureProxy> wrapRenderableBackendTexture(const GrBackendTexture&, GrSurfaceOrigin,
int sampleCnt, GrWrapOwnership,
- GrWrapCacheable);
+ GrWrapCacheable, ReleaseProc,
+ ReleaseContext);
/*
* Create a render target proxy that wraps a backend render target
*/
- sk_sp<GrSurfaceProxy> wrapBackendRenderTarget(const GrBackendRenderTarget&, GrSurfaceOrigin);
+ sk_sp<GrSurfaceProxy> wrapBackendRenderTarget(const GrBackendRenderTarget&, GrSurfaceOrigin,
+ ReleaseProc, ReleaseContext);
/*
* Create a render target proxy that wraps a backend texture
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index c51ce9b..272e18b 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -308,7 +308,8 @@
sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
GrSurfaceOrigin origin, int sampleCnt,
SkColorType, sk_sp<SkColorSpace>,
- const SkSurfaceProps*) {
+ const SkSurfaceProps*,
+ TextureReleaseProc, ReleaseContext) {
return nullptr;
}
@@ -317,7 +318,8 @@
GrSurfaceOrigin origin,
SkColorType,
sk_sp<SkColorSpace>,
- const SkSurfaceProps*) {
+ const SkSurfaceProps*,
+ RenderTargetReleaseProc, ReleaseContext) {
return nullptr;
}
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 89959f1..7163f21 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -421,7 +421,9 @@
GrSurfaceOrigin origin, int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
- const SkSurfaceProps* props) {
+ const SkSurfaceProps* props,
+ SkSurface::TextureReleaseProc textureReleaseProc,
+ SkSurface::ReleaseContext releaseContext) {
if (!context) {
return nullptr;
}
@@ -445,7 +447,9 @@
origin,
sampleCnt,
std::move(colorSpace),
- props));
+ props,
+ textureReleaseProc,
+ releaseContext));
if (!rtc) {
return nullptr;
}
@@ -490,7 +494,9 @@
GrSurfaceOrigin origin,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
- const SkSurfaceProps* props) {
+ const SkSurfaceProps* props,
+ SkSurface::RenderTargetReleaseProc relProc,
+ SkSurface::ReleaseContext releaseContext) {
if (!context) {
return nullptr;
}
@@ -509,7 +515,7 @@
sk_sp<GrRenderTargetContext> rtc(
context->priv().makeBackendRenderTargetRenderTargetContext(
- rtCopy, origin, std::move(colorSpace), props));
+ rtCopy, origin, std::move(colorSpace), props, relProc, releaseContext));
if (!rtc) {
return nullptr;
}
diff --git a/tests/ProxyConversionTest.cpp b/tests/ProxyConversionTest.cpp
index 638092d..58ba26b 100644
--- a/tests/ProxyConversionTest.cpp
+++ b/tests/ProxyConversionTest.cpp
@@ -29,7 +29,7 @@
GrSRGBEncoded srgbEncoded;
auto ct = GrPixelConfigToColorTypeAndEncoding(desc.fConfig, &srgbEncoded);
auto backendRT = gpu->createTestingOnlyBackendRenderTarget(desc.fWidth, desc.fHeight, ct);
- return provider->wrapBackendRenderTarget(backendRT, origin);
+ return provider->wrapBackendRenderTarget(backendRT, origin, nullptr, nullptr);
}
void clean_up_wrapped_rt(GrGpu* gpu, sk_sp<GrSurfaceProxy> proxy) {
diff --git a/tests/ProxyTest.cpp b/tests/ProxyTest.cpp
index b638069..87b92ee 100644
--- a/tests/ProxyTest.cpp
+++ b/tests/ProxyTest.cpp
@@ -228,7 +228,8 @@
GrBackendRenderTarget backendRT = gpu->createTestingOnlyBackendRenderTarget(
kWidthHeight, kWidthHeight, SkColorTypeToGrColorType(colorType));
sk_sp<GrSurfaceProxy> sProxy(
- proxyProvider->wrapBackendRenderTarget(backendRT, origin));
+ proxyProvider->wrapBackendRenderTarget(backendRT, origin, nullptr,
+ nullptr));
check_surface(reporter, sProxy.get(), origin, kWidthHeight, kWidthHeight,
backendRT.pixelConfig(), SkBudgeted::kNo);
static constexpr int kExpectedNumSamples = 1;
@@ -258,7 +259,8 @@
kStencilBits, fboInfo);
backendRT.setPixelConfig(config);
sk_sp<GrSurfaceProxy> sProxy(
- proxyProvider->wrapBackendRenderTarget(backendRT, origin));
+ proxyProvider->wrapBackendRenderTarget(backendRT, origin, nullptr,
+ nullptr));
check_surface(reporter, sProxy.get(), origin,
kWidthHeight, kWidthHeight,
backendRT.pixelConfig(), SkBudgeted::kNo);
@@ -300,7 +302,7 @@
sk_sp<GrSurfaceProxy> sProxy = proxyProvider->wrapRenderableBackendTexture(
backendTex, origin, supportedNumSamples, kBorrow_GrWrapOwnership,
- GrWrapCacheable::kNo);
+ GrWrapCacheable::kNo, nullptr, nullptr);
if (!sProxy) {
gpu->deleteTestingOnlyBackendTexture(backendTex);
continue; // This can fail on Mesa
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index 166ac6b..78e068a 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -869,6 +869,76 @@
}
}
+struct ReleaseChecker {
+ ReleaseChecker() : fReleaseCount(0) {}
+ int fReleaseCount;
+ static void Release(void* self) {
+ static_cast<ReleaseChecker*>(self)->fReleaseCount++;
+ }
+};
+
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWrappedWithRelease_Gpu, reporter, ctxInfo) {
+ const int kWidth = 10;
+ const int kHeight = 10;
+ std::unique_ptr<uint32_t[]> pixels(new uint32_t[kWidth * kHeight]);
+
+ GrContext* ctx = ctxInfo.grContext();
+ GrGpu* gpu = ctx->priv().getGpu();
+
+ for (bool useTexture : {false, true}) {
+ GrBackendTexture backendTex;
+ GrBackendRenderTarget backendRT;
+ sk_sp<SkSurface> surface;
+
+ ReleaseChecker releaseChecker;
+ GrSurfaceOrigin texOrigin = kBottomLeft_GrSurfaceOrigin;
+
+ if (useTexture) {
+ backendTex = gpu->createTestingOnlyBackendTexture(
+ pixels.get(), kWidth, kHeight, GrColorType::kRGBA_8888, true, GrMipMapped::kNo);
+ if (!backendTex.isValid()) {
+ continue;
+ }
+
+ surface = SkSurface::MakeFromBackendTexture(ctx, backendTex, texOrigin, 1,
+ kRGBA_8888_SkColorType,
+ nullptr, nullptr,
+ ReleaseChecker::Release,
+ &releaseChecker);
+ } else {
+ backendRT = gpu->createTestingOnlyBackendRenderTarget(kWidth, kHeight,
+ GrColorType::kRGBA_8888);
+ if (!backendRT.isValid()) {
+ continue;
+ }
+ surface = SkSurface::MakeFromBackendRenderTarget(ctx, backendRT, texOrigin,
+ kRGBA_8888_SkColorType,
+ nullptr, nullptr,
+ ReleaseChecker::Release,
+ &releaseChecker);
+ }
+ if (!surface) {
+ ERRORF(reporter, "Failed to create surface");
+ continue;
+ }
+
+ surface->getCanvas()->clear(SK_ColorRED);
+ surface->flush();
+ gpu->testingOnly_flushGpuAndSync();
+
+ // Now exercise the release proc
+ REPORTER_ASSERT(reporter, 0 == releaseChecker.fReleaseCount);
+ surface.reset(nullptr); // force a release of the surface
+ REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
+
+ if (useTexture) {
+ gpu->deleteTestingOnlyBackendTexture(backendTex);
+ } else {
+ gpu->deleteTestingOnlyBackendRenderTarget(backendRT);
+ }
+ }
+}
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceAttachStencil_Gpu, reporter, ctxInfo) {
GrGpu* gpu = ctxInfo.grContext()->priv().getGpu();
diff --git a/tools/gpu/ProxyUtils.cpp b/tools/gpu/ProxyUtils.cpp
index d9f00e6..31b9ddd 100644
--- a/tools/gpu/ProxyUtils.cpp
+++ b/tools/gpu/ProxyUtils.cpp
@@ -33,7 +33,8 @@
// Adopt ownership so our caller doesn't have to worry about deleting the backend texture.
if (isRT) {
proxy = context->priv().proxyProvider()->wrapRenderableBackendTexture(
- backendTex, origin, 1, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo);
+ backendTex, origin, 1, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo, nullptr,
+ nullptr);
} else {
proxy = context->priv().proxyProvider()->wrapBackendTexture(
backendTex, origin, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType);