Remove color type from promise image proxy callback.

The color type used to influence the GrPixelConfig and the swizzles
used with the proxy and its GrTextures. So we had to create a new proxy
if the same API texture was used to fulfill a promise image of a
different color type. That has all been removed or lifted out of proxies
and into views. So now it is fine to reuse the same proxy/GrTexture with
a different color type.

Also remove unit test that checked required a new GrTexture be made if
a different color type was used.

Bug: skia:10078

Change-Id: Ib74c419b5d54d382ea95720af7026640e35013f0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/281056
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2020-04-01 16:52:37 -04:00 committed by Skia Commit-Bot
parent 27801a82e4
commit c3ce54a8a7
5 changed files with 9 additions and 105 deletions

View File

@ -508,7 +508,7 @@ sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrContext* context,
}
callDone.clear();
auto proxy = MakePromiseImageLazyProxy(context, width, height, grColorType, backendFormat,
auto proxy = MakePromiseImageLazyProxy(context, width, height, backendFormat,
mipMapped, textureFulfillProc, textureReleaseProc,
textureDoneProc, textureContext, version);
if (!proxy) {

View File

@ -355,7 +355,7 @@ bool SkImage_GpuBase::RenderYUVAToRGBA(GrContext* ctx, GrRenderTargetContext* re
}
sk_sp<GrTextureProxy> SkImage_GpuBase::MakePromiseImageLazyProxy(
GrContext* context, int width, int height, GrColorType colorType,
GrContext* context, int width, int height,
GrBackendFormat backendFormat, GrMipMapped mipMapped,
PromiseImageTextureFulfillProc fulfillProc, PromiseImageTextureReleaseProc releaseProc,
PromiseImageTextureDoneProc doneProc, PromiseImageTextureContext textureContext,
@ -363,7 +363,6 @@ sk_sp<GrTextureProxy> SkImage_GpuBase::MakePromiseImageLazyProxy(
SkASSERT(context);
SkASSERT(width > 0 && height > 0);
SkASSERT(doneProc);
SkASSERT(colorType != GrColorType::kUnknown);
if (!fulfillProc || !releaseProc) {
doneProc(textureContext);
@ -398,11 +397,9 @@ sk_sp<GrTextureProxy> SkImage_GpuBase::MakePromiseImageLazyProxy(
PromiseImageTextureReleaseProc releaseProc,
PromiseImageTextureDoneProc doneProc,
PromiseImageTextureContext context,
GrColorType colorType,
PromiseImageApiVersion version)
: fFulfillProc(fulfillProc)
, fReleaseProc(releaseProc)
, fColorType(colorType)
, fVersion(version) {
fDoneCallback = sk_make_sp<GrRefCntedCallback>(doneProc, context);
}
@ -447,7 +444,7 @@ sk_sp<GrTextureProxy> SkImage_GpuBase::MakePromiseImageLazyProxy(
// Fulfill once. So return our cached result.
if (fTexture) {
return {sk_ref_sp(fTexture), kReleaseCallbackOnInstantiation, kKeySyncMode};
} else if (fColorType == GrColorType::kUnknown) {
} else if (fFulfillProcFailed) {
// We've already called fulfill and it failed. Our contract says that we should only
// call each callback once.
return {};
@ -459,8 +456,7 @@ sk_sp<GrTextureProxy> SkImage_GpuBase::MakePromiseImageLazyProxy(
// the return from fulfill was invalid or we fail for some other reason.
auto releaseCallback = sk_make_sp<GrRefCntedCallback>(fReleaseProc, textureContext);
if (!promiseTexture) {
// This records that we have failed.
fColorType = GrColorType::kUnknown;
fFulfillProcFailed = true;
return {};
}
@ -472,9 +468,8 @@ sk_sp<GrTextureProxy> SkImage_GpuBase::MakePromiseImageLazyProxy(
sk_sp<GrTexture> tex;
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key;
GrUniqueKey::Builder builder(&key, kDomain, 2, "promise");
GrUniqueKey::Builder builder(&key, kDomain, 1, "promise");
builder[0] = promiseTexture->uniqueID();
builder[1] = (uint32_t)fColorType;
builder.finish();
// 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
@ -514,9 +509,9 @@ sk_sp<GrTextureProxy> SkImage_GpuBase::MakePromiseImageLazyProxy(
sk_sp<GrRefCntedCallback> fDoneCallback;
GrTexture* fTexture = nullptr;
uint32_t fTextureContextID = SK_InvalidUniqueID;
GrColorType fColorType;
PromiseImageApiVersion fVersion;
} callback(fulfillProc, releaseProc, doneProc, textureContext, colorType, version);
bool fFulfillProcFailed = false;
} callback(fulfillProc, releaseProc, doneProc, textureContext, version);
GrProxyProvider* proxyProvider = context->priv().proxyProvider();

View File

@ -79,7 +79,7 @@ protected:
// proxy along with the TextureFulfillProc and TextureReleaseProc. PromiseDoneProc must not
// be null.
static sk_sp<GrTextureProxy> MakePromiseImageLazyProxy(
GrContext*, int width, int height, GrColorType, GrBackendFormat, GrMipMapped,
GrContext*, int width, int height, GrBackendFormat, GrMipMapped,
PromiseImageTextureFulfillProc, PromiseImageTextureReleaseProc,
PromiseImageTextureDoneProc, PromiseImageTextureContext, PromiseImageApiVersion);

View File

@ -381,7 +381,7 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(
}
auto proxy = MakePromiseImageLazyProxy(
context, yuvaSizes[texIdx].width(), yuvaSizes[texIdx].height(), colorType,
context, yuvaSizes[texIdx].width(), yuvaSizes[texIdx].height(),
yuvaFormats[texIdx], GrMipMapped::kNo, textureFulfillProc, textureReleaseProc,
promiseDoneProc, textureContexts[texIdx], version);
++proxiesCreated;

View File

@ -232,97 +232,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTest, reporter, ctxInfo) {
ctx->deleteBackendTexture(backendTex);
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureReuseDifferentConfig, reporter, ctxInfo) {
// Try making two promise SkImages backed by the same texture but with different uses/views.
// This will only be testable on backends where a single texture format (8bit red unorm) can
// be used for both alpha and gray image color types.
const int kWidth = 10;
const int kHeight = 10;
GrContext* ctx = ctxInfo.grContext();
GrGpu* gpu = ctx->priv().getGpu();
GrBackendFormat gray8Format = ctx->defaultBackendFormat(kGray_8_SkColorType,
GrRenderable::kNo);
GrBackendFormat alpha8Format = ctx->defaultBackendFormat(kAlpha_8_SkColorType,
GrRenderable::kNo);
if (gray8Format != alpha8Format) {
// kGray_8 and kAlpha_8 won't share the same backend texture
return;
}
GrBackendTexture grayBackendTex = ctx->createBackendTexture(
kWidth, kHeight, gray8Format,
SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
REPORTER_ASSERT(reporter, grayBackendTex.isValid());
SkImageInfo info =
SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
SkCanvas* canvas = surface->getCanvas();
PromiseTextureChecker promiseChecker(grayBackendTex, reporter, true);
sk_sp<SkImage> alphaImg(SkImage_Gpu::MakePromiseTexture(
ctx, alpha8Format, kWidth, kHeight, GrMipMapped::kNo,
kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
PromiseTextureChecker::Done, &promiseChecker,
SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
REPORTER_ASSERT(reporter, alphaImg);
sk_sp<SkImage> grayImg(SkImage_Gpu::MakePromiseTexture(
ctx, gray8Format, kWidth, kHeight, GrMipMapped::kNo,
kBottomLeft_GrSurfaceOrigin, kGray_8_SkColorType, kOpaque_SkAlphaType, nullptr,
PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
PromiseTextureChecker::Done, &promiseChecker,
SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
REPORTER_ASSERT(reporter, grayImg);
canvas->drawImage(alphaImg, 0, 0);
canvas->drawImage(grayImg, 1, 1);
surface->flush();
gpu->testingOnly_flushGpuAndSync();
check_only_fulfilled(reporter, promiseChecker, 2);
// Because they use different backend formats, each image should have created a different
// GrTexture and they both should still be cached.
ctx->priv().getResourceCache()->purgeAsNeeded();
auto keys = promiseChecker.uniqueKeys();
REPORTER_ASSERT(reporter, keys.count() == 2);
for (const auto& key : keys) {
auto surf = ctx->priv().resourceProvider()->findByUniqueKey<GrSurface>(key);
REPORTER_ASSERT(reporter, surf && surf->asTexture());
if (surf && surf->asTexture()) {
GrTexture* texture = surf->asTexture();
// The backend texture should be shared between the two uses
REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(
grayBackendTex, texture->getBackendTexture()));
}
}
// Invalidate the backing texture, this should invalidate the keys.
promiseChecker.releaseTexture();
ctx->priv().getResourceCache()->purgeAsNeeded();
for (const auto& key : keys) {
auto surf = ctx->priv().resourceProvider()->findByUniqueKey<GrSurface>(key);
REPORTER_ASSERT(reporter, !surf);
}
alphaImg.reset();
ctx->flush(); // We do this to pick up any unref messages that are sent by unref'ing the image.
check_fulfill_and_release_cnts(reporter, promiseChecker, 2,
ReleaseBalanceExpectation::kUnbalancedByOne,
DoneBalanceExpectation::kUnbalancedByOne);
grayImg.reset();
ctx->flush(); // We do this to pick up any unref messages that are sent by unref'ing the image.
check_all_done(reporter, promiseChecker, 2);
ctx->deleteBackendTexture(grayBackendTex);
}
DEF_GPUTEST(PromiseImageTextureShutdown, reporter, ctxInfo) {
const int kWidth = 10;
const int kHeight = 10;