Report optimizations in master gradient effects
All of the FPs for the gradient components have had to be updated to
include the @optimizationFlags section. Layout FPs now can use the
opacity preserving optimization to report whether or not they might
reject a fragment (e.g. 2 point conical gradients).
The previous composition logic that handled ensuring the gradient shader
output a premul color was removing optimizations that should have been
valid for gradients, so the make premul logic has been inlined into
the top-level effect FPs.
Bug: skia:
Change-Id: I73e4224d8dc0e3420a215b0aa805d829b08f6c76
Reviewed-on: https://skia-review.googlesource.com/151547
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/gradients/GrGradientShader.cpp b/src/gpu/gradients/GrGradientShader.cpp
index 7e14025..b4d2b65 100644
--- a/src/gpu/gradients/GrGradientShader.cpp
+++ b/src/gpu/gradients/GrGradientShader.cpp
@@ -115,6 +115,7 @@
// Convert all colors into destination space and into GrColor4fs, and handle
// premul issues depending on the interpolation mode
bool inputPremul = shader.getGradFlags() & SkGradientShader::kInterpolateColorsInPremul_Flag;
+ bool allOpaque = true;
SkAutoSTMalloc<4, GrColor4f> colors(shader.fColorCount);
SkColor4fXformer xformedColors(shader.fOrigColors4f, shader.fColorCount,
shader.fColorSpace.get(), args.fDstColorSpaceInfo->colorSpace());
@@ -123,6 +124,9 @@
if (inputPremul) {
colors[i] = colors[i].premul();
}
+ if (allOpaque && !SkScalarNearlyEqual(colors[i].fRGBA[3], 1.0)) {
+ allOpaque = false;
+ }
}
// SkGradientShader stores positions implicitly when they are evenly spaced, but the getPos()
@@ -148,16 +152,23 @@
return nullptr;
}
+ // The master effect has to export premul colors, but under certain conditions it doesn't need
+ // to do anything to achieve that: i.e. its interpolating already premul colors (inputPremul)
+ // or all the colors have a = 1, in which case premul is a no op. Note that this allOpaque
+ // check is more permissive than SkGradientShaderBase's isOpaque(), since we can optimize away
+ // the make-premul op for two point conical gradients (which report false for isOpaque).
+ bool makePremul = !inputPremul && !allOpaque;
+
// All tile modes are supported (unless something was added to SkShader)
std::unique_ptr<GrFragmentProcessor> master;
switch(shader.getTileMode()) {
case SkShader::kRepeat_TileMode:
master = GrTiledGradientEffect::Make(std::move(colorizer), std::move(layout),
- /* mirror */ false);
+ /* mirror */ false, makePremul, allOpaque);
break;
case SkShader::kMirror_TileMode:
master = GrTiledGradientEffect::Make(std::move(colorizer), std::move(layout),
- /* mirror */ true);
+ /* mirror */ true, makePremul, allOpaque);
break;
case SkShader::kClamp_TileMode:
// For the clamped mode, the border colors are the first and last colors, corresponding
@@ -165,12 +176,14 @@
// appropriate. If there is a hard stop, this grabs the expected outer colors for the
// border.
master = GrClampedGradientEffect::Make(std::move(colorizer), std::move(layout),
- colors[0], colors[shader.fColorCount - 1]);
+ colors[0], colors[shader.fColorCount - 1], makePremul, allOpaque);
break;
case SkShader::kDecal_TileMode:
+ // Even if the gradient colors are opaque, the decal borders are transparent so
+ // disable that optimization
master = GrClampedGradientEffect::Make(std::move(colorizer), std::move(layout),
- GrColor4f::TransparentBlack(),
- GrColor4f::TransparentBlack());
+ GrColor4f::TransparentBlack(), GrColor4f::TransparentBlack(),
+ makePremul, /* colorsAreOpaque */ false);
break;
}
@@ -179,14 +192,6 @@
return nullptr;
}
- if (!inputPremul) {
- // When interpolating unpremul colors, the output of the gradient
- // effect fp's will also be unpremul, so wrap it to ensure its premul.
- // - this is unnecessary when interpolating premul colors since the
- // output color is premul by nature
- master = GrFragmentProcessor::PremulOutput(std::move(master));
- }
-
return GrFragmentProcessor::MulChildByInputAlpha(std::move(master));
}