Add color space xform support to GrDisplacementEffect

BUG=skia:

Change-Id: I7508f27d4da6cec7acb801aa389f70c30cb5bfb5
Reviewed-on: https://skia-review.googlesource.com/6340
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 661dacd..d9c1079 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -23,6 +23,7 @@
 #include "SkGr.h"
 #include "SkGrPriv.h"
 #include "effects/GrTextureDomain.h"
+#include "glsl/GrGLSLColorSpaceXformHelper.h"
 #include "glsl/GrGLSLFragmentProcessor.h"
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
 #include "glsl/GrGLSLProgramDataManager.h"
@@ -221,10 +222,11 @@
                 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
                 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, SkVector scale,
                 GrTexture* displacement, const SkMatrix& offsetMatrix, GrTexture* color,
-                const SkISize& colorDimensions) {
+                sk_sp<GrColorSpaceXform> colorSpaceXform, const SkISize& colorDimensions) {
         return sk_sp<GrFragmentProcessor>(
             new GrDisplacementMapEffect(xChannelSelector, yChannelSelector, scale, displacement,
-                                        offsetMatrix, color, colorDimensions));
+                                        offsetMatrix, color, std::move(colorSpaceXform),
+                                        colorDimensions));
     }
 
     virtual ~GrDisplacementMapEffect();
@@ -239,6 +241,7 @@
 
     const char* name() const override { return "DisplacementMap"; }
     const GrTextureDomain& domain() const { return fDomain; }
+    GrColorSpaceXform* colorSpaceXform() const { return fColorSpaceXform.get(); }
 
 private:
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
@@ -253,7 +256,7 @@
                             SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
                             const SkVector& scale,
                             GrTexture* displacement, const SkMatrix& offsetMatrix,
-                            GrTexture* color,
+                            GrTexture* color, sk_sp<GrColorSpaceXform> colorSpaceXform,
                             const SkISize& colorDimensions);
 
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
@@ -263,6 +266,7 @@
     GrCoordTransform            fColorTransform;
     GrTextureDomain             fDomain;
     TextureSampler              fColorSampler;
+    sk_sp<GrColorSpaceXform>    fColorSpaceXform;
     SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
     SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
     SkVector fScale;
@@ -332,11 +336,13 @@
             return nullptr;
         }
 
-        GrPaint paint;
         SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displTexture.get());
         offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displOffset.fX),
                                   SkIntToScalar(colorOffset.fY - displOffset.fY));
-
+        SkColorSpace* colorSpace = ctx.outputProperties().colorSpace();
+        sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(color->getColorSpace(),
+                                                                           colorSpace);
+        GrPaint paint;
         paint.addColorFragmentProcessor(
             GrDisplacementMapEffect::Make(fXChannelSelector,
                                           fYChannelSelector,
@@ -344,12 +350,12 @@
                                           displTexture.get(),
                                           offsetMatrix,
                                           colorTexture.get(),
+                                          std::move(colorSpaceXform),
                                           SkISize::Make(color->width(), color->height())));
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
         SkMatrix matrix;
         matrix.setTranslate(-SkIntToScalar(colorBounds.x()), -SkIntToScalar(colorBounds.y()));
 
-        SkColorSpace* colorSpace = ctx.outputProperties().colorSpace();
         sk_sp<GrRenderTargetContext> renderTargetContext(
             context->makeDeferredRenderTargetContext(SkBackingFit::kApprox,
                                                      bounds.width(), bounds.height(),
@@ -461,7 +467,10 @@
     void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
 
 private:
-    GrGLSLProgramDataManager::UniformHandle fScaleUni;
+    typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
+
+    UniformHandle fScaleUni;
+    UniformHandle fColorSpaceXformUni;
     GrTextureDomain::GLDomain fGLDomain;
 
     typedef GrGLSLFragmentProcessor INHERITED;
@@ -485,6 +494,7 @@
                              GrTexture* displacement,
                              const SkMatrix& offsetMatrix,
                              GrTexture* color,
+                             sk_sp<GrColorSpaceXform> colorSpaceXform,
                              const SkISize& colorDimensions)
     : fDisplacementTransform(offsetMatrix, displacement, GrSamplerParams::kNone_FilterMode)
     , fDisplacementSampler(displacement)
@@ -492,6 +502,7 @@
     , fDomain(GrTextureDomain::MakeTexelDomain(color, SkIRect::MakeSize(colorDimensions)),
               GrTextureDomain::kDecal_Mode)
     , fColorSampler(color)
+    , fColorSpaceXform(std::move(colorSpaceXform))
     , fXChannelSelector(xChannelSelector)
     , fYChannelSelector(yChannelSelector)
     , fScale(scale) {
@@ -542,9 +553,11 @@
     SkISize colorDimensions;
     colorDimensions.fWidth = d->fRandom->nextRangeU(0, d->fTextures[texIdxColor]->width());
     colorDimensions.fHeight = d->fRandom->nextRangeU(0, d->fTextures[texIdxColor]->height());
+    auto colorSpaceXform = GrTest::TestColorXform(d->fRandom);
     return GrDisplacementMapEffect::Make(xChannelSelector, yChannelSelector, scale,
                                          d->fTextures[texIdxDispl], SkMatrix::I(),
-                                         d->fTextures[texIdxColor], colorDimensions);
+                                         d->fTextures[texIdxColor], colorSpaceXform,
+                                         colorDimensions);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -562,6 +575,10 @@
                                    // a number smaller than that to approximate 0, but
                                    // leave room for 32-bit float GPU rounding errors.
 
+    GrGLSLColorSpaceXformHelper colorSpaceHelper(args.fUniformHandler,
+                                                 displacementMap.colorSpaceXform(),
+                                                 &fColorSpaceXformUni);
+
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     fragBuilder->codeAppendf("\t\tvec4 %s = ", dColor);
     fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fTransformedCoords[0].c_str(),
@@ -619,7 +636,9 @@
                             domain,
                             args.fOutputColor,
                             SkString(cCoords),
-                            args.fTexSamplers[1]);
+                            args.fTexSamplers[1],
+                            nullptr,
+                            &colorSpaceHelper);
     fragBuilder->codeAppend(";\n");
 }
 
@@ -633,6 +652,9 @@
                 colorTex->origin() == kTopLeft_GrSurfaceOrigin ?
                 SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY));
     fGLDomain.setData(pdman, displacementMap.domain(), colorTex->origin());
+    if (SkToBool(displacementMap.colorSpaceXform())) {
+        pdman.setSkMatrix44(fColorSpaceXformUni, displacementMap.colorSpaceXform()->srcToDst());
+    }
 }
 
 void GrGLDisplacementMapEffect::GenKey(const GrProcessor& proc,
@@ -643,5 +665,6 @@
     uint32_t yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits;
 
     b->add32(xKey | yKey);
+    b->add32(GrColorSpaceXform::XformKey(displacementMap.colorSpaceXform()));
 }
 #endif