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:
parent
8516c0dce4
commit
b1fdcf3e68
@ -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"(
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user