From 49fdd7ad1875f0a26317921367f6e21a60493ca8 Mon Sep 17 00:00:00 2001 From: Jim Van Verth Date: Wed, 3 Oct 2018 10:47:05 -0400 Subject: [PATCH] Bundle shared SkImage_Gpu methods. Also adds an enum to make YUV index more explicit. Bug: skia:7903 Change-Id: I21ae4cac126275fa7fd257235910fd3be155d293 Reviewed-on: https://skia-review.googlesource.com/c/159160 Commit-Queue: Jim Van Verth Reviewed-by: Brian Salomon Reviewed-by: Robert Phillips --- gn/gpu.gni | 2 + src/core/SkImagePriv.h | 8 ++++ src/image/SkImage_Gpu.cpp | 69 ++++++-------------------- src/image/SkImage_Gpu.h | 6 ++- src/image/SkImage_GpuShared.cpp | 79 ++++++++++++++++++++++++++++++ src/image/SkImage_GpuShared.h | 37 ++++++++++++++ src/image/SkImage_GpuYUVA.cpp | 85 ++++++++------------------------- src/image/SkImage_GpuYUVA.h | 5 +- 8 files changed, 169 insertions(+), 122 deletions(-) create mode 100644 src/image/SkImage_GpuShared.cpp create mode 100644 src/image/SkImage_GpuShared.h diff --git a/gn/gpu.gni b/gn/gpu.gni index d42cad9681..5b6311afa7 100644 --- a/gn/gpu.gni +++ b/gn/gpu.gni @@ -542,6 +542,8 @@ skia_gpu_sources = [ "$_src/image/SkImage_Gpu.h", "$_src/image/SkImage_Gpu.cpp", + "$_src/image/SkImage_GpuShared.h", + "$_src/image/SkImage_GpuShared.cpp", "$_src/image/SkImage_GpuYUVA.h", "$_src/image/SkImage_GpuYUVA.cpp", "$_src/image/SkSurface_Gpu.h", diff --git a/src/core/SkImagePriv.h b/src/core/SkImagePriv.h index 1c104b531c..4a89bd9a1e 100644 --- a/src/core/SkImagePriv.h +++ b/src/core/SkImagePriv.h @@ -116,6 +116,14 @@ enum SkImageSourceChannel { to read from. */ struct SK_API SkYUVAIndex { + // Index in the array of SkYUVAIndex + enum Index { + kY_Index = 0, + kU_Index = 1, + kV_Index = 2, + kA_Index = 3 + }; + /** The index is a number between -1..3 which definies which image source to read from, where -1 * means the image source doesn't exist. The assumption is we will always have image sources for * each of YUV planes, but optionally have image source for A plane. */ diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index ad0a150455..aa70299a9c 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -37,6 +37,7 @@ #include "SkGr.h" #include "SkImageInfoPriv.h" #include "SkImage_Gpu.h" +#include "SkImage_GpuShared.h" #include "SkMipMap.h" #include "SkPixelRef.h" #include "SkReadPixelsRec.h" @@ -44,6 +45,8 @@ #include "effects/GrYUVtoRGBEffect.h" #include "gl/GrGLTexture.h" +using namespace SkImage_GpuShared; + SkImage_Gpu::SkImage_Gpu(sk_sp context, uint32_t uniqueID, SkAlphaType at, sk_sp proxy, sk_sp colorSpace, SkBudgeted budgeted) @@ -121,14 +124,8 @@ sk_sp SkImage_Gpu::asTextureProxyRef(GrContext* context, SkColorSpace* dstColorSpace, sk_sp* texColorSpace, SkScalar scaleAdjust[2]) const { - if (context->uniqueID() != fContext->uniqueID()) { - SkASSERT(0); - return nullptr; - } - - GrTextureAdjuster adjuster(fContext.get(), fProxy, this->alphaType(), this->uniqueID(), - this->fColorSpace.get()); - return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, scaleAdjust); + return AsTextureProxyRef(context, params, dstColorSpace, texColorSpace, scaleAdjust, + fContext.get(), this, fAlphaType, fColorSpace.get()); } static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) { @@ -246,28 +243,6 @@ bool SkImage_Gpu::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size return true; } -sk_sp SkImage_Gpu::onMakeSubset(const SkIRect& subset) const { - GrSurfaceDesc desc; - desc.fWidth = subset.width(); - desc.fHeight = subset.height(); - desc.fConfig = fProxy->config(); - - sk_sp sContext(fContext->contextPriv().makeDeferredSurfaceContext( - desc, fProxy->origin(), GrMipMapped::kNo, SkBackingFit::kExact, fBudgeted)); - if (!sContext) { - return nullptr; - } - - if (!sContext->copy(fProxy.get(), subset, SkIPoint::Make(0, 0))) { - return nullptr; - } - - // MDB: this call is okay bc we know 'sContext' was kExact - return sk_make_sp(fContext, kNeedNewImageUniqueID, - fAlphaType, sContext->asTextureProxyRef(), - fColorSpace, fBudgeted); -} - /////////////////////////////////////////////////////////////////////////////////////////////////// static sk_sp new_wrapped_texture_common(GrContext* ctx, @@ -291,22 +266,6 @@ static sk_sp new_wrapped_texture_common(GrContext* ctx, std::move(colorSpace), SkBudgeted::kNo); } -static bool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex, - GrPixelConfig* config, SkColorType ct, SkAlphaType at, - sk_sp cs) { - if (!tex.isValid()) { - return false; - } - // TODO: Create a SkImageColorInfo struct for color, alpha, and color space so we don't need to - // create a fake image info here. - SkImageInfo info = SkImageInfo::Make(1, 1, ct, at, cs); - if (!SkImageInfoIsValid(info)) { - return false; - } - - return ctx->contextPriv().caps()->validateBackendTexture(tex, ct, config); -} - sk_sp SkImage::MakeFromTexture(GrContext* ctx, const GrBackendTexture& tex, GrSurfaceOrigin origin, SkColorType ct, SkAlphaType at, sk_sp cs, @@ -315,7 +274,7 @@ sk_sp SkImage::MakeFromTexture(GrContext* ctx, return nullptr; } GrBackendTexture texCopy = tex; - if (!validate_backend_texture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) { + if (!ValidateBackendTexture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) { return nullptr; } return new_wrapped_texture_common(ctx, texCopy, origin, at, std::move(cs), @@ -331,7 +290,7 @@ sk_sp SkImage::MakeFromAdoptedTexture(GrContext* ctx, return nullptr; } GrBackendTexture texCopy = tex; - if (!validate_backend_texture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) { + if (!ValidateBackendTexture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) { return nullptr; } return new_wrapped_texture_common(ctx, texCopy, origin, at, std::move(cs), @@ -371,8 +330,8 @@ sk_sp SkImage_Gpu::ConvertYUVATexturesToRGB( yuvaTexturesCopy[yuvaIndex.fIndex] = yuvaTextures[yuvaIndex.fIndex]; // TODO: Instead of using assumption about whether it is NV12 format to guess colorType, // actually use channel information here. - if (!validate_backend_texture(ctx, yuvaTexturesCopy[i], &yuvaTexturesCopy[i].fConfig, - ct, kPremul_SkAlphaType, nullptr)) { + if (!ValidateBackendTexture(ctx, yuvaTexturesCopy[i], &yuvaTexturesCopy[i].fConfig, + ct, kPremul_SkAlphaType, nullptr)) { return nullptr; } } @@ -469,8 +428,8 @@ sk_sp SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackendImpl( sk_sp imageColorSpace) { GrBackendTexture backendTextureCopy = backendTexture; - if (!validate_backend_texture(ctx, backendTextureCopy, &backendTextureCopy.fConfig, kRGBA_8888_SkColorType, - kPremul_SkAlphaType, nullptr)) { + if (!ValidateBackendTexture(ctx, backendTextureCopy, &backendTextureCopy.fConfig, + kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr)) { return nullptr; } @@ -864,7 +823,7 @@ sk_sp SkImage_Gpu::MakePromiseYUVATexture(GrContext* context, bool slotUsed[4] = { false, false, false, false }; for (int i = 0; i < 4; ++i) { if (yuvaIndices[i].fIndex < 0) { - SkASSERT(3 == i); // We had better have YUV channels + SkASSERT(SkYUVAIndex::kA_Index == i); // We had better have YUV channels continue; } @@ -903,7 +862,7 @@ sk_sp SkImage_Gpu::MakePromiseYUVATexture(GrContext* context, desc.fWidth = imageWidth; desc.fHeight = imageHeight; // Hack since we're just returning the Y-plane - desc.fConfig = params.fConfigs[params.fLocalIndices[0].fIndex]; + desc.fConfig = params.fConfigs[params.fLocalIndices[SkYUVAIndex::kY_Index].fIndex]; desc.fSampleCnt = 1; @@ -936,7 +895,7 @@ sk_sp SkImage_Gpu::MakePromiseYUVATexture(GrContext* context, // For the time being, simply return the Y-plane. The reason for this is that // this lazy proxy is instantiated at flush time, after the sort, therefore // we cannot be introducing a new opList (in order to render the YUV texture). - int yIndex = params.fLocalIndices[0].fIndex; + int yIndex = params.fLocalIndices[SkYUVAIndex::kY_Index].fIndex; return params.fPromiseHelpers[yIndex].getTexture(resourceProvider, params.fConfigs[yIndex]); #else diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h index 32928b0cef..87892c40c7 100644 --- a/src/image/SkImage_Gpu.h +++ b/src/image/SkImage_Gpu.h @@ -14,6 +14,7 @@ #include "SkGr.h" #include "SkImagePriv.h" #include "SkImage_Base.h" +#include "SkImage_GpuShared.h" class GrTexture; @@ -28,7 +29,10 @@ public: SkImageInfo onImageInfo() const override; bool getROPixels(SkBitmap*, SkColorSpace* dstColorSpace, CachingHint) const override; - sk_sp onMakeSubset(const SkIRect&) const override; + sk_sp onMakeSubset(const SkIRect& subset) const override { + return SkImage_GpuShared::OnMakeSubset(subset, fContext, this, fAlphaType, fColorSpace, + fBudgeted); + } GrContext* context() const override { return fContext.get(); } GrTextureProxy* peekProxy() const override { diff --git a/src/image/SkImage_GpuShared.cpp b/src/image/SkImage_GpuShared.cpp new file mode 100644 index 0000000000..71a9964814 --- /dev/null +++ b/src/image/SkImage_GpuShared.cpp @@ -0,0 +1,79 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrBackendSurface.h" +#include "GrContext.h" +#include "GrContextPriv.h" +#include "GrTextureAdjuster.h" +#include "SkImage_Gpu.h" +#include "SkImage_GpuShared.h" + +namespace SkImage_GpuShared { + +bool ValidateBackendTexture(GrContext* ctx, const GrBackendTexture& tex, + GrPixelConfig* config, SkColorType ct, SkAlphaType at, + sk_sp cs) { + if (!tex.isValid()) { + return false; + } + // TODO: Create a SkImageColorInfo struct for color, alpha, and color space so we don't need to + // create a fake image info here. + SkImageInfo info = SkImageInfo::Make(1, 1, ct, at, cs); + if (!SkImageInfoIsValid(info)) { + return false; + } + + return ctx->contextPriv().caps()->validateBackendTexture(tex, ct, config); +} + +sk_sp AsTextureProxyRef(GrContext* context, + const GrSamplerState& params, + SkColorSpace* dstColorSpace, + sk_sp* texColorSpace, + SkScalar scaleAdjust[2], + GrContext* imageContext, + const SkImage_Base* image, + const SkAlphaType imageAlphaType, + SkColorSpace* imageColorSpace) { + if (context->uniqueID() != imageContext->uniqueID()) { + SkASSERT(0); + return nullptr; + } + + GrTextureAdjuster adjuster(imageContext, image->asTextureProxyRef(), imageAlphaType, + image->uniqueID(), imageColorSpace); + return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, scaleAdjust); +} + +sk_sp OnMakeSubset(const SkIRect& subset, sk_sp imageContext, + const SkImage_Base* image, const SkAlphaType imageAlphaType, + sk_sp imageColorSpace, const SkBudgeted budgeted){ + sk_sp proxy = image->asTextureProxyRef(); + + GrSurfaceDesc desc; + desc.fWidth = subset.width(); + desc.fHeight = subset.height(); + desc.fConfig = proxy->config(); + + sk_sp sContext(imageContext->contextPriv().makeDeferredSurfaceContext( + desc, proxy->origin(), GrMipMapped::kNo, SkBackingFit::kExact, budgeted)); + if (!sContext) { + return nullptr; + } + + if (!sContext->copy(proxy.get(), subset, SkIPoint::Make(0, 0))) { + return nullptr; + } + + // MDB: this call is okay bc we know 'sContext' was kExact + return sk_make_sp(imageContext, kNeedNewImageUniqueID, + imageAlphaType, sContext->asTextureProxyRef(), + imageColorSpace, budgeted); +} + + +} diff --git a/src/image/SkImage_GpuShared.h b/src/image/SkImage_GpuShared.h new file mode 100644 index 0000000000..ad171e6ee8 --- /dev/null +++ b/src/image/SkImage_GpuShared.h @@ -0,0 +1,37 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkImage_GpuShared_DEFINED +#define SkImage_GpuShared_DEFINED + +#include "SkImageInfo.h" +#include "SkTypes.h" + +class GrContext; +class SkImage_Base; + +namespace SkImage_GpuShared { + +bool ValidateBackendTexture(GrContext* ctx, const GrBackendTexture& tex, + GrPixelConfig* config, SkColorType ct, SkAlphaType at, + sk_sp cs); + +sk_sp AsTextureProxyRef(GrContext* context, + const GrSamplerState& params, + SkColorSpace* dstColorSpace, + sk_sp* texColorSpace, + SkScalar scaleAdjust[2], + GrContext* imageContext, + const SkImage_Base* image, + const SkAlphaType imageAlphaType, + SkColorSpace* imageColorSpace); + +sk_sp OnMakeSubset(const SkIRect& subset, sk_sp imageContext, + const SkImage_Base* image, const SkAlphaType imageAlphaType, + sk_sp imageColorSpace, const SkBudgeted budgeted); +} +#endif diff --git a/src/image/SkImage_GpuYUVA.cpp b/src/image/SkImage_GpuYUVA.cpp index a89d54b69d..6eb60f43c4 100644 --- a/src/image/SkImage_GpuYUVA.cpp +++ b/src/image/SkImage_GpuYUVA.cpp @@ -16,10 +16,13 @@ #include "GrTexture.h" #include "GrTextureAdjuster.h" #include "SkImage_Gpu.h" +#include "SkImage_GpuShared.h" #include "SkImage_GpuYUVA.h" #include "SkReadPixelsRec.h" #include "effects/GrYUVtoRGBEffect.h" +using namespace SkImage_GpuShared; + SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp context, uint32_t uniqueID, SkYUVColorSpace colorSpace, sk_sp proxies[], SkYUVAIndex yuvaIndices[4], SkISize size, GrSurfaceOrigin origin, @@ -37,7 +40,7 @@ SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp context, uint32_t uniqueID, memcpy(fYUVAIndices, yuvaIndices, 4*sizeof(SkYUVAIndex)); // If an alpha channel is present we always switch to kPremul. This is because, although the // planar data is always un-premul, the final interleaved RGB image is/would-be premul. - if (-1 != yuvaIndices[3].fIndex) { + if (-1 != yuvaIndices[SkYUVAIndex::kA_Index].fIndex) { fImageAlphaType = kPremul_SkAlphaType; } } @@ -50,32 +53,13 @@ SkImageInfo SkImage_GpuYUVA::onImageInfo() const { fImageAlphaType, fImageColorSpace); } -////////////////////////////////////////////////////////////////////////////////////////////////// -// need shared defs with SkImage_Gpu - -static bool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex, - GrPixelConfig* config, SkColorType ct, SkAlphaType at, - sk_sp cs) { - if (!tex.isValid()) { - return false; - } - // TODO: Create a SkImageColorInfo struct for color, alpha, and color space so we don't need to - // create a fake image info here. - SkImageInfo info = SkImageInfo::Make(1, 1, ct, at, cs); - if (!SkImageInfoIsValid(info)) { - return false; - } - - return ctx->contextPriv().caps()->validateBackendTexture(tex, ct, config); -} - ////////////////////////////////////////////////////////////////////////////////////////////////// sk_sp SkImage_GpuYUVA::asTextureProxyRef() const { if (!fRGBProxy) { - sk_sp yProxy = fProxies[fYUVAIndices[0].fIndex]; - sk_sp uProxy = fProxies[fYUVAIndices[1].fIndex]; - sk_sp vProxy = fProxies[fYUVAIndices[2].fIndex]; + sk_sp yProxy = fProxies[fYUVAIndices[SkYUVAIndex::kY_Index].fIndex]; + sk_sp uProxy = fProxies[fYUVAIndices[SkYUVAIndex::kU_Index].fIndex]; + sk_sp vProxy = fProxies[fYUVAIndices[SkYUVAIndex::kV_Index].fIndex]; if (!yProxy || !uProxy || !vProxy) { return nullptr; @@ -85,7 +69,8 @@ sk_sp SkImage_GpuYUVA::asTextureProxyRef() const { paint.setPorterDuffXPFactory(SkBlendMode::kSrc); // TODO: Modify the fragment processor to sample from different channel // instead of taking nv12 bool. - bool nv12 = (fYUVAIndices[1].fIndex == fYUVAIndices[2].fIndex); + bool nv12 = (fYUVAIndices[SkYUVAIndex::kU_Index].fIndex == + fYUVAIndices[SkYUVAIndex::kV_Index].fIndex); // TODO: modify the YUVtoRGBEffect to do premul if fImageAlphaType is kPremul_AlphaType paint.addColorFragmentProcessor(GrYUVtoRGBEffect::Make(std::move(yProxy), std::move(uProxy), std::move(vProxy), fColorSpace, @@ -122,14 +107,8 @@ sk_sp SkImage_GpuYUVA::asTextureProxyRef(GrContext* context, SkColorSpace* dstColorSpace, sk_sp* texColorSpace, SkScalar scaleAdjust[2]) const { - if (context->uniqueID() != fContext->uniqueID()) { - SkASSERT(0); - return nullptr; - } - - GrTextureAdjuster adjuster(fContext.get(), this->asTextureProxyRef(), this->alphaType(), - this->uniqueID(), this->fImageColorSpace.get()); - return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, scaleAdjust); + return AsTextureProxyRef(context, params, dstColorSpace, texColorSpace, scaleAdjust, + fContext.get(), this, fImageAlphaType, fImageColorSpace.get()); } bool SkImage_GpuYUVA::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, @@ -172,32 +151,6 @@ bool SkImage_GpuYUVA::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, return true; } -sk_sp SkImage_GpuYUVA::onMakeSubset(const SkIRect& subset) const { - // Flatten the YUVA planes to a single texture - sk_sp proxy = this->asTextureProxyRef(); - - GrSurfaceDesc desc; - desc.fWidth = subset.width(); - desc.fHeight = subset.height(); - desc.fConfig = proxy->config(); - - sk_sp sContext(fContext->contextPriv().makeDeferredSurfaceContext( - desc, proxy->origin(), GrMipMapped::kNo, SkBackingFit::kExact, fBudgeted)); - if (!sContext) { - return nullptr; - } - - if (!sContext->copy(proxy.get(), subset, SkIPoint::Make(0, 0))) { - return nullptr; - } - - // MDB: this call is okay bc we know 'sContext' was kExact - return sk_make_sp(fContext, kNeedNewImageUniqueID, - fImageAlphaType, sContext->asTextureProxyRef(), - fImageColorSpace, fBudgeted); -} - - ////////////////////////////////////////////////////////////////////////////////////////////////// //*** bundle this into a helper function used by this and SkImage_Gpu? @@ -212,7 +165,8 @@ sk_sp SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx, // Right now this still only deals with YUV and NV12 formats. Assuming that YUV has different // textures for U and V planes, while NV12 uses same texture for U and V planes. - bool nv12 = (yuvaIndices[1].fIndex == yuvaIndices[2].fIndex); + bool nv12 = (yuvaIndices[SkYUVAIndex::kU_Index].fIndex == + yuvaIndices[SkYUVAIndex::kV_Index].fIndex); auto ct = nv12 ? kRGBA_8888_SkColorType : kAlpha_8_SkColorType; // We need to make a copy of the input backend textures because we need to preserve the result @@ -221,7 +175,7 @@ sk_sp SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx, for (int i = 0; i < 4; ++i) { // Validate that the yuvaIndices refer to valid backend textures. const SkYUVAIndex& yuvaIndex = yuvaIndices[i]; - if (3 == i && yuvaIndex.fIndex == -1) { + if (SkYUVAIndex::kA_Index == i && yuvaIndex.fIndex == -1) { // Meaning the A plane isn't passed in. continue; } @@ -234,8 +188,8 @@ sk_sp SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx, yuvaTexturesCopy[yuvaIndex.fIndex] = yuvaTextures[yuvaIndex.fIndex]; // TODO: Instead of using assumption about whether it is NV12 format to guess colorType, // actually use channel information here. - if (!validate_backend_texture(ctx, yuvaTexturesCopy[i], &yuvaTexturesCopy[i].fConfig, - ct, kUnpremul_SkAlphaType, nullptr)) { + if (!ValidateBackendTexture(ctx, yuvaTexturesCopy[i], &yuvaTexturesCopy[i].fConfig, + ct, kUnpremul_SkAlphaType, nullptr)) { return nullptr; } } @@ -251,7 +205,7 @@ sk_sp SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx, // Safely ignore since this means we are missing the A plane. if (textureIndex == -1) { - SkASSERT(3 == i); + SkASSERT(SkYUVAIndex::kA_Index == i); continue; } @@ -261,8 +215,9 @@ sk_sp SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx, proxyProvider->wrapBackendTexture(yuvaTexturesCopy[textureIndex], origin); } } - if (!tempTextureProxies[yuvaIndices[0].fIndex] || !tempTextureProxies[yuvaIndices[1].fIndex] || - !tempTextureProxies[yuvaIndices[2].fIndex]) { + if (!tempTextureProxies[yuvaIndices[SkYUVAIndex::kY_Index].fIndex] || + !tempTextureProxies[yuvaIndices[SkYUVAIndex::kU_Index].fIndex] || + !tempTextureProxies[yuvaIndices[SkYUVAIndex::kV_Index].fIndex]) { return nullptr; } diff --git a/src/image/SkImage_GpuYUVA.h b/src/image/SkImage_GpuYUVA.h index 8f9ebfde06..92917832d5 100644 --- a/src/image/SkImage_GpuYUVA.h +++ b/src/image/SkImage_GpuYUVA.h @@ -32,7 +32,10 @@ public: bool getROPixels(SkBitmap*, SkColorSpace* dstColorSpace, CachingHint) const override { return false; } - sk_sp onMakeSubset(const SkIRect&) const override; + sk_sp onMakeSubset(const SkIRect& subset) const override { + return SkImage_GpuShared::OnMakeSubset(subset, fContext, this, fImageAlphaType, + fImageColorSpace, fBudgeted); + } GrContext* context() const override { return fContext.get(); } GrTextureProxy* peekProxy() const override { return nullptr; }