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);