Pass GrRenderTargetContext's GrColorSpaceInfo to SkShader and SkColorFilter.

Also to SkColorTo(Premul|Unpremul)GrColor4f.

This can avoid cache lookups to find GrColorSpaceXforms as the xform pointer is stored in GrColorSpaceInfo after the first lookup.

Also uses GrColorSpaceInfo to construct GrTextUtils::Paint.

Bug: skia:
Change-Id: Idf19d512a60d2269e6921c7fb54d93aee499a70d
Reviewed-on: https://skia-review.googlesource.com/63660
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h
index 3241a2b..fde3d26 100644
--- a/include/core/SkColorFilter.h
+++ b/include/core/SkColorFilter.h
@@ -14,6 +14,7 @@
 #include "SkRefCnt.h"
 
 class GrContext;
+class GrColorSpaceInfo;
 class GrFragmentProcessor;
 class SkArenaAlloc;
 class SkBitmap;
@@ -132,7 +133,7 @@
      *  A null return indicates that the color filter isn't implemented for the GPU backend.
      */
     virtual std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
-            GrContext*, SkColorSpace* dstColorSpace) const;
+            GrContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const;
 #endif
 
     bool affectsTransparentBlack() const {
diff --git a/include/effects/SkLumaColorFilter.h b/include/effects/SkLumaColorFilter.h
index 1c35fc4..ff7fa66 100644
--- a/include/effects/SkLumaColorFilter.h
+++ b/include/effects/SkLumaColorFilter.h
@@ -29,8 +29,8 @@
     static sk_sp<SkColorFilter> Make();
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrContext*,
-                                                             SkColorSpace*) const override;
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext*, const GrColorSpaceInfo&) const override;
 #endif
 
     SK_TO_STRING_OVERRIDE()
diff --git a/include/effects/SkOverdrawColorFilter.h b/include/effects/SkOverdrawColorFilter.h
index ac97821..63f636a 100644
--- a/include/effects/SkOverdrawColorFilter.h
+++ b/include/effects/SkOverdrawColorFilter.h
@@ -28,8 +28,8 @@
     }
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrContext*,
-                                                             SkColorSpace*) const override;
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext*, const GrColorSpaceInfo&) const override;
 #endif
 
     void toString(SkString* str) const override;
diff --git a/include/effects/SkToSRGBColorFilter.h b/include/effects/SkToSRGBColorFilter.h
index 431cc02..8642c01 100644
--- a/include/effects/SkToSRGBColorFilter.h
+++ b/include/effects/SkToSRGBColorFilter.h
@@ -22,8 +22,8 @@
     static sk_sp<SkColorFilter> Make(sk_sp<SkColorSpace> srcColorSpace);
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrContext*,
-                                                             SkColorSpace*) const override;
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext*, const GrColorSpaceInfo&) const override;
 #endif
 
     SK_TO_STRING_OVERRIDE()
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index 22b8221..9a8b399 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -36,8 +36,8 @@
 }
 
 #if SK_SUPPORT_GPU
-std::unique_ptr<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*,
-                                                                        SkColorSpace*) const {
+std::unique_ptr<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(
+        GrContext*, const GrColorSpaceInfo&) const {
     return nullptr;
 }
 #endif
@@ -121,9 +121,9 @@
 
 #if SK_SUPPORT_GPU
     std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
-            GrContext* context, SkColorSpace* dstColorSpace) const override {
-        auto innerFP = fInner->asFragmentProcessor(context, dstColorSpace);
-        auto outerFP = fOuter->asFragmentProcessor(context, dstColorSpace);
+            GrContext* context, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
+        auto innerFP = fInner->asFragmentProcessor(context, dstColorSpaceInfo);
+        auto outerFP = fOuter->asFragmentProcessor(context, dstColorSpaceInfo);
         if (!innerFP || !outerFP) {
             return nullptr;
         }
@@ -216,8 +216,8 @@
     SkSRGBGammaColorFilter(Direction dir) : fDir(dir) {}
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrContext* x,
-                                                             SkColorSpace* cs) const override {
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext*, const GrColorSpaceInfo&) const override {
         // wish our caller would let us know if our input was opaque...
         GrSRGBEffect::Alpha alpha = GrSRGBEffect::Alpha::kPremul;
         switch (fDir) {
diff --git a/src/core/SkColorMatrixFilterRowMajor255.cpp b/src/core/SkColorMatrixFilterRowMajor255.cpp
index 59b3f3c..4e598aa 100644
--- a/src/core/SkColorMatrixFilterRowMajor255.cpp
+++ b/src/core/SkColorMatrixFilterRowMajor255.cpp
@@ -293,7 +293,7 @@
 #endif
 
 std::unique_ptr<GrFragmentProcessor> SkColorMatrixFilterRowMajor255::asFragmentProcessor(
-        GrContext*, SkColorSpace*) const {
+        GrContext*, const GrColorSpaceInfo&) const {
     return ColorMatrixEffect::Make(fMatrix);
 }
 
diff --git a/src/core/SkColorMatrixFilterRowMajor255.h b/src/core/SkColorMatrixFilterRowMajor255.h
index 7767646..f8eed4c 100644
--- a/src/core/SkColorMatrixFilterRowMajor255.h
+++ b/src/core/SkColorMatrixFilterRowMajor255.h
@@ -23,8 +23,8 @@
     sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter>) const override;
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrContext*,
-                                                             SkColorSpace*) const override;
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext*, const GrColorSpaceInfo&) const override;
 #endif
 
     SK_TO_STRING_OVERRIDE()
diff --git a/src/core/SkModeColorFilter.cpp b/src/core/SkModeColorFilter.cpp
index 98c6532..06e7469 100644
--- a/src/core/SkModeColorFilter.cpp
+++ b/src/core/SkModeColorFilter.cpp
@@ -98,12 +98,12 @@
 #include "SkGr.h"
 
 std::unique_ptr<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor(
-        GrContext*, SkColorSpace* dstColorSpace) const {
+        GrContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const {
     if (SkBlendMode::kDst == fMode) {
         return nullptr;
     }
 
-    auto constFP = GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpace),
+    auto constFP = GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpaceInfo),
                                                GrConstColorProcessor::kIgnore_InputMode);
     auto fp = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode);
     if (!fp) {
diff --git a/src/core/SkModeColorFilter.h b/src/core/SkModeColorFilter.h
index c5bd785..efaba4e 100644
--- a/src/core/SkModeColorFilter.h
+++ b/src/core/SkModeColorFilter.h
@@ -27,8 +27,8 @@
 #endif
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrContext*,
-                                                             SkColorSpace*) const override;
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext*, const GrColorSpaceInfo&) const override;
 #endif
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
 
diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp
index 43a3941..6d524c2 100644
--- a/src/effects/SkColorMatrixFilter.cpp
+++ b/src/effects/SkColorMatrixFilter.cpp
@@ -66,9 +66,9 @@
     Factory getFactory() const override             { return fMatrixFilter->getFactory(); }
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrContext* ctx,
-                                                             SkColorSpace* cs) const override {
-        return fMatrixFilter->asFragmentProcessor(ctx, cs);
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext* ctx, const GrColorSpaceInfo& csi) const override {
+        return fMatrixFilter->asFragmentProcessor(ctx, csi);
     }
 #endif
 
diff --git a/src/effects/SkHighContrastFilter.cpp b/src/effects/SkHighContrastFilter.cpp
index 1d67b3f..1d80710 100644
--- a/src/effects/SkHighContrastFilter.cpp
+++ b/src/effects/SkHighContrastFilter.cpp
@@ -35,8 +35,8 @@
     ~SkHighContrast_Filter() override {}
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrContext*,
-                                                             SkColorSpace*) const override;
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext*, const GrColorSpaceInfo&) const override;
  #endif
 
     void onAppendStages(SkRasterPipeline* p,
@@ -353,7 +353,7 @@
 }
 
 std::unique_ptr<GrFragmentProcessor> SkHighContrast_Filter::asFragmentProcessor(
-        GrContext*, SkColorSpace*) const {
+        GrContext*, const GrColorSpaceInfo&) const {
     return HighContrastFilterEffect::Make(fConfig);
 }
 #endif
diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp
index 3b3845e..22c0285 100644
--- a/src/effects/SkLumaColorFilter.cpp
+++ b/src/effects/SkLumaColorFilter.cpp
@@ -103,8 +103,8 @@
     typedef GrFragmentProcessor INHERITED;
 };
 
-std::unique_ptr<GrFragmentProcessor> SkLumaColorFilter::asFragmentProcessor(GrContext*,
-                                                                            SkColorSpace*) const {
+std::unique_ptr<GrFragmentProcessor> SkLumaColorFilter::asFragmentProcessor(
+        GrContext*, const GrColorSpaceInfo&) const {
     return LumaColorFilterEffect::Make();
 }
 #endif
diff --git a/src/effects/SkOverdrawColorFilter.cpp b/src/effects/SkOverdrawColorFilter.cpp
index a4fa070..2dd4a43 100644
--- a/src/effects/SkOverdrawColorFilter.cpp
+++ b/src/effects/SkOverdrawColorFilter.cpp
@@ -109,7 +109,7 @@
 };
 
 std::unique_ptr<GrFragmentProcessor> SkOverdrawColorFilter::asFragmentProcessor(
-        GrContext*, SkColorSpace*) const {
+        GrContext*, const GrColorSpaceInfo&) const {
     return OverdrawFragmentProcessor::Make(fColors);
 }
 
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index 6e4e068..75ffbd6 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -86,8 +86,8 @@
     sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter> inner) const override;
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrContext*,
-                                                             SkColorSpace*) const override;
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext*, const GrColorSpaceInfo&) const override;
 #endif
 
     SK_TO_STRING_OVERRIDE()
@@ -320,6 +320,7 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrColorSpaceInfo.h"
 #include "GrContext.h"
 #include "GrFragmentProcessor.h"
 #include "GrTextureStripAtlas.h"
@@ -538,14 +539,15 @@
         (flags & (1 << 3)) ? luts[3] : nullptr
     ));
     sk_sp<SkColorSpace> colorSpace = GrTest::TestColorSpace(d->fRandom);
-    auto fp = filter->asFragmentProcessor(d->context(), colorSpace.get());
+    auto fp = filter->asFragmentProcessor(
+            d->context(), GrColorSpaceInfo(std::move(colorSpace), kRGBA_8888_GrPixelConfig));
     SkASSERT(fp);
     return fp;
 }
 #endif
 
-std::unique_ptr<GrFragmentProcessor> SkTable_ColorFilter::asFragmentProcessor(GrContext* context,
-                                                                              SkColorSpace*) const {
+std::unique_ptr<GrFragmentProcessor> SkTable_ColorFilter::asFragmentProcessor(
+        GrContext* context, const GrColorSpaceInfo&) const {
     SkBitmap bitmap;
     this->asComponentTable(&bitmap);
 
diff --git a/src/effects/SkToSRGBColorFilter.cpp b/src/effects/SkToSRGBColorFilter.cpp
index 150877f..fa26350 100644
--- a/src/effects/SkToSRGBColorFilter.cpp
+++ b/src/effects/SkToSRGBColorFilter.cpp
@@ -86,8 +86,8 @@
 #endif
 
 #if SK_SUPPORT_GPU
-std::unique_ptr<GrFragmentProcessor> SkToSRGBColorFilter::asFragmentProcessor(GrContext*,
-                                                                              SkColorSpace*) const {
+std::unique_ptr<GrFragmentProcessor> SkToSRGBColorFilter::asFragmentProcessor(
+        GrContext*, const GrColorSpaceInfo&) const {
     return GrNonlinearColorSpaceXformEffect::Make(fSrcColorSpace.get(),
                                                   SkColorSpace::MakeSRGB().get());
 }
diff --git a/src/gpu/GrColorSpaceInfo.cpp b/src/gpu/GrColorSpaceInfo.cpp
index 1cb8430..cd0dc16 100644
--- a/src/gpu/GrColorSpaceInfo.cpp
+++ b/src/gpu/GrColorSpaceInfo.cpp
@@ -20,5 +20,7 @@
         fColorXformFromSRGB = GrColorSpaceXform::Make(srgbColorSpace.get(), fColorSpace.get());
         fInitializedColorSpaceXformFromSRGB = true;
     }
+    // You can't be color-space aware in legacy mode
+    SkASSERT(fColorSpace || !fColorXformFromSRGB);
     return fColorXformFromSRGB.get();
 }
diff --git a/src/gpu/GrTestUtils.cpp b/src/gpu/GrTestUtils.cpp
index 901fe4d..da3cb97 100644
--- a/src/gpu/GrTestUtils.cpp
+++ b/src/gpu/GrTestUtils.cpp
@@ -6,11 +6,12 @@
  */
 
 #include "GrTestUtils.h"
-#include "GrColorSpaceXform.h"
+#include "GrColorSpaceInfo.h"
 #include "GrProcessorUnitTest.h"
 #include "GrStyle.h"
 #include "SkColorSpace_Base.h"
 #include "SkDashPathPriv.h"
+#include "SkMakeUnique.h"
 #include "SkMatrix.h"
 #include "SkPath.h"
 #include "SkRRect.h"
@@ -334,15 +335,18 @@
 
 TestAsFPArgs::TestAsFPArgs(GrProcessorTestData* d) {
     fViewMatrixStorage = TestMatrix(d->fRandom);
-    fColorSpaceStorage = TestColorSpace(d->fRandom);
+    fColorSpaceInfoStorage = skstd::make_unique<GrColorSpaceInfo>(TestColorSpace(d->fRandom),
+                                                                  kRGBA_8888_GrPixelConfig);
 
     fArgs.fContext = d->context();
     fArgs.fViewMatrix = &fViewMatrixStorage;
     fArgs.fLocalMatrix = nullptr;
     fArgs.fFilterQuality = kNone_SkFilterQuality;
-    fArgs.fDstColorSpace = fColorSpaceStorage.get();
+    fArgs.fDstColorSpaceInfo = fColorSpaceInfoStorage.get();
 }
 
+TestAsFPArgs::~TestAsFPArgs() {}
+
 }  // namespace GrTest
 
 #endif
diff --git a/src/gpu/GrTestUtils.h b/src/gpu/GrTestUtils.h
index a788dfb..9a1ae28 100644
--- a/src/gpu/GrTestUtils.h
+++ b/src/gpu/GrTestUtils.h
@@ -20,6 +20,7 @@
 #include "SkShaderBase.h"
 #include "SkStrokeRec.h"
 
+class GrColorSpaceInfo;
 class GrColorSpaceXform;
 struct GrProcessorTestData;
 class GrStyle;
@@ -52,12 +53,13 @@
 class TestAsFPArgs {
 public:
     TestAsFPArgs(GrProcessorTestData*);
+    ~TestAsFPArgs();
     const SkShaderBase::AsFPArgs& args() const { return fArgs; }
 
 private:
     SkShaderBase::AsFPArgs fArgs;
     SkMatrix fViewMatrixStorage;
-    sk_sp<SkColorSpace> fColorSpaceStorage;
+    std::unique_ptr<GrColorSpaceInfo> fColorSpaceInfoStorage;
 };
 
 // We have a simplified dash path effect here to avoid relying on SkDashPathEffect which
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 983bb5b..026a748 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -305,36 +305,18 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-// TODO(bsalomon): Pass GrColorSpaceInfo to these conversion functions?
-
-GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace) {
+GrColor4f SkColorToPremulGrColor4f(SkColor c, const GrColorSpaceInfo& colorSpaceInfo) {
     // We want to premultiply after linearizing, so this is easy:
-    return SkColorToUnpremulGrColor4f(c, dstColorSpace).premul();
+    return SkColorToUnpremulGrColor4f(c, colorSpaceInfo).premul();
 }
 
-GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace) {
-    if (dstColorSpace) {
-        auto srgbColorSpace = SkColorSpace::MakeSRGB();
-        auto gamutXform = GrColorSpaceXform::Make(srgbColorSpace.get(), dstColorSpace);
-        return SkColorToUnpremulGrColor4f(c, dstColorSpace, gamutXform.get());
-    } else {
-        return SkColorToUnpremulGrColor4f(c, nullptr, nullptr);
-    }
+GrColor4f SkColorToPremulGrColor4fLegacy(SkColor c) {
+    return GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c)).premul();
 }
 
-GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace,
-                                   GrColorSpaceXform* gamutXform) {
-    // We want to premultiply after linearizing, so this is easy:
-    return SkColorToUnpremulGrColor4f(c, dstColorSpace, gamutXform).premul();
-}
-
-GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace,
-                                     GrColorSpaceXform* gamutXform) {
-    // You can't be color-space aware in legacy mode
-    SkASSERT(dstColorSpace || !gamutXform);
-
+GrColor4f SkColorToUnpremulGrColor4f(SkColor c, const GrColorSpaceInfo& colorSpaceInfo) {
     GrColor4f color;
-    if (dstColorSpace) {
+    if (colorSpaceInfo.colorSpace()) {
         // SkColor4f::FromColor does sRGB -> Linear
         color = GrColor4f::FromSkColor4f(SkColor4f::FromColor(c));
     } else {
@@ -342,8 +324,8 @@
         color = GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c));
     }
 
-    if (gamutXform) {
-        color = gamutXform->clampedXform(color);
+    if (auto* xform = colorSpaceInfo.colorSpaceXformFromSRGB()) {
+        color = xform->clampedXform(color);
     }
 
     return color;
@@ -451,9 +433,7 @@
     grPaint->setAllowSRGBInputs(colorSpaceInfo.isGammaCorrect());
 
     // Convert SkPaint color to 4f format, including optional linearizing and gamut conversion.
-    GrColor4f origColor =
-            SkColorToUnpremulGrColor4f(skPaint.getColor(), colorSpaceInfo.colorSpace(),
-                                       colorSpaceInfo.colorSpaceXformFromSRGB());
+    GrColor4f origColor = SkColorToUnpremulGrColor4f(skPaint.getColor(), colorSpaceInfo);
 
     // Setup the initial color considering the shader, the SkPaint color, and the presence or not
     // of per-vertex colors.
@@ -462,9 +442,8 @@
         if (shaderProcessor) {
             shaderFP = std::move(*shaderProcessor);
         } else if (const auto* shader = as_SB(skPaint.getShader())) {
-            shaderFP = shader->asFragmentProcessor(
-                    SkShaderBase::AsFPArgs(context, &viewM, nullptr, skPaint.getFilterQuality(),
-                                           colorSpaceInfo.colorSpace()));
+            shaderFP = shader->asFragmentProcessor(SkShaderBase::AsFPArgs(
+                    context, &viewM, nullptr, skPaint.getFilterQuality(), &colorSpaceInfo));
             if (!shaderFP) {
                 return false;
             }
@@ -547,11 +526,11 @@
                 grPaint->setColor4f(GrColor4f::FromSkColor4f(
                     colorFilter->filterColor4f(origColor.toSkColor4f())).premul());
             } else {
-                grPaint->setColor4f(SkColorToPremulGrColor4f(
-                    colorFilter->filterColor(skPaint.getColor()), nullptr, nullptr));
+                grPaint->setColor4f(SkColorToPremulGrColor4fLegacy(
+                        colorFilter->filterColor(skPaint.getColor())));
             }
         } else {
-            auto cfFP = colorFilter->asFragmentProcessor(context, colorSpaceInfo.colorSpace());
+            auto cfFP = colorFilter->asFragmentProcessor(context, colorSpaceInfo);
             if (cfFP) {
                 grPaint->addColorFragmentProcessor(std::move(cfFP));
             } else {
@@ -643,9 +622,8 @@
     std::unique_ptr<GrFragmentProcessor> shaderFP;
     if (textureIsAlphaOnly) {
         if (const auto* shader = as_SB(paint.getShader())) {
-            shaderFP = shader->asFragmentProcessor(
-                    SkShaderBase::AsFPArgs(context, &viewM, nullptr, paint.getFilterQuality(),
-                                           colorSpaceInfo.colorSpace()));
+            shaderFP = shader->asFragmentProcessor(SkShaderBase::AsFPArgs(
+                    context, &viewM, nullptr, paint.getFilterQuality(), &colorSpaceInfo));
             if (!shaderFP) {
                 return false;
             }
diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h
index 2fedc06..0b972b4 100644
--- a/src/gpu/SkGr.h
+++ b/src/gpu/SkGr.h
@@ -58,18 +58,10 @@
     return GrColorPackRGBA(r, g, b, a);
 }
 
-/** Transform an SkColor (sRGB bytes) to GrColor4f for the specified color space. */
-GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace);
-GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace);
-
-/**
- * As above, but with a caller-supplied color space xform object. Faster for the cases where we
- * have that cached.
- */
-GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace,
-                                   GrColorSpaceXform* gamutXform);
-GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace,
-                                     GrColorSpaceXform* gamutXform);
+/** Transform an SkColor (sRGB bytes) to GrColor4f for the specified color space info. */
+GrColor4f SkColorToPremulGrColor4f(SkColor, const GrColorSpaceInfo&);
+GrColor4f SkColorToPremulGrColor4fLegacy(SkColor);
+GrColor4f SkColorToUnpremulGrColor4f(SkColor, const GrColorSpaceInfo&);
 
 /** Replicates the SkColor's alpha to all four channels of the GrColor. */
 static inline GrColor SkColorAlphaToGrColor(SkColor c) {
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 4f8748b..adf4980 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -118,7 +118,7 @@
         cacheBlob = cache->find(key);
     }
 
-    GrTextUtils::Paint paint(&skPaint, rtc->colorSpaceInfo());
+    GrTextUtils::Paint paint(&skPaint, &rtc->colorSpaceInfo());
     if (cacheBlob) {
         if (cacheBlob->mustRegenerate(paint, blurRec, viewMatrix, x, y)) {
             // We have to remake the blob because changes may invalidate our masks.
@@ -295,7 +295,7 @@
     if (context->abandoned()) {
         return;
     }
-    GrTextUtils::Paint paint(&skPaint, rtc->colorSpaceInfo());
+    GrTextUtils::Paint paint(&skPaint, &rtc->colorSpaceInfo());
     if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
         sk_sp<GrAtlasTextBlob> blob(
                 MakeDrawTextBlob(context->getTextBlobCache(), context->getAtlasGlyphCache(),
@@ -320,7 +320,7 @@
                                      const char text[], size_t byteLength, const SkScalar pos[],
                                      int scalarsPerPosition, const SkPoint& offset,
                                      const SkIRect& regionClipBounds) {
-    GrTextUtils::Paint paint(&skPaint, rtc->colorSpaceInfo());
+    GrTextUtils::Paint paint(&skPaint, &rtc->colorSpaceInfo());
     if (context->abandoned()) {
         return;
     } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
@@ -370,7 +370,7 @@
     skPaint.setLCDRenderText(random->nextBool());
     skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool());
     skPaint.setSubpixelText(random->nextBool());
-    GrTextUtils::Paint utilsPaint(&skPaint, rtc->colorSpaceInfo());
+    GrTextUtils::Paint utilsPaint(&skPaint, &rtc->colorSpaceInfo());
 
     const char* text = "The quick brown fox jumps over the lazy dog.";
     int textLen = (int)strlen(text);
diff --git a/src/gpu/text/GrStencilAndCoverTextContext.cpp b/src/gpu/text/GrStencilAndCoverTextContext.cpp
index 502f4ad..6d09c11 100644
--- a/src/gpu/text/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/text/GrStencilAndCoverTextContext.cpp
@@ -133,7 +133,7 @@
                                                         SkScalar x, SkScalar y,
                                                         SkDrawFilter* drawFilter,
                                                         const SkIRect& clipBounds) {
-    GrTextUtils::Paint paint(&skPaint, rtc->colorSpaceInfo());
+    GrTextUtils::Paint paint(&skPaint, &rtc->colorSpaceInfo());
     GrTextUtils::RunPaint runPaint(&paint, drawFilter, props);
     SkTextBlobRunIterator it(blob);
     for (;!it.done(); it.next()) {
diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp
index f920ec4..5465d28 100644
--- a/src/gpu/text/GrTextUtils.cpp
+++ b/src/gpu/text/GrTextUtils.cpp
@@ -54,9 +54,9 @@
 
 void GrTextUtils::Paint::initFilteredColor() {
     // This mirrors the logic in skpaint_to_grpaint_impl for handling paint colors
-    if (fDstColorSpace) {
-        GrColor4f filteredColor = SkColorToUnpremulGrColor4f(fPaint->getColor(), fDstColorSpace,
-                                                             fColorXformFromSRGB);
+    if (fDstColorSpaceInfo->colorSpace()) {
+        GrColor4f filteredColor =
+                SkColorToUnpremulGrColor4f(fPaint->getColor(), *fDstColorSpaceInfo);
         if (fPaint->getColorFilter()) {
             filteredColor = GrColor4f::FromSkColor4f(
                 fPaint->getColorFilter()->filterColor4f(filteredColor.toSkColor4f()));
diff --git a/src/gpu/text/GrTextUtils.h b/src/gpu/text/GrTextUtils.h
index 0a6b2cc..bd0a1ad 100644
--- a/src/gpu/text/GrTextUtils.h
+++ b/src/gpu/text/GrTextUtils.h
@@ -48,10 +48,8 @@
      */
     class Paint {
     public:
-        explicit Paint(const SkPaint* paint, const GrColorSpaceInfo& dstColorSpaceInfo)
-                : fPaint(paint)
-                , fDstColorSpace(dstColorSpaceInfo.colorSpace())
-                , fColorXformFromSRGB(dstColorSpaceInfo.colorSpaceXformFromSRGB()) {
+        explicit Paint(const SkPaint* paint, const GrColorSpaceInfo* dstColorSpaceInfo)
+                : fPaint(paint), fDstColorSpaceInfo(dstColorSpaceInfo) {
             this->initFilteredColor();
         }
 
@@ -67,15 +65,13 @@
                        GrPaint*) const;
 
         // Just for RunPaint's constructor
-        SkColorSpace* dstColorSpace() const { return fDstColorSpace; }
-        GrColorSpaceXform* colorXformFromSRGB() const { return fColorXformFromSRGB; }
+        const GrColorSpaceInfo* dstColorSpaceInfo() const { return fDstColorSpaceInfo; }
 
     protected:
         void initFilteredColor();
         Paint() = default;
         const SkPaint* fPaint;
-        SkColorSpace* fDstColorSpace;
-        GrColorSpaceXform* fColorXformFromSRGB;
+        const GrColorSpaceInfo* fDstColorSpaceInfo;
         // This is the paint's color run through its color filter, if present. This color should
         // be used except when rendering bitmap text, in which case the bitmap must be filtered in
         // the fragment shader.
@@ -93,8 +89,7 @@
                 : fOriginalPaint(paint), fFilter(filter), fProps(props) {
             // Initially we represent the original paint.
             fPaint = &fOriginalPaint->skPaint();
-            fDstColorSpace = fOriginalPaint->dstColorSpace();
-            fColorXformFromSRGB = fOriginalPaint->colorXformFromSRGB();
+            fDstColorSpaceInfo = fOriginalPaint->dstColorSpaceInfo();
             fFilteredPremulColor = fOriginalPaint->filteredPremulColor();
         }
 
diff --git a/src/shaders/SkColorFilterShader.cpp b/src/shaders/SkColorFilterShader.cpp
index d19b8ec..b407ed8 100644
--- a/src/shaders/SkColorFilterShader.cpp
+++ b/src/shaders/SkColorFilterShader.cpp
@@ -61,7 +61,7 @@
         return nullptr;
     }
 
-    auto fp2 = fFilter->asFragmentProcessor(args.fContext, args.fDstColorSpace);
+    auto fp2 = fFilter->asFragmentProcessor(args.fContext, *args.fDstColorSpaceInfo);
     if (!fp2) {
         return fp1;
     }
diff --git a/src/shaders/SkColorShader.cpp b/src/shaders/SkColorShader.cpp
index 33d3166..4bc7d71 100644
--- a/src/shaders/SkColorShader.cpp
+++ b/src/shaders/SkColorShader.cpp
@@ -91,7 +91,7 @@
 #include "effects/GrConstColorProcessor.h"
 std::unique_ptr<GrFragmentProcessor> SkColorShader::asFragmentProcessor(
         const AsFPArgs& args) const {
-    GrColor4f color = SkColorToPremulGrColor4f(fColor, args.fDstColorSpace);
+    GrColor4f color = SkColorToPremulGrColor4f(fColor, *args.fDstColorSpaceInfo);
     return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode);
 }
 
@@ -204,13 +204,15 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrColorSpaceInfo.h"
+#include "GrColorSpaceXform.h"
 #include "SkGr.h"
 #include "effects/GrConstColorProcessor.h"
-#include "GrColorSpaceXform.h"
+
 std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(
         const AsFPArgs& args) const {
-    sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(),
-                                                                       args.fDstColorSpace);
+    sk_sp<GrColorSpaceXform> colorSpaceXform =
+            GrColorSpaceXform::Make(fColorSpace.get(), args.fDstColorSpaceInfo->colorSpace());
     GrColor4f color = GrColor4f::FromSkColor4f(fColor4);
     if (colorSpaceXform) {
         color = colorSpaceXform->clampedXform(color);
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 9e71027..753024d 100644
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -165,10 +165,9 @@
 
 #if SK_SUPPORT_GPU
 
-#include "SkGr.h"
-#include "GrColorSpaceXform.h"
+#include "GrColorSpaceInfo.h"
 #include "GrContext.h"
-#include "effects/GrSimpleTextureEffect.h"
+#include "SkGr.h"
 #include "effects/GrBicubicEffect.h"
 #include "effects/GrSimpleTextureEffect.h"
 
@@ -213,7 +212,8 @@
     sk_sp<SkColorSpace> texColorSpace;
     SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
     sk_sp<GrTextureProxy> proxy(as_IB(fImage)->asTextureProxyRef(
-            args.fContext, samplerState, args.fDstColorSpace, &texColorSpace, scaleAdjust));
+            args.fContext, samplerState, args.fDstColorSpaceInfo->colorSpace(), &texColorSpace,
+            scaleAdjust));
     if (!proxy) {
         return nullptr;
     }
@@ -229,7 +229,7 @@
         inner = GrSimpleTextureEffect::Make(std::move(proxy), lmInverse, samplerState);
     }
     inner = GrColorSpaceXformEffect::Make(std::move(inner), texColorSpace.get(),
-                                          args.fDstColorSpace);
+                                          args.fDstColorSpaceInfo->colorSpace());
     if (isAlphaOnly) {
         return inner;
     }
diff --git a/src/shaders/SkLocalMatrixShader.cpp b/src/shaders/SkLocalMatrixShader.cpp
index 377e6f6..172eca1 100644
--- a/src/shaders/SkLocalMatrixShader.cpp
+++ b/src/shaders/SkLocalMatrixShader.cpp
@@ -18,8 +18,9 @@
     if (args.fLocalMatrix) {
         tmp.preConcat(*args.fLocalMatrix);
     }
-    return as_SB(fProxyShader)->asFragmentProcessor(AsFPArgs(
-        args.fContext, args.fViewMatrix, &tmp, args.fFilterQuality, args.fDstColorSpace));
+    return as_SB(fProxyShader)
+            ->asFragmentProcessor(AsFPArgs(args.fContext, args.fViewMatrix, &tmp,
+                                           args.fFilterQuality, args.fDstColorSpaceInfo));
 }
 #endif
 
diff --git a/src/shaders/SkPictureShader.cpp b/src/shaders/SkPictureShader.cpp
index 1a86af6..677c0e1 100644
--- a/src/shaders/SkPictureShader.cpp
+++ b/src/shaders/SkPictureShader.cpp
@@ -21,8 +21,9 @@
 #include "SkResourceCache.h"
 
 #if SK_SUPPORT_GPU
-#include "GrContext.h"
 #include "GrCaps.h"
+#include "GrColorSpaceInfo.h"
+#include "GrContext.h"
 #include "GrFragmentProcessor.h"
 #endif
 
@@ -374,11 +375,14 @@
         maxTextureSize = args.fContext->caps()->maxTextureSize();
     }
     sk_sp<SkShader> bitmapShader(this->refBitmapShader(*args.fViewMatrix, args.fLocalMatrix,
-                                                       args.fDstColorSpace, maxTextureSize));
+                                                       args.fDstColorSpaceInfo->colorSpace(),
+                                                       maxTextureSize));
     if (!bitmapShader) {
         return nullptr;
     }
-    return as_SB(bitmapShader)->asFragmentProcessor(SkShaderBase::AsFPArgs(
-        args.fContext, args.fViewMatrix, nullptr, args.fFilterQuality, args.fDstColorSpace));
+    return as_SB(bitmapShader)
+            ->asFragmentProcessor(SkShaderBase::AsFPArgs(args.fContext, args.fViewMatrix, nullptr,
+                                                         args.fFilterQuality,
+                                                         args.fDstColorSpaceInfo));
 }
 #endif
diff --git a/src/shaders/SkShaderBase.h b/src/shaders/SkShaderBase.h
index d63813c..85c08fe 100644
--- a/src/shaders/SkShaderBase.h
+++ b/src/shaders/SkShaderBase.h
@@ -13,6 +13,7 @@
 #include "SkShader.h"
 
 class GrContext;
+class GrColorSpaceInfo;
 class GrFragmentProcessor;
 class SkArenaAlloc;
 class SkColorSpace;
@@ -140,18 +141,18 @@
                  const SkMatrix* viewMatrix,
                  const SkMatrix* localMatrix,
                  SkFilterQuality filterQuality,
-                 SkColorSpace* dstColorSpace)
-            : fContext(context)
-            , fViewMatrix(viewMatrix)
-            , fLocalMatrix(localMatrix)
-            , fFilterQuality(filterQuality)
-            , fDstColorSpace(dstColorSpace) {}
+                 const GrColorSpaceInfo* dstColorSpaceInfo)
+                : fContext(context)
+                , fViewMatrix(viewMatrix)
+                , fLocalMatrix(localMatrix)
+                , fFilterQuality(filterQuality)
+                , fDstColorSpaceInfo(dstColorSpaceInfo) {}
 
-        GrContext*                    fContext;
-        const SkMatrix*               fViewMatrix;
-        const SkMatrix*               fLocalMatrix;
-        SkFilterQuality               fFilterQuality;
-        SkColorSpace*                 fDstColorSpace;
+        GrContext* fContext;
+        const SkMatrix* fViewMatrix;
+        const SkMatrix* fLocalMatrix;
+        SkFilterQuality fFilterQuality;
+        const GrColorSpaceInfo* fDstColorSpaceInfo;
     };
 
     /**
diff --git a/src/shaders/gradients/SkGradientShaderPriv.h b/src/shaders/gradients/SkGradientShaderPriv.h
index 7916e69..26bc033 100644
--- a/src/shaders/gradients/SkGradientShaderPriv.h
+++ b/src/shaders/gradients/SkGradientShaderPriv.h
@@ -257,7 +257,7 @@
 
 #if SK_SUPPORT_GPU
 
-#include "GrColorSpaceXform.h"
+#include "GrColorSpaceInfo.h"
 #include "GrCoordTransform.h"
 #include "GrFragmentProcessor.h"
 #include "glsl/GrGLSLFragmentProcessor.h"
diff --git a/src/shaders/gradients/SkLinearGradient.cpp b/src/shaders/gradients/SkLinearGradient.cpp
index c0cade3..10d0973 100644
--- a/src/shaders/gradients/SkLinearGradient.cpp
+++ b/src/shaders/gradients/SkLinearGradient.cpp
@@ -5,9 +5,9 @@
  * found in the LICENSE file.
  */
 
+#include "SkLinearGradient.h"
 #include "Sk4fLinearGradient.h"
 #include "SkColorSpaceXformer.h"
-#include "SkLinearGradient.h"
 #include "SkRefCnt.h"
 
 static SkMatrix pts_to_unit_matrix(const SkPoint pts[2]) {
@@ -88,7 +88,6 @@
 
 #if SK_SUPPORT_GPU
 
-#include "GrColorSpaceXform.h"
 #include "GrShaderCaps.h"
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
 #include "SkGr.h"
@@ -214,7 +213,7 @@
     matrix.postConcat(fPtsToUnit);
 
     return GrLinearGradient::Make(GrGradientEffect::CreateArgs(
-            args.fContext, this, &matrix, fTileMode, args.fDstColorSpace));
+            args.fContext, this, &matrix, fTileMode, args.fDstColorSpaceInfo->colorSpace()));
 }
 
 
diff --git a/src/shaders/gradients/SkRadialGradient.cpp b/src/shaders/gradients/SkRadialGradient.cpp
index e704554..d411c3a 100644
--- a/src/shaders/gradients/SkRadialGradient.cpp
+++ b/src/shaders/gradients/SkRadialGradient.cpp
@@ -187,7 +187,7 @@
     matrix.postConcat(fPtsToUnit);
 
     return GrRadialGradient::Make(GrGradientEffect::CreateArgs(
-            args.fContext, this, &matrix, fTileMode, args.fDstColorSpace));
+            args.fContext, this, &matrix, fTileMode, args.fDstColorSpaceInfo->colorSpace()));
 }
 
 #endif
diff --git a/src/shaders/gradients/SkSweepGradient.cpp b/src/shaders/gradients/SkSweepGradient.cpp
index 551a6fb..b505426 100644
--- a/src/shaders/gradients/SkSweepGradient.cpp
+++ b/src/shaders/gradients/SkSweepGradient.cpp
@@ -243,7 +243,7 @@
 
     return GrSweepGradient::Make(
             GrGradientEffect::CreateArgs(args.fContext, this, &matrix, fTileMode,
-                                         args.fDstColorSpace),
+                                         args.fDstColorSpaceInfo->colorSpace()),
             fTBias, fTScale);
 }
 
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.cpp b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
index d84108b..22555e0 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
@@ -130,8 +130,9 @@
 std::unique_ptr<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProcessor(
         const AsFPArgs& args) const {
     SkASSERT(args.fContext);
-    return Gr2PtConicalGradientEffect::Make(GrGradientEffect::CreateArgs(
-            args.fContext, this, args.fLocalMatrix, fTileMode, args.fDstColorSpace));
+    return Gr2PtConicalGradientEffect::Make(
+            GrGradientEffect::CreateArgs(args.fContext, this, args.fLocalMatrix, fTileMode,
+                                         args.fDstColorSpaceInfo->colorSpace()));
 }
 
 #endif
diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp
index 288ae96..757b65c 100644
--- a/src/utils/SkShadowUtils.cpp
+++ b/src/utils/SkShadowUtils.cpp
@@ -38,8 +38,8 @@
     }
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrContext*,
-                                                             SkColorSpace*) const override;
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext*, const GrColorSpaceInfo&) const override;
 #endif
 
     SK_TO_STRING_OVERRIDE()
@@ -70,7 +70,7 @@
 #if SK_SUPPORT_GPU
 
 std::unique_ptr<GrFragmentProcessor> SkGaussianColorFilter::asFragmentProcessor(
-        GrContext*, SkColorSpace*) const {
+        GrContext*, const GrColorSpaceInfo&) const {
     return GrBlurredEdgeFragmentProcessor::Make(GrBlurredEdgeFragmentProcessor::kGaussian_Mode);
 }
 #endif
diff --git a/tests/TessellatingPathRendererTests.cpp b/tests/TessellatingPathRendererTests.cpp
index 62bf059..6c414df 100644
--- a/tests/TessellatingPathRendererTests.cpp
+++ b/tests/TessellatingPathRendererTests.cpp
@@ -379,8 +379,9 @@
     SkColor colors[2] = { SK_ColorGREEN, SK_ColorBLUE };
     sk_sp<SkShader> shader = SkGradientShader::MakeLinear(
         pts, colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode);
-    SkShaderBase::AsFPArgs args(
-        ctx, &SkMatrix::I(), &SkMatrix::I(), SkFilterQuality::kLow_SkFilterQuality, nullptr);
+    GrColorSpaceInfo colorSpaceInfo(nullptr, kRGBA_8888_GrPixelConfig);
+    SkShaderBase::AsFPArgs args(ctx, &SkMatrix::I(), &SkMatrix::I(),
+                                SkFilterQuality::kLow_SkFilterQuality, &colorSpaceInfo);
     return as_SB(shader)->asFragmentProcessor(args);
 }