Short circuit the gainmap shader if we would not apply the gainmap

This is needed for correctness when authoring to a PDF. The gainmap
shader otherwise manually de-gammas into a working space to do the
gainmap math, then uses toLinearSrgb to re-gamma to the destination
space.

But, SkPicture records commands while being colorspace agnostic, so
manually de-gammaing means we never re-gamma, which has the effect over
crushing the resulting image.

This is probably also nice for performance too, because we avoid
sampling the gainmap and a bunch of math operations.

Bug: 341006313
Test: Photos > 1up > Print
Flag: EXEMPT low risk bug fix
Change-Id: Id2de97b112a8eff8ef56a802a3f44d83abdd6d41
diff --git a/libs/hwui/effects/GainmapRenderer.cpp b/libs/hwui/effects/GainmapRenderer.cpp
index 0a30c6c..eac0360 100644
--- a/libs/hwui/effects/GainmapRenderer.cpp
+++ b/libs/hwui/effects/GainmapRenderer.cpp
@@ -96,6 +96,7 @@
 #ifdef __ANDROID__
 
 static constexpr char gGainmapSKSL[] = R"SKSL(
+    uniform shader linearBase;
     uniform shader base;
     uniform shader gainmap;
     uniform colorFilter workingSpaceToLinearSrgb;
@@ -117,7 +118,11 @@
     }
 
     half4 main(float2 coord) {
-        half4 S = base.eval(coord);
+        if (W == 0.0) {
+            return base.eval(coord);
+        }
+
+        half4 S = linearBase.eval(coord);
         half4 G = gainmap.eval(coord);
         if (gainmapIsAlpha == 1) {
             G = half4(G.a, G.a, G.a, 1.0);
@@ -186,8 +191,10 @@
                 SkColorFilterPriv::MakeColorSpaceXform(baseColorSpace, gainmapMathColorSpace);
 
         // The base image shader will convert into the color space in which the gainmap is applied.
-        auto baseImageShader = baseImage->makeRawShader(tileModeX, tileModeY, samplingOptions)
-                                       ->makeWithColorFilter(colorXformSdrToGainmap);
+        auto linearBaseImageShader = baseImage->makeRawShader(tileModeX, tileModeY, samplingOptions)
+                                             ->makeWithColorFilter(colorXformSdrToGainmap);
+
+        auto baseImageShader = baseImage->makeShader(tileModeX, tileModeY, samplingOptions);
 
         // The gainmap image shader will ignore any color space that the gainmap has.
         const SkMatrix gainmapRectToDstRect =
@@ -201,6 +208,7 @@
         auto colorXformGainmapToDst = SkColorFilterPriv::MakeColorSpaceXform(
                 gainmapMathColorSpace, SkColorSpace::MakeSRGBLinear());
 
+        mBuilder.child("linearBase") = std::move(linearBaseImageShader);
         mBuilder.child("base") = std::move(baseImageShader);
         mBuilder.child("gainmap") = std::move(gainmapImageShader);
         mBuilder.child("workingSpaceToLinearSrgb") = std::move(colorXformGainmapToDst);