Support children in SkRuntimeEffect::makeColorFilter

Change-Id: Icf8c69464a44341a08df16dce53aebedc2826bfd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/270064
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/include/effects/SkRuntimeEffect.h b/include/effects/SkRuntimeEffect.h
index 71d93a6..921b42e 100644
--- a/include/effects/SkRuntimeEffect.h
+++ b/include/effects/SkRuntimeEffect.h
@@ -82,6 +82,8 @@
     sk_sp<SkShader> makeShader(sk_sp<SkData> inputs, sk_sp<SkShader> children[], size_t childCount,
                                const SkMatrix* localMatrix, bool isOpaque);
 
+    sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> inputs, sk_sp<SkColorFilter> children[],
+                                         size_t childCount);
     sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> inputs);
 
     const SkString& source() const { return fSkSL; }
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index efa9d61..468ff5c 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -401,14 +401,25 @@
 
 class SkRuntimeColorFilter : public SkColorFilter {
 public:
-    SkRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs)
-        : fEffect(std::move(effect))
-        , fInputs(std::move(inputs)) {}
+    SkRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs,
+                         sk_sp<SkColorFilter> children[], size_t childCount)
+            : fEffect(std::move(effect))
+            , fInputs(std::move(inputs))
+            , fChildren(children, children + childCount) {}
 
 #if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrRecordingContext* context,
-                                                             const GrColorInfo&) const override {
-        return GrSkSLFP::Make(context, fEffect, "Runtime Color Filter", fInputs);
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrRecordingContext* context, const GrColorInfo& colorInfo) const override {
+        auto fp = GrSkSLFP::Make(context, fEffect, "Runtime Color Filter", fInputs);
+        for (const auto& child : fChildren) {
+            auto childFP = child ? child->asFragmentProcessor(context, colorInfo) : nullptr;
+            if (!childFP) {
+                // TODO: This is the case that should eventually mean "the original input color"
+                return nullptr;
+            }
+            fp->addChild(std::move(childFP));
+        }
+        return fp;
     }
 #endif
 
@@ -445,6 +456,10 @@
         } else {
             buffer.writeByteArray(nullptr, 0);
         }
+        buffer.write32(fChildren.size());
+        for (const auto& child : fChildren) {
+            buffer.writeFlattenable(child.get());
+        }
     }
 
 private:
@@ -452,6 +467,7 @@
 
     sk_sp<SkRuntimeEffect> fEffect;
     sk_sp<SkData> fInputs;
+    std::vector<sk_sp<SkColorFilter>> fChildren;
 
     mutable SkMutex fInterpreterMutex;
     mutable std::unique_ptr<SkSL::Interpreter<SkRasterPipeline_InterpreterCtx::VECTOR_WIDTH>>
@@ -468,13 +484,21 @@
     buffer.readString(&sksl);
     sk_sp<SkData> inputs = buffer.readByteArrayAsData();
 
+    std::vector<sk_sp<SkColorFilter>> children;
+    children.resize(buffer.read32());
+    for (size_t i = 0; i < children.size(); ++i) {
+        children[i] = buffer.readColorFilter();
+    }
+
     auto effect = std::get<0>(SkRuntimeEffect::Make(std::move(sksl)));
-    return effect->makeColorFilter(std::move(inputs));
+    return effect->makeColorFilter(std::move(inputs), children.data(), children.size());
 }
 
 // Private helper method so SkRuntimeEffect can access SkRuntimeColorFilter
-sk_sp<SkColorFilter> SkMakeRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs) {
-    return sk_sp<SkColorFilter>(new SkRuntimeColorFilter(std::move(effect), std::move(inputs)));
+sk_sp<SkColorFilter> SkMakeRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs,
+                                              sk_sp<SkColorFilter> children[], size_t childCount) {
+    return sk_sp<SkColorFilter>(
+            new SkRuntimeColorFilter(std::move(effect), std::move(inputs), children, childCount));
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp
index efdb658..926b1f4 100644
--- a/src/core/SkRuntimeEffect.cpp
+++ b/src/core/SkRuntimeEffect.cpp
@@ -296,16 +296,23 @@
 sk_sp<SkShader> SkRuntimeEffect::makeShader(sk_sp<SkData> inputs,
                                             sk_sp<SkShader> children[], size_t childCount,
                                             const SkMatrix* localMatrix, bool isOpaque) {
-    return inputs && inputs->size() == this->inputSize() && childCount >= fChildren.size()
+    return inputs && inputs->size() == this->inputSize() && childCount == fChildren.size()
         ? sk_sp<SkShader>(new SkRTShader(sk_ref_sp(this), std::move(inputs), localMatrix,
                                          children, childCount, isOpaque))
         : nullptr;
 }
 
-sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> inputs) {
-    extern sk_sp<SkColorFilter> SkMakeRuntimeColorFilter(sk_sp<SkRuntimeEffect>, sk_sp<SkData>);
+sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> inputs,
+                                                      sk_sp<SkColorFilter> children[],
+                                                      size_t childCount) {
+    extern sk_sp<SkColorFilter> SkMakeRuntimeColorFilter(sk_sp<SkRuntimeEffect>, sk_sp<SkData>,
+                                                         sk_sp<SkColorFilter>[], size_t);
 
-    return inputs && inputs->size() == this->inputSize()
-        ? SkMakeRuntimeColorFilter(sk_ref_sp(this), std::move(inputs))
+    return inputs && inputs->size() == this->inputSize() && childCount == fChildren.size()
+        ? SkMakeRuntimeColorFilter(sk_ref_sp(this), std::move(inputs), children, childCount)
         : nullptr;
 }
+
+sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> inputs) {
+    return this->makeColorFilter(std::move(inputs), nullptr, 0);
+}