Restore batching of (varying) paint alpha to shader FP trees

The previous version forced unique draws as the alpha changed (because
paint color was converted to a uniform). This version just uses a simple
wrapper FP that invokes the shader FP with the opaque paint color, then
multiplies the paint alpha against the result.

Bug: skia:11942
Bug: chromium:1265678
Bug: chromium:1265736
Cq-Include-Trybots: luci.skia.skia.primary:Canary-Chromium
Change-Id: I21fab1f1b0746e410509ddb4cbce5acdd21c89db
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/467077
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Osman 2021-11-02 15:45:00 -04:00 committed by SkCQ
parent 390edeb88d
commit 02b8a09274
3 changed files with 25 additions and 13 deletions

View File

@ -220,6 +220,20 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulInputByChildAlpha(
SkBlendMode::kSrcIn); SkBlendMode::kSrcIn);
} }
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ApplyPaintAlpha(
std::unique_ptr<GrFragmentProcessor> child) {
SkASSERT(child);
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter, R"(
uniform colorFilter fp;
half4 main(half4 inColor) {
return fp.eval(inColor.rgb1) * inColor.a;
}
)");
return GrSkSLFP::Make(effect, "ApplyPaintAlpha", /*inputFP=*/nullptr,
GrSkSLFP::OptFlags::kPreservesOpaqueInput,
"fp", std::move(child));
}
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ModulateAlpha( std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ModulateAlpha(
std::unique_ptr<GrFragmentProcessor> inputFP, const SkPMColor4f& color) { std::unique_ptr<GrFragmentProcessor> inputFP, const SkPMColor4f& color) {
auto colorFP = MakeColor(color); auto colorFP = MakeColor(color);

View File

@ -71,6 +71,13 @@ public:
static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha( static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
std::unique_ptr<GrFragmentProcessor> child); std::unique_ptr<GrFragmentProcessor> child);
/**
* Invokes child with an opaque version of the input color, then applies the input alpha to
* the result. Used to incorporate paint alpha to the evaluation of an SkShader tree FP.
*/
static std::unique_ptr<GrFragmentProcessor> ApplyPaintAlpha(
std::unique_ptr<GrFragmentProcessor> child);
/** /**
* Returns a fragment processor that generates the passed-in color, modulated by the child's * Returns a fragment processor that generates the passed-in color, modulated by the child's
* alpha channel. The child's input color will be the parent's fInputColor. (Pass a null FP to * alpha channel. The child's input color will be the parent's fInputColor. (Pass a null FP to

View File

@ -473,19 +473,10 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
#else #else
float paintAlpha = skPaint.getColor4f().fA; float paintAlpha = skPaint.getColor4f().fA;
if (paintAlpha != 1.0f) { if (paintAlpha != 1.0f) {
// TODO (skbug.com/11942): Can we instead make a single FP that does: // This invokes the shader's FP tree with an opaque version of the paint color,
// uniform colorFilter fp; // then multiplies the final result by the incoming (paint) alpha.
// half4 main(half4 inColor) { paintFP = GrFragmentProcessor::ApplyPaintAlpha(std::move(paintFP));
// return fp.eval(inColor.rgb1) * inColor.a; grPaint->setColor4f({origColor.fR, origColor.fG, origColor.fB, origColor.fA});
// }
// That's slightly different - we're relying on the input color being the paint
// color, but it would avoid the uniform (so might restore batching)?
SkPMColor4f shaderInput = origColor.makeOpaque().premul();
paintFP = GrFragmentProcessor::OverrideInput(std::move(paintFP), shaderInput);
paintFP = GrFragmentProcessor::ModulateRGBA(
std::move(paintFP), {paintAlpha, paintAlpha, paintAlpha, paintAlpha});
grPaint->setColor4f(shaderInput);
} else { } else {
grPaint->setColor4f(origColor.premul()); grPaint->setColor4f(origColor.premul());
} }