Introduce GrColorSpaceXform, for gamut conversion on textures

GrTextureAccess optionally includes an instance, computed from the src
and dst color spaces. In all common cases (no color space for either src
or dst, or same color space for both), no object is allocated.

This change is orthogonal to my attempts to get color space attached to
render targets - regardless of how we choose to do that, this will give
us the source color space at all points where we are connecting src to
dst.

There are many dangling injection points where I've been inserting
nullptr, but I have a record of all of them. Additionally, there are now
three places (the most common simple paths for bitmap/image rendering)
where things are plumbed enough that I expect to have access to the dst
color space (all marked with XFORMTODO).

In addition to getting the dst color space, I need to inject shader code
and uniform uploading for appendTextureLookup and friends.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2154753003

Review-Url: https://codereview.chromium.org/2154753003
diff --git a/src/gpu/effects/Gr1DKernelEffect.h b/src/gpu/effects/Gr1DKernelEffect.h
index 519d6db..d300f2d 100644
--- a/src/gpu/effects/Gr1DKernelEffect.h
+++ b/src/gpu/effects/Gr1DKernelEffect.h
@@ -31,7 +31,7 @@
     Gr1DKernelEffect(GrTexture* texture,
                      Direction direction,
                      int radius)
-        : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture))
+        : INHERITED(texture, nullptr, GrCoordTransform::MakeDivByTextureWHMatrix(texture))
         , fDirection(direction)
         , fRadius(radius) {}
 
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index 5e6967c..db42f35 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -7,6 +7,7 @@
 
 #include "GrBicubicEffect.h"
 #include "GrInvariantOutput.h"
+#include "glsl/GrGLSLColorSpaceXformHelper.h"
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
 #include "glsl/GrGLSLProgramDataManager.h"
 #include "glsl/GrGLSLUniformHandler.h"
@@ -27,8 +28,9 @@
 
     static inline void GenKey(const GrProcessor& effect, const GrGLSLCaps&,
                               GrProcessorKeyBuilder* b) {
-        const GrTextureDomain& domain = effect.cast<GrBicubicEffect>().domain();
-        b->add32(GrTextureDomain::GLDomain::DomainKey(domain));
+        const GrBicubicEffect& bicubicEffect = effect.cast<GrBicubicEffect>();
+        b->add32(GrTextureDomain::GLDomain::DomainKey(bicubicEffect.domain()));
+        b->add32(SkToInt(SkToBool(bicubicEffect.colorSpaceXform())));
     }
 
 protected:
@@ -39,13 +41,14 @@
 
     UniformHandle               fCoefficientsUni;
     UniformHandle               fImageIncrementUni;
+    UniformHandle               fColorSpaceXformUni;
     GrTextureDomain::GLDomain   fDomain;
 
     typedef GrGLSLFragmentProcessor INHERITED;
 };
 
 void GrGLBicubicEffect::emitCode(EmitArgs& args) {
-    const GrTextureDomain& domain = args.fFp.cast<GrBicubicEffect>().domain();
+    const GrBicubicEffect& bicubicEffect = args.fFp.cast<GrBicubicEffect>();
 
     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     fCoefficientsUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
@@ -58,6 +61,9 @@
     const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
     const char* coeff = uniformHandler->getUniformCStr(fCoefficientsUni);
 
+    GrGLSLColorSpaceXformHelper colorSpaceHelper(uniformHandler, bicubicEffect.colorSpaceXform(),
+                                                 &fColorSpaceXformUni);
+
     SkString cubicBlendName;
 
     static const GrGLSLShaderVar gCubicBlendArgs[] = {
@@ -96,7 +102,7 @@
             fDomain.sampleTexture(fragBuilder,
                                   args.fUniformHandler,
                                   args.fGLSLCaps,
-                                  domain,
+                                  bicubicEffect.domain(),
                                   sampleVar.c_str(),
                                   coord,
                                   args.fTexSamplers[0]);
@@ -107,6 +113,9 @@
     }
     SkString bicubicColor;
     bicubicColor.printf("%s(%s, f.y, s0, s1, s2, s3)", cubicBlendName.c_str(), coeff);
+    if (colorSpaceHelper.getXformMatrix()) {
+        bicubicColor.appendf(" * %s", colorSpaceHelper.getXformMatrix());
+    }
     fragBuilder->codeAppendf("\t%s = %s;\n",
                              args.fOutputColor, (GrGLSLExpr4(bicubicColor.c_str()) *
                                                  GrGLSLExpr4(args.fInputColor)).c_str());
@@ -122,6 +131,11 @@
     pdman.set2fv(fImageIncrementUni, 1, imageIncrement);
     pdman.setMatrix4f(fCoefficientsUni, bicubicEffect.coefficients());
     fDomain.setData(pdman, bicubicEffect.domain(), texture.origin());
+    if (SkToBool(bicubicEffect.colorSpaceXform())) {
+        float xformMatrix[16];
+        bicubicEffect.colorSpaceXform()->srcToDst().asColMajorf(xformMatrix);
+        pdman.setMatrix4f(fColorSpaceXformUni, xformMatrix);
+    }
 }
 
 static inline void convert_row_major_scalar_coeffs_to_column_major_floats(float dst[16],
@@ -134,22 +148,27 @@
 }
 
 GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
+                                 sk_sp<GrColorSpaceXform> colorSpaceXform,
                                  const SkScalar coefficients[16],
                                  const SkMatrix &matrix,
                                  const SkShader::TileMode tileModes[2])
-  : INHERITED(texture, matrix, GrTextureParams(tileModes, GrTextureParams::kNone_FilterMode))
-  , fDomain(GrTextureDomain::IgnoredDomain()) {
+  : INHERITED(texture, nullptr, matrix,
+              GrTextureParams(tileModes, GrTextureParams::kNone_FilterMode))
+  , fDomain(GrTextureDomain::IgnoredDomain())
+  , fColorSpaceXform(std::move(colorSpaceXform)) {
     this->initClassID<GrBicubicEffect>();
     convert_row_major_scalar_coeffs_to_column_major_floats(fCoefficients, coefficients);
 }
 
 GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
+                                 sk_sp<GrColorSpaceXform> colorSpaceXform,
                                  const SkScalar coefficients[16],
                                  const SkMatrix &matrix,
                                  const SkRect& domain)
-  : INHERITED(texture, matrix,
+  : INHERITED(texture, nullptr, matrix,
               GrTextureParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode))
-  , fDomain(domain, GrTextureDomain::kClamp_Mode) {
+  , fDomain(domain, GrTextureDomain::kClamp_Mode)
+  , fColorSpaceXform(std::move(colorSpaceXform)) {
     this->initClassID<GrBicubicEffect>();
     convert_row_major_scalar_coeffs_to_column_major_floats(fCoefficients, coefficients);
 }
@@ -186,7 +205,7 @@
     for (int i = 0; i < 16; i++) {
         coefficients[i] = d->fRandom->nextSScalar1();
     }
-    return GrBicubicEffect::Make(d->fTextures[texIdx], coefficients);
+    return GrBicubicEffect::Make(d->fTextures[texIdx], nullptr, coefficients);
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/effects/GrBicubicEffect.h b/src/gpu/effects/GrBicubicEffect.h
index 3c84f97..58bb068 100644
--- a/src/gpu/effects/GrBicubicEffect.h
+++ b/src/gpu/effects/GrBicubicEffect.h
@@ -29,19 +29,23 @@
 
     const GrTextureDomain& domain() const { return fDomain; }
 
+    GrColorSpaceXform* colorSpaceXform() const { return fColorSpaceXform.get(); }
+
     /**
      * Create a simple filter effect with custom bicubic coefficients and optional domain.
      */
-    static sk_sp<GrFragmentProcessor> Make(GrTexture* tex, const SkScalar coefficients[16],
+    static sk_sp<GrFragmentProcessor> Make(GrTexture* tex,
+                                           sk_sp<GrColorSpaceXform> colorSpaceXform,
+                                           const SkScalar coefficients[16],
                                            const SkRect* domain = nullptr) {
         if (nullptr == domain) {
             static const SkShader::TileMode kTileModes[] = { SkShader::kClamp_TileMode,
                                                              SkShader::kClamp_TileMode };
-            return Make(tex, coefficients, GrCoordTransform::MakeDivByTextureWHMatrix(tex),
-                        kTileModes);
+            return Make(tex, std::move(colorSpaceXform), coefficients,
+                        GrCoordTransform::MakeDivByTextureWHMatrix(tex), kTileModes);
         } else {
             return sk_sp<GrFragmentProcessor>(
-                new GrBicubicEffect(tex, coefficients,
+                new GrBicubicEffect(tex, std::move(colorSpaceXform), coefficients,
                                     GrCoordTransform::MakeDivByTextureWHMatrix(tex), *domain));
         }
     }
@@ -49,28 +53,35 @@
     /**
      * Create a Mitchell filter effect with specified texture matrix and x/y tile modes.
      */
-    static sk_sp<GrFragmentProcessor> Make(GrTexture* tex, const SkMatrix& matrix,
+    static sk_sp<GrFragmentProcessor> Make(GrTexture* tex,
+                                           sk_sp<GrColorSpaceXform> colorSpaceXform,
+                                           const SkMatrix& matrix,
                                            const SkShader::TileMode tileModes[2]) {
-        return Make(tex, gMitchellCoefficients, matrix, tileModes);
+        return Make(tex, std::move(colorSpaceXform), gMitchellCoefficients, matrix, tileModes);
     }
 
     /**
      * Create a filter effect with custom bicubic coefficients, the texture matrix, and the x/y
      * tilemodes.
      */
-    static sk_sp<GrFragmentProcessor> Make(GrTexture* tex, const SkScalar coefficients[16],
+    static sk_sp<GrFragmentProcessor> Make(GrTexture* tex,
+                                           sk_sp<GrColorSpaceXform> colorSpaceXform, 
+                                           const SkScalar coefficients[16],
                                            const SkMatrix& matrix,
                                            const SkShader::TileMode tileModes[2]) {
-        return sk_sp<GrFragmentProcessor>(new GrBicubicEffect(tex, coefficients, matrix,
-                                                              tileModes));
+        return sk_sp<GrFragmentProcessor>(new GrBicubicEffect(tex, std::move(colorSpaceXform),
+                                                              coefficients, matrix, tileModes));
     }
 
     /**
      * Create a Mitchell filter effect with a texture matrix and a domain.
      */
-    static sk_sp<GrFragmentProcessor> Make(GrTexture* tex, const SkMatrix& matrix,
+    static sk_sp<GrFragmentProcessor> Make(GrTexture* tex,
+                                           sk_sp<GrColorSpaceXform> colorSpaceXform,
+                                           const SkMatrix& matrix,
                                            const SkRect& domain) {
-        return sk_sp<GrFragmentProcessor>(new GrBicubicEffect(tex, gMitchellCoefficients, matrix,
+        return sk_sp<GrFragmentProcessor>(new GrBicubicEffect(tex, std::move(colorSpaceXform),
+                                                              gMitchellCoefficients, matrix,
                                                               domain));
     }
 
@@ -85,10 +96,10 @@
                                  GrTextureParams::FilterMode* filterMode);
 
 private:
-    GrBicubicEffect(GrTexture*, const SkScalar coefficients[16], const SkMatrix &matrix,
-                    const SkShader::TileMode tileModes[2]);
-    GrBicubicEffect(GrTexture*, const SkScalar coefficients[16], const SkMatrix &matrix,
-                    const SkRect& domain);
+    GrBicubicEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkScalar coefficients[16],
+                    const SkMatrix &matrix, const SkShader::TileMode tileModes[2]);
+    GrBicubicEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkScalar coefficients[16],
+                    const SkMatrix &matrix, const SkRect& domain);
 
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
 
@@ -100,6 +111,7 @@
 
     float           fCoefficients[16];
     GrTextureDomain fDomain;
+    sk_sp<GrColorSpaceXform> fColorSpaceXform;
 
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
 
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index d2fde96..ed53276 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -98,7 +98,7 @@
                                                    const GrSwizzle& swizzle,
                                                    PMConversion pmConversion,
                                                    const SkMatrix& matrix)
-    : INHERITED(texture, matrix)
+    : INHERITED(texture, nullptr, matrix)
     , fSwizzle(swizzle)
     , fPMConversion(pmConversion) {
     this->initClassID<GrConfigConversionEffect>();
@@ -296,7 +296,7 @@
         // If we returned a GrConfigConversionEffect that was equivalent to a GrSimpleTextureEffect
         // then we may pollute our texture cache with redundant shaders. So in the case that no
         // conversions were requested we instead return a GrSimpleTextureEffect.
-        return GrSimpleTextureEffect::Make(texture, matrix);
+        return GrSimpleTextureEffect::Make(texture, nullptr, matrix);
     } else {
         if (kRGBA_8888_GrPixelConfig != texture->config() &&
             kBGRA_8888_GrPixelConfig != texture->config() &&
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index 5422755..8f03190 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -155,7 +155,7 @@
                                                      const SkIPoint& kernelOffset,
                                                      GrTextureDomain::Mode tileMode,
                                                      bool convolveAlpha)
-  : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)),
+  : INHERITED(texture, nullptr, GrCoordTransform::MakeDivByTextureWHMatrix(texture)),
     fKernelSize(kernelSize),
     fGain(SkScalarToFloat(gain)),
     fBias(SkScalarToFloat(bias) / 255.0f),
diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp
index 7e7b828..a452d3e 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.cpp
+++ b/src/gpu/effects/GrSimpleTextureEffect.cpp
@@ -68,5 +68,5 @@
     GrCoordSet coordSet = kCoordSets[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kCoordSets))];
 
     const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
-    return GrSimpleTextureEffect::Make(d->fTextures[texIdx], matrix, coordSet);
+    return GrSimpleTextureEffect::Make(d->fTextures[texIdx], nullptr, matrix, coordSet);
 }
diff --git a/src/gpu/effects/GrSimpleTextureEffect.h b/src/gpu/effects/GrSimpleTextureEffect.h
index 08eb8c1..44e5c06 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.h
+++ b/src/gpu/effects/GrSimpleTextureEffect.h
@@ -22,26 +22,32 @@
 public:
     /* unfiltered, clamp mode */
     static sk_sp<GrFragmentProcessor> Make(GrTexture* tex,
+                                           sk_sp<GrColorSpaceXform> colorSpaceXform,
                                            const SkMatrix& matrix,
                                            GrCoordSet coordSet = kLocal_GrCoordSet) {
         return sk_sp<GrFragmentProcessor>(
-            new GrSimpleTextureEffect(tex, matrix, GrTextureParams::kNone_FilterMode, coordSet));
+            new GrSimpleTextureEffect(tex, std::move(colorSpaceXform), matrix,
+                                      GrTextureParams::kNone_FilterMode, coordSet));
     }
 
     /* clamp mode */
     static sk_sp<GrFragmentProcessor> Make(GrTexture* tex,
+                                           sk_sp<GrColorSpaceXform> colorSpaceXform,
                                             const SkMatrix& matrix,
                                             GrTextureParams::FilterMode filterMode,
                                             GrCoordSet coordSet = kLocal_GrCoordSet) {
         return sk_sp<GrFragmentProcessor>(
-            new GrSimpleTextureEffect(tex, matrix, filterMode, coordSet));
+            new GrSimpleTextureEffect(tex, std::move(colorSpaceXform), matrix, filterMode,
+                                      coordSet));
     }
 
     static sk_sp<GrFragmentProcessor> Make(GrTexture* tex,
+                                           sk_sp<GrColorSpaceXform> colorSpaceXform,
                                            const SkMatrix& matrix,
                                            const GrTextureParams& p,
                                            GrCoordSet coordSet = kLocal_GrCoordSet) {
-        return sk_sp<GrFragmentProcessor>(new GrSimpleTextureEffect(tex, matrix, p, coordSet));
+        return sk_sp<GrFragmentProcessor>(new GrSimpleTextureEffect(tex, std::move(colorSpaceXform),
+                                                                    matrix, p, coordSet));
     }
 
     virtual ~GrSimpleTextureEffect() {}
@@ -50,18 +56,20 @@
 
 private:
     GrSimpleTextureEffect(GrTexture* texture,
+                          sk_sp<GrColorSpaceXform> colorSpaceXform,
                           const SkMatrix& matrix,
                           GrTextureParams::FilterMode filterMode,
                           GrCoordSet coordSet)
-        : GrSingleTextureEffect(texture, matrix, filterMode, coordSet) {
+        : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, filterMode, coordSet) {
         this->initClassID<GrSimpleTextureEffect>();
     }
 
     GrSimpleTextureEffect(GrTexture* texture,
+                          sk_sp<GrColorSpaceXform> colorSpaceXform,
                           const SkMatrix& matrix,
                           const GrTextureParams& params,
                           GrCoordSet coordSet)
-        : GrSingleTextureEffect(texture, matrix, params, coordSet) {
+        : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, params, coordSet) {
         this->initClassID<GrSimpleTextureEffect>();
     }
 
diff --git a/src/gpu/effects/GrSingleTextureEffect.cpp b/src/gpu/effects/GrSingleTextureEffect.cpp
index c291735..c84e95e 100644
--- a/src/gpu/effects/GrSingleTextureEffect.cpp
+++ b/src/gpu/effects/GrSingleTextureEffect.cpp
@@ -8,30 +8,36 @@
 #include "effects/GrSingleTextureEffect.h"
 
 GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
+                                             sk_sp<GrColorSpaceXform> colorSpaceXform,
                                              const SkMatrix& m,
                                              GrCoordSet coordSet)
     : fCoordTransform(coordSet, m, texture, GrTextureParams::kNone_FilterMode)
-    , fTextureAccess(texture) {
+    , fTextureAccess(texture)
+    , fColorSpaceXform(std::move(colorSpaceXform)) {
     this->addCoordTransform(&fCoordTransform);
     this->addTextureAccess(&fTextureAccess);
 }
 
 GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
+                                             sk_sp<GrColorSpaceXform> colorSpaceXform,
                                              const SkMatrix& m,
                                              GrTextureParams::FilterMode filterMode,
                                              GrCoordSet coordSet)
     : fCoordTransform(coordSet, m, texture, filterMode)
-    , fTextureAccess(texture, filterMode) {
+    , fTextureAccess(texture, filterMode)
+    , fColorSpaceXform(std::move(colorSpaceXform)) {
     this->addCoordTransform(&fCoordTransform);
     this->addTextureAccess(&fTextureAccess);
 }
 
 GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
+                                             sk_sp<GrColorSpaceXform> colorSpaceXform,
                                              const SkMatrix& m,
                                              const GrTextureParams& params,
                                              GrCoordSet coordSet)
     : fCoordTransform(coordSet, m, texture, params.filterMode())
-    , fTextureAccess(texture, params) {
+    , fTextureAccess(texture, params)
+    , fColorSpaceXform(std::move(colorSpaceXform)) {
     this->addCoordTransform(&fCoordTransform);
     this->addTextureAccess(&fTextureAccess);
 }
diff --git a/src/gpu/effects/GrSingleTextureEffect.h b/src/gpu/effects/GrSingleTextureEffect.h
index 4169e40..ae7c694 100644
--- a/src/gpu/effects/GrSingleTextureEffect.h
+++ b/src/gpu/effects/GrSingleTextureEffect.h
@@ -9,6 +9,7 @@
 #define GrSingleTextureEffect_DEFINED
 
 #include "GrFragmentProcessor.h"
+#include "GrColorSpaceXform.h"
 #include "GrCoordTransform.h"
 #include "GrInvariantOutput.h"
 #include "SkMatrix.h"
@@ -31,11 +32,13 @@
 
 protected:
     /** unfiltered, clamp mode */
-    GrSingleTextureEffect(GrTexture*, const SkMatrix&, GrCoordSet = kLocal_GrCoordSet);
-    /** clamp mode */
-    GrSingleTextureEffect(GrTexture*, const SkMatrix&, GrTextureParams::FilterMode filterMode,
+    GrSingleTextureEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkMatrix&,
                           GrCoordSet = kLocal_GrCoordSet);
+    /** clamp mode */
+    GrSingleTextureEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkMatrix&,
+                          GrTextureParams::FilterMode filterMode, GrCoordSet = kLocal_GrCoordSet);
     GrSingleTextureEffect(GrTexture*,
+                          sk_sp<GrColorSpaceXform>,
                           const SkMatrix&,
                           const GrTextureParams&,
                           GrCoordSet = kLocal_GrCoordSet);
@@ -58,6 +61,7 @@
 private:
     GrCoordTransform fCoordTransform;
     GrTextureAccess  fTextureAccess;
+    sk_sp<GrColorSpaceXform> fColorSpaceXform;
 
     typedef GrFragmentProcessor INHERITED;
 };
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index 3fbf000..814d193 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -219,6 +219,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 sk_sp<GrFragmentProcessor> GrTextureDomainEffect::Make(GrTexture* texture,
+                                                       sk_sp<GrColorSpaceXform> colorSpaceXform,
                                                        const SkMatrix& matrix,
                                                        const SkRect& domain,
                                                        GrTextureDomain::Mode mode,
@@ -227,20 +228,22 @@
     static const SkRect kFullRect = {0, 0, SK_Scalar1, SK_Scalar1};
     if (GrTextureDomain::kIgnore_Mode == mode ||
         (GrTextureDomain::kClamp_Mode == mode && domain.contains(kFullRect))) {
-        return GrSimpleTextureEffect::Make(texture, matrix, filterMode);
+        return GrSimpleTextureEffect::Make(texture, std::move(colorSpaceXform), matrix, filterMode);
     } else {
         return sk_sp<GrFragmentProcessor>(
-            new GrTextureDomainEffect(texture, matrix, domain, mode, filterMode, coordSet));
+            new GrTextureDomainEffect(texture, std::move(colorSpaceXform), matrix, domain, mode,
+                                      filterMode, coordSet));
     }
 }
 
 GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture,
+                                             sk_sp<GrColorSpaceXform> colorSpaceXform,
                                              const SkMatrix& matrix,
                                              const SkRect& domain,
                                              GrTextureDomain::Mode mode,
                                              GrTextureParams::FilterMode filterMode,
                                              GrCoordSet coordSet)
-    : GrSingleTextureEffect(texture, matrix, filterMode, coordSet)
+    : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, filterMode, coordSet)
     , fTextureDomain(domain, mode) {
     SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
             filterMode == GrTextureParams::kNone_FilterMode);
@@ -294,6 +297,7 @@
     GrCoordSet coords = d->fRandom->nextBool() ? kLocal_GrCoordSet : kDevice_GrCoordSet;
     return GrTextureDomainEffect::Make(
         d->fTextures[texIdx],
+        nullptr,
         matrix,
         domain,
         mode,
diff --git a/src/gpu/effects/GrTextureDomain.h b/src/gpu/effects/GrTextureDomain.h
index a86ce95..9edecac 100644
--- a/src/gpu/effects/GrTextureDomain.h
+++ b/src/gpu/effects/GrTextureDomain.h
@@ -167,6 +167,7 @@
 
 public:
     static sk_sp<GrFragmentProcessor> Make(GrTexture*,
+                                           sk_sp<GrColorSpaceXform>,
                                            const SkMatrix&,
                                            const SkRect& domain,
                                            GrTextureDomain::Mode,
@@ -193,6 +194,7 @@
 
 private:
     GrTextureDomainEffect(GrTexture*,
+                          sk_sp<GrColorSpaceXform>,
                           const SkMatrix&,
                           const SkRect& domain,
                           GrTextureDomain::Mode,