Reland "SkMixerColorFilter GPU impl"

This reverts commit c2949ec67b92e455edd58e470564023c37df6e7a.

Reason for revert: not related to crossfade

Original change's description:
> Revert "SkMixerColorFilter GPU impl"
> 
> This reverts commit e80f7eb9d6a15d42827108700990291d3efb5995.
> 
> Reason for revert: break crossfade in chrome roll?
> 
> Original change's description:
> > SkMixerColorFilter GPU impl
> > 
> > Bug: skia:
> > Change-Id: Ia1e25e0c99737d9720c17f92f0d76a1cb7897ea8
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/193163
> > Commit-Queue: Florin Malita <fmalita@chromium.org>
> > Reviewed-by: Brian Salomon <bsalomon@google.com>
> 
> TBR=bsalomon@google.com,ethannicholas@google.com,fmalita@chromium.org,reed@google.com
> 
> Change-Id: Ib9464fcabc649b95ba131146690d6208af728436
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/197760
> Reviewed-by: Mike Reed <reed@google.com>
> Commit-Queue: Mike Reed <reed@google.com>

TBR=bsalomon@google.com,ethannicholas@google.com,fmalita@chromium.org,reed@google.com

Change-Id: Ie96e80e153aeab16c4ea35d5f1350372060228aa
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/197763
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index b692e18..bf6be62 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -343,6 +343,8 @@
   "$_src/gpu/effects/GrMagnifierEffect.h",
   "$_src/gpu/effects/GrMatrixConvolutionEffect.cpp",
   "$_src/gpu/effects/GrMatrixConvolutionEffect.h",
+  "$_src/gpu/effects/GrMixerEffect.cpp",
+  "$_src/gpu/effects/GrMixerEffect.h",
   "$_src/gpu/effects/GrOvalEffect.cpp",
   "$_src/gpu/effects/GrOvalEffect.h",
   "$_src/gpu/effects/GrPorterDuffXferProcessor.cpp",
diff --git a/gn/sksl.gni b/gn/sksl.gni
index 5890597..755fa95 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -41,6 +41,7 @@
   "$_src/gpu/effects/GrEllipseEffect.fp",
   "$_src/gpu/effects/GrLumaColorFilterEffect.fp",
   "$_src/gpu/effects/GrMagnifierEffect.fp",
+  "$_src/gpu/effects/GrMixerEffect.fp",
   "$_src/gpu/effects/GrPremulInputFragmentProcessor.fp",
   "$_src/gpu/effects/GrRectBlurEffect.fp",
   "$_src/gpu/effects/GrRRectBlurEffect.fp",
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index 9d6ee47..333dddf 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -21,6 +21,7 @@
 
 #if SK_SUPPORT_GPU
 #include "GrFragmentProcessor.h"
+#include "effects/GrMixerEffect.h"
 #endif
 
 bool SkColorFilter::asColorMode(SkColor*, SkBlendMode*) const {
@@ -325,8 +326,11 @@
 
 #if SK_SUPPORT_GPU
     std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
-            GrRecordingContext* context, const GrColorSpaceInfo&) const override {
-        return nullptr;
+            GrRecordingContext* context, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
+        return GrMixerEffect::Make(
+                fCF0->asFragmentProcessor(context, dstColorSpaceInfo),
+                fCF1 ? fCF1->asFragmentProcessor(context, dstColorSpaceInfo) : nullptr,
+                fWeight);
     }
 #endif
 
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index 19ab4ab..ba01e44 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -120,6 +120,7 @@
         kGrMatrixConvolutionEffect_ClassID,
         kGrMeshTestProcessor_ClassID,
         kGrMorphologyEffect_ClassID,
+        kGrMixerEffect_ClassID,
         kGrOverdrawFragmentProcessor_ClassID,
         kGrPathProcessor_ClassID,
         kGrPerlinNoise2Effect_ClassID,
diff --git a/src/gpu/effects/GrMixerEffect.cpp b/src/gpu/effects/GrMixerEffect.cpp
new file mode 100644
index 0000000..6e79f51
--- /dev/null
+++ b/src/gpu/effects/GrMixerEffect.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2019 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 GrMixerEffect.fp; do not modify.
+ **************************************************************************************************/
+#include "GrMixerEffect.h"
+#include "glsl/GrGLSLFragmentProcessor.h"
+#include "glsl/GrGLSLFragmentShaderBuilder.h"
+#include "glsl/GrGLSLProgramBuilder.h"
+#include "GrTexture.h"
+#include "SkSLCPP.h"
+#include "SkSLUtil.h"
+class GrGLSLMixerEffect : public GrGLSLFragmentProcessor {
+public:
+    GrGLSLMixerEffect() {}
+    void emitCode(EmitArgs& args) override {
+        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
+        const GrMixerEffect& _outer = args.fFp.cast<GrMixerEffect>();
+        (void)_outer;
+        auto weight = _outer.weight();
+        (void)weight;
+        fWeightVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
+                                                      kDefault_GrSLPrecision, "weight");
+        SkString _input0 = SkStringPrintf("%s", args.fInputColor);
+        SkString _child0("_child0");
+        this->emitChild(_outer.fp0_index(), _input0.c_str(), &_child0, args);
+        fragBuilder->codeAppendf("half4 in0 = %s;", _child0.c_str());
+        SkString _input1 = SkStringPrintf("%s", args.fInputColor);
+        SkString _child1("_child1");
+        if (_outer.fp1_index() >= 0) {
+            this->emitChild(_outer.fp1_index(), _input1.c_str(), &_child1, args);
+        } else {
+            fragBuilder->codeAppendf("half4 %s;", _child1.c_str());
+        }
+        fragBuilder->codeAppendf("\nhalf4 in1 = %s ? %s : %s;\n%s = mix(in0, in1, %s);\n",
+                                 _outer.fp1_index() >= 0 ? "true" : "false", _child1.c_str(),
+                                 args.fInputColor, args.fOutputColor,
+                                 args.fUniformHandler->getUniformCStr(fWeightVar));
+    }
+
+private:
+    void onSetData(const GrGLSLProgramDataManager& pdman,
+                   const GrFragmentProcessor& _proc) override {
+        const GrMixerEffect& _outer = _proc.cast<GrMixerEffect>();
+        { pdman.set1f(fWeightVar, (_outer.weight())); }
+    }
+    UniformHandle fWeightVar;
+};
+GrGLSLFragmentProcessor* GrMixerEffect::onCreateGLSLInstance() const {
+    return new GrGLSLMixerEffect();
+}
+void GrMixerEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
+                                          GrProcessorKeyBuilder* b) const {}
+bool GrMixerEffect::onIsEqual(const GrFragmentProcessor& other) const {
+    const GrMixerEffect& that = other.cast<GrMixerEffect>();
+    (void)that;
+    if (fWeight != that.fWeight) return false;
+    return true;
+}
+GrMixerEffect::GrMixerEffect(const GrMixerEffect& src)
+        : INHERITED(kGrMixerEffect_ClassID, src.optimizationFlags())
+        , fFp0_index(src.fFp0_index)
+        , fFp1_index(src.fFp1_index)
+        , fWeight(src.fWeight) {
+    this->registerChildProcessor(src.childProcessor(fFp0_index).clone());
+    if (fFp1_index >= 0) {
+        this->registerChildProcessor(src.childProcessor(fFp1_index).clone());
+    }
+}
+std::unique_ptr<GrFragmentProcessor> GrMixerEffect::clone() const {
+    return std::unique_ptr<GrFragmentProcessor>(new GrMixerEffect(*this));
+}
diff --git a/src/gpu/effects/GrMixerEffect.fp b/src/gpu/effects/GrMixerEffect.fp
new file mode 100644
index 0000000..40fd336
--- /dev/null
+++ b/src/gpu/effects/GrMixerEffect.fp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// Mixes the output of two FPs.
+
+in fragmentProcessor  fp0;
+in fragmentProcessor? fp1;
+in uniform half      weight;
+
+@class {
+
+    static OptimizationFlags OptFlags(const std::unique_ptr<GrFragmentProcessor>& fp0,
+                                      const std::unique_ptr<GrFragmentProcessor>& fp1) {
+        auto get_flags = [](const std::unique_ptr<GrFragmentProcessor>& fp) {
+            auto flags = kNone_OptimizationFlags;
+
+            if (fp->compatibleWithCoverageAsAlpha()) {
+                flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
+            }
+
+            if (fp->preservesOpaqueInput()) {
+                flags |= kPreservesOpaqueInput_OptimizationFlag;
+            }
+
+            if (fp->hasConstantOutputForConstantInput()) {
+                flags |= kConstantOutputForConstantInput_OptimizationFlag;
+            }
+
+            return flags;
+        };
+
+        const auto fp0_flags = get_flags(fp0);
+
+        return fp1 ? (fp0_flags & get_flags(fp1)) : fp0_flags;
+    }
+
+    SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+        const auto c0 = ConstantOutputForConstantInput(this->childProcessor(0), input),
+                   c1 = (this->numChildProcessors() > 1)
+                      ? ConstantOutputForConstantInput(this->childProcessor(1), input)
+                      : input;
+        return {
+            c0.fR + (c1.fR - c0.fR) * fWeight,
+            c0.fG + (c1.fG - c0.fG) * fWeight,
+            c0.fB + (c1.fB - c0.fB) * fWeight,
+            c0.fA + (c1.fA - c0.fA) * fWeight
+        };
+    }
+}
+
+@optimizationFlags { OptFlags(fp0, fp1) }
+
+void main() {
+    half4 in0 = process(fp0, sk_InColor);
+    half4 in1 = (fp1 != null) ? process(fp1, sk_InColor) : sk_InColor;
+
+    sk_OutColor = mix(in0, in1, weight);
+}
diff --git a/src/gpu/effects/GrMixerEffect.h b/src/gpu/effects/GrMixerEffect.h
new file mode 100644
index 0000000..16ce6fc
--- /dev/null
+++ b/src/gpu/effects/GrMixerEffect.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2019 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 GrMixerEffect.fp; do not modify.
+ **************************************************************************************************/
+#ifndef GrMixerEffect_DEFINED
+#define GrMixerEffect_DEFINED
+#include "SkTypes.h"
+#include "GrFragmentProcessor.h"
+#include "GrCoordTransform.h"
+class GrMixerEffect : public GrFragmentProcessor {
+public:
+    static OptimizationFlags OptFlags(const std::unique_ptr<GrFragmentProcessor>& fp0,
+                                      const std::unique_ptr<GrFragmentProcessor>& fp1) {
+        auto get_flags = [](const std::unique_ptr<GrFragmentProcessor>& fp) {
+            auto flags = kNone_OptimizationFlags;
+
+            if (fp->compatibleWithCoverageAsAlpha()) {
+                flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
+            }
+
+            if (fp->preservesOpaqueInput()) {
+                flags |= kPreservesOpaqueInput_OptimizationFlag;
+            }
+
+            if (fp->hasConstantOutputForConstantInput()) {
+                flags |= kConstantOutputForConstantInput_OptimizationFlag;
+            }
+
+            return flags;
+        };
+
+        const auto fp0_flags = get_flags(fp0);
+
+        return fp1 ? (fp0_flags & get_flags(fp1)) : fp0_flags;
+    }
+
+    SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+        const auto c0 = ConstantOutputForConstantInput(this->childProcessor(0), input),
+                   c1 = (this->numChildProcessors() > 1)
+                                ? ConstantOutputForConstantInput(this->childProcessor(1), input)
+                                : input;
+        return {c0.fR + (c1.fR - c0.fR) * fWeight, c0.fG + (c1.fG - c0.fG) * fWeight,
+                c0.fB + (c1.fB - c0.fB) * fWeight, c0.fA + (c1.fA - c0.fA) * fWeight};
+    }
+    int fp0_index() const { return fFp0_index; }
+    int fp1_index() const { return fFp1_index; }
+    float weight() const { return fWeight; }
+    static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp0,
+                                                     std::unique_ptr<GrFragmentProcessor>
+                                                             fp1,
+                                                     float weight) {
+        return std::unique_ptr<GrFragmentProcessor>(
+                new GrMixerEffect(std::move(fp0), std::move(fp1), weight));
+    }
+    GrMixerEffect(const GrMixerEffect& src);
+    std::unique_ptr<GrFragmentProcessor> clone() const override;
+    const char* name() const override { return "MixerEffect"; }
+
+private:
+    GrMixerEffect(std::unique_ptr<GrFragmentProcessor> fp0,
+                  std::unique_ptr<GrFragmentProcessor>
+                          fp1,
+                  float weight)
+            : INHERITED(kGrMixerEffect_ClassID, (OptimizationFlags)OptFlags(fp0, fp1))
+            , fWeight(weight) {
+        SkASSERT(fp0);
+        fFp0_index = this->numChildProcessors();
+        this->registerChildProcessor(std::move(fp0));
+        if (fp1) {
+            fFp1_index = this->numChildProcessors();
+            this->registerChildProcessor(std::move(fp1));
+        }
+    }
+    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
+    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
+    bool onIsEqual(const GrFragmentProcessor&) const override;
+    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
+    int fFp0_index = -1;
+    int fFp1_index = -1;
+    float fWeight;
+    typedef GrFragmentProcessor INHERITED;
+};
+#endif