Allow sampling from SkBlenders.

Runtime shaders, color filters, and blenders are all able to sample from
a blender. These use the blend-function signature; both a src-color and
dst-color must be passed to sample. i.e.: sample(blender, s, d)

Change-Id: I3738e6b0b4af6d1d79e62ca1815c80d6a1ae9d6f
Bug: skia:12257
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/432056
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/codegen/SkSLVMCodeGenerator.cpp b/src/sksl/codegen/SkSLVMCodeGenerator.cpp
index f36dfea..0e8f16c 100644
--- a/src/sksl/codegen/SkSLVMCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLVMCodeGenerator.cpp
@@ -873,7 +873,7 @@
     if (intrinsicKind == k_sample_IntrinsicKind) {
         // Sample is very special. The first argument is a child (shader/colorFilter/blender),
         // which is opaque and can't be evaluated.
-        SkASSERT(nargs == 2);
+        SkASSERT(nargs >= 2);
         const Expression* child = c.arguments()[0].get();
         SkASSERT(child->type().isEffectChild());
         SkASSERT(child->is<VariableReference>());
@@ -887,16 +887,43 @@
         Value argVal = this->writeExpression(*arg);
         skvm::Color color;
 
-        if (child->type().typeKind() == Type::TypeKind::kShader) {
-            SkASSERT(arg->type() == *fProgram.fContext->fTypes.fFloat2);
-            skvm::Coord coord = {f32(argVal[0]), f32(argVal[1])};
-            color = fSampleShader(fp_it->second, coord);
-        } else {
-            SkASSERT(child->type().typeKind() == Type::TypeKind::kColorFilter);
-            SkASSERT(arg->type() == *fProgram.fContext->fTypes.fHalf4 ||
-                     arg->type() == *fProgram.fContext->fTypes.fFloat4);
-            skvm::Color inColor = {f32(argVal[0]), f32(argVal[1]), f32(argVal[2]), f32(argVal[3])};
-            color = fSampleColorFilter(fp_it->second, inColor);
+        switch (child->type().typeKind()) {
+            case Type::TypeKind::kShader: {
+                SkASSERT(nargs == 2);
+                SkASSERT(arg->type() == *fProgram.fContext->fTypes.fFloat2);
+                skvm::Coord coord = {f32(argVal[0]), f32(argVal[1])};
+                color = fSampleShader(fp_it->second, coord);
+                break;
+            }
+            case Type::TypeKind::kColorFilter: {
+                SkASSERT(nargs == 2);
+                SkASSERT(arg->type() == *fProgram.fContext->fTypes.fHalf4 ||
+                         arg->type() == *fProgram.fContext->fTypes.fFloat4);
+                skvm::Color inColor = {f32(argVal[0]), f32(argVal[1]),
+                                       f32(argVal[2]), f32(argVal[3])};
+                color = fSampleColorFilter(fp_it->second, inColor);
+                break;
+            }
+            case Type::TypeKind::kBlender: {
+                SkASSERT(nargs == 3);
+                SkASSERT(arg->type() == *fProgram.fContext->fTypes.fHalf4 ||
+                         arg->type() == *fProgram.fContext->fTypes.fFloat4);
+                skvm::Color srcColor = {f32(argVal[0]), f32(argVal[1]),
+                                        f32(argVal[2]), f32(argVal[3])};
+
+                arg = c.arguments()[2].get();
+                argVal = this->writeExpression(*arg);
+                SkASSERT(arg->type() == *fProgram.fContext->fTypes.fHalf4 ||
+                         arg->type() == *fProgram.fContext->fTypes.fFloat4);
+                skvm::Color dstColor = {f32(argVal[0]), f32(argVal[1]),
+                                        f32(argVal[2]), f32(argVal[3])};
+
+                color = fSampleBlender(fp_it->second, srcColor, dstColor);
+                break;
+            }
+            default: {
+                SkDEBUGFAILF("cannot sample from type '%s'", child->type().description().c_str());
+            }
         }
 
         Value result(4);