Convert the dither runtime effect into a regular .fp effect.

This was previously implemented as a runtime effect in order to dogfood
runtime effects when they were new. However, runtime effects do not
support passing a color to a FP via `sample(fp, inputColor)`, which
is needed to properly implement SkPaintToGrPaint.

Change-Id: Ic826860ab06038f13633be677d79a9138d41db85
Bug: skia:10217
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/301547
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 3f918e2..d6c9371 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -328,6 +328,8 @@
   "$_src/gpu/effects/generated/GrConstColorProcessor.h",
   "$_src/gpu/effects/generated/GrDeviceSpaceEffect.cpp",
   "$_src/gpu/effects/generated/GrDeviceSpaceEffect.h",
+  "$_src/gpu/effects/generated/GrDitherEffect.cpp",
+  "$_src/gpu/effects/generated/GrDitherEffect.h",
   "$_src/gpu/effects/generated/GrEllipseEffect.cpp",
   "$_src/gpu/effects/generated/GrEllipseEffect.h",
   "$_src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp",
diff --git a/gn/sksl.gni b/gn/sksl.gni
index aa80bd7..6c0454a 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -88,6 +88,7 @@
   "$_src/gpu/effects/GrConfigConversionEffect.fp",
   "$_src/gpu/effects/GrConstColorProcessor.fp",
   "$_src/gpu/effects/GrDeviceSpaceEffect.fp",
+  "$_src/gpu/effects/GrDitherEffect.fp",
   "$_src/gpu/effects/GrEllipseEffect.fp",
   "$_src/gpu/effects/GrHSLToRGBFilterEffect.fp",
   "$_src/gpu/effects/GrLumaColorFilterEffect.fp",
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index 1f1a20a..e905f94 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -105,6 +105,7 @@
         kGrDistanceFieldA8TextGeoProc_ClassID,
         kGrDistanceFieldLCDTextGeoProc_ClassID,
         kGrDistanceFieldPathGeoProc_ClassID,
+        kGrDitherEffect_ClassID,
         kGrDualIntervalGradientColorizer_ClassID,
         kGrEllipseEffect_ClassID,
         kGrFillRRectOp_Processor_ClassID,
diff --git a/src/gpu/GrProcessorUnitTest.cpp b/src/gpu/GrProcessorUnitTest.cpp
index e4e4b98..f584171 100644
--- a/src/gpu/GrProcessorUnitTest.cpp
+++ b/src/gpu/GrProcessorUnitTest.cpp
@@ -81,7 +81,7 @@
  * we verify the count is as expected.  If a new factory is added, then these numbers must be
  * manually adjusted.
  */
-static const int kFPFactoryCount = 34;
+static const int kFPFactoryCount = 35;
 static const int kGPFactoryCount = 14;
 static const int kXPFactoryCount = 4;
 
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 6c0a2b5..46514d5 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -41,54 +41,13 @@
 #include "src/gpu/GrXferProcessor.h"
 #include "src/gpu/effects/GrBicubicEffect.h"
 #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
-#include "src/gpu/effects/GrSkSLFP.h"
 #include "src/gpu/effects/GrXfermodeFragmentProcessor.h"
 #include "src/gpu/effects/generated/GrClampFragmentProcessor.h"
 #include "src/gpu/effects/generated/GrConstColorProcessor.h"
+#include "src/gpu/effects/generated/GrDitherEffect.h"
 #include "src/image/SkImage_Base.h"
 #include "src/shaders/SkShaderBase.h"
 
-GR_FP_SRC_STRING SKSL_DITHER_SRC = R"(
-// This controls the range of values added to color channels and is based on the destination color
-// type; as such it doesn't really affect our program cache to have a variant per-range.
-in half range;
-
-void main(inout half4 color) {
-    half value;
-    @if (sk_Caps.integerSupport)
-    {
-        // This ordered-dither code is lifted from the cpu backend.
-        uint x = uint(sk_FragCoord.x);
-        uint y = uint(sk_FragCoord.y) ^ x;
-        uint m = (y & 1) << 5 | (x & 1) << 4 |
-                 (y & 2) << 2 | (x & 2) << 1 |
-                 (y & 4) >> 1 | (x & 4) >> 2;
-        value = half(m) * 1.0 / 64.0 - 63.0 / 128.0;
-    } else {
-        // Simulate the integer effect used above using step/mod/abs. For speed, simulates a 4x4
-        // dither pattern rather than an 8x8 one. Since it's 4x4, this is effectively computing:
-        // uint m = (y & 1) << 3 | (x & 1) << 2 |
-        //          (y & 2) << 0 | (x & 2) >> 1;
-        // where 'y' has already been XOR'ed with 'x' as in the integer-supported case.
-
-        // To get the low bit of p.x and p.y, we compute mod 2.0; for the high bit, we mod 4.0
-        half4 bits = mod(half4(sk_FragCoord.yxyx), half4(2.0, 2.0, 4.0, 4.0));
-        // Use step to convert the 0-3 value in bits.zw into a 0|1 value. bits.xy is already 0|1.
-        bits.zw = step(2.0, bits.zw);
-        // bits was constructed such that the p.x bits were already in the right place for
-        // interleaving (in bits.yw). We just need to update the other bits from p.y to (p.x ^ p.y).
-        // These are in bits.xz. Since the values are 0|1, we can simulate ^ as abs(y - x).
-        bits.xz = abs(bits.xz - bits.yw);
-
-        // Manual binary sum, divide by N^2, and offset
-        value = dot(bits, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
-    }
-    // For each color channel, add the random offset to the channel value and then clamp
-    // between 0 and alpha to keep the color premultiplied.
-    color = half4(clamp(color.rgb + value * range, 0.0, color.a), color.a);
-}
-)";
-
 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
     SkASSERT(key);
     SkASSERT(imageID);
@@ -354,10 +313,6 @@
         }
     }
 
-    if (paintFP) {
-        grPaint->addColorFragmentProcessor(std::move(paintFP));
-    }
-
     SkMaskFilterBase* maskFilter = as_MFB(skPaint.getMaskFilter());
     if (maskFilter) {
         // We may have set this before passing to the SkShader.
@@ -376,19 +331,16 @@
 
 #ifndef SK_IGNORE_GPU_DITHER
     GrColorType ct = dstColorInfo.colorType();
-    if (SkPaintPriv::ShouldDither(skPaint, GrColorTypeToSkColorType(ct)) &&
-        grPaint->numColorFragmentProcessors() > 0) {
+    if (SkPaintPriv::ShouldDither(skPaint, GrColorTypeToSkColorType(ct)) && paintFP != nullptr) {
         float ditherRange = dither_range_for_config(ct);
-        if (ditherRange > 0.f) {
-            static auto effect = std::get<0>(SkRuntimeEffect::Make(SkString(SKSL_DITHER_SRC)));
-            auto ditherFP = GrSkSLFP::Make(context, effect, "Dither",
-                                           SkData::MakeWithCopy(&ditherRange, sizeof(ditherRange)));
-            if (ditherFP) {
-                grPaint->addColorFragmentProcessor(std::move(ditherFP));
-            }
-        }
+        paintFP = GrDitherEffect::Make(std::move(paintFP), ditherRange);
     }
 #endif
+
+    if (paintFP) {
+        grPaint->addColorFragmentProcessor(std::move(paintFP));
+    }
+
     if (GrColorTypeClampType(dstColorInfo.colorType()) == GrClampType::kManual) {
         if (grPaint->numColorFragmentProcessors()) {
             grPaint->addColorFragmentProcessor(
diff --git a/src/gpu/effects/GrDitherEffect.fp b/src/gpu/effects/GrDitherEffect.fp
new file mode 100644
index 0000000..92f817d
--- /dev/null
+++ b/src/gpu/effects/GrDitherEffect.fp
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+in fragmentProcessor inputFP;
+
+// Larger values increase the strength of the dithering effect.
+in uniform half range;
+
+void main() {
+    half4 color = sample(inputFP, sk_InColor);
+    half value;
+    @if (sk_Caps.integerSupport)
+    {
+        // This ordered-dither code is lifted from the cpu backend.
+        uint x = uint(sk_FragCoord.x);
+        uint y = uint(sk_FragCoord.y) ^ x;
+        uint m = (y & 1) << 5 | (x & 1) << 4 |
+                 (y & 2) << 2 | (x & 2) << 1 |
+                 (y & 4) >> 1 | (x & 4) >> 2;
+        value = half(m) * 1.0 / 64.0 - 63.0 / 128.0;
+    } else {
+        // Simulate the integer effect used above using step/mod/abs. For speed, simulates a 4x4
+        // dither pattern rather than an 8x8 one. Since it's 4x4, this is effectively computing:
+        // uint m = (y & 1) << 3 | (x & 1) << 2 |
+        //          (y & 2) << 0 | (x & 2) >> 1;
+        // where 'y' has already been XOR'ed with 'x' as in the integer-supported case.
+
+        // To get the low bit of p.x and p.y, we compute mod 2.0; for the high bit, we mod 4.0
+        half4 bits = mod(half4(sk_FragCoord.yxyx), half4(2.0, 2.0, 4.0, 4.0));
+        // Use step to convert the 0-3 value in bits.zw into a 0|1 value. bits.xy is already 0|1.
+        bits.zw = step(2.0, bits.zw);
+        // bits was constructed such that the p.x bits were already in the right place for
+        // interleaving (in bits.yw). We just need to update the other bits from p.y to (p.x ^ p.y).
+        // These are in bits.xz. Since the values are 0|1, we can simulate ^ as abs(y - x).
+        bits.xz = abs(bits.xz - bits.yw);
+
+        // Manual binary sum, divide by N^2, and offset
+        value = dot(bits, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
+    }
+    // For each color channel, add the random offset to the channel value and then clamp
+    // between 0 and alpha to keep the color premultiplied.
+    sk_OutColor = half4(clamp(color.rgb + value * range, 0.0, color.a), color.a);
+}
+
+@optimizationFlags {
+    (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags)
+    & kPreservesOpaqueInput_OptimizationFlag
+}
+
+@test(d) {
+    float range = d->fRandom->nextRangeF(0.0, 1.0);
+    return GrDitherEffect::Make(GrProcessorUnitTest::MakeChildFP(d), range);
+}
+
+@make {
+    static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+                                                     float range) {
+        if (range == 0.0 || inputFP == nullptr) {
+            return inputFP;
+        }
+        return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(std::move(inputFP), range));
+    }
+}
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index 7ee0c09..8f66b4f 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -265,22 +265,14 @@
 #include "src/gpu/effects/generated/GrConstColorProcessor.h"
 
 extern const char* SKSL_ARITHMETIC_SRC;
-extern const char* SKSL_DITHER_SRC;
 extern const char* SKSL_OVERDRAW_SRC;
 
 using Value = SkSL::Program::Settings::Value;
 
 std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) {
-    int type = d->fRandom->nextULessThan(3);
+    int type = d->fRandom->nextULessThan(2);
     switch (type) {
         case 0: {
-            static auto effect = std::get<0>(SkRuntimeEffect::Make(SkString(SKSL_DITHER_SRC)));
-            int rangeType = d->fRandom->nextULessThan(3);
-            auto result = GrSkSLFP::Make(d->context(), effect, "Dither",
-                                         SkData::MakeWithCopy(&rangeType, sizeof(rangeType)));
-            return std::unique_ptr<GrFragmentProcessor>(result.release());
-        }
-        case 1: {
             static auto effect = std::get<0>(SkRuntimeEffect::Make(SkString(SKSL_ARITHMETIC_SRC)));
             ArithmeticFPInputs inputs{d->fRandom->nextF(), d->fRandom->nextF(), d->fRandom->nextF(),
                                       d->fRandom->nextF(), d->fRandom->nextBool()};
@@ -290,7 +282,7 @@
                 /*inputFP=*/nullptr, SK_PMColor4fWHITE, GrConstColorProcessor::InputMode::kIgnore));
             return std::unique_ptr<GrFragmentProcessor>(result.release());
         }
-        case 2: {
+        case 1: {
             SkColor colors[SkOverdrawColorFilter::kNumColors];
             for (SkColor& c : colors) {
                 c = d->fRandom->nextU();
diff --git a/src/gpu/effects/generated/GrDitherEffect.cpp b/src/gpu/effects/generated/GrDitherEffect.cpp
new file mode 100644
index 0000000..6bdb808
--- /dev/null
+++ b/src/gpu/effects/generated/GrDitherEffect.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**************************************************************************************************
+ *** This file was autogenerated from GrDitherEffect.fp; do not modify.
+ **************************************************************************************************/
+#include "GrDitherEffect.h"
+
+#include "src/gpu/GrTexture.h"
+#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
+#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
+#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
+#include "src/sksl/SkSLCPP.h"
+#include "src/sksl/SkSLUtil.h"
+class GrGLSLDitherEffect : public GrGLSLFragmentProcessor {
+public:
+    GrGLSLDitherEffect() {}
+    void emitCode(EmitArgs& args) override {
+        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
+        const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>();
+        (void)_outer;
+        auto range = _outer.range;
+        (void)range;
+        rangeVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf_GrSLType,
+                                                    "range");
+        SkString _input302(args.fInputColor);
+        SkString _sample302;
+        _sample302 = this->invokeChild(_outer.inputFP_index, _input302.c_str(), args);
+        fragBuilder->codeAppendf(
+                R"SkSL(half4 color = %s;
+half value;
+@if (sk_Caps.integerSupport) {
+    uint x = uint(sk_FragCoord.x);
+    uint y = uint(sk_FragCoord.y) ^ x;
+    uint m = (((((y & 1) << 5 | (x & 1) << 4) | (y & 2) << 2) | (x & 2) << 1) | (y & 4) >> 1) | (x & 4) >> 2;
+    value = half(m) / 64.0 - 0.4921875;
+} else {
+    half4 bits = mod(half4(sk_FragCoord.yxyx), half4(2.0, 2.0, 4.0, 4.0));
+    bits.zw = step(2.0, bits.zw);
+    bits.xz = abs(bits.xz - bits.yw);
+    value = dot(bits, half4(0.5, 0.25, 0.125, 0.0625)) - 0.46875;
+}
+%s = half4(clamp(color.xyz + value * %s, 0.0, color.w), color.w);
+)SkSL",
+                _sample302.c_str(), args.fOutputColor,
+                args.fUniformHandler->getUniformCStr(rangeVar));
+    }
+
+private:
+    void onSetData(const GrGLSLProgramDataManager& pdman,
+                   const GrFragmentProcessor& _proc) override {
+        const GrDitherEffect& _outer = _proc.cast<GrDitherEffect>();
+        { pdman.set1f(rangeVar, (_outer.range)); }
+    }
+    UniformHandle rangeVar;
+};
+GrGLSLFragmentProcessor* GrDitherEffect::onCreateGLSLInstance() const {
+    return new GrGLSLDitherEffect();
+}
+void GrDitherEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
+                                           GrProcessorKeyBuilder* b) const {}
+bool GrDitherEffect::onIsEqual(const GrFragmentProcessor& other) const {
+    const GrDitherEffect& that = other.cast<GrDitherEffect>();
+    (void)that;
+    if (range != that.range) return false;
+    return true;
+}
+GrDitherEffect::GrDitherEffect(const GrDitherEffect& src)
+        : INHERITED(kGrDitherEffect_ClassID, src.optimizationFlags()), range(src.range) {
+    { inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); }
+}
+std::unique_ptr<GrFragmentProcessor> GrDitherEffect::clone() const {
+    return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(*this));
+}
+GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDitherEffect);
+#if GR_TEST_UTILS
+std::unique_ptr<GrFragmentProcessor> GrDitherEffect::TestCreate(GrProcessorTestData* d) {
+    float range = d->fRandom->nextRangeF(0.0, 1.0);
+    return GrDitherEffect::Make(GrProcessorUnitTest::MakeChildFP(d), range);
+}
+#endif
diff --git a/src/gpu/effects/generated/GrDitherEffect.h b/src/gpu/effects/generated/GrDitherEffect.h
new file mode 100644
index 0000000..43505e5
--- /dev/null
+++ b/src/gpu/effects/generated/GrDitherEffect.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**************************************************************************************************
+ *** This file was autogenerated from GrDitherEffect.fp; do not modify.
+ **************************************************************************************************/
+#ifndef GrDitherEffect_DEFINED
+#define GrDitherEffect_DEFINED
+
+#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
+
+#include "src/gpu/GrFragmentProcessor.h"
+
+class GrDitherEffect : public GrFragmentProcessor {
+public:
+    static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+                                                     float range) {
+        if (range == 0.0 || inputFP == nullptr) {
+            return inputFP;
+        }
+        return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(std::move(inputFP), range));
+    }
+    GrDitherEffect(const GrDitherEffect& src);
+    std::unique_ptr<GrFragmentProcessor> clone() const override;
+    const char* name() const override { return "DitherEffect"; }
+    int inputFP_index = -1;
+    float range;
+
+private:
+    GrDitherEffect(std::unique_ptr<GrFragmentProcessor> inputFP, float range)
+            : INHERITED(kGrDitherEffect_ClassID,
+                        (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+                                                    : kAll_OptimizationFlags) &
+                                kPreservesOpaqueInput_OptimizationFlag)
+            , range(range) {
+        SkASSERT(inputFP);
+        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+    }
+    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
+    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
+    bool onIsEqual(const GrFragmentProcessor&) const override;
+    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
+    typedef GrFragmentProcessor INHERITED;
+};
+#endif