diff options
-rw-r--r-- | src/gpu/effects/GrPorterDuffXferProcessor.cpp | 53 | ||||
-rw-r--r-- | tests/GrPorterDuffTest.cpp | 127 |
2 files changed, 97 insertions, 83 deletions
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp index 269262b343..834f3af950 100644 --- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp +++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp @@ -775,7 +775,7 @@ sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::makeXferProcessor( } if ((blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) || - (isLCD && !color.isOpaque())) { + (isLCD && (SkBlendMode::kSrcOver != fBlendMode || !color.isOpaque()))) { return sk_sp<const GrXferProcessor>(new ShaderPDXferProcessor(hasMixedSamples, fBlendMode, coverage)); } @@ -795,36 +795,41 @@ static inline GrXPFactory::AnalysisProperties analysis_properties( } else { formula = gBlendTable[color.isOpaque()][hasCoverage][(int)mode]; } - if (formula.canTweakAlphaForCoverage()) { + + if (formula.canTweakAlphaForCoverage() && !isLCD) { props |= AnalysisProperties::kCompatibleWithAlphaAsCoverage; } - // With dual-source blending we never need the destination color in the shader. - if (!caps.shaderCaps()->dualSourceBlendingSupport()) { - // Mixed samples implicity computes a fractional coverage from sample coverage. This could - // affect the formula used. However, we don't expect to have mixed samples without dual - // source blending. - SkASSERT(!caps.usesMixedSamples()); - if (GrProcessorAnalysisCoverage::kLCD == coverage) { - // Check for special case of srcover with a known color which can be done using the - // blend constant. - if (SkBlendMode::kSrcOver == mode && color.isConstant() && color.isOpaque() && - !caps.shaderCaps()->dstReadInShaderSupport()) { - props |= AnalysisProperties::kIgnoresInputColor; - } else { - if (get_lcd_blend_formula(mode).hasSecondaryOutput() || !color.isOpaque()) { - props |= AnalysisProperties::kReadsDstInShader; - } + + if (isLCD) { + if (SkBlendMode::kSrcOver == mode && color.isConstant() && color.isOpaque() && + !caps.shaderCaps()->dualSourceBlendingSupport() && + !caps.shaderCaps()->dstReadInShaderSupport()) { + props |= AnalysisProperties::kIgnoresInputColor; + } else { + // For LCD blending, if the color is not opaque we must read the dst in shader even if + // we have dual source blending. The opaqueness check must be done after blending so for + // simplicity we only allow src-over to not take the dst read path (though src, src-in, + // and DstATop would also work). We also fall into the dst read case for src-over if we + // do not have dual source blending. + if (SkBlendMode::kSrcOver != mode || + !color.isOpaque() || + !caps.shaderCaps()->dualSourceBlendingSupport()) { + props |= AnalysisProperties::kReadsDstInShader; } - } else if (formula.hasSecondaryOutput()) { - props |= AnalysisProperties::kReadsDstInShader; } } else { - // For LCD blending, if the color is not opaque we must read the dst in shader even if we - // have dual source blending. - if (isLCD && !color.isOpaque()) { - props |= AnalysisProperties::kReadsDstInShader; + // With dual-source blending we never need the destination color in the shader. + if (!caps.shaderCaps()->dualSourceBlendingSupport()) { + // Mixed samples implicity computes a fractional coverage from sample coverage. This + // could affect the formula used. However, we don't expect to have mixed samples without + // dual source blending. + SkASSERT(!caps.usesMixedSamples()); + if (formula.hasSecondaryOutput()) { + props |= AnalysisProperties::kReadsDstInShader; + } } } + if (!formula.modifiesDst() || !formula.usesInputColor()) { props |= AnalysisProperties::kIgnoresInputColor; } diff --git a/tests/GrPorterDuffTest.cpp b/tests/GrPorterDuffTest.cpp index f000077f8a..90c9b50ce2 100644 --- a/tests/GrPorterDuffTest.cpp +++ b/tests/GrPorterDuffTest.cpp @@ -56,6 +56,7 @@ enum { kISAModulate_OutputType, kISCModulate_OutputType }; +static const int kInvalid_OutputType = -1; static GrProcessorSet::Analysis do_analysis(const GrXPFactory* xpf, const GrProcessorAnalysisColor& colorInput, @@ -77,16 +78,24 @@ public: GrProcessorAnalysisColor inputColor, GrProcessorAnalysisCoverage inputCoverage) { const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode); + bool isLCD = GrProcessorAnalysisCoverage::kLCD == inputCoverage; + GrProcessorSet::Analysis analysis = do_analysis(xpf, inputColor, inputCoverage, caps); fCompatibleWithCoverageAsAlpha = analysis.isCompatibleWithCoverageAsAlpha(); fCanCombineOverlappedStencilAndCover = analysis.canCombineOverlappedStencilAndCover(); fIgnoresInputColor = analysis.inputColorIsIgnored(); sk_sp<const GrXferProcessor> xp( GrXPFactory::MakeXferProcessor(xpf, inputColor, inputCoverage, false, caps)); - TEST_ASSERT(!analysis.requiresDstTexture()); + TEST_ASSERT(!analysis.requiresDstTexture() || + (isLCD && + !caps.shaderCaps()->dstReadInShaderSupport() && + (SkBlendMode::kSrcOver != xfermode || + !inputColor.isOpaque()))); GetXPOutputTypes(xp.get(), &fPrimaryOutputType, &fSecondaryOutputType); xp->getBlendInfo(&fBlendInfo); - TEST_ASSERT(!xp->willReadDstColor()); + TEST_ASSERT(!xp->willReadDstColor() || + (isLCD && (SkBlendMode::kSrcOver != xfermode || + !inputColor.isOpaque()))); TEST_ASSERT(xp->hasSecondaryOutput() == GrBlendCoeffRefsSrc2(fBlendInfo.fDstBlend)); } @@ -115,34 +124,34 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrc: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDst: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcOver: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); @@ -159,121 +168,121 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcIn: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstIn: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kISAModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcOut: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstOut: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kSAModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcATop: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstATop: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kISAModulate_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kXor: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kPlus: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kModulate: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); + TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kScreen: TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(!xpi.fIgnoresInputColor); TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fPrimaryOutputType); + TEST_ASSERT(kInvalid_OutputType == xpi.fSecondaryOutputType); TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); + TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; default: |