converted ConstColorProcessor to SkSL

Bug: skia:
Change-Id: Ic3b18f82c1ab940637fb26dec1cf376dd859b35d
Reviewed-on: https://skia-review.googlesource.com/73720
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/core/SkModeColorFilter.cpp b/src/core/SkModeColorFilter.cpp
index 06e7469..0aca662 100644
--- a/src/core/SkModeColorFilter.cpp
+++ b/src/core/SkModeColorFilter.cpp
@@ -104,7 +104,7 @@
     }
 
     auto constFP = GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpaceInfo),
-                                               GrConstColorProcessor::kIgnore_InputMode);
+                                               GrConstColorProcessor::InputMode::kIgnore);
     auto fp = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode);
     if (!fp) {
         return nullptr;
diff --git a/src/effects/SkArithmeticImageFilter.cpp b/src/effects/SkArithmeticImageFilter.cpp
index 0a85cda..f3d0f03 100644
--- a/src/effects/SkArithmeticImageFilter.cpp
+++ b/src/effects/SkArithmeticImageFilter.cpp
@@ -316,7 +316,7 @@
                                              bgConfig, outputProperties.colorSpace());
     } else {
         bgFP = GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
-                                           GrConstColorProcessor::kIgnore_InputMode);
+                                           GrConstColorProcessor::InputMode::kIgnore);
     }
 
     if (foregroundProxy) {
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 57c4c57..42fb249 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -305,7 +305,7 @@
                                              bgConfig, outputProperties.colorSpace());
     } else {
         bgFP = GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
-                                           GrConstColorProcessor::kIgnore_InputMode);
+                                           GrConstColorProcessor::InputMode::kIgnore);
     }
 
     if (foregroundProxy) {
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index a50be79..0c7c06f 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -450,7 +450,7 @@
     int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
     if (leadingFPsToEliminate) {
         std::unique_ptr<GrFragmentProcessor> colorFP(
-                GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::kIgnore_InputMode));
+                GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::InputMode::kIgnore));
         if (leadingFPsToEliminate == cnt) {
             return colorFP;
         }
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 684d4d7..def99c3 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -479,7 +479,7 @@
                 // color channels. It's value should be treated as the same in ANY color space.
                 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
                     GrColor4f::FromGrColor(paintAlpha),
-                    GrConstColorProcessor::kModulateRGBA_InputMode));
+                    GrConstColorProcessor::InputMode::kModulateRGBA));
             }
         } else {
             // The shader's FP sees the paint unpremul color
@@ -491,7 +491,7 @@
             // 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::kIgnore_InputMode);
+                                                         GrConstColorProcessor::InputMode::kIgnore);
             processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
                                                                           *primColorMode);
             if (processor) {
@@ -507,7 +507,7 @@
                 // color channels. It's value should be treated as the same in ANY color space.
                 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
                     GrColor4f::FromGrColor(paintAlpha),
-                    GrConstColorProcessor::kModulateRGBA_InputMode));
+                    GrConstColorProcessor::InputMode::kModulateRGBA));
             }
         } else {
             // No shader, no primitive color.
diff --git a/src/gpu/effects/GrAARectEffect.cpp b/src/gpu/effects/GrAARectEffect.cpp
index fcc54dc..0e49e0f 100644
--- a/src/gpu/effects/GrAARectEffect.cpp
+++ b/src/gpu/effects/GrAARectEffect.cpp
@@ -74,7 +74,7 @@
             prevRect = newRect;
         }
     }
-    SkRect prevRect;
+    SkRect prevRect = float4(0);
     UniformHandle fRectUniformVar;
 };
 GrGLSLFragmentProcessor* GrAARectEffect::onCreateGLSLInstance() const {
diff --git a/src/gpu/effects/GrCircleEffect.cpp b/src/gpu/effects/GrCircleEffect.cpp
index d3eecb7..3bd2138 100644
--- a/src/gpu/effects/GrCircleEffect.cpp
+++ b/src/gpu/effects/GrCircleEffect.cpp
@@ -75,8 +75,8 @@
             prevRadius = radius;
         }
     }
-    SkPoint prevCenter;
-    float prevRadius;
+    SkPoint prevCenter = half2(0);
+    float prevRadius = 0;
     UniformHandle fCircleVar;
 };
 GrGLSLFragmentProcessor* GrCircleEffect::onCreateGLSLInstance() const {
diff --git a/src/gpu/effects/GrConstColorProcessor.cpp b/src/gpu/effects/GrConstColorProcessor.cpp
index 7051872..b2ac825 100644
--- a/src/gpu/effects/GrConstColorProcessor.cpp
+++ b/src/gpu/effects/GrConstColorProcessor.cpp
@@ -1,102 +1,88 @@
 /*
- * Copyright 2015 Google Inc.
+ * Copyright 2017 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#include "effects/GrConstColorProcessor.h"
+/*
+ * This file was autogenerated from GrConstColorProcessor.fp; do not modify.
+ */
+#include "GrConstColorProcessor.h"
+#if SK_SUPPORT_GPU
 #include "glsl/GrGLSLFragmentProcessor.h"
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
-#include "glsl/GrGLSLProgramDataManager.h"
-#include "glsl/GrGLSLUniformHandler.h"
-
-class GLConstColorProcessor : public GrGLSLFragmentProcessor {
+#include "glsl/GrGLSLProgramBuilder.h"
+#include "SkSLCPP.h"
+#include "SkSLUtil.h"
+class GrGLSLConstColorProcessor : public GrGLSLFragmentProcessor {
 public:
-    GLConstColorProcessor() : fPrevColor(GrColor4f::kIllegalConstructor) {}
-
+    GrGLSLConstColorProcessor() {}
     void emitCode(EmitArgs& args) override {
         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-        const char* colorUni;
-        fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                         kHalf4_GrSLType,
-                                                         "constantColor",
-                                                         &colorUni);
-        GrConstColorProcessor::InputMode mode = args.fFp.cast<GrConstColorProcessor>().inputMode();
-        if (!args.fInputColor) {
-            mode = GrConstColorProcessor::kIgnore_InputMode;
-        }
-        switch (mode) {
-            case GrConstColorProcessor::kIgnore_InputMode:
-                fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, colorUni);
-                break;
-            case GrConstColorProcessor::kModulateRGBA_InputMode:
-                fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputColor, args.fInputColor,
-                                       colorUni);
-                break;
-            case GrConstColorProcessor::kModulateA_InputMode:
-                fragBuilder->codeAppendf("%s = %s.a * %s;", args.fOutputColor, args.fInputColor,
-                                       colorUni);
-                break;
-        }
-    }
-
-protected:
-    void onSetData(const GrGLSLProgramDataManager& pdm,
-                   const GrFragmentProcessor& processor) override {
-        GrColor4f color = processor.cast<GrConstColorProcessor>().color();
-        // We use the "illegal" color value as an uninit sentinel. With GrColor4f, the "illegal"
-        // color is *really* illegal (not just unpremultiplied), so this check is simple.
-        if (fPrevColor != color) {
-            pdm.set4fv(fColorUniform, 1, color.fRGBA);
-            fPrevColor = color;
-        }
+        const GrConstColorProcessor& _outer = args.fFp.cast<GrConstColorProcessor>();
+        (void)_outer;
+        auto color = _outer.color();
+        (void)color;
+        auto mode = _outer.mode();
+        (void)mode;
+        fColorUniformVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
+                                                            kDefault_GrSLPrecision, "colorUniform");
+        fragBuilder->codeAppendf(
+                "half4 prevColor;\n@switch (%d) {\n    case 0:\n        %s = %s;\n        break;\n "
+                "   case 1:\n        %s = %s * %s;\n        break;\n    case 2:\n        %s = %s.w "
+                "* %s;\n        break;\n}\n",
+                (int)_outer.mode(), args.fOutputColor,
+                args.fUniformHandler->getUniformCStr(fColorUniformVar), args.fOutputColor,
+                args.fInputColor ? args.fInputColor : "half4(1)",
+                args.fUniformHandler->getUniformCStr(fColorUniformVar), args.fOutputColor,
+                args.fInputColor ? args.fInputColor : "half4(1)",
+                args.fUniformHandler->getUniformCStr(fColorUniformVar));
     }
 
 private:
-    GrGLSLProgramDataManager::UniformHandle fColorUniform;
-    GrColor4f                               fPrevColor;
+    void onSetData(const GrGLSLProgramDataManager& pdman,
+                   const GrFragmentProcessor& _proc) override {
+        const GrConstColorProcessor& _outer = _proc.cast<GrConstColorProcessor>();
+        auto color = _outer.color();
+        (void)color;
+        UniformHandle& colorUniform = fColorUniformVar;
+        (void)colorUniform;
+        auto mode = _outer.mode();
+        (void)mode;
 
-    typedef GrGLSLFragmentProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::clone() const {
-    return Make(fColor, fMode);
-}
-
-GrColor4f GrConstColorProcessor::constantOutputForConstantInput(GrColor4f input) const {
-    switch (fMode) {
-        case kIgnore_InputMode:
-            return fColor;
-        case kModulateA_InputMode:
-            return fColor.mulByScalar(input.fRGBA[3]);
-        case kModulateRGBA_InputMode:
-            return fColor.modulate(input);
+        // We use the "illegal" color value as an uninit sentinel. With GrColor4f, the "illegal"
+        // color is *really* illegal (not just unpremultiplied), so this check is simple.
+        if (prevColor != color) {
+            pdman.set4fv(colorUniform, 1, color.fRGBA);
+            prevColor = color;
+        }
     }
-    SK_ABORT("Unexpected mode");
-    return GrColor4f::TransparentBlack();
+    GrColor4f prevColor = GrColor4f::kIllegalConstructor;
+    UniformHandle fColorUniformVar;
+};
+GrGLSLFragmentProcessor* GrConstColorProcessor::onCreateGLSLInstance() const {
+    return new GrGLSLConstColorProcessor();
 }
-
-void GrConstColorProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
+void GrConstColorProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                                   GrProcessorKeyBuilder* b) const {
-    b->add32(fMode);
+    b->add32((int32_t)fMode);
 }
-
-GrGLSLFragmentProcessor* GrConstColorProcessor::onCreateGLSLInstance() const  {
-    return new GLConstColorProcessor;
-}
-
 bool GrConstColorProcessor::onIsEqual(const GrFragmentProcessor& other) const {
     const GrConstColorProcessor& that = other.cast<GrConstColorProcessor>();
-    return fMode == that.fMode && fColor == that.fColor;
+    (void)that;
+    if (fColor != that.fColor) return false;
+    if (fMode != that.fMode) return false;
+    return true;
 }
-
-///////////////////////////////////////////////////////////////////////////////
-
+GrConstColorProcessor::GrConstColorProcessor(const GrConstColorProcessor& src)
+        : INHERITED(kGrConstColorProcessor_ClassID, src.optimizationFlags())
+        , fColor(src.fColor)
+        , fMode(src.fMode) {}
+std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::clone() const {
+    return std::unique_ptr<GrFragmentProcessor>(new GrConstColorProcessor(*this));
+}
 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConstColorProcessor);
-
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::TestCreate(GrProcessorTestData* d) {
     GrColor4f color;
@@ -104,9 +90,9 @@
     switch (colorPicker) {
         case 0: {
             uint32_t a = d->fRandom->nextULessThan(0x100);
-            uint32_t r = d->fRandom->nextULessThan(a+1);
-            uint32_t g = d->fRandom->nextULessThan(a+1);
-            uint32_t b = d->fRandom->nextULessThan(a+1);
+            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));
             break;
         }
@@ -122,3 +108,4 @@
     return GrConstColorProcessor::Make(color, mode);
 }
 #endif
+#endif
diff --git a/src/gpu/effects/GrConstColorProcessor.fp b/src/gpu/effects/GrConstColorProcessor.fp
new file mode 100644
index 0000000..d7db4f0
--- /dev/null
+++ b/src/gpu/effects/GrConstColorProcessor.fp
@@ -0,0 +1,91 @@
+enum class InputMode {
+    kIgnore,
+    kModulateRGBA,
+    kModulateA,
+
+    kLast = kModulateA
+};
+
+layout(ctype=GrColor4f) in half4 color;
+uniform half4 colorUniform;
+layout(ctype=GrColor4f) half4 prevColor;
+layout(key) in InputMode mode;
+
+@optimizationFlags {
+    OptFlags(color, mode)
+}
+
+void main() {
+    @switch (mode) {
+        case InputMode::kIgnore:
+            sk_OutColor = colorUniform;
+            break;
+        case InputMode::kModulateRGBA:
+            sk_OutColor = sk_InColor * colorUniform;
+            break;
+        case InputMode::kModulateA:
+            sk_OutColor = sk_InColor.a * colorUniform;
+            break;
+    }
+}
+
+@setData(pdman) {
+    // We use the "illegal" color value as an uninit sentinel. With GrColor4f, the "illegal"
+    // color is *really* illegal (not just unpremultiplied), so this check is simple.
+    if (prevColor != color) {
+        pdman.set4fv(colorUniform, 1, color.fRGBA);
+        prevColor = color;
+    }
+}
+
+@class {
+    static const int kInputModeCnt = (int) InputMode::kLast + 1;
+
+    static OptimizationFlags OptFlags(GrColor4f color, InputMode mode) {
+        OptimizationFlags flags = kConstantOutputForConstantInput_OptimizationFlag;
+        if (mode != InputMode::kIgnore) {
+            flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
+        }
+        if (color.isOpaque()) {
+            flags |= kPreservesOpaqueInput_OptimizationFlag;
+        }
+        return flags;
+    }
+
+    GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
+        switch (fMode) {
+            case InputMode::kIgnore:
+                return fColor;
+            case InputMode::kModulateA:
+                return fColor.mulByScalar(input.fRGBA[3]);
+            case InputMode::kModulateRGBA:
+                return fColor.modulate(input);
+        }
+        SK_ABORT("Unexpected mode");
+        return GrColor4f::TransparentBlack();
+    }
+}
+
+@test(d) {
+    GrColor4f color;
+    int colorPicker = d->fRandom->nextULessThan(3);
+    switch (colorPicker) {
+        case 0: {
+            uint32_t a = d->fRandom->nextULessThan(0x100);
+            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));
+            break;
+        }
+        case 1:
+            color = GrColor4f::TransparentBlack();
+            break;
+        case 2:
+            uint32_t c = d->fRandom->nextULessThan(0x100);
+            color = GrColor4f::FromGrColor(c | (c << 8) | (c << 16) | (c << 24));
+            break;
+    }
+    InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt));
+    return GrConstColorProcessor::Make(color, mode);
+}
\ No newline at end of file
diff --git a/src/gpu/effects/GrConstColorProcessor.h b/src/gpu/effects/GrConstColorProcessor.h
index 1429e9b..62a9a0c 100644
--- a/src/gpu/effects/GrConstColorProcessor.h
+++ b/src/gpu/effects/GrConstColorProcessor.h
@@ -1,53 +1,28 @@
 /*
- * Copyright 2015 Google Inc.
+ * Copyright 2017 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef GrColorProcessor_DEFINED
-#define GrColorProcessor_DEFINED
-
-#include "GrFragmentProcessor.h"
-
-/**
- * This is a simple GrFragmentProcessor that outputs a constant color. It may do one of the
- * following with its input color: ignore it, or multiply it by the constant color, multiply its
- * alpha by the constant color and ignore the input color's r, g, and b.
+/*
+ * This file was autogenerated from GrConstColorProcessor.fp; do not modify.
  */
+#ifndef GrConstColorProcessor_DEFINED
+#define GrConstColorProcessor_DEFINED
+#include "SkTypes.h"
+#if SK_SUPPORT_GPU
+#include "GrFragmentProcessor.h"
+#include "GrCoordTransform.h"
 class GrConstColorProcessor : public GrFragmentProcessor {
 public:
-    enum InputMode {
-        kIgnore_InputMode,
-        kModulateRGBA_InputMode,
-        kModulateA_InputMode,
+    enum class InputMode { kLast = 2, kModulateA = 2, kModulateRGBA = 1, kIgnore = 0 };
 
-        kLastInputMode = kModulateA_InputMode
-    };
-    static const int kInputModeCnt = kLastInputMode + 1;
+    static const int kInputModeCnt = (int)InputMode::kLast + 1;
 
-    static std::unique_ptr<GrFragmentProcessor> Make(GrColor4f color, InputMode mode) {
-        return std::unique_ptr<GrFragmentProcessor>(new GrConstColorProcessor(color, mode));
-    }
-
-    const char* name() const override { return "Color"; }
-
-    SkString dumpInfo() const override {
-        SkString str;
-        str.appendf("Color: 0x%08x", fColor.toGrColor());
-        return str;
-    }
-
-    std::unique_ptr<GrFragmentProcessor> clone() const override;
-
-    GrColor4f color() const { return fColor; }
-
-    InputMode inputMode() const { return fMode; }
-
-private:
     static OptimizationFlags OptFlags(GrColor4f color, InputMode mode) {
         OptimizationFlags flags = kConstantOutputForConstantInput_OptimizationFlag;
-        if (mode != kIgnore_InputMode) {
+        if (mode != InputMode::kIgnore) {
             flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
         }
         if (color.isOpaque()) {
@@ -56,27 +31,39 @@
         return flags;
     }
 
-    GrConstColorProcessor(GrColor4f color, InputMode mode)
-            : INHERITED(kGrConstColorProcessor_ClassID
-            , OptFlags(color, mode))
-            , fColor(color)
-            , fMode(mode) {
+    GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
+        switch (fMode) {
+            case InputMode::kIgnore:
+                return fColor;
+            case InputMode::kModulateA:
+                return fColor.mulByScalar(input.fRGBA[3]);
+            case InputMode::kModulateRGBA:
+                return fColor.modulate(input);
+        }
+        SK_ABORT("Unexpected mode");
+        return GrColor4f::TransparentBlack();
     }
+    GrColor4f color() const { return fColor; }
+    InputMode mode() const { return fMode; }
+    static std::unique_ptr<GrFragmentProcessor> Make(GrColor4f color, InputMode mode) {
+        return std::unique_ptr<GrFragmentProcessor>(new GrConstColorProcessor(color, mode));
+    }
+    GrConstColorProcessor(const GrConstColorProcessor& src);
+    std::unique_ptr<GrFragmentProcessor> clone() const override;
+    const char* name() const override { return "ConstColorProcessor"; }
 
+private:
+    GrConstColorProcessor(GrColor4f color, InputMode mode)
+            : INHERITED(kGrConstColorProcessor_ClassID, (OptimizationFlags)OptFlags(color, mode))
+            , fColor(color)
+            , fMode(mode) {}
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
-
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
-
     bool onIsEqual(const GrFragmentProcessor&) const override;
-
-    GrColor4f constantOutputForConstantInput(GrColor4f input) const override;
-
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
-
-    GrColor4f   fColor;
-    InputMode   fMode;
-
+    GrColor4f fColor;
+    InputMode fMode;
     typedef GrFragmentProcessor INHERITED;
 };
-
+#endif
 #endif
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 6df92ee..753d34e 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -105,14 +105,14 @@
     if (!SkPathPriv::CheapComputeFirstDirection(path, &dir)) {
         if (GrProcessorEdgeTypeIsInverseFill(type)) {
             return GrConstColorProcessor::Make(GrColor4f::OpaqueWhite(),
-                                               GrConstColorProcessor::kModulateRGBA_InputMode);
+                                               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(),
-                                           GrConstColorProcessor::kModulateRGBA_InputMode);
+                                           GrConstColorProcessor::InputMode::kModulateRGBA);
     }
 
     SkScalar        edges[3 * kMaxEdges];
diff --git a/src/gpu/effects/GrEllipseEffect.cpp b/src/gpu/effects/GrEllipseEffect.cpp
index 6b1a8cc..b41af39 100644
--- a/src/gpu/effects/GrEllipseEffect.cpp
+++ b/src/gpu/effects/GrEllipseEffect.cpp
@@ -98,9 +98,9 @@
             prevRadii = radii;
         }
     }
-    SkPoint prevCenter;
-    SkPoint prevRadii;
-    bool useScale;
+    SkPoint prevCenter = float2(0);
+    SkPoint prevRadii = float2(0);
+    bool useScale = false;
     UniformHandle fEllipseVar;
     UniformHandle fScaleVar;
 };
diff --git a/src/gpu/effects/GrRectBlurEffect.cpp b/src/gpu/effects/GrRectBlurEffect.cpp
index 940674e..573c131 100644
--- a/src/gpu/effects/GrRectBlurEffect.cpp
+++ b/src/gpu/effects/GrRectBlurEffect.cpp
@@ -124,7 +124,7 @@
 
         pdman.set1f(profileSize, SkScalarCeilToScalar(6 * sigma));
     }
-    bool highPrecision;
+    bool highPrecision = false;
     UniformHandle fProxyRectHalfVar;
     UniformHandle fProxyRectFloatVar;
     UniformHandle fProfileSizeVar;
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index 4a92289..6b764f4 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -249,7 +249,7 @@
     switch (mode) {
         case SkBlendMode::kClear:
             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
-                                               GrConstColorProcessor::kIgnore_InputMode);
+                                               GrConstColorProcessor::InputMode::kIgnore);
         case SkBlendMode::kSrc:
             return src;
         case SkBlendMode::kDst:
@@ -516,7 +516,7 @@
     switch (mode) {
         case SkBlendMode::kClear:
             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
-                                               GrConstColorProcessor::kIgnore_InputMode);
+                                               GrConstColorProcessor::InputMode::kIgnore);
         case SkBlendMode::kSrc:
             return nullptr;
         default:
@@ -530,7 +530,7 @@
     switch (mode) {
         case SkBlendMode::kClear:
             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
-                                               GrConstColorProcessor::kIgnore_InputMode);
+                                               GrConstColorProcessor::InputMode::kIgnore);
         case SkBlendMode::kDst:
             return nullptr;
         default:
diff --git a/src/shaders/SkColorShader.cpp b/src/shaders/SkColorShader.cpp
index 8618987..74680d6 100644
--- a/src/shaders/SkColorShader.cpp
+++ b/src/shaders/SkColorShader.cpp
@@ -92,7 +92,7 @@
 std::unique_ptr<GrFragmentProcessor> SkColorShader::asFragmentProcessor(
         const AsFPArgs& args) const {
     GrColor4f color = SkColorToPremulGrColor4f(fColor, *args.fDstColorSpaceInfo);
-    return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode);
+    return GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kModulateA);
 }
 
 #endif
@@ -219,7 +219,8 @@
     if (colorSpaceXform) {
         color = colorSpaceXform->clampedXform(color);
     }
-    return GrConstColorProcessor::Make(color.premul(), GrConstColorProcessor::kModulateA_InputMode);
+    return GrConstColorProcessor::Make(color.premul(),
+                                       GrConstColorProcessor::InputMode::kModulateA);
 }
 
 #endif
diff --git a/src/shaders/SkComposeShader.cpp b/src/shaders/SkComposeShader.cpp
index a587f52..34e5486 100644
--- a/src/shaders/SkComposeShader.cpp
+++ b/src/shaders/SkComposeShader.cpp
@@ -129,7 +129,7 @@
         SkASSERT(fMode != SkBlendMode::kSrc && fMode != SkBlendMode::kDst); // caught in factory
         if (fMode == SkBlendMode::kClear) {
             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
-                                               GrConstColorProcessor::kIgnore_InputMode);
+                                               GrConstColorProcessor::InputMode::kIgnore);
         }
     }
 
diff --git a/src/shaders/SkPerlinNoiseShader.cpp b/src/shaders/SkPerlinNoiseShader.cpp
index 6a59e89..6c53401 100644
--- a/src/shaders/SkPerlinNoiseShader.cpp
+++ b/src/shaders/SkPerlinNoiseShader.cpp
@@ -1426,12 +1426,12 @@
             // the destination.
             auto inner =
                     GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
-                                                GrConstColorProcessor::kModulateRGBA_InputMode);
+                                                GrConstColorProcessor::InputMode::kModulateRGBA);
             return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
         }
         // Emit zero.
         return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
-                                           GrConstColorProcessor::kIgnore_InputMode);
+                                           GrConstColorProcessor::InputMode::kIgnore);
     }
 
     sk_sp<GrTextureProxy> permutationsProxy = GrMakeCachedBitmapProxy(
diff --git a/src/sksl/SkSLCPP.h b/src/sksl/SkSLCPP.h
index 970e2c7..fc9cafa 100644
--- a/src/sksl/SkSLCPP.h
+++ b/src/sksl/SkSLCPP.h
@@ -15,6 +15,28 @@
 
 using std::abs;
 
+struct Float4 {
+    Float4(float x, float y, float z, float w)
+    : fX(x)
+    , fY(y)
+    , fZ(z)
+    , fW(w) {}
+
+    operator SkRect() const {
+        return SkRect::MakeLTRB(fX, fY, fZ, fW);
+    }
+
+    operator GrColor4f() const {
+        return GrColor4f(fX, fY, fZ, fW);
+    }
+
+private:
+    float fX;
+    float fY;
+    float fZ;
+    float fW;
+};
+
 // macros to make sk_Caps.<cap name> work from C++ code
 #define sk_Caps (*args.fShaderCaps)
 
@@ -25,10 +47,14 @@
 
 inline SkPoint float2(float x, float y) { return SkPoint::Make(x, y); }
 
-inline SkRect float4(float ltrb) { return SkRect::MakeLTRB(ltrb, ltrb, ltrb, ltrb); }
+inline Float4 float4(float xyzw) { return Float4(xyzw, xyzw, xyzw, xyzw); }
 
-inline SkRect float4(float l, float t, float r, float b) { return SkRect::MakeLTRB(l, t, r, b); }
+inline Float4 float4(float x, float y, float z, float w) { return Float4(x, y, z, w); }
 
 #define half2 float2
 
+#define half3 float3
+
+#define half4 float4
+
 #endif
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index fc2a6e3..5b0b497 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -115,6 +115,9 @@
 }
 
 static String default_value(const Type& type) {
+    if (type.fName == "bool") {
+        return "false";
+    }
     switch (type.kind()) {
         case Type::kScalar_Kind: return "0";
         case Type::kVector_Kind: return type.name() + "(0)";
@@ -123,6 +126,13 @@
     }
 }
 
+static String default_value(const Variable& var) {
+    if (var.fModifiers.fLayout.fCType == "GrColor4f") {
+        return "GrColor4f::kIllegalConstructor";
+    }
+    return default_value(var.fType);
+}
+
 static bool is_private(const Variable& var) {
     return !(var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
            !(var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
@@ -152,6 +162,11 @@
             fFormatArgs.push_back("SkGetPackedG32(" + cppCode + ") / 255.0");
             fFormatArgs.push_back("SkGetPackedB32(" + cppCode + ") / 255.0");
             fFormatArgs.push_back("SkGetPackedA32(" + cppCode + ") / 255.0");
+        } else if (layout.fCType == "GrColor4f") {
+            fFormatArgs.push_back(cppCode + ".fRGBA[0]");
+            fFormatArgs.push_back(cppCode + ".fRGBA[1]");
+            fFormatArgs.push_back(cppCode + ".fRGBA[2]");
+            fFormatArgs.push_back(cppCode + ".fRGBA[3]");
         } else {
             fFormatArgs.push_back(cppCode + ".left()");
             fFormatArgs.push_back(cppCode + ".top()");
@@ -424,10 +439,11 @@
                                       "fragmentProcessor variables must be declared 'in'");
                         return;
                     }
-                    this->writef("%s %s;\n",
+                    this->writef("%s %s = %s;\n",
                                  HCodeGenerator::FieldType(fContext, decl.fVar->fType,
                                                            decl.fVar->fModifiers.fLayout).c_str(),
-                                 String(decl.fVar->fName).c_str());
+                                 String(decl.fVar->fName).c_str(),
+                                 default_value(*decl.fVar).c_str());
                 }
             }
         }
diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp
index 37eef60..819b85a 100644
--- a/src/sksl/SkSLHCodeGenerator.cpp
+++ b/src/sksl/SkSLHCodeGenerator.cpp
@@ -266,12 +266,12 @@
     this->writef("class %s : public GrFragmentProcessor {\n"
                  "public:\n",
                  fFullName.c_str());
-    this->writeSection(CLASS_SECTION);
     for (const auto& p : fProgram.fElements) {
         if (ProgramElement::kEnum_Kind == p->fKind && !((Enum&) *p).fBuiltin) {
             this->writef("%s\n", p->description().c_str());
         }
     }
+    this->writeSection(CLASS_SECTION);
     for (const auto& param : fSectionAndParameterHelper.getParameters()) {
         if (param->fType.kind() == Type::kSampler_Kind ||
             param->fType.kind() == Type::kOther_Kind) {
diff --git a/src/sksl/SkSLString.cpp b/src/sksl/SkSLString.cpp
index bd6de35..c9242d3 100644
--- a/src/sksl/SkSLString.cpp
+++ b/src/sksl/SkSLString.cpp
@@ -148,11 +148,21 @@
 }
 
 bool StringFragment::operator==(const char* s) const {
-    return !strncmp(fChars, s, fLength);
+    for (size_t i = 0; i < fLength; ++i) {
+        if (fChars[i] != s[i]) {
+            return false;
+        }
+    }
+    return 0 == s[fLength];
 }
 
 bool StringFragment::operator!=(const char* s) const {
-    return strncmp(fChars, s, fLength);
+    for (size_t i = 0; i < fLength; ++i) {
+        if (fChars[i] != s[i]) {
+            return true;
+        }
+    }
+    return 0 != s[fLength];
 }
 
 bool operator==(const char* s1, StringFragment s2) {