Convert GrDitherEffect to a runtime FP

Includes a change so that we can create non-ES2 runtime effects, even
outside of tests/tools. It's still locked to a private API, so clients
can't access the functionality.

Change-Id: Ie0643da2071bd223fccf05b35f3a7b6f7bbc4876
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/423578
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index b10fa96..2d31725 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -63,7 +63,6 @@
         kGrDistanceFieldA8TextGeoProc_ClassID,
         kGrDistanceFieldLCDTextGeoProc_ClassID,
         kGrDistanceFieldPathGeoProc_ClassID,
-        kGrDitherEffect_ClassID,
         kGrDSLFPTest_DoStatement_ClassID,
         kGrDSLFPTest_ForStatement_ClassID,
         kGrDSLFPTest_IfStatement_ClassID,
diff --git a/src/gpu/GrProcessorUnitTest.cpp b/src/gpu/GrProcessorUnitTest.cpp
index b4c673f..1779050 100644
--- a/src/gpu/GrProcessorUnitTest.cpp
+++ b/src/gpu/GrProcessorUnitTest.cpp
@@ -146,7 +146,7 @@
  * we verify the count is as expected.  If a new factory is added, then these numbers must be
  * manually adjusted.
  */
-static constexpr int kFPFactoryCount = 17;
+static constexpr int kFPFactoryCount = 16;
 static constexpr int kGPFactoryCount = 14;
 static constexpr int kXPFactoryCount = 4;
 
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 5917100..04e0ccd 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -28,6 +28,7 @@
 #include "src/core/SkMipmap.h"
 #include "src/core/SkPaintPriv.h"
 #include "src/core/SkResourceCache.h"
+#include "src/core/SkRuntimeEffectPriv.h"
 #include "src/core/SkTraceEvent.h"
 #include "src/gpu/GrCaps.h"
 #include "src/gpu/GrColorInfo.h"
@@ -42,7 +43,7 @@
 #include "src/gpu/effects/GrBicubicEffect.h"
 #include "src/gpu/effects/GrBlendFragmentProcessor.h"
 #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
-#include "src/gpu/effects/generated/GrDitherEffect.h"
+#include "src/gpu/effects/GrSkSLFP.h"
 #include "src/image/SkImage_Base.h"
 #include "src/shaders/SkShaderBase.h"
 
@@ -322,6 +323,67 @@
     }
     SkUNREACHABLE;
 }
+
+static std::unique_ptr<GrFragmentProcessor> make_dither_effect(
+        std::unique_ptr<GrFragmentProcessor> inputFP, float range, const GrShaderCaps* caps) {
+    if (range == 0 || inputFP == nullptr) {
+        return inputFP;
+    }
+
+    if (caps->integerSupport()) {
+        // This ordered-dither code is lifted from the cpu backend.
+        static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
+            uniform half range;
+            half4 main(float2 xy, half4 color) {
+                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;
+                half value = half(m) * 1.0 / 64.0 - 63.0 / 128.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.
+                return half4(clamp(color.rgb + value * range, 0.0, color.a), color.a);
+            }
+        )", SkRuntimeEffectPriv::ES3Options());
+        return GrSkSLFP::Make(effect, "Dither", std::move(inputFP),
+                              GrSkSLFP::OptFlags::kPreservesOpaqueInput,
+                              "range", range);
+    } 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.
+        static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
+            uniform half range;
+            half4 main(float2 xy, half4 color) {
+                // To get the low bit of p.xy, 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.
+                return half4(clamp(color.rgb + value * range, 0.0, color.a), color.a);
+            }
+        )");
+        return GrSkSLFP::Make(effect, "Dither", std::move(inputFP),
+                              GrSkSLFP::OptFlags::kPreservesOpaqueInput,
+                              "range", range);
+    }
+}
 #endif
 
 static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
@@ -435,7 +497,8 @@
     GrColorType ct = dstColorInfo.colorType();
     if (SkPaintPriv::ShouldDither(skPaint, GrColorTypeToSkColorType(ct)) && paintFP != nullptr) {
         float ditherRange = dither_range_for_config(ct);
-        paintFP = GrDitherEffect::Make(std::move(paintFP), ditherRange);
+        paintFP = make_dither_effect(
+                std::move(paintFP), ditherRange, context->priv().caps()->shaderCaps());
     }
 #endif
 
diff --git a/src/gpu/effects/GrDitherEffect.fp b/src/gpu/effects/GrDitherEffect.fp
deleted file mode 100644
index e2eac5e..0000000
--- a/src/gpu/effects/GrDitherEffect.fp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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;
-
-half4 main() {
-    half4 color = sample(inputFP);
-    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.
-    return half4(clamp(color.rgb + value * range, 0.0, color.a), color.a);
-}
-
-@optimizationFlags {
-    ProcessorOptimizationFlags(inputFP.get()) & kPreservesOpaqueInput_OptimizationFlag
-}
-
-@test(d) {
-    float range = 1.0f - d->fRandom->nextRangeF(0.0f, 1.0f);
-    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/generated/GrDitherEffect.cpp b/src/gpu/effects/generated/GrDitherEffect.cpp
deleted file mode 100644
index db73639..0000000
--- a/src/gpu/effects/generated/GrDitherEffect.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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/core/SkUtils.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 _sample0 = this->invokeChild(0, 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;
-}
-return half4(clamp(color.xyz + value * %s, 0.0, color.w), color.w);
-)SkSL",
-                _sample0.c_str(),
-                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;
-};
-std::unique_ptr<GrGLSLFragmentProcessor> GrDitherEffect::onMakeProgramImpl() const {
-    return std::make_unique<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) {
-    this->cloneAndRegisterAllChildProcessors(src);
-}
-std::unique_ptr<GrFragmentProcessor> GrDitherEffect::clone() const {
-    return std::make_unique<GrDitherEffect>(*this);
-}
-#if GR_TEST_UTILS
-SkString GrDitherEffect::onDumpInfo() const { return SkStringPrintf("(range=%f)", range); }
-#endif
-GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDitherEffect);
-#if GR_TEST_UTILS
-std::unique_ptr<GrFragmentProcessor> GrDitherEffect::TestCreate(GrProcessorTestData* d) {
-    float range = 1.0f - d->fRandom->nextRangeF(0.0f, 1.0f);
-    return GrDitherEffect::Make(GrProcessorUnitTest::MakeChildFP(d), range);
-}
-#endif
diff --git a/src/gpu/effects/generated/GrDitherEffect.h b/src/gpu/effects/generated/GrDitherEffect.h
deleted file mode 100644
index 2abfdf2..0000000
--- a/src/gpu/effects/generated/GrDitherEffect.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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"; }
-    float range;
-
-private:
-    GrDitherEffect(std::unique_ptr<GrFragmentProcessor> inputFP, float range)
-            : INHERITED(kGrDitherEffect_ClassID,
-                        (OptimizationFlags)ProcessorOptimizationFlags(inputFP.get()) &
-                                kPreservesOpaqueInput_OptimizationFlag)
-            , range(range) {
-        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
-    }
-    std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;
-    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
-    bool onIsEqual(const GrFragmentProcessor&) const override;
-#if GR_TEST_UTILS
-    SkString onDumpInfo() const override;
-#endif
-    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
-    using INHERITED = GrFragmentProcessor;
-};
-#endif