| Index: src/gpu/effects/GrPorterDuffXferProcessor.cpp
|
| diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
|
| index 5f34f75854838a6d419eedcabf366b0dde7586c5..4c50e47ab9ae1d3845fb603a4f8d42c639a7cbff 100644
|
| --- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
|
| +++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
|
| @@ -31,6 +31,7 @@ public:
|
| kNone_OutputType, //<! 0
|
| kCoverage_OutputType, //<! inputCoverage
|
| kModulate_OutputType, //<! inputColor * inputCoverage
|
| + kSAModulate_OutputType, //<! inputColor.a * inputCoverage
|
| kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
|
| kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage
|
|
|
| @@ -139,6 +140,15 @@ GR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
|
| kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
|
|
|
| /**
|
| + * Basic coeff formula similar to COEFF_FORMULA but we will make the src f*Sa. This is used in
|
| + * LCD dst-out.
|
| + */
|
| +#define COEFF_FORMULA_SA_MODULATE(SRC_COEFF, DST_COEFF) \
|
| + INIT_BLEND_FORMULA(BlendFormula::kSAModulate_OutputType, \
|
| + BlendFormula::kNone_OutputType, \
|
| + kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
|
| +
|
| +/**
|
| * When the coeffs are (Zero, Zero), we clear the dst. This formula has its own macro so we can set
|
| * the primary output type to none.
|
| */
|
| @@ -289,6 +299,24 @@ static const BlendFormula gBlendTable[2][2][SkXfermode::kLastCoeffMode + 1] = {
|
| /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
|
| }}};
|
|
|
| +static const BlendFormula gLCDBlendTable[SkXfermode::kLastCoeffMode + 1] = {
|
| + /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
|
| + /* src */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
|
| + /* dst */ NO_DST_WRITE_FORMULA,
|
| + /* src-over */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff),
|
| + /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
|
| + /* src-in */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff),
|
| + /* dst-in */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType),
|
| + /* src-out */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff),
|
| + /* dst-out */ COEFF_FORMULA_SA_MODULATE( kZero_GrBlendCoeff, kISC_GrBlendCoeff),
|
| + /* src-atop */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff),
|
| + /* dst-atop */ COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
|
| + /* xor */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff),
|
| + /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
|
| + /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
|
| + /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
|
| +};
|
| +
|
| static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI,
|
| const GrProcOptInfo& coveragePOI,
|
| bool hasMixedSamples,
|
| @@ -300,6 +328,14 @@ static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI,
|
| return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode];
|
| }
|
|
|
| +static BlendFormula get_lcd_blend_formula(const GrProcOptInfo& coveragePOI,
|
| + SkXfermode::Mode xfermode) {
|
| + SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
|
| + SkASSERT(coveragePOI.isFourChannelOutput());
|
| +
|
| + return gLCDBlendTable[xfermode];
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| class PorterDuffXferProcessor : public GrXferProcessor {
|
| @@ -363,6 +399,13 @@ static void append_color_output(const PorterDuffXferProcessor& xp, GrGLXPFragmen
|
| fsBuilder->codeAppendf("%s = %s;", output, inColor);
|
| }
|
| break;
|
| + case BlendFormula::kSAModulate_OutputType:
|
| + if (xp.readsCoverage()) {
|
| + fsBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage);
|
| + } else {
|
| + fsBuilder->codeAppendf("%s = %s;", output, inColor);
|
| + }
|
| + break;
|
| case BlendFormula::kISAModulate_OutputType:
|
| if (xp.readsCoverage()) {
|
| fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
|
| @@ -444,7 +487,9 @@ PorterDuffXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI,
|
| if (coveragePOI.isSolidWhite()) {
|
| optFlags |= GrXferProcessor::kIgnoreCoverage_OptFlag;
|
| }
|
| - if (colorPOI.allStagesMultiplyInput() && fBlendFormula.canTweakAlphaForCoverage()) {
|
| + if (colorPOI.allStagesMultiplyInput() &&
|
| + fBlendFormula.canTweakAlphaForCoverage() &&
|
| + !coveragePOI.isFourChannelOutput()) {
|
| optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
|
| }
|
| }
|
| @@ -579,7 +624,6 @@ public:
|
| private:
|
| void emitOutputsForBlendState(const EmitArgs& args) override {
|
| GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
|
| -
|
| fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor,
|
| args.fInputCoverage);
|
| }
|
| @@ -684,12 +728,18 @@ GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
|
| const GrProcOptInfo& covPOI,
|
| bool hasMixedSamples,
|
| const DstTexture* dstTexture) const {
|
| + BlendFormula blendFormula;
|
| if (covPOI.isFourChannelOutput()) {
|
| - SkASSERT(!dstTexture || !dstTexture->texture());
|
| - return PDLCDXferProcessor::Create(fXfermode, colorPOI);
|
| + if (SkXfermode::kSrcOver_Mode == fXfermode &&
|
| + kRGBA_GrColorComponentFlags == colorPOI.validFlags()) {
|
| + SkASSERT(!dstTexture || !dstTexture->texture());
|
| + return PDLCDXferProcessor::Create(fXfermode, colorPOI);
|
| + }
|
| + blendFormula = get_lcd_blend_formula(covPOI, fXfermode);
|
| + } else {
|
| + blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode);
|
| }
|
|
|
| - BlendFormula blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode);
|
| if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
|
| return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode);
|
| }
|
| @@ -698,15 +748,6 @@ GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
|
| return new PorterDuffXferProcessor(blendFormula);
|
| }
|
|
|
| -bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/,
|
| - uint32_t knownColorFlags) const {
|
| - if (SkXfermode::kSrcOver_Mode == fXfermode &&
|
| - kRGBA_GrColorComponentFlags == knownColorFlags) {
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
|
| InvariantBlendedColor* blendedColor) const {
|
| // Find the blended color info based on the formula that does not have coverage.
|
| @@ -745,8 +786,16 @@ bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps,
|
| if (caps.shaderCaps()->dualSourceBlendingSupport()) {
|
| return false;
|
| }
|
| +
|
| + // When we have four channel coverage we always need to read the dst in order to correctly
|
| + // blend. The one exception is when we are using srcover mode and we know the input color into
|
| + // the XP.
|
| if (covPOI.isFourChannelOutput()) {
|
| - return false; // The LCD XP will abort rather than doing a dst read.
|
| + if (SkXfermode::kSrcOver_Mode == fXfermode &&
|
| + kRGBA_GrColorComponentFlags == colorPOI.validFlags()) {
|
| + return false;
|
| + }
|
| + return get_lcd_blend_formula(covPOI, fXfermode).hasSecondaryOutput();
|
| }
|
| // We fallback on the shader XP when the blend formula would use dual source blending but we
|
| // don't have support for it.
|
|
|