aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Brian Osman <brianosman@google.com>2018-06-18 10:58:51 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-18 16:25:48 +0000
commit47c275133be674f498fc03db555adfac49b12644 (patch)
tree2f7cecaf683cbe57a1a37c212b44f215e73a6239
parent4da70190aadd8a346ea967a3c435d20a80a5cccd (diff)
Remove GrNonlinearColorSpaceXformEffect
Convert all uses to GrColorSpaceXformEffect Change-Id: Icc9d093a00450001c1b915db7a8676c9c66073b1 Reviewed-on: https://skia-review.googlesource.com/132090 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com> Commit-Queue: Mike Klein <mtklein@google.com>
-rw-r--r--gn/gpu.gni2
-rw-r--r--src/effects/SkToSRGBColorFilter.cpp5
-rw-r--r--src/gpu/GrProcessor.cpp2
-rw-r--r--src/gpu/GrProcessor.h1
-rw-r--r--src/gpu/GrYUVProvider.cpp4
-rw-r--r--src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp259
-rw-r--r--src/gpu/effects/GrNonlinearColorSpaceXformEffect.h75
-rw-r--r--src/image/SkImage_Gpu.cpp4
8 files changed, 7 insertions, 345 deletions
diff --git a/gn/gpu.gni b/gn/gpu.gni
index c06522b466..bf448ced0a 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -377,8 +377,6 @@ skia_gpu_sources = [
"$_src/gpu/effects/GrMagnifierEffect.h",
"$_src/gpu/effects/GrMatrixConvolutionEffect.cpp",
"$_src/gpu/effects/GrMatrixConvolutionEffect.h",
- "$_src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp",
- "$_src/gpu/effects/GrNonlinearColorSpaceXformEffect.h",
"$_src/gpu/effects/GrOverdrawFragmentProcessor.cpp",
"$_src/gpu/effects/GrOverdrawFragmentProcessor.h",
"$_src/gpu/effects/GrOvalEffect.cpp",
diff --git a/src/effects/SkToSRGBColorFilter.cpp b/src/effects/SkToSRGBColorFilter.cpp
index 5831bf0b1a..a9bd65c625 100644
--- a/src/effects/SkToSRGBColorFilter.cpp
+++ b/src/effects/SkToSRGBColorFilter.cpp
@@ -13,7 +13,7 @@
#include "SkWriteBuffer.h"
#if SK_SUPPORT_GPU
- #include "effects/GrNonlinearColorSpaceXformEffect.h"
+ #include "GrColorSpaceXform.h"
#endif
void SkToSRGBColorFilter::onAppendStages(SkRasterPipeline* p,
@@ -73,7 +73,6 @@ void SkToSRGBColorFilter::flatten(SkWriteBuffer& buffer) const {
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> SkToSRGBColorFilter::asFragmentProcessor(
GrContext*, const GrColorSpaceInfo&) const {
- return GrNonlinearColorSpaceXformEffect::Make(fSrcColorSpace.get(),
- SkColorSpace::MakeSRGB().get());
+ return GrColorSpaceXformEffect::Make(fSrcColorSpace.get(), SkColorSpace::MakeSRGB().get());
}
#endif
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 561fd4fee8..f2b810252f 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -57,7 +57,7 @@ SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories()
* we verify the count is as expected. If a new factory is added, then these numbers must be
* manually adjusted.
*/
-static const int kFPFactoryCount = 38;
+static const int kFPFactoryCount = 37;
static const int kGPFactoryCount = 14;
static const int kXPFactoryCount = 4;
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index 5d7fbd7a62..f8b336d9fb 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -120,7 +120,6 @@ public:
kGrMatrixConvolutionEffect_ClassID,
kGrMeshTestProcessor_ClassID,
kGrMorphologyEffect_ClassID,
- kGrNonlinearColorSpaceXformEffect_ClassID,
kGrOverdrawFragmentProcessor_ClassID,
kGrPathProcessor_ClassID,
kGrPerlinNoise2Effect_ClassID,
diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp
index 65dd46d71a..f235684f88 100644
--- a/src/gpu/GrYUVProvider.cpp
+++ b/src/gpu/GrYUVProvider.cpp
@@ -7,6 +7,7 @@
#include "GrYUVProvider.h"
#include "GrClip.h"
+#include "GrColorSpaceXform.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrProxyProvider.h"
@@ -17,7 +18,6 @@
#include "SkRefCnt.h"
#include "SkResourceCache.h"
#include "SkYUVPlanesCache.h"
-#include "effects/GrNonlinearColorSpaceXformEffect.h"
#include "effects/GrSRGBEffect.h"
#include "effects/GrYUVtoRGBEffect.h"
@@ -143,7 +143,7 @@ sk_sp<GrTextureProxy> GrYUVProvider::refAsTextureProxy(GrContext* ctx, const GrS
// If the caller expects the pixels in a different color space than the one from the image,
// apply a color conversion to do this.
std::unique_ptr<GrFragmentProcessor> colorConversionProcessor =
- GrNonlinearColorSpaceXformEffect::Make(srcColorSpace, dstColorSpace);
+ GrColorSpaceXformEffect::Make(srcColorSpace, dstColorSpace);
if (colorConversionProcessor) {
paint.addColorFragmentProcessor(std::move(colorConversionProcessor));
}
diff --git a/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp b/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp
deleted file mode 100644
index cec9da3590..0000000000
--- a/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrNonlinearColorSpaceXformEffect.h"
-#include "GrColorSpaceXform.h"
-#include "GrProcessor.h"
-#include "glsl/GrGLSLFragmentProcessor.h"
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-
-class GrGLNonlinearColorSpaceXformEffect : public GrGLSLFragmentProcessor {
-public:
- void emitCode(EmitArgs& args) override {
- const GrNonlinearColorSpaceXformEffect& csxe =
- args.fFp.cast<GrNonlinearColorSpaceXformEffect>();
- GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-
- const char* srcCoeffsName = nullptr;
- if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kSrcTransfer_Op)) {
- fSrcTransferFnUni = uniformHandler->addUniformArray(
- kFragment_GrShaderFlag, kHalf_GrSLType, "SrcTransferFn",
- GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs, &srcCoeffsName);
- }
-
- const char* dstCoeffsName = nullptr;
- if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kDstTransfer_Op)) {
- fDstTransferFnUni = uniformHandler->addUniformArray(
- kFragment_GrShaderFlag, kHalf_GrSLType, "DstTransferFn",
- GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs, &dstCoeffsName);
- }
-
- const char* gamutXformName = nullptr;
- if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kGamutXform_Op)) {
- fGamutXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4x4_GrSLType,
- "GamutXform", &gamutXformName);
- }
-
- // Helper function to apply the src or dst transfer function to a single value
- SkString tfFuncNames[2];
- for (size_t i = 0; i < 2; ++i) {
- const char* coeffsName = i ? dstCoeffsName : srcCoeffsName;
- if (!coeffsName) {
- continue;
- }
- const char* fnName = i ? "dst_transfer_fn" : "src_transfer_fn";
- static const GrShaderVar gTransferFnFuncArgs[] = {
- GrShaderVar("x", kHalf_GrSLType),
- };
- SkString transferFnBody;
- // Temporaries to make evaluation line readable
- transferFnBody.printf("half A = %s[0];", coeffsName);
- transferFnBody.appendf("half B = %s[1];", coeffsName);
- transferFnBody.appendf("half C = %s[2];", coeffsName);
- transferFnBody.appendf("half D = %s[3];", coeffsName);
- transferFnBody.appendf("half E = %s[4];", coeffsName);
- transferFnBody.appendf("half F = %s[5];", coeffsName);
- transferFnBody.appendf("half G = %s[6];", coeffsName);
- transferFnBody.append("half s = sign(x);");
- transferFnBody.append("x = abs(x);");
- transferFnBody.appendf("return s * ((x < D) ? (C * x) + F : pow(A * x + B, G) + E);");
- fragBuilder->emitFunction(kHalf_GrSLType, fnName, SK_ARRAY_COUNT(gTransferFnFuncArgs),
- gTransferFnFuncArgs, transferFnBody.c_str(), &tfFuncNames[i]);
- }
-
- if (nullptr == args.fInputColor) {
- args.fInputColor = "half4(1)";
- }
- fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
-
- // 1: Un-premultiply the input color (if necessary)
- fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
- fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
-
- // 2: Apply src transfer function (to get to linear RGB)
- if (srcCoeffsName) {
- fragBuilder->codeAppendf("color.r = %s(color.r);", tfFuncNames[0].c_str());
- fragBuilder->codeAppendf("color.g = %s(color.g);", tfFuncNames[0].c_str());
- fragBuilder->codeAppendf("color.b = %s(color.b);", tfFuncNames[0].c_str());
- }
-
- // 3: Apply gamut matrix
- if (gamutXformName) {
- fragBuilder->codeAppendf(
- "color.rgb = (%s * half4(color.rgb, 1.0)).rgb;", gamutXformName);
- }
-
- // 4: Apply dst transfer fn
- if (dstCoeffsName) {
- fragBuilder->codeAppendf("color.r = %s(color.r);", tfFuncNames[1].c_str());
- fragBuilder->codeAppendf("color.g = %s(color.g);", tfFuncNames[1].c_str());
- fragBuilder->codeAppendf("color.b = %s(color.b);", tfFuncNames[1].c_str());
- }
-
- // 5: Premultiply again
- fragBuilder->codeAppendf("%s = half4(color.rgb * color.a, color.a);", args.fOutputColor);
- }
-
- static inline void GenKey(const GrProcessor& processor, const GrShaderCaps&,
- GrProcessorKeyBuilder* b) {
- const GrNonlinearColorSpaceXformEffect& csxe =
- processor.cast<GrNonlinearColorSpaceXformEffect>();
- b->add32(csxe.ops());
- }
-
-protected:
- void onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& processor) override {
- const GrNonlinearColorSpaceXformEffect& csxe =
- processor.cast<GrNonlinearColorSpaceXformEffect>();
- if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kSrcTransfer_Op)) {
- pdman.set1fv(fSrcTransferFnUni, GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs,
- csxe.srcTransferFnCoeffs());
- }
- if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kDstTransfer_Op)) {
- pdman.set1fv(fDstTransferFnUni, GrNonlinearColorSpaceXformEffect::kNumTransferFnCoeffs,
- csxe.dstTransferFnCoeffs());
- }
- if (SkToBool(csxe.ops() & GrNonlinearColorSpaceXformEffect::kGamutXform_Op)) {
- pdman.setSkMatrix44(fGamutXformUni, csxe.gamutXform());
- }
- }
-
-private:
- GrGLSLProgramDataManager::UniformHandle fSrcTransferFnUni;
- GrGLSLProgramDataManager::UniformHandle fDstTransferFnUni;
- GrGLSLProgramDataManager::UniformHandle fGamutXformUni;
-
- typedef GrGLSLFragmentProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-GrNonlinearColorSpaceXformEffect::GrNonlinearColorSpaceXformEffect(
- uint32_t ops, const SkColorSpaceTransferFn& srcTransferFn,
- const SkColorSpaceTransferFn& dstTransferFn, const SkMatrix44& gamutXform)
- : INHERITED(kGrNonlinearColorSpaceXformEffect_ClassID,
- kPreservesOpaqueInput_OptimizationFlag)
- , fGamutXform(gamutXform)
- , fOps(ops) {
-
- fSrcTransferFnCoeffs[0] = srcTransferFn.fA;
- fSrcTransferFnCoeffs[1] = srcTransferFn.fB;
- fSrcTransferFnCoeffs[2] = srcTransferFn.fC;
- fSrcTransferFnCoeffs[3] = srcTransferFn.fD;
- fSrcTransferFnCoeffs[4] = srcTransferFn.fE;
- fSrcTransferFnCoeffs[5] = srcTransferFn.fF;
- fSrcTransferFnCoeffs[6] = srcTransferFn.fG;
-
- fDstTransferFnCoeffs[0] = dstTransferFn.fA;
- fDstTransferFnCoeffs[1] = dstTransferFn.fB;
- fDstTransferFnCoeffs[2] = dstTransferFn.fC;
- fDstTransferFnCoeffs[3] = dstTransferFn.fD;
- fDstTransferFnCoeffs[4] = dstTransferFn.fE;
- fDstTransferFnCoeffs[5] = dstTransferFn.fF;
- fDstTransferFnCoeffs[6] = dstTransferFn.fG;
-}
-
-GrNonlinearColorSpaceXformEffect::GrNonlinearColorSpaceXformEffect(
- const GrNonlinearColorSpaceXformEffect& that)
- : INHERITED(kGrNonlinearColorSpaceXformEffect_ClassID,
- kPreservesOpaqueInput_OptimizationFlag)
- , fGamutXform(that.fGamutXform)
- , fOps(that.fOps) {
- memcpy(fSrcTransferFnCoeffs, that.fSrcTransferFnCoeffs, sizeof(fSrcTransferFnCoeffs));
- memcpy(fDstTransferFnCoeffs, that.fDstTransferFnCoeffs, sizeof(fDstTransferFnCoeffs));
-}
-
-std::unique_ptr<GrFragmentProcessor> GrNonlinearColorSpaceXformEffect::clone() const {
- return std::unique_ptr<GrFragmentProcessor>(new GrNonlinearColorSpaceXformEffect(*this));
-}
-
-bool GrNonlinearColorSpaceXformEffect::onIsEqual(const GrFragmentProcessor& s) const {
- const GrNonlinearColorSpaceXformEffect& other = s.cast<GrNonlinearColorSpaceXformEffect>();
- if (other.fOps != fOps) {
- return false;
- }
- if (SkToBool(fOps & kSrcTransfer_Op) &&
- memcmp(&other.fSrcTransferFnCoeffs, &fSrcTransferFnCoeffs, sizeof(fSrcTransferFnCoeffs))) {
- return false;
- }
- if (SkToBool(fOps & kDstTransfer_Op) &&
- memcmp(&other.fDstTransferFnCoeffs, &fDstTransferFnCoeffs, sizeof(fDstTransferFnCoeffs))) {
- return false;
- }
- if (SkToBool(fOps & kGamutXform_Op) && other.fGamutXform != fGamutXform) {
- return false;
- }
- return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrNonlinearColorSpaceXformEffect);
-
-#if GR_TEST_UTILS
-std::unique_ptr<GrFragmentProcessor> GrNonlinearColorSpaceXformEffect::TestCreate(
- GrProcessorTestData* d) {
- // TODO: Generate a random variety of color spaces for this effect (it can handle wacky
- // transfer functions, etc...)
- sk_sp<SkColorSpace> srcSpace = SkColorSpace::MakeSRGBLinear();
- sk_sp<SkColorSpace> dstSpace = SkColorSpace::MakeSRGB();
- return GrNonlinearColorSpaceXformEffect::Make(srcSpace.get(), dstSpace.get());
-}
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GrNonlinearColorSpaceXformEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
- GrProcessorKeyBuilder* b) const {
- GrGLNonlinearColorSpaceXformEffect::GenKey(*this, caps, b);
-}
-
-GrGLSLFragmentProcessor* GrNonlinearColorSpaceXformEffect::onCreateGLSLInstance() const {
- return new GrGLNonlinearColorSpaceXformEffect();
-}
-
-std::unique_ptr<GrFragmentProcessor> GrNonlinearColorSpaceXformEffect::Make(SkColorSpace* src,
- SkColorSpace* dst) {
- if (!src || !dst || SkColorSpace::Equals(src, dst)) {
- // No conversion possible (or necessary)
- return nullptr;
- }
-
- uint32_t ops = 0;
-
- const SkMatrix44* toXYZ = src->toXYZD50();
- const SkMatrix44* fromXYZ = dst->fromXYZD50();
- SkMatrix44 srcToDstMtx(SkMatrix44::kUninitialized_Constructor);
- if (toXYZ && fromXYZ && src->toXYZD50Hash() != dst->toXYZD50Hash()) {
- srcToDstMtx.setConcat(*fromXYZ, *toXYZ);
- ops |= kGamutXform_Op;
- }
-
- SkColorSpaceTransferFn srcTransferFn;
- if (!src->gammaIsLinear()) {
- if (src->isNumericalTransferFn(&srcTransferFn)) {
- ops |= kSrcTransfer_Op;
- } else {
- return nullptr;
- }
- }
-
- SkColorSpaceTransferFn dstTransferFn;
- if (!dst->gammaIsLinear()) {
- if (dst->isNumericalTransferFn(&dstTransferFn)) {
- dstTransferFn = dstTransferFn.invert();
- ops |= kDstTransfer_Op;
- } else {
- return nullptr;
- }
- }
-
- return std::unique_ptr<GrFragmentProcessor>(
- new GrNonlinearColorSpaceXformEffect(ops, srcTransferFn, dstTransferFn, srcToDstMtx));
-}
diff --git a/src/gpu/effects/GrNonlinearColorSpaceXformEffect.h b/src/gpu/effects/GrNonlinearColorSpaceXformEffect.h
deleted file mode 100644
index 6dfb778071..0000000000
--- a/src/gpu/effects/GrNonlinearColorSpaceXformEffect.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrNonlinearColorSpaceXformEffect_DEFINED
-#define GrNonlinearColorSpaceXformEffect_DEFINED
-
-#include "GrFragmentProcessor.h"
-#include "SkColorSpace.h"
-#include "SkMatrix44.h"
-
-/**
- * The output of this effect is the input, transformed into a different color space.
- * This effect is used for nonlinear blending color space support - it does not assume HW sRGB
- * capabilities, and performs both the source and destination transfer functions numerically in
- * the shader. Any parametric transfer function is supported. Because of the nonlinear blending,
- * premultiplication is also nonlinear - source pixels are unpremultiplied before the source
- * transfer function, and then premultiplied after the destination transfer function.
- */
-class GrNonlinearColorSpaceXformEffect : public GrFragmentProcessor {
-public:
- /**
- * The conversion effect is only well defined with a valid source and destination color space.
- * This will return nullptr if either space is nullptr, if both spaces are equal, or if either
- * space has a non-parametric transfer funcion (e.g. lookup table or A2B).
- */
- static std::unique_ptr<GrFragmentProcessor> Make(SkColorSpace* src, SkColorSpace* dst);
-
- const char* name() const override { return "NonlinearColorSpaceXform"; }
-
- std::unique_ptr<GrFragmentProcessor> clone() const override;
-
- static const int kNumTransferFnCoeffs = 7;
-
- /**
- * Flags that specify which operations are performed for one particular conversion.
- * Some color space pairs may not need all operations, if one or both transfer functions
- * is linear, or if the gamuts are the same.
- */
- enum Ops {
- kSrcTransfer_Op = 0x1,
- kGamutXform_Op = 0x2,
- kDstTransfer_Op = 0x4,
- };
-
- uint32_t ops() const { return fOps; }
- const float* srcTransferFnCoeffs() const { return fSrcTransferFnCoeffs; }
- const float* dstTransferFnCoeffs() const { return fDstTransferFnCoeffs; }
- const SkMatrix44& gamutXform() const { return fGamutXform; }
-
-private:
- GrNonlinearColorSpaceXformEffect(uint32_t ops,
- const SkColorSpaceTransferFn& srcTransferFn,
- const SkColorSpaceTransferFn& dstTransferFn,
- const SkMatrix44& gamutXform);
- GrNonlinearColorSpaceXformEffect(const GrNonlinearColorSpaceXformEffect&);
-
- GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
- void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
- bool onIsEqual(const GrFragmentProcessor&) const override;
-
- float fSrcTransferFnCoeffs[kNumTransferFnCoeffs];
- float fDstTransferFnCoeffs[kNumTransferFnCoeffs];
- SkMatrix44 fGamutXform;
- uint32_t fOps;
-
- GR_DECLARE_FRAGMENT_PROCESSOR_TEST
-
- typedef GrFragmentProcessor INHERITED;
-};
-
-#endif
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index faba37383c..b13abe1d45 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -15,6 +15,7 @@
#include "GrAHardwareBufferImageGenerator.h"
#include "GrBitmapTextureMaker.h"
#include "GrCaps.h"
+#include "GrColorSpaceXform.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrGpu.h"
@@ -30,7 +31,6 @@
#include "GrTextureProxy.h"
#include "GrTextureProxyPriv.h"
#include "gl/GrGLDefines.h"
-#include "effects/GrNonlinearColorSpaceXformEffect.h"
#include "effects/GrYUVtoRGBEffect.h"
#include "SkCanvas.h"
#include "SkBitmapCache.h"
@@ -974,7 +974,7 @@ sk_sp<SkImage> SkImage_Gpu::onMakeColorSpace(sk_sp<SkColorSpace> target, SkColor
srcSpace = SkColorSpace::MakeSRGB();
}
- auto xform = GrNonlinearColorSpaceXformEffect::Make(srcSpace.get(), target.get());
+ auto xform = GrColorSpaceXformEffect::Make(srcSpace.get(), target.get());
if (!xform) {
return sk_ref_sp(const_cast<SkImage_Gpu*>(this));
}