Add SkPMColor4f support to SkSL

Convert GrConstColorProcessor to store SkPMColor4f

Bug: skia:
Change-Id: I6c505856653a02e576ae11fca59dc307545437f7
Reviewed-on: https://skia-review.googlesource.com/c/159152
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/gm/constcolorprocessor.cpp b/gm/constcolorprocessor.cpp
index e5d303f..aefba19 100644
--- a/gm/constcolorprocessor.cpp
+++ b/gm/constcolorprocessor.cpp
@@ -103,7 +103,7 @@
                                                     skPaint, viewMatrix, &grPaint));
 
                     GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m;
-                    GrColor4f color = GrColor4f::FromGrColor(kColors[procColor]);
+                    SkPMColor4f color = GrColorToPMColor4f(kColors[procColor]);
                     auto fp = GrConstColorProcessor::Make(color, mode);
 
                     grPaint.addColorFragmentProcessor(std::move(fp));
diff --git a/include/core/SkColor.h b/include/core/SkColor.h
index 5bca335..077547c 100644
--- a/include/core/SkColor.h
+++ b/include/core/SkColor.h
@@ -263,6 +263,11 @@
         return this->vec()[index];
     }
 
+    bool isOpaque() const {
+        SkASSERT(fA <= 1.0f && fA >= 0.0f);
+        return fA == 1.0f;
+    }
+
     static SkRGBA4f Pin(float r, float g, float b, float a);  // impl. depends on kAT
     SkRGBA4f pin() const { return Pin(fR, fG, fB, fA); }
 
diff --git a/include/private/GrColor.h b/include/private/GrColor.h
index c28ace1..88f0dbd 100644
--- a/include/private/GrColor.h
+++ b/include/private/GrColor.h
@@ -112,6 +112,14 @@
     rgba[3] = GrColorUnpackA(color) * ONE_OVER_255;
 }
 
+/** Converts a GrColor to an SkPMColor4f */
+static inline SkRGBA4f<kPremul_SkAlphaType> GrColorToPMColor4f(GrColor color) {
+    GrColorIsPMAssert(color);
+    SkRGBA4f<kPremul_SkAlphaType> result;
+    GrColorToRGBAFloat(color, result.vec());
+    return result;
+}
+
 /** Normalizes and coverts an uint8_t to a float. [0, 255] -> [0.0, 1.0] */
 static inline float GrNormalizeByteToFloat(uint8_t value) {
     static const float ONE_OVER_255 = 1.f / 255.f;
diff --git a/src/core/SkBlendMode.cpp b/src/core/SkBlendMode.cpp
index 56f57f4..d7f9ded 100644
--- a/src/core/SkBlendMode.cpp
+++ b/src/core/SkBlendMode.cpp
@@ -124,7 +124,7 @@
 SkPMColor4f SkBlendMode_Apply(SkBlendMode mode, const SkPMColor4f& src, const SkPMColor4f& dst) {
     // special-case simple/common modes...
     switch (mode) {
-        case SkBlendMode::kClear:   return { 0, 0, 0, 0 };
+        case SkBlendMode::kClear:   return SK_PMColor4fTRANSPARENT;
         case SkBlendMode::kSrc:     return src;
         case SkBlendMode::kDst:     return dst;
         case SkBlendMode::kSrcOver: {
diff --git a/src/core/SkModeColorFilter.cpp b/src/core/SkModeColorFilter.cpp
index ba75a19..20981d2 100644
--- a/src/core/SkModeColorFilter.cpp
+++ b/src/core/SkModeColorFilter.cpp
@@ -91,7 +91,7 @@
         return nullptr;
     }
 
-    auto constFP = GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpaceInfo),
+    auto constFP = GrConstColorProcessor::Make(SkColorToPMColor4f(fColor, dstColorSpaceInfo),
                                                GrConstColorProcessor::InputMode::kIgnore);
     auto fp = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode);
     if (!fp) {
diff --git a/src/core/SkPM4f.h b/src/core/SkPM4f.h
index a5e00a7..07d6733 100644
--- a/src/core/SkPM4f.h
+++ b/src/core/SkPM4f.h
@@ -46,4 +46,7 @@
 
 using SkPMColor4f = SkRGBA4f<kPremul_SkAlphaType>;
 
+constexpr SkPMColor4f SK_PMColor4fTRANSPARENT = { 0, 0, 0, 0 };
+constexpr SkPMColor4f SK_PMColor4fWHITE       = { 1, 1, 1, 1 };
+
 #endif
diff --git a/src/effects/imagefilters/SkArithmeticImageFilter.cpp b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
index 86ace3c..bd72e3a 100644
--- a/src/effects/imagefilters/SkArithmeticImageFilter.cpp
+++ b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
@@ -318,7 +318,7 @@
                                              background->alphaType(),
                                              outputProperties.colorSpace());
     } else {
-        bgFP = GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+        bgFP = GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                            GrConstColorProcessor::InputMode::kIgnore);
     }
 
diff --git a/src/effects/imagefilters/SkXfermodeImageFilter.cpp b/src/effects/imagefilters/SkXfermodeImageFilter.cpp
index 9dc577d..d7637f2 100644
--- a/src/effects/imagefilters/SkXfermodeImageFilter.cpp
+++ b/src/effects/imagefilters/SkXfermodeImageFilter.cpp
@@ -289,7 +289,7 @@
                                              background->alphaType(),
                                              outputProperties.colorSpace());
     } else {
-        bgFP = GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+        bgFP = GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                            GrConstColorProcessor::InputMode::kIgnore);
     }
 
diff --git a/src/gpu/GrColorSpaceXform.cpp b/src/gpu/GrColorSpaceXform.cpp
index fdcc0cd..fc0e934 100644
--- a/src/gpu/GrColorSpaceXform.cpp
+++ b/src/gpu/GrColorSpaceXform.cpp
@@ -54,6 +54,12 @@
     return result;
 }
 
+SkColor4f GrColorSpaceXform::apply(const SkColor4f& srcColor) {
+    SkColor4f result = srcColor;
+    fSteps.apply(result.vec());
+    return result;
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 class GrGLColorSpaceXformEffect : public GrGLSLFragmentProcessor {
diff --git a/src/gpu/GrColorSpaceXform.h b/src/gpu/GrColorSpaceXform.h
index 4542d5c..0cff9ef 100644
--- a/src/gpu/GrColorSpaceXform.h
+++ b/src/gpu/GrColorSpaceXform.h
@@ -39,6 +39,7 @@
     static bool Equals(const GrColorSpaceXform* a, const GrColorSpaceXform* b);
 
     GrColor4f apply(const GrColor4f& srcColor);
+    SkColor4f apply(const SkColor4f& srcColor);
 
 private:
     friend class GrGLSLColorSpaceXformHelper;
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index dde1875..550134b 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -265,7 +265,7 @@
 
         SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
             SkPMColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
-                                                                    { 1, 1, 1, 1 });
+                                                                    SK_PMColor4fWHITE);
             SkPMColor4f premulInput = SkColor4f{ input.fR, input.fG, input.fB, input.fA }.premul();
             return premulInput * childColor;
         }
@@ -454,7 +454,7 @@
     GrColorFragmentProcessorAnalysis info(inputColor, unique_ptr_address_as_pointer_address(series),
                                           cnt);
     SkTArray<std::unique_ptr<GrFragmentProcessor>> replacementSeries;
-    GrColor4f knownColor;
+    SkPMColor4f knownColor;
     int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
     if (leadingFPsToEliminate) {
         std::unique_ptr<GrFragmentProcessor> colorFP(
diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h
index f82146d..19ce61b 100644
--- a/src/gpu/GrFragmentProcessor.h
+++ b/src/gpu/GrFragmentProcessor.h
@@ -341,7 +341,7 @@
 private:
     virtual SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& /* inputColor */) const {
         SK_ABORT("Subclass must override this if advertising this optimization.");
-        return { 0, 0, 0, 0 };
+        return SK_PMColor4fTRANSPARENT;
     }
 
     /** Returns a new instance of the appropriate *GL* implementation class
diff --git a/src/gpu/GrProcessorAnalysis.cpp b/src/gpu/GrProcessorAnalysis.cpp
index e22f4c2..1d58870 100644
--- a/src/gpu/GrProcessorAnalysis.cpp
+++ b/src/gpu/GrProcessorAnalysis.cpp
@@ -30,7 +30,7 @@
         if (fKnowOutputColor &&
             fp->hasConstantOutputForConstantInput(fLastKnownOutputColor, &fLastKnownOutputColor)) {
             ++fProcessorsToEliminate;
-            fIsOpaque = fLastKnownOutputColor.fA >= 1.0f;
+            fIsOpaque = fLastKnownOutputColor.isOpaque();
             // We reset these since the caller is expected to not use the earlier fragment
             // processors.
             fCompatibleWithCoverageAsAlpha = true;
diff --git a/src/gpu/GrProcessorAnalysis.h b/src/gpu/GrProcessorAnalysis.h
index 85943e1..b7475db 100644
--- a/src/gpu/GrProcessorAnalysis.h
+++ b/src/gpu/GrProcessorAnalysis.h
@@ -129,9 +129,9 @@
         return fProcessorsToEliminate;
     }
 
-    int initialProcessorsToEliminate(GrColor4f* newPipelineInputColor) const {
+    int initialProcessorsToEliminate(SkPMColor4f* newPipelineInputColor) const {
         if (fProcessorsToEliminate > 0) {
-            *newPipelineInputColor = GrColor4f::FromRGBA4f(fLastKnownOutputColor);
+            *newPipelineInputColor = fLastKnownOutputColor;
         }
         return fProcessorsToEliminate;
     }
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 23d92b5..8f08d6d 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -271,6 +271,14 @@
     return color;
 }
 
+SkPMColor4f SkColorToPMColor4f(SkColor c, const GrColorSpaceInfo& colorSpaceInfo) {
+    SkColor4f color = SkColor4f::FromColor(c);
+    if (auto* xform = colorSpaceInfo.colorSpaceXformFromSRGB()) {
+        color = xform->apply(color);
+    }
+    return color.premul();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 GrPixelConfig SkColorType2GrPixelConfig(const SkColorType type) {
@@ -413,7 +421,7 @@
                 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
                 // color channels. It's value should be treated as the same in ANY color space.
                 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
-                    GrColor4f::FromGrColor(paintAlpha),
+                    GrColorToPMColor4f(paintAlpha),
                     GrConstColorProcessor::InputMode::kModulateRGBA));
             }
         } else {
@@ -425,8 +433,9 @@
         if (primColorMode) {
             // There is a blend between the primitive color and the paint color. The blend considers
             // the opaque paint color. The paint's alpha is applied to the post-blended color.
-            auto processor = GrConstColorProcessor::Make(origColor.opaque(),
-                                                         GrConstColorProcessor::InputMode::kIgnore);
+            auto processor = GrConstColorProcessor::Make(
+                    origColor.opaque().asRGBA4f<kPremul_SkAlphaType>(),
+                    GrConstColorProcessor::InputMode::kIgnore);
             processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
                                                                           *primColorMode);
             if (processor) {
@@ -441,7 +450,7 @@
                 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
                 // color channels. It's value should be treated as the same in ANY color space.
                 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
-                    GrColor4f::FromGrColor(paintAlpha),
+                    GrColorToPMColor4f(paintAlpha),
                     GrConstColorProcessor::InputMode::kModulateRGBA));
             }
         } else {
diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h
index f17c4af..cdc885a 100644
--- a/src/gpu/SkGr.h
+++ b/src/gpu/SkGr.h
@@ -63,6 +63,9 @@
 GrColor4f SkColor4fToPremulGrColor4fLegacy(SkColor4f);
 GrColor4f SkColor4fToUnpremulGrColor4f(SkColor4f, const GrColorSpaceInfo&);
 
+/** Similar, but using SkPMColor4f. */
+SkPMColor4f SkColorToPMColor4f(SkColor, const GrColorSpaceInfo&);
+
 ////////////////////////////////////////////////////////////////////////////////
 // Paint conversion
 
diff --git a/src/gpu/effects/GrConstColorProcessor.cpp b/src/gpu/effects/GrConstColorProcessor.cpp
index 5b07eca..7cf221b 100644
--- a/src/gpu/effects/GrConstColorProcessor.cpp
+++ b/src/gpu/effects/GrConstColorProcessor.cpp
@@ -44,14 +44,14 @@
                    const GrFragmentProcessor& _proc) override {
         const GrConstColorProcessor& _outer = _proc.cast<GrConstColorProcessor>();
         {
-            const GrColor4f& colorValue = _outer.color();
+            const SkPMColor4f& colorValue = _outer.color();
             if (fColorPrev != colorValue) {
                 fColorPrev = colorValue;
-                pdman.set4fv(fColorVar, 1, colorValue.fRGBA);
+                pdman.set4fv(fColorVar, 1, colorValue.vec());
             }
         }
     }
-    GrColor4f fColorPrev = GrColor4f::kIllegalConstructor;
+    SkPMColor4f fColorPrev = {SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN};
     UniformHandle fColorVar;
 };
 GrGLSLFragmentProcessor* GrConstColorProcessor::onCreateGLSLInstance() const {
@@ -78,7 +78,7 @@
 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConstColorProcessor);
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::TestCreate(GrProcessorTestData* d) {
-    GrColor4f color;
+    SkPMColor4f color;
     int colorPicker = d->fRandom->nextULessThan(3);
     switch (colorPicker) {
         case 0: {
@@ -86,15 +86,15 @@
             uint32_t r = d->fRandom->nextULessThan(a + 1);
             uint32_t g = d->fRandom->nextULessThan(a + 1);
             uint32_t b = d->fRandom->nextULessThan(a + 1);
-            color = GrColor4f::FromGrColor(GrColorPackRGBA(r, g, b, a));
+            color = GrColorToPMColor4f(GrColorPackRGBA(r, g, b, a));
             break;
         }
         case 1:
-            color = GrColor4f::TransparentBlack();
+            color = SK_PMColor4fTRANSPARENT;
             break;
         case 2:
             uint32_t c = d->fRandom->nextULessThan(0x100);
-            color = GrColor4f::FromGrColor(c | (c << 8) | (c << 16) | (c << 24));
+            color = GrColorToPMColor4f(c | (c << 8) | (c << 16) | (c << 24));
             break;
     }
     InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt));
diff --git a/src/gpu/effects/GrConstColorProcessor.fp b/src/gpu/effects/GrConstColorProcessor.fp
index adc1bb5..fd45328 100644
--- a/src/gpu/effects/GrConstColorProcessor.fp
+++ b/src/gpu/effects/GrConstColorProcessor.fp
@@ -13,7 +13,7 @@
     kLast = kModulateA
 };
 
-layout(ctype=GrColor4f, tracked) in uniform half4 color;
+layout(ctype=SkPMColor4f, tracked) in uniform half4 color;
 layout(key) in InputMode mode;
 
 @optimizationFlags {
@@ -37,7 +37,7 @@
 @class {
     static const int kInputModeCnt = (int) InputMode::kLast + 1;
 
-    static OptimizationFlags OptFlags(GrColor4f color, InputMode mode) {
+    static OptimizationFlags OptFlags(const SkPMColor4f& color, InputMode mode) {
         OptimizationFlags flags = kConstantOutputForConstantInput_OptimizationFlag;
         if (mode != InputMode::kIgnore) {
             flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
@@ -49,22 +49,21 @@
     }
 
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
-        SkPMColor4f color = fColor.asRGBA4f<kPremul_SkAlphaType>();
         switch (fMode) {
             case InputMode::kIgnore:
-                return color;
+                return fColor;
             case InputMode::kModulateA:
-                return color * input.fA;
+                return fColor * input.fA;
             case InputMode::kModulateRGBA:
-                return color * input;
+                return fColor * input;
         }
         SK_ABORT("Unexpected mode");
-        return { 0, 0, 0, 0 };
+        return SK_PMColor4fTRANSPARENT;
     }
 }
 
 @test(d) {
-    GrColor4f color;
+    SkPMColor4f color;
     int colorPicker = d->fRandom->nextULessThan(3);
     switch (colorPicker) {
         case 0: {
@@ -72,15 +71,15 @@
             uint32_t r = d->fRandom->nextULessThan(a+1);
             uint32_t g = d->fRandom->nextULessThan(a+1);
             uint32_t b = d->fRandom->nextULessThan(a+1);
-            color = GrColor4f::FromGrColor(GrColorPackRGBA(r, g, b, a));
+            color = GrColorToPMColor4f(GrColorPackRGBA(r, g, b, a));
             break;
         }
         case 1:
-            color = GrColor4f::TransparentBlack();
+            color = SK_PMColor4fTRANSPARENT;
             break;
         case 2:
             uint32_t c = d->fRandom->nextULessThan(0x100);
-            color = GrColor4f::FromGrColor(c | (c << 8) | (c << 16) | (c << 24));
+            color = GrColorToPMColor4f(c | (c << 8) | (c << 16) | (c << 24));
             break;
     }
     InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt));
diff --git a/src/gpu/effects/GrConstColorProcessor.h b/src/gpu/effects/GrConstColorProcessor.h
index c5cccc9..ca166f2 100644
--- a/src/gpu/effects/GrConstColorProcessor.h
+++ b/src/gpu/effects/GrConstColorProcessor.h
@@ -19,7 +19,7 @@
 
     static const int kInputModeCnt = (int)InputMode::kLast + 1;
 
-    static OptimizationFlags OptFlags(GrColor4f color, InputMode mode) {
+    static OptimizationFlags OptFlags(const SkPMColor4f& color, InputMode mode) {
         OptimizationFlags flags = kConstantOutputForConstantInput_OptimizationFlag;
         if (mode != InputMode::kIgnore) {
             flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
@@ -31,21 +31,20 @@
     }
 
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
-        SkPMColor4f color = fColor.asRGBA4f<kPremul_SkAlphaType>();
         switch (fMode) {
             case InputMode::kIgnore:
-                return color;
+                return fColor;
             case InputMode::kModulateA:
-                return color * input.fA;
+                return fColor * input.fA;
             case InputMode::kModulateRGBA:
-                return color * input;
+                return fColor * input;
         }
         SK_ABORT("Unexpected mode");
-        return {0, 0, 0, 0};
+        return SK_PMColor4fTRANSPARENT;
     }
-    const GrColor4f& color() const { return fColor; }
+    const SkPMColor4f& color() const { return fColor; }
     const InputMode& mode() const { return fMode; }
-    static std::unique_ptr<GrFragmentProcessor> Make(GrColor4f color, InputMode mode) {
+    static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f color, InputMode mode) {
         return std::unique_ptr<GrFragmentProcessor>(new GrConstColorProcessor(color, mode));
     }
     GrConstColorProcessor(const GrConstColorProcessor& src);
@@ -53,7 +52,7 @@
     const char* name() const override { return "ConstColorProcessor"; }
 
 private:
-    GrConstColorProcessor(GrColor4f color, InputMode mode)
+    GrConstColorProcessor(SkPMColor4f color, InputMode mode)
             : INHERITED(kGrConstColorProcessor_ClassID, (OptimizationFlags)OptFlags(color, mode))
             , fColor(color)
             , fMode(mode) {}
@@ -61,7 +60,7 @@
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
     bool onIsEqual(const GrFragmentProcessor&) const override;
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
-    GrColor4f fColor;
+    SkPMColor4f fColor;
     InputMode fMode;
     typedef GrFragmentProcessor INHERITED;
 };
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 251f127..4751fec 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -103,14 +103,14 @@
     // skip the draw or omit the clip element.
     if (!SkPathPriv::CheapComputeFirstDirection(path, &dir)) {
         if (GrProcessorEdgeTypeIsInverseFill(type)) {
-            return GrConstColorProcessor::Make(GrColor4f::OpaqueWhite(),
+            return GrConstColorProcessor::Make(SK_PMColor4fWHITE,
                                                GrConstColorProcessor::InputMode::kModulateRGBA);
         }
         // This could use kIgnore instead of kModulateRGBA but it would trigger a debug print
         // about a coverage processor not being compatible with the alpha-as-coverage optimization.
         // We don't really care about this unlikely case so we just use kModulateRGBA to suppress
         // the print.
-        return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+        return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                            GrConstColorProcessor::InputMode::kModulateRGBA);
     }
 
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index 9ed8345..aa81ea5 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -428,7 +428,7 @@
                                                               "Arithmetic", SKSL_ARITHMETIC_SRC,
                                                               &inputs, sizeof(inputs));
             result->addChild(GrConstColorProcessor::Make(
-                                                        GrColor4f::OpaqueWhite(),
+                                                        SK_PMColor4fWHITE,
                                                         GrConstColorProcessor::InputMode::kIgnore));
             return std::unique_ptr<GrFragmentProcessor>(result.release());
         }
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index 154322a..12cb1b6 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -245,7 +245,7 @@
         SkBlendMode mode) {
     switch (mode) {
         case SkBlendMode::kClear:
-            return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+            return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                                GrConstColorProcessor::InputMode::kIgnore);
         case SkBlendMode::kSrc:
             return src;
@@ -402,7 +402,7 @@
 
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inputColor) const override {
         SkPMColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
-                                                                { 1, 1, 1, 1 });
+                                                                SK_PMColor4fWHITE);
         SkPMColor4f src, dst;
         if (kSrc_Child == fChild) {
             src = childColor;
@@ -504,7 +504,7 @@
         std::unique_ptr<GrFragmentProcessor> dst, SkBlendMode mode) {
     switch (mode) {
         case SkBlendMode::kClear:
-            return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+            return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                                GrConstColorProcessor::InputMode::kIgnore);
         case SkBlendMode::kSrc:
             return nullptr;
@@ -518,7 +518,7 @@
         std::unique_ptr<GrFragmentProcessor> src, SkBlendMode mode) {
     switch (mode) {
         case SkBlendMode::kClear:
-            return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+            return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                                GrConstColorProcessor::InputMode::kIgnore);
         case SkBlendMode::kDst:
             return nullptr;
diff --git a/src/shaders/SkColorShader.cpp b/src/shaders/SkColorShader.cpp
index e887110..6858965 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 GrFPArgs& args) const {
-    GrColor4f color = SkColorToPremulGrColor4f(fColor, *args.fDstColorSpaceInfo);
+    SkPMColor4f color = SkColorToPMColor4f(fColor, *args.fDstColorSpaceInfo);
     return GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kModulateA);
 }
 
@@ -210,14 +210,10 @@
 
 std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(
         const GrFPArgs& args) const {
-    auto xform = GrColorSpaceXform::Make(
-            fColorSpace.get(),                     kUnpremul_SkAlphaType,
-            args.fDstColorSpaceInfo->colorSpace(), kUnpremul_SkAlphaType);
-
-    GrColor4f color = GrColor4f::FromRGBA4f(fColor4);
-    if (xform) {
-        color = xform->apply(color);
-    }
+    SkColorSpaceXformSteps steps{ fColorSpace.get(),                     kUnpremul_SkAlphaType,
+                                  args.fDstColorSpaceInfo->colorSpace(), kUnpremul_SkAlphaType };
+    SkColor4f color = fColor4;
+    steps.apply(color.vec());
     return GrConstColorProcessor::Make(color.premul(),
                                        GrConstColorProcessor::InputMode::kModulateA);
 }
diff --git a/src/shaders/SkComposeShader.cpp b/src/shaders/SkComposeShader.cpp
index 845d320..3e3d06d 100644
--- a/src/shaders/SkComposeShader.cpp
+++ b/src/shaders/SkComposeShader.cpp
@@ -123,7 +123,7 @@
     if (this->isJustMode()) {
         SkASSERT(fMode != SkBlendMode::kSrc && fMode != SkBlendMode::kDst); // caught in factory
         if (fMode == SkBlendMode::kClear) {
-            return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+            return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                                GrConstColorProcessor::InputMode::kIgnore);
         }
     }
diff --git a/src/shaders/SkPerlinNoiseShader.cpp b/src/shaders/SkPerlinNoiseShader.cpp
index 7153fa2..d778448 100644
--- a/src/shaders/SkPerlinNoiseShader.cpp
+++ b/src/shaders/SkPerlinNoiseShader.cpp
@@ -1442,12 +1442,12 @@
             // color space of the noise. Either way, this case (and the GLSL) need to convert to
             // the destination.
             auto inner =
-                    GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
+                    GrConstColorProcessor::Make(GrColorToPMColor4f(0x80404040),
                                                 GrConstColorProcessor::InputMode::kModulateRGBA);
             return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
         }
         // Emit zero.
-        return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+        return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                            GrConstColorProcessor::InputMode::kIgnore);
     }
 
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index 1a14cba..5882104 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -134,6 +134,8 @@
 static String default_value(const Variable& var) {
     if (var.fModifiers.fLayout.fCType == SkSL::Layout::CType::kGrColor4f) {
         return "GrColor4f::kIllegalConstructor";
+    } else if (var.fModifiers.fLayout.fCType == SkSL::Layout::CType::kSkPMColor4f) {
+        return "{SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN}";
     }
     return default_value(var.fType);
 }
@@ -181,6 +183,12 @@
                 fFormatArgs.push_back(cppCode + ".fRGBA[2]");
                 fFormatArgs.push_back(cppCode + ".fRGBA[3]");
                 break;
+            case Layout::CType::kSkPMColor4f:
+                fFormatArgs.push_back(cppCode + ".fR");
+                fFormatArgs.push_back(cppCode + ".fG");
+                fFormatArgs.push_back(cppCode + ".fB");
+                fFormatArgs.push_back(cppCode + ".fA");
+                break;
             case Layout::CType::kSkRect: // fall through
             case Layout::CType::kDefault:
                 fFormatArgs.push_back(cppCode + ".left()");
diff --git a/src/sksl/SkSLCPPUniformCTypes.cpp b/src/sksl/SkSLCPPUniformCTypes.cpp
index f48b9f9..0ff556c 100644
--- a/src/sksl/SkSLCPPUniformCTypes.cpp
+++ b/src/sksl/SkSLCPPUniformCTypes.cpp
@@ -161,6 +161,10 @@
         "${pdman}.set4fv(${uniform}, 1, ${var}.fRGBA)",                            // to gpu
         "GrColor4f::kIllegalConstructor"),                                         // default value
 
+    REGISTER(Layout::CType::kSkPMColor4f, { "half4", "float4", "double4" },
+        "${pdman}.set4fv(${uniform}, 1, ${var}.vec())",                            // to gpu
+        "{SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN}"),                   // default value
+
     REGISTER(Layout::CType::kSkPoint, { "half2", "float2", "double2" } ,
         "${pdman}.set2f(${uniform}, ${var}.fX, ${var}.fY)",                        // to gpu
         "SkPoint::Make(SK_FloatNaN, SK_FloatNaN)"),                                // default value
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index 412a09e..91f2168 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -122,6 +122,7 @@
     TOKEN(TRACKED,                      "tracked");
     TOKEN(CTYPE,                        "ctype");
     TOKEN(GRCOLOR4F,                    "GrColor4f");
+    TOKEN(SKPMCOLOR4F,                  "SkPMColor4f");
     TOKEN(SKRECT,                       "SkRect");
     TOKEN(SKIRECT,                      "SkIRect");
     TOKEN(SKPMCOLOR,                    "SkPMColor");
@@ -730,6 +731,8 @@
             switch (found->second) {
                 case LayoutToken::GRCOLOR4F:
                     return Layout::CType::kGrColor4f;
+                case LayoutToken::SKPMCOLOR4F:
+                    return Layout::CType::kSkPMColor4f;
                 case LayoutToken::SKRECT:
                     return Layout::CType::kSkRect;
                 case LayoutToken::SKIRECT:
diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h
index febc6bb..33bc10f 100644
--- a/src/sksl/SkSLParser.h
+++ b/src/sksl/SkSLParser.h
@@ -92,6 +92,7 @@
         TRACKED,
         CTYPE,
         GRCOLOR4F,
+        SKPMCOLOR4F,
         SKRECT,
         SKIRECT,
         SKPMCOLOR,
diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h
index 38295ce..29024e7 100644
--- a/src/sksl/ir/SkSLLayout.h
+++ b/src/sksl/ir/SkSLLayout.h
@@ -83,6 +83,7 @@
         kSkRect,
         kSkIRect,
         kGrColor4f,
+        kSkPMColor4f,
         kSkPMColor,
         kSkPoint,
         kSkIPoint,
@@ -150,6 +151,8 @@
                 return "SkIRect";
             case CType::kGrColor4f:
                 return "GrColor4f";
+            case CType::kSkPMColor4f:
+                return "SkPMColor4f";
             case CType::kSkPMColor:
                 return "SkPMColor";
             case CType::kSkPoint:
diff --git a/tests/DefaultPathRendererTest.cpp b/tests/DefaultPathRendererTest.cpp
index 61778ca..9596c00 100644
--- a/tests/DefaultPathRendererTest.cpp
+++ b/tests/DefaultPathRendererTest.cpp
@@ -90,7 +90,7 @@
 
         GrPaint paint;
 
-        const GrColor4f color = { 1.0f, 0.0f, 0.0f, 1.0f };
+        const SkPMColor4f color = { 1.0f, 0.0f, 0.0f, 1.0f };
         auto fp = GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kIgnore);
         paint.addColorFragmentProcessor(std::move(fp));
 
@@ -110,7 +110,7 @@
 
         GrPaint paint;
 
-        const GrColor4f color = { 0.0f, 1.0f, 0.0f, 1.0f };
+        const SkPMColor4f color = { 0.0f, 1.0f, 0.0f, 1.0f };
         auto fp = GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kIgnore);
         paint.addColorFragmentProcessor(std::move(fp));