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>
This commit is contained in:
Greg Daniel 2019-02-05 10:08:43 -05:00 committed by Skia Commit-Bot
parent 09a66aca2e
commit 8ce7991242
11 changed files with 184 additions and 52 deletions

View File

@ -167,6 +167,15 @@ public:
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 @@ public:
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 @@ public:
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,

View File

@ -886,12 +886,15 @@ sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContex
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 @@ sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetC
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;
}

View File

@ -70,18 +70,26 @@ public:
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,

View File

@ -475,7 +475,7 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapBackendTexture(const GrBackendTexture
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::wrapBackendTexture(const GrBackendTexture
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 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture(
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<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture(
}
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 @@ sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendRenderTarget(
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

View File

@ -121,12 +121,14 @@ public:
*/
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

View File

@ -308,7 +308,8 @@ sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, const SkSurfaceCharacte
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 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
GrSurfaceOrigin origin,
SkColorType,
sk_sp<SkColorSpace>,
const SkSurfaceProps*) {
const SkSurfaceProps*,
RenderTargetReleaseProc, ReleaseContext) {
return nullptr;
}

View File

@ -421,7 +421,9 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrB
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 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrB
origin,
sampleCnt,
std::move(colorSpace),
props));
props,
textureReleaseProc,
releaseContext));
if (!rtc) {
return nullptr;
}
@ -490,7 +494,9 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext* context,
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<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext* context,
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;
}

View File

@ -29,7 +29,7 @@ static sk_sp<GrSurfaceProxy> make_wrapped_rt(GrProxyProvider* provider,
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) {

View File

@ -228,7 +228,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
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 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
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 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
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

View File

@ -869,6 +869,76 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacePartialDraw_Gpu, reporter, ctxInfo) {
}
}
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();

View File

@ -33,7 +33,8 @@ sk_sp<GrTextureProxy> MakeTextureProxyFromData(GrContext* context, bool isRT, in
// 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);