Revert "Move alpha modulation into paint conversion (Step 2)"

This reverts commit ccb459d57b.

Reason for revert: Speculative - reverting this for now in case Chrome needs to revert the flag-flip.

Original change's description:
> Move alpha modulation into paint conversion (Step 2)
>
> With paint conversion changed, this CL cleans up several SkShader
> classes, based on the fact that input alpha will always be opaque.
>
> Bug: skia:11942
> Change-Id: I91c919a69b6dfe4fea40b799888dd6179defdd70
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/463799
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Brian Osman <brianosman@google.com>

Bug: skia:11942
Change-Id: Ia6a7ac236e75f37df3bf0af235b2862fead3f523
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/466446
Auto-Submit: Brian Osman <brianosman@google.com>
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
This commit is contained in:
Brian Osman 2021-11-01 20:35:44 +00:00 committed by SkCQ
parent 8516c0dce4
commit b1fdcf3e68
7 changed files with 139 additions and 38 deletions

View File

@ -200,6 +200,16 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeColor(SkPMColor4f
"color", color);
}
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulChildByInputAlpha(
std::unique_ptr<GrFragmentProcessor> fp) {
if (!fp) {
return nullptr;
}
return GrBlendFragmentProcessor::Make(/*src=*/nullptr,
OverrideInput(std::move(fp), SK_PMColor4fWHITE),
SkBlendMode::kDstIn);
}
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulInputByChildAlpha(
std::unique_ptr<GrFragmentProcessor> fp) {
if (!fp) {
@ -320,6 +330,72 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(
return SwizzleFragmentProcessor::Make(std::move(fp), swizzle);
}
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
std::unique_ptr<GrFragmentProcessor> fp) {
class PremulFragmentProcessor : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(
std::unique_ptr<GrFragmentProcessor> processor) {
return std::unique_ptr<GrFragmentProcessor>(
new PremulFragmentProcessor(std::move(processor)));
}
const char* name() const override { return "Premultiply"; }
std::unique_ptr<GrFragmentProcessor> clone() const override {
return Make(this->childProcessor(0)->clone());
}
private:
PremulFragmentProcessor(std::unique_ptr<GrFragmentProcessor> processor)
: INHERITED(kPremulFragmentProcessor_ClassID, OptFlags(processor.get())) {
this->registerChild(std::move(processor));
}
std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override {
class Impl : public ProgramImpl {
public:
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
SkString temp = this->invokeChild(/*childIndex=*/0, "half4(1)", args);
fragBuilder->codeAppendf("half4 color = %s;", temp.c_str());
fragBuilder->codeAppendf("color.rgb *= %s.rgb;", args.fInputColor);
fragBuilder->codeAppendf("return color * %s.a;", args.fInputColor);
}
};
return std::make_unique<Impl>();
}
void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
OptimizationFlags flags = kNone_OptimizationFlags;
if (inner->preservesOpaqueInput()) {
flags |= kPreservesOpaqueInput_OptimizationFlag;
}
if (inner->hasConstantOutputForConstantInput()) {
flags |= kConstantOutputForConstantInput_OptimizationFlag;
}
return flags;
}
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
SkPMColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
SK_PMColor4fWHITE);
SkPMColor4f premulInput = SkColor4f{ input.fR, input.fG, input.fB, input.fA }.premul();
return premulInput * childColor;
}
using INHERITED = GrFragmentProcessor;
};
if (!fp) {
return nullptr;
}
return PremulFragmentProcessor::Make(std::move(fp));
}
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(
@ -344,21 +420,6 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::DisableCoverageAsAlpha(
std::unique_ptr<GrFragmentProcessor> fp) {
if (!fp || !fp->compatibleWithCoverageAsAlpha()) {
return fp;
}
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter, R"(
half4 main(half4 inColor) { return inColor; }
)");
SkASSERT(SkRuntimeEffectPriv::SupportsConstantOutputForConstantInput(effect));
return GrSkSLFP::Make(effect, "DisableCoverageAsAlpha", std::move(fp),
GrSkSLFP::OptFlags::kPreservesOpaqueInput);
}
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::UseDestColorAsInput(
std::unique_ptr<GrFragmentProcessor> fp) {
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForBlender, R"(

View File

@ -52,8 +52,19 @@ public:
static std::unique_ptr<GrFragmentProcessor> MakeColor(SkPMColor4f color);
/**
* Returns the input color, modulated by the child's alpha. The passed in FP will not receive
* an input color.
* In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
* only consider the input color's alpha. However, there is a competing desire to have reusable
* GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
* color is considered. This function exists to filter the input color and pass it to a FP. It
* does so by returning a parent FP that multiplies the passed in FPs output by the parent's
* input alpha. The passed in FP will not receive an input color.
*/
static std::unique_ptr<GrFragmentProcessor> MulChildByInputAlpha(
std::unique_ptr<GrFragmentProcessor> child);
/**
* Like MulChildByInputAlpha(), but reverses the sense of src and dst. In this case, return
* the input modulated by the child's alpha. The passed in FP will not receive an input color.
*
* output = input * child.a
*/
@ -76,6 +87,15 @@ public:
static std::unique_ptr<GrFragmentProcessor> ModulateRGBA(
std::unique_ptr<GrFragmentProcessor> child, const SkPMColor4f& color);
/**
* This assumes that the input color to the returned processor will be unpremul and that the
* passed processor (which becomes the returned processor's child) produces a premul output.
* The result of the returned processor is a premul of its input color modulated by the child
* processor's premul output.
*/
static std::unique_ptr<GrFragmentProcessor> MakeInputPremulAndMulByOutput(
std::unique_ptr<GrFragmentProcessor>);
/**
* Returns a parent fragment processor that adopts the passed fragment processor as a child.
* The parent will ignore its input color and instead feed the passed in color as input to the
@ -85,14 +105,6 @@ public:
const SkPMColor4f&,
bool useUniform = true);
/**
* Returns a parent fragment processor that adopts the passed fragment processor as a child.
* The parent will simply return the child's color, but disable the coverage-as-alpha
* optimization.
*/
static std::unique_ptr<GrFragmentProcessor> DisableCoverageAsAlpha(
std::unique_ptr<GrFragmentProcessor>);
/**
* Returns a fragment processor which samples the passed-in fragment processor using
* `args.fDestColor` as its input color. Pass a null FP to access `args.fDestColor` directly.

View File

@ -769,8 +769,15 @@ static std::unique_ptr<GrFragmentProcessor> make_gradient(
// Unexpected tile mode
return nullptr;
}
// TODO (skbug.com/11942): Does this belong here? Can we handle this in paint conversion?
return GrFragmentProcessor::DisableCoverageAsAlpha(std::move(gradient));
if (args.fInputColorIsOpaque) {
// If the input alpha is known to be 1, we don't need to take the kSrcIn path. This is
// just an optimization. However, we can't just return 'gradient' here. We need to actually
// inhibit the coverage-as-alpha optimization, or we'll fail to incorporate AA correctly.
// The OverrideInput FP happens to do that, so wrap our fp in one of those. The gradient FP
// doesn't actually use the input color at all, so the overridden input is irrelevant.
return GrFragmentProcessor::OverrideInput(std::move(gradient), SK_PMColor4fWHITE, false);
}
return GrFragmentProcessor::MulChildByInputAlpha(std::move(gradient));
}
namespace GrGradientShader {

View File

@ -520,12 +520,26 @@ void draw_image(GrRecordingContext* rContext,
fp = GrBlendFragmentProcessor::Make(
std::move(fp), std::move(shaderFP), SkBlendMode::kDstIn);
} else {
// Multiply the input (paint) color by the texture (alpha)
fp = GrFragmentProcessor::MulInputByChildAlpha(std::move(fp));
// This takes the input (paint) color, premultiplies it, then multiplies by the texture
fp = GrFragmentProcessor::MakeInputPremulAndMulByOutput(std::move(fp));
}
} else {
// TODO (skbug.com/11942): Does this belong here? Can we handle this in paint conversion?
fp = GrFragmentProcessor::DisableCoverageAsAlpha(std::move(fp));
if (paint.getColor4f().isOpaque()) {
// If the input alpha is known to be 1, we don't need to take the kSrcIn path. This is
// just an optimization. However, we can't just return 'fp' here. We need to actually
// inhibit the coverage-as-alpha optimization, or we'll fail to incorporate AA
// correctly. The OverrideInput FP happens to do that, so wrap our fp in one of those.
// The texture FP doesn't actually use the input color at all, so the overridden input
// is irrelevant.
fp = GrFragmentProcessor::OverrideInput(std::move(fp), SK_PMColor4fWHITE, false);
} else {
// If the paint color isn't opaque, then scale the shader's output by input (paint)
// alpha.
// TODO(skia:11942): Move this alpha modulation to paint-conversion. This won't need to
// do anything.
fp = GrFragmentProcessor::MulChildByInputAlpha(std::move(fp));
}
}
GrPaint grPaint;

View File

@ -298,10 +298,15 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
kPremul_SkAlphaType);
if (fImage->isAlphaOnly()) {
return GrBlendFragmentProcessor::Make(std::move(fp), nullptr, SkBlendMode::kDstIn);
} else {
// TODO (skbug.com/11942): Does this belong here? Can we handle this in paint conversion?
return GrFragmentProcessor::DisableCoverageAsAlpha(std::move(fp));
} else if (args.fInputColorIsOpaque) {
// If the input alpha is known to be 1, we don't need to take the kSrcIn path. This is
// just an optimization. However, we can't just return 'fp' here. We need to actually
// inhibit the coverage-as-alpha optimization, or we'll fail to incorporate AA correctly.
// The OverrideInput FP happens to do that, so wrap our fp in one of those. The texture FP
// doesn't actually use the input color at all, so the overridden input is irrelevant.
return GrFragmentProcessor::OverrideInput(std::move(fp), SK_PMColor4fWHITE, false);
}
return GrBlendFragmentProcessor::Make(std::move(fp), nullptr, SkBlendMode::kSrcIn);
}
#endif

View File

@ -941,11 +941,13 @@ std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcesso
if (0 == fNumOctaves) {
if (kFractalNoise_Type == fType) {
// Incoming alpha is assumed to be 1. So emit rgba = (1/4, 1/4, 1/4, 1/2)
// Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
// TODO: Either treat the output of this shader as sRGB or allow client to specify a
// color space of the noise. Either way, this case (and the GLSL) need to convert to
// the destination.
return GrFragmentProcessor::MakeColor(SkPMColor4f::FromBytes_RGBA(0x80404040));
auto inner = GrFragmentProcessor::ModulateRGBA(
/*child=*/nullptr, SkPMColor4f::FromBytes_RGBA(0x80404040));
return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
}
// Emit zero.
return GrFragmentProcessor::MakeColor(SK_PMColor4fTRANSPARENT);
@ -966,7 +968,7 @@ std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcesso
std::move(noiseView),
m,
*context->priv().caps());
return GrFragmentProcessor::DisableCoverageAsAlpha(std::move(inner));
return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
}
return nullptr;
}

View File

@ -426,7 +426,7 @@ std::unique_ptr<GrFragmentProcessor> SkPictureShader::asFragmentProcessor(
static_cast<GrSamplerState::WrapMode>(fTmy),
fFilter);
return GrFragmentProcessor::DisableCoverageAsAlpha(
return GrFragmentProcessor::MulChildByInputAlpha(
GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, inv, sampler,
*ctx->priv().caps()));
}