Improve inputColor handling in fragment processor implementations.

EmitArgs explicitly checks for null constructor arguments and uses
"half4(1)" for fInputColor to ensure its fields are non-null.

Cleans up accesses of fInputColor in existing fragment processors to no
longer check for null and hardcode a "half4(1)".

Updates .fp CPP generation to remove the null check for fInputArgs.

Updates the internals of emitChild() to emit an extra local variable
with a mangled variable name for storing the provided input expression.


Bug: skia:
Change-Id: Iad807f269655689dcb2e8d58f2eb506685ba2757
Reviewed-on: https://skia-review.googlesource.com/149231
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/core/SkColorMatrixFilterRowMajor255.cpp b/src/core/SkColorMatrixFilterRowMajor255.cpp
index ad36006..2307b7b 100644
--- a/src/core/SkColorMatrixFilterRowMajor255.cpp
+++ b/src/core/SkColorMatrixFilterRowMajor255.cpp
@@ -206,10 +206,6 @@
             fVectorHandle = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                        "ColorMatrixVector");
 
-            if (nullptr == args.fInputColor) {
-                // could optimize this case, but we aren't for now.
-                args.fInputColor = "half4(1)";
-            }
             GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
             // The max() is to guard against 0 / 0 during unpremul when the incoming color is
             // transparent black.
diff --git a/src/effects/SkHighContrastFilter.cpp b/src/effects/SkHighContrastFilter.cpp
index de0eebf..a007490 100644
--- a/src/effects/SkHighContrastFilter.cpp
+++ b/src/effects/SkHighContrastFilter.cpp
@@ -243,10 +243,6 @@
     fContrastUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                                     "contrast", &contrast);
 
-    if (nullptr == args.fInputColor) {
-        args.fInputColor = "half4(1)";
-    }
-
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
 
     fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
diff --git a/src/gpu/GrColorSpaceXform.cpp b/src/gpu/GrColorSpaceXform.cpp
index b0b23ea..f7b924a 100644
--- a/src/gpu/GrColorSpaceXform.cpp
+++ b/src/gpu/GrColorSpaceXform.cpp
@@ -74,9 +74,6 @@
             fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputColor, xformedColor.c_str(),
                                      args.fInputColor);
         } else {
-            if (nullptr == args.fInputColor) {
-                args.fInputColor = "half4(1)";
-            }
             SkString xformedColor;
             fragBuilder->appendColorGamutXform(&xformedColor, args.fInputColor, &fColorSpaceHelper);
             fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, xformedColor.c_str());
diff --git a/src/gpu/effects/GrAARectEffect.cpp b/src/gpu/effects/GrAARectEffect.cpp
index 663471e..9ee0ad5 100644
--- a/src/gpu/effects/GrAARectEffect.cpp
+++ b/src/gpu/effects/GrAARectEffect.cpp
@@ -54,7 +54,7 @@
                 (int)_outer.edgeType(),
                 (int)_outer.edgeType(),
                 args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "half4(1)");
+                args.fInputColor);
     }
 
 private:
diff --git a/src/gpu/effects/GrAlphaThresholdFragmentProcessor.cpp b/src/gpu/effects/GrAlphaThresholdFragmentProcessor.cpp
index 6e12bd4..45852ed 100644
--- a/src/gpu/effects/GrAlphaThresholdFragmentProcessor.cpp
+++ b/src/gpu/effects/GrAlphaThresholdFragmentProcessor.cpp
@@ -48,7 +48,7 @@
                 "color.w;\n        color.xyz *= scale;\n        color.w = %s;\n    }\n} else if "
                 "(color.w < %s) {\n    half scale = float(%s) / max(0.001, float(color.w));\n    "
                 "color.xyz *= scale;\n    color.w = %s;\n}\n%s = color;\n",
-                args.fInputColor ? args.fInputColor : "half4(1)",
+                args.fInputColor,
                 fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
                 sk_TransformedCoords2D_0.c_str(),
                 fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
diff --git a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp
index 9542b1a..eb5762e 100644
--- a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp
@@ -31,8 +31,7 @@
                 "0.017999999999999999);\n        break;\n    case 1:\n        factor = "
                 "half(smoothstep(1.0, 0.0, float(factor)));\n        break;\n}\n%s = "
                 "half4(factor);\n",
-                args.fInputColor ? args.fInputColor : "half4(1)", (int)_outer.mode(),
-                args.fOutputColor);
+                args.fInputColor, (int)_outer.mode(), args.fOutputColor);
     }
 
 private:
diff --git a/src/gpu/effects/GrCircleBlurFragmentProcessor.cpp b/src/gpu/effects/GrCircleBlurFragmentProcessor.cpp
index 02d84bb..3770c0d 100644
--- a/src/gpu/effects/GrCircleBlurFragmentProcessor.cpp
+++ b/src/gpu/effects/GrCircleBlurFragmentProcessor.cpp
@@ -283,7 +283,7 @@
                 args.fUniformHandler->getUniformCStr(fCircleDataVar),
                 args.fUniformHandler->getUniformCStr(fCircleDataVar),
                 args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "half4(1)",
+                args.fInputColor,
                 fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
                 fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
     }
diff --git a/src/gpu/effects/GrCircleEffect.cpp b/src/gpu/effects/GrCircleEffect.cpp
index f1324d6..30b81cc 100644
--- a/src/gpu/effects/GrCircleEffect.cpp
+++ b/src/gpu/effects/GrCircleEffect.cpp
@@ -46,7 +46,7 @@
                 args.fUniformHandler->getUniformCStr(fCircleVar),
                 args.fUniformHandler->getUniformCStr(fCircleVar), (int)_outer.edgeType(),
                 (int)_outer.edgeType(), (int)_outer.edgeType(), args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "half4(1)");
+                args.fInputColor);
     }
 
 private:
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index d2967fe..6493fcb 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -32,9 +32,9 @@
                 "0.5)) / 255.0);\n        break;\n    case 1:\n        %s.xyz = float(%s.w) <= 0.0 "
                 "? half3(0.0) : half3(floor(float3(float3((%s.xyz / %s.w) * 255.0) + 0.5)) / "
                 "255.0);\n        break;\n}\n",
-                args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)",
-                (int)_outer.pmConversion(), args.fOutputColor, args.fOutputColor, args.fOutputColor,
-                args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor);
+                args.fOutputColor, args.fInputColor, (int)_outer.pmConversion(), args.fOutputColor,
+                args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor,
+                args.fOutputColor, args.fOutputColor);
     }
 
 private:
diff --git a/src/gpu/effects/GrConstColorProcessor.cpp b/src/gpu/effects/GrConstColorProcessor.cpp
index b175119..43e9ffc 100644
--- a/src/gpu/effects/GrConstColorProcessor.cpp
+++ b/src/gpu/effects/GrConstColorProcessor.cpp
@@ -34,9 +34,8 @@
                 "* %s;\n        break;\n}\n",
                 (int)_outer.mode(), args.fOutputColor,
                 args.fUniformHandler->getUniformCStr(fColorUniformVar), args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "half4(1)",
-                args.fUniformHandler->getUniformCStr(fColorUniformVar), args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "half4(1)",
+                args.fInputColor, args.fUniformHandler->getUniformCStr(fColorUniformVar),
+                args.fOutputColor, args.fInputColor,
                 args.fUniformHandler->getUniformCStr(fColorUniformVar));
     }
 
diff --git a/src/gpu/effects/GrEllipseEffect.cpp b/src/gpu/effects/GrEllipseEffect.cpp
index 6c0d5b9..566e504 100644
--- a/src/gpu/effects/GrEllipseEffect.cpp
+++ b/src/gpu/effects/GrEllipseEffect.cpp
@@ -55,7 +55,7 @@
                 "2:\n        alpha = half(approx_dist > 0.0 ? 1.0 : 0.0);\n        break;\n    "
                 "case 3:\n        alpha = half(clamp(0.5 + approx_dist, 0.0, 1.0));\n        "
                 "break;\n    default:\n        discard;\n}\n%s = %s * alpha;\n",
-                args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)");
+                args.fOutputColor, args.fInputColor);
     }
 
 private:
diff --git a/src/gpu/effects/GrLumaColorFilterEffect.cpp b/src/gpu/effects/GrLumaColorFilterEffect.cpp
index cfa2a2f..b21dbc6 100644
--- a/src/gpu/effects/GrLumaColorFilterEffect.cpp
+++ b/src/gpu/effects/GrLumaColorFilterEffect.cpp
@@ -25,7 +25,7 @@
         fragBuilder->codeAppendf(
                 "\nhalf luma = dot(half3(0.21260000000000001, 0.71519999999999995, 0.0722), "
                 "%s.xyz);\n%s = half4(0.0, 0.0, 0.0, luma);\n",
-                args.fInputColor ? args.fInputColor : "half4(1)", args.fOutputColor);
+                args.fInputColor, args.fOutputColor);
     }
 
 private:
diff --git a/src/gpu/effects/GrOverdrawFragmentProcessor.cpp b/src/gpu/effects/GrOverdrawFragmentProcessor.cpp
index 48f2429..7170484 100644
--- a/src/gpu/effects/GrOverdrawFragmentProcessor.cpp
+++ b/src/gpu/effects/GrOverdrawFragmentProcessor.cpp
@@ -41,22 +41,21 @@
                 "else if (float(alpha) < 3.5) {\n    %s = half4(%f, %f, %f, %f);\n} else if "
                 "(float(alpha) < 4.5) {\n    %s = half4(%f, %f, %f, %f);\n} else {\n    %s = "
                 "half4(%f, %f, %f, %f);\n}\n",
-                args.fInputColor ? args.fInputColor : "half4(1)", args.fOutputColor,
-                SkGetPackedR32(_outer.color0()) / 255.0, SkGetPackedG32(_outer.color0()) / 255.0,
-                SkGetPackedB32(_outer.color0()) / 255.0, SkGetPackedA32(_outer.color0()) / 255.0,
-                args.fOutputColor, SkGetPackedR32(_outer.color1()) / 255.0,
-                SkGetPackedG32(_outer.color1()) / 255.0, SkGetPackedB32(_outer.color1()) / 255.0,
-                SkGetPackedA32(_outer.color1()) / 255.0, args.fOutputColor,
-                SkGetPackedR32(_outer.color2()) / 255.0, SkGetPackedG32(_outer.color2()) / 255.0,
-                SkGetPackedB32(_outer.color2()) / 255.0, SkGetPackedA32(_outer.color2()) / 255.0,
-                args.fOutputColor, SkGetPackedR32(_outer.color3()) / 255.0,
-                SkGetPackedG32(_outer.color3()) / 255.0, SkGetPackedB32(_outer.color3()) / 255.0,
-                SkGetPackedA32(_outer.color3()) / 255.0, args.fOutputColor,
-                SkGetPackedR32(_outer.color4()) / 255.0, SkGetPackedG32(_outer.color4()) / 255.0,
-                SkGetPackedB32(_outer.color4()) / 255.0, SkGetPackedA32(_outer.color4()) / 255.0,
-                args.fOutputColor, SkGetPackedR32(_outer.color5()) / 255.0,
-                SkGetPackedG32(_outer.color5()) / 255.0, SkGetPackedB32(_outer.color5()) / 255.0,
-                SkGetPackedA32(_outer.color5()) / 255.0);
+                args.fInputColor, args.fOutputColor, SkGetPackedR32(_outer.color0()) / 255.0,
+                SkGetPackedG32(_outer.color0()) / 255.0, SkGetPackedB32(_outer.color0()) / 255.0,
+                SkGetPackedA32(_outer.color0()) / 255.0, args.fOutputColor,
+                SkGetPackedR32(_outer.color1()) / 255.0, SkGetPackedG32(_outer.color1()) / 255.0,
+                SkGetPackedB32(_outer.color1()) / 255.0, SkGetPackedA32(_outer.color1()) / 255.0,
+                args.fOutputColor, SkGetPackedR32(_outer.color2()) / 255.0,
+                SkGetPackedG32(_outer.color2()) / 255.0, SkGetPackedB32(_outer.color2()) / 255.0,
+                SkGetPackedA32(_outer.color2()) / 255.0, args.fOutputColor,
+                SkGetPackedR32(_outer.color3()) / 255.0, SkGetPackedG32(_outer.color3()) / 255.0,
+                SkGetPackedB32(_outer.color3()) / 255.0, SkGetPackedA32(_outer.color3()) / 255.0,
+                args.fOutputColor, SkGetPackedR32(_outer.color4()) / 255.0,
+                SkGetPackedG32(_outer.color4()) / 255.0, SkGetPackedB32(_outer.color4()) / 255.0,
+                SkGetPackedA32(_outer.color4()) / 255.0, args.fOutputColor,
+                SkGetPackedR32(_outer.color5()) / 255.0, SkGetPackedG32(_outer.color5()) / 255.0,
+                SkGetPackedB32(_outer.color5()) / 255.0, SkGetPackedA32(_outer.color5()) / 255.0);
     }
 
 private:
diff --git a/src/gpu/effects/GrPremulInputFragmentProcessor.cpp b/src/gpu/effects/GrPremulInputFragmentProcessor.cpp
index d5373d5..846a4f8 100644
--- a/src/gpu/effects/GrPremulInputFragmentProcessor.cpp
+++ b/src/gpu/effects/GrPremulInputFragmentProcessor.cpp
@@ -23,10 +23,8 @@
         const GrPremulInputFragmentProcessor& _outer =
                 args.fFp.cast<GrPremulInputFragmentProcessor>();
         (void)_outer;
-        fragBuilder->codeAppendf("%s = %s;\n%s.xyz *= %s.w;\n", args.fOutputColor,
-                                 args.fInputColor ? args.fInputColor : "half4(1)",
-                                 args.fOutputColor,
-                                 args.fInputColor ? args.fInputColor : "half4(1)");
+        fragBuilder->codeAppendf("%s = %s;\n%s.xyz *= %s.w;\n", args.fOutputColor, args.fInputColor,
+                                 args.fOutputColor, args.fInputColor);
     }
 
 private:
diff --git a/src/gpu/effects/GrRRectBlurEffect.cpp b/src/gpu/effects/GrRRectBlurEffect.cpp
index e9659f5..ac17b17 100644
--- a/src/gpu/effects/GrRRectBlurEffect.cpp
+++ b/src/gpu/effects/GrRRectBlurEffect.cpp
@@ -91,7 +91,7 @@
                 "   translatedFragPos.y -= float(middle.y) - 1.0;\n}\nhalf2 proxyDims = "
                 "half2(half(2.0 * float(threshold) + 1.0));\nhalf2 texCoord = translatedFragPos / "
                 "proxyDims;\n%s = %s * texture(%s, float2(texCoord)).%s;\n",
-                args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)",
+                args.fOutputColor, args.fInputColor,
                 fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
                 fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
     }
diff --git a/src/gpu/effects/GrRectBlurEffect.cpp b/src/gpu/effects/GrRectBlurEffect.cpp
index 7b7b658..4c4ca86 100644
--- a/src/gpu/effects/GrRectBlurEffect.cpp
+++ b/src/gpu/effects/GrRectBlurEffect.cpp
@@ -75,8 +75,7 @@
                 args.fUniformHandler->getUniformCStr(fProfileSizeVar),
                 fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
                 fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
-                args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)",
-                args.fUniformHandler->getUniformCStr(fRectVar),
+                args.fOutputColor, args.fInputColor, args.fUniformHandler->getUniformCStr(fRectVar),
                 args.fUniformHandler->getUniformCStr(fRectVar),
                 args.fUniformHandler->getUniformCStr(fRectVar),
                 args.fUniformHandler->getUniformCStr(fRectVar),
@@ -98,7 +97,7 @@
                 args.fUniformHandler->getUniformCStr(fProfileSizeVar),
                 fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
                 fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(),
-                args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)");
+                args.fOutputColor, args.fInputColor);
     }
 
 private:
diff --git a/src/gpu/effects/GrSRGBEffect.cpp b/src/gpu/effects/GrSRGBEffect.cpp
index 6ca9759..1e2c162 100644
--- a/src/gpu/effects/GrSRGBEffect.cpp
+++ b/src/gpu/effects/GrSRGBEffect.cpp
@@ -43,10 +43,6 @@
                 break;
         }
 
-        if (nullptr == args.fInputColor) {
-            args.fInputColor = "half4(1)";
-        }
-
         // Mali Bifrost uses fp16 for mediump. Making the intermediate color variable highp causes
         // calculations to be performed with sufficient precision.
         fragBuilder->codeAppendf("float4 color = %s;", args.fInputColor);
diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp
index 0dda499..5b70a3e 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.cpp
+++ b/src/gpu/effects/GrSimpleTextureEffect.cpp
@@ -26,8 +26,7 @@
         (void)matrix;
         SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
         fragBuilder->codeAppendf(
-                "%s = %s * texture(%s, %s).%s;\n", args.fOutputColor,
-                args.fInputColor ? args.fInputColor : "half4(1)",
+                "%s = %s * texture(%s, %s).%s;\n", args.fOutputColor, args.fInputColor,
                 fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
                 sk_TransformedCoords2D_0.c_str(),
                 fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index 0ebd5c4..2a52909 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -149,8 +149,7 @@
                         SkSL::Compiler::FormatArg& arg = fFormatArgs[formatArgIndex++];
                         switch (arg.fKind) {
                             case SkSL::Compiler::FormatArg::Kind::kInput:
-                                fragBuilder->codeAppend(args.fInputColor ? args.fInputColor
-                                                                         : "half4(1)");
+                                fragBuilder->codeAppend(args.fInputColor);
                                 break;
                             case SkSL::Compiler::FormatArg::Kind::kOutput:
                                 fragBuilder->codeAppend(args.fOutputColor);
diff --git a/src/gpu/effects/GrUnpremulInputFragmentProcessor.cpp b/src/gpu/effects/GrUnpremulInputFragmentProcessor.cpp
index b3565d7..ab922a5 100644
--- a/src/gpu/effects/GrUnpremulInputFragmentProcessor.cpp
+++ b/src/gpu/effects/GrUnpremulInputFragmentProcessor.cpp
@@ -25,9 +25,8 @@
         (void)_outer;
         fragBuilder->codeAppendf(
                 "%s = %s;\nhalf invAlpha = %s.w <= 0.0 ? 0.0 : 1.0 / %s.w;\n%s.xyz *= invAlpha;\n",
-                args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)",
-                args.fInputColor ? args.fInputColor : "half4(1)",
-                args.fInputColor ? args.fInputColor : "half4(1)", args.fOutputColor);
+                args.fOutputColor, args.fInputColor, args.fInputColor, args.fInputColor,
+                args.fOutputColor);
     }
 
 private:
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index 2ce40c8..9793ee4 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -450,20 +450,13 @@
         SkString childColor("child");
         this->emitChild(0, &childColor, args);
 
-        const char* inputColor = args.fInputColor;
-        // We don't try to optimize for this case at all
-        if (!inputColor) {
-            fragBuilder->codeAppendf("const half4 ones = half4(1);");
-            inputColor = "ones";
-        }
-
         // emit blend code
         fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
         const char* childStr = childColor.c_str();
         if (ComposeOneFragmentProcessor::kDst_Child == child) {
-            GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
+            GrGLSLBlend::AppendMode(fragBuilder, args.fInputColor, childStr, args.fOutputColor, mode);
         } else {
-            GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
+            GrGLSLBlend::AppendMode(fragBuilder, childStr, args.fInputColor, args.fOutputColor, mode);
         }
     }
 
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
index 49b518f..78c427d 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
@@ -35,11 +35,21 @@
 
 void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inputColor,
                                                 const char* outputColor, EmitArgs& args) {
-    SkASSERT(inputColor);
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
 
     fragBuilder->onBeforeChildProcEmitCode();  // call first so mangleString is updated
 
+    // Prepare a mangled input color variable if the default is not used,
+    // inputName remains the empty string if no variable is needed.
+    SkString inputName;
+    if (inputColor&& strcmp("half4(1.0)", inputColor) != 0 && strcmp("half4(1)", inputColor) != 0) {
+        // The input name is based off of the current mangle string, and
+        // since this is called after onBeforeChildProcEmitCode(), it will be
+        // unique to the child processor (exactly what we want for its input).
+        inputName.appendf("_childInput%s", fragBuilder->getMangleString().c_str());
+        fragBuilder->codeAppendf("half4 %s = %s;", inputName.c_str(), inputColor);
+    }
+
     const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
 
     // emit the code for the child in its own scope
@@ -48,12 +58,14 @@
                              fragBuilder->getMangleString().c_str(), childProc.name());
     TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex);
     TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex);
+
+    // EmitArgs properly updates inputColor to half4(1) if it was null
     EmitArgs childArgs(fragBuilder,
                        args.fUniformHandler,
                        args.fShaderCaps,
                        childProc,
                        outputColor,
-                       inputColor,
+                       inputName.size() > 0 ? inputName.c_str() : nullptr,
                        coordVars,
                        textureSamplers);
     this->childProcessor(childIndex)->emitCode(childArgs);
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h
index 591146e..357b80e 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.h
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h
@@ -83,8 +83,9 @@
         @param outputColor       A predefined half4 in the FS in which the stage should place its
                                  output color (or coverage).
         @param inputColor        A half4 that holds the input color to the stage in the FS. This may
-                                 be nullptr in which case the implied input is solid white (all
-                                 ones). TODO: Better system for communicating optimization info
+                                 be nullptr in which case the fInputColor is set to "half4(1.0)"
+                                 (solid white) so this is guaranteed non-null.
+                                 TODO: Better system for communicating optimization info
                                  (e.g. input color is solid white, trans black, known to be opaque,
                                  etc.) that allows the processor to communicate back similar known
                                  info about its output.
@@ -108,7 +109,7 @@
                 , fShaderCaps(caps)
                 , fFp(fp)
                 , fOutputColor(outputColor)
-                , fInputColor(inputColor)
+                , fInputColor(inputColor ? inputColor : "half4(1.0)")
                 , fTransformedCoords(transformedCoordVars)
                 , fTexSamplers(textureSamplers) {}
         GrGLSLFPFragmentBuilder* fFragBuilder;
@@ -131,8 +132,9 @@
         return fChildProcessors[index];
     }
 
+    // Emit the child with the default input color (solid white)
     inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) {
-        this->emitChild(childIndex, "half4(1.0)", outputColor, parentArgs);
+        this->emitChild(childIndex, nullptr, outputColor, parentArgs);
     }
 
     /** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and
@@ -146,8 +148,11 @@
     void emitChild(int childIndex, const char* inputColor, SkString* outputColor,
                    EmitArgs& parentArgs);
 
+    // Use the parent's output color to hold child's output, and use the
+    // default input color of solid white
     inline void emitChild(int childIndex, EmitArgs& args) {
-        this->emitChild(childIndex, "half4(1.0)", args);
+        // null pointer cast required to disambiguate the function call
+        this->emitChild(childIndex, (const char*) nullptr, args);
     }
 
     /** Variation that uses the parent's output color variable to hold the child's output.*/
diff --git a/src/gpu/glsl/GrGLSLXferProcessor.h b/src/gpu/glsl/GrGLSLXferProcessor.h
index 10658a9..465e2a7 100644
--- a/src/gpu/glsl/GrGLSLXferProcessor.h
+++ b/src/gpu/glsl/GrGLSLXferProcessor.h
@@ -40,7 +40,7 @@
                 , fUniformHandler(uniformHandler)
                 , fShaderCaps(caps)
                 , fXP(xp)
-                , fInputColor(inputColor)
+                , fInputColor(inputColor ? inputColor : "half4(1.0)")
                 , fInputCoverage(inputCoverage)
                 , fOutputPrimary(outputPrimary)
                 , fOutputSecondary(outputSecondary)
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index 4eab6ba..7e8f492 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -240,7 +240,9 @@
     switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
         case SK_INCOLOR_BUILTIN:
             this->write("%s");
-            fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"half4(1)\""));
+            // EmitArgs.fInputColor is automatically set to half4(1) if
+            // no input was specified
+            fFormatArgs.push_back(String("args.fInputColor"));
             break;
         case SK_OUTCOLOR_BUILTIN:
             this->write("%s");