Always send premul paint color to shader FPs

Fixes a bug with alpha-only image shaders not being modulated by paint
alpha (demonstrated by included GM). Compose shaders were the only
thing relaying on the old behavior, so make those manually unpremul the
input color, with a comment explaining the rationale.

This makes runtime shaders (and other new FPs) simpler to reason about:
sampling a child shader always produces a premul color, even if that
child is null (eg, the input color).

Bug: skia:10556
Change-Id: Ie629a9129d04ea80dae0b263c3811ca754202aab
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/306947
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index fc7ceaf..fde9029 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -266,9 +266,7 @@
                         std::move(paintFP), {paintAlpha, paintAlpha, paintAlpha, paintAlpha});
             }
         } else {
-            // The shader's FP sees the paint *unpremul* color
-            SkPMColor4f origColorAsPM = { origColor.fR, origColor.fG, origColor.fB, origColor.fA };
-            grPaint->setColor4f(origColorAsPM);
+            grPaint->setColor4f(origColor.premul());
         }
     } else {
         if (primColorMode) {
diff --git a/src/gpu/effects/GrBlendFragmentProcessor.cpp b/src/gpu/effects/GrBlendFragmentProcessor.cpp
index 609e2bf..83d701a 100644
--- a/src/gpu/effects/GrBlendFragmentProcessor.cpp
+++ b/src/gpu/effects/GrBlendFragmentProcessor.cpp
@@ -287,7 +287,9 @@
 
         case BlendBehavior::kComposeTwoBehavior:
             // Compose-two operations historically have forced the input color to opaque.
-            fragBuilder->codeAppendf("half4 inputOpaque = %s.rgb1;\n", args.fInputColor);
+            // We're going to re-apply the input color's alpha below, so feed the *unpremul* RGB
+            // to the children, to avoid double-applying alpha.
+            fragBuilder->codeAppendf("half4 inputOpaque = unpremul(%s).rgb1;\n", args.fInputColor);
             srcColor = this->invokeChild(0, "inputOpaque", args);
             dstColor = this->invokeChild(1, "inputOpaque", args);
             break;