Remove template from SkRuntimeEffectBuilder.

fChildren in the Builder is now a vector of ChildPtrs instead of a
vector of one particular type of child. This gives builder.child() the
flexibility to accept a color-filter, shader, or any other type that a
ChildPtr can hold.

Change-Id: I9e1ecf51aab1c74a9a15738bee7900b0c690ce9a
Bug: skia:11813
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/431196
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
diff --git a/include/effects/SkRuntimeEffect.h b/include/effects/SkRuntimeEffect.h
index f3eb3f5..cecfedf 100644
--- a/include/effects/SkRuntimeEffect.h
+++ b/include/effects/SkRuntimeEffect.h
@@ -163,6 +163,7 @@
 
     // Object that allows passing either an SkShader or SkColorFilter as a child
     struct ChildPtr {
+        ChildPtr() = default;
         ChildPtr(sk_sp<SkShader> s) : shader(std::move(s)) {}
         ChildPtr(sk_sp<SkColorFilter> cf) : colorFilter(std::move(cf)) {}
         sk_sp<SkShader> shader;
@@ -181,8 +182,7 @@
 
     sk_sp<SkImage> makeImage(GrRecordingContext*,
                              sk_sp<SkData> uniforms,
-                             sk_sp<SkShader> children[],
-                             size_t childCount,
+                             SkSpan<ChildPtr> children,
                              const SkMatrix* localMatrix,
                              SkImageInfo resultInfo,
                              bool mipmapped) const;
@@ -291,7 +291,7 @@
 };
 
 /** Base class for SkRuntimeShaderBuilder, defined below. */
-template <typename Child> class SkRuntimeEffectBuilder {
+class SkRuntimeEffectBuilder {
 public:
     struct BuilderUniform {
         // Copy 'val' to this variable. No type conversion is performed - 'val' must be same
@@ -319,7 +319,8 @@
             } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
                 SkDEBUGFAIL("Incorrect value size");
             } else {
-                float* data = SkTAddOffset<float>(fOwner->writableUniformData(), fVar->offset);
+                float* data = SkTAddOffset<float>(fOwner->writableUniformData(),
+                                                  (ptrdiff_t)fVar->offset);
                 data[0] = val.get(0); data[1] = val.get(3); data[2] = val.get(6);
                 data[3] = val.get(1); data[4] = val.get(4); data[5] = val.get(7);
                 data[6] = val.get(2); data[7] = val.get(5); data[8] = val.get(8);
@@ -348,13 +349,20 @@
     };
 
     struct BuilderChild {
-        template <typename C> BuilderChild& operator=(C&& val) {
-            // TODO(skbug:11813): Validate that the type of val lines up with the type of the child
-            // (SkShader vs. SkColorFilter).
+        template <typename T> BuilderChild& operator=(sk_sp<T> val) {
             if (!fChild) {
                 SkDEBUGFAIL("Assigning to missing child");
             } else {
-                fOwner->fChildren[fChild->index] = std::forward<C>(val);
+                fOwner->fChildren[(size_t)fChild->index] = std::move(val);
+            }
+            return *this;
+        }
+
+        BuilderChild& operator=(std::nullptr_t) {
+            if (!fChild) {
+                SkDEBUGFAIL("Assigning to missing child");
+            } else {
+                fOwner->fChildren[(size_t)fChild->index] = SkRuntimeEffect::ChildPtr{};
             }
             return *this;
         }
@@ -388,7 +396,7 @@
     SkRuntimeEffectBuilder& operator=(const SkRuntimeEffectBuilder&) = delete;
 
     sk_sp<SkData> uniforms() { return fUniforms; }
-    Child* children() { return fChildren.data(); }
+    SkRuntimeEffect::ChildPtr* children() { return fChildren.data(); }
     size_t numChildren() { return fChildren.size(); }
 
 private:
@@ -399,9 +407,9 @@
         return fUniforms->writable_data();
     }
 
-    sk_sp<SkRuntimeEffect> fEffect;
-    sk_sp<SkData>          fUniforms;
-    std::vector<Child>     fChildren;
+    sk_sp<SkRuntimeEffect>                 fEffect;
+    sk_sp<SkData>                          fUniforms;
+    std::vector<SkRuntimeEffect::ChildPtr> fChildren;
 };
 
 /**
@@ -424,7 +432,7 @@
  * Note that SkRuntimeShaderBuilder is built entirely on the public API of SkRuntimeEffect,
  * so can be used as-is or serve as inspiration for other interfaces or binding techniques.
  */
-class SK_API SkRuntimeShaderBuilder : public SkRuntimeEffectBuilder<sk_sp<SkShader>> {
+class SK_API SkRuntimeShaderBuilder : public SkRuntimeEffectBuilder {
 public:
     explicit SkRuntimeShaderBuilder(sk_sp<SkRuntimeEffect>);
     // This is currently required by Android Framework but may go away if that dependency
@@ -439,13 +447,13 @@
                              bool mipmapped);
 
 private:
-    using INHERITED = SkRuntimeEffectBuilder<sk_sp<SkShader>>;
+    using INHERITED = SkRuntimeEffectBuilder;
 };
 
 /**
  * SkRuntimeBlendBuilder is a utility to simplify creation and uniform setup of runtime blenders.
  */
-class SK_API SkRuntimeBlendBuilder : public SkRuntimeEffectBuilder<sk_sp<SkBlender>> {
+class SK_API SkRuntimeBlendBuilder : public SkRuntimeEffectBuilder {
 public:
     explicit SkRuntimeBlendBuilder(sk_sp<SkRuntimeEffect>);
     ~SkRuntimeBlendBuilder();
@@ -456,7 +464,7 @@
     sk_sp<SkBlender> makeBlender();
 
 private:
-    using INHERITED = SkRuntimeEffectBuilder<sk_sp<SkBlender>>;
+    using INHERITED = SkRuntimeEffectBuilder;
 };
 
 #endif  // SK_ENABLE_SKSL
diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp
index f62aea8..4420576 100644
--- a/src/core/SkRuntimeEffect.cpp
+++ b/src/core/SkRuntimeEffect.cpp
@@ -1200,8 +1200,7 @@
 
 sk_sp<SkImage> SkRuntimeEffect::makeImage(GrRecordingContext* recordingContext,
                                           sk_sp<SkData> uniforms,
-                                          sk_sp<SkShader> children[],
-                                          size_t childCount,
+                                          SkSpan<ChildPtr> children,
                                           const SkMatrix* localMatrix,
                                           SkImageInfo resultInfo,
                                           bool mipmapped) const {
@@ -1225,11 +1224,12 @@
         GrColorInfo colorInfo(resultInfo.colorInfo());
         GrFPArgs args(recordingContext, matrixProvider, &colorInfo);
         SkSTArray<8, std::unique_ptr<GrFragmentProcessor>> childFPs;
-        for (size_t i = 0; i < childCount; ++i) {
-            if (!children[i]) {
+        for (size_t i = 0; i < children.size(); ++i) {
+            // TODO: add support for other types of child effects
+            if (!children[i].shader) {
                 return nullptr;
             }
-            childFPs.push_back(as_SB(children[i])->asFragmentProcessor(args));
+            childFPs.push_back(as_SB(children[i].shader)->asFragmentProcessor(args));
         }
         auto fp = GrSkSLFP::MakeWithData(sk_ref_sp(this),
                                          "runtime_image",
@@ -1268,7 +1268,7 @@
     }
     SkCanvas* canvas = surf->getCanvas();
     SkTLazy<SkCanvas> tempCanvas;
-    auto shader = this->makeShader(std::move(uniforms), children, childCount, localMatrix, false);
+    auto shader = this->makeShader(std::move(uniforms), children, localMatrix, false);
     if (!shader) {
         return nullptr;
     }
@@ -1344,8 +1344,7 @@
                                                  bool mipmapped) {
     return this->effect()->makeImage(recordingContext,
                                      this->uniforms(),
-                                     this->children(),
-                                     this->numChildren(),
+                                     SkMakeSpan(this->children(), this->numChildren()),
                                      localMatrix,
                                      resultInfo,
                                      mipmapped);
@@ -1353,8 +1352,7 @@
 
 sk_sp<SkShader> SkRuntimeShaderBuilder::makeShader(const SkMatrix* localMatrix, bool isOpaque) {
     return this->effect()->makeShader(this->uniforms(),
-                                      this->children(),
-                                      this->numChildren(),
+                                      SkMakeSpan(this->children(), this->numChildren()),
                                       localMatrix,
                                       isOpaque);
 }