diff options
Diffstat (limited to 'src/gpu/effects')
-rw-r--r-- | src/gpu/effects/GrCoverageSetOpXP.cpp | 8 | ||||
-rw-r--r-- | src/gpu/effects/GrCoverageSetOpXP.h | 7 | ||||
-rw-r--r-- | src/gpu/effects/GrCustomXfermode.cpp | 141 | ||||
-rw-r--r-- | src/gpu/effects/GrDisableColorXP.cpp | 4 | ||||
-rw-r--r-- | src/gpu/effects/GrDisableColorXP.h | 9 | ||||
-rw-r--r-- | src/gpu/effects/GrPorterDuffXferProcessor.cpp | 140 | ||||
-rw-r--r-- | src/gpu/effects/GrPorterDuffXferProcessor.h | 16 |
7 files changed, 130 insertions, 195 deletions
diff --git a/src/gpu/effects/GrCoverageSetOpXP.cpp b/src/gpu/effects/GrCoverageSetOpXP.cpp index 1013706842..84219aef11 100644 --- a/src/gpu/effects/GrCoverageSetOpXP.cpp +++ b/src/gpu/effects/GrCoverageSetOpXP.cpp @@ -33,8 +33,6 @@ public: private: CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage); - GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override; - void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override; @@ -103,12 +101,6 @@ GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const { return new GLCoverageSetOpXP(*this); } -GrXferProcessor::OptFlags CoverageSetOpXP::onGetOptimizations( - const FragmentProcessorAnalysis&) const { - // We never look at the color input - return GrXferProcessor::kIgnoreColor_OptFlag; -} - void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const { switch (fRegionOp) { case SkRegion::kReplace_Op: diff --git a/src/gpu/effects/GrCoverageSetOpXP.h b/src/gpu/effects/GrCoverageSetOpXP.h index a0cb0c518c..b7239f3a19 100644 --- a/src/gpu/effects/GrCoverageSetOpXP.h +++ b/src/gpu/effects/GrCoverageSetOpXP.h @@ -35,11 +35,12 @@ private: bool hasMixedSamples, const DstTexture*) const override; - bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override { - return false; + AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&, + const GrPipelineAnalysisCoverage&, + const GrCaps&) const override { + return AnalysisProperties::kIgnoresInputColor; } - bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const override { return false; } GR_DECLARE_XP_FACTORY_TEST; diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp index 1f2771cb52..2e6d27cdfa 100644 --- a/src/gpu/effects/GrCustomXfermode.cpp +++ b/src/gpu/effects/GrCustomXfermode.cpp @@ -98,8 +98,6 @@ public: } private: - GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override; - void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; GrXferBarrierType onXferBarrier(const GrRenderTarget*, const GrCaps&) const override; @@ -189,11 +187,68 @@ bool CustomXP::onIsEqual(const GrXferProcessor& other) const { return fMode == s.fMode && fHWBlendEquation == s.fHWBlendEquation; } -GrXferProcessor::OptFlags CustomXP::onGetOptimizations( - const FragmentProcessorAnalysis& analysis) const { - /* - Most the optimizations we do here are based on tweaking alpha for coverage. +GrXferBarrierType CustomXP::onXferBarrier(const GrRenderTarget* rt, const GrCaps& caps) const { + if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport()) { + return kBlend_GrXferBarrierType; + } + return kNone_GrXferBarrierType; +} +void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const { + if (this->hasHWBlendEquation()) { + blendInfo->fEquation = this->hwBlendEquation(); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +// See the comment above GrXPFactory's definition about this warning suppression. +#if defined(__GNUC__) || defined(__clang) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif +class CustomXPFactory : public GrXPFactory { +public: + constexpr CustomXPFactory(SkBlendMode mode) + : fMode(mode), fHWBlendEquation(hw_blend_equation(mode)) {} + +private: + GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, + const FragmentProcessorAnalysis&, + bool hasMixedSamples, + const DstTexture*) const override; + + AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&, + const GrPipelineAnalysisCoverage&, + const GrCaps&) const override; + + GR_DECLARE_XP_FACTORY_TEST; + + SkBlendMode fMode; + GrBlendEquation fHWBlendEquation; + + typedef GrXPFactory INHERITED; +}; +#if defined(__GNUC__) || defined(__clang) +#pragma GCC diagnostic pop +#endif + +GrXferProcessor* CustomXPFactory::onCreateXferProcessor(const GrCaps& caps, + const FragmentProcessorAnalysis& analysis, + bool hasMixedSamples, + const DstTexture* dstTexture) const { + SkASSERT(GrCustomXfermode::IsSupportedMode(fMode)); + if (can_use_hw_blend_equation(fHWBlendEquation, analysis.outputCoverageType(), caps)) { + SkASSERT(!dstTexture || !dstTexture->texture()); + return new CustomXP(fMode, fHWBlendEquation); + } + return new CustomXP(dstTexture, hasMixedSamples, fMode); +} + +GrXPFactory::AnalysisProperties CustomXPFactory::analysisProperties( + const GrPipelineAnalysisColor&, const GrPipelineAnalysisCoverage& coverage, + const GrCaps& caps) const { + /* The general SVG blend equation is defined in the spec as follows: Dca' = B(Sc, Dc) * Sa * Da + Y * Sca * (1-Da) + Z * Dca * (1-Sa) @@ -287,76 +342,12 @@ GrXferProcessor::OptFlags CustomXP::onGetOptimizations( = f*Sa - f*Sa * Da + Da = f*Sa + Da - f*Sa * Da = blend(f*Sa, Da) - */ - - OptFlags flags = kNone_OptFlags; - if (analysis.isCompatibleWithCoverageAsAlpha()) { - flags |= kCanTweakAlphaForCoverage_OptFlag; + */ + if (can_use_hw_blend_equation(fHWBlendEquation, coverage, caps)) { + return AnalysisProperties::kCompatibleWithAlphaAsCoverage; } - return flags; -} - -GrXferBarrierType CustomXP::onXferBarrier(const GrRenderTarget* rt, const GrCaps& caps) const { - if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport()) { - return kBlend_GrXferBarrierType; - } - return kNone_GrXferBarrierType; -} - -void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const { - if (this->hasHWBlendEquation()) { - blendInfo->fEquation = this->hwBlendEquation(); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -// See the comment above GrXPFactory's definition about this warning suppression. -#if defined(__GNUC__) || defined(__clang) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" -#endif -class CustomXPFactory : public GrXPFactory { -public: - constexpr CustomXPFactory(SkBlendMode mode) - : fMode(mode), fHWBlendEquation(hw_blend_equation(mode)) {} - -private: - GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, - const FragmentProcessorAnalysis&, - bool hasMixedSamples, - const DstTexture*) const override; - - bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override; - - bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const override { return true; } - - GR_DECLARE_XP_FACTORY_TEST; - - SkBlendMode fMode; - GrBlendEquation fHWBlendEquation; - - typedef GrXPFactory INHERITED; -}; -#if defined(__GNUC__) || defined(__clang) -#pragma GCC diagnostic pop -#endif - -GrXferProcessor* CustomXPFactory::onCreateXferProcessor(const GrCaps& caps, - const FragmentProcessorAnalysis& analysis, - bool hasMixedSamples, - const DstTexture* dstTexture) const { - SkASSERT(GrCustomXfermode::IsSupportedMode(fMode)); - if (can_use_hw_blend_equation(fHWBlendEquation, analysis.outputCoverageType(), caps)) { - SkASSERT(!dstTexture || !dstTexture->texture()); - return new CustomXP(fMode, fHWBlendEquation); - } - return new CustomXP(dstTexture, hasMixedSamples, fMode); -} - -bool CustomXPFactory::willReadDstInShader(const GrCaps& caps, - const FragmentProcessorAnalysis& analysis) const { - return !can_use_hw_blend_equation(fHWBlendEquation, analysis.outputCoverageType(), caps); + return AnalysisProperties::kCompatibleWithAlphaAsCoverage | + AnalysisProperties::kReadsDstInShader; } GR_DEFINE_XP_FACTORY_TEST(CustomXPFactory); diff --git a/src/gpu/effects/GrDisableColorXP.cpp b/src/gpu/effects/GrDisableColorXP.cpp index f95cd9b81a..226809725c 100644 --- a/src/gpu/effects/GrDisableColorXP.cpp +++ b/src/gpu/effects/GrDisableColorXP.cpp @@ -29,10 +29,6 @@ public: private: DisableColorXP(); - GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override { - return GrXferProcessor::kIgnoreColor_OptFlag; - } - void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override; diff --git a/src/gpu/effects/GrDisableColorXP.h b/src/gpu/effects/GrDisableColorXP.h index 821ad2768e..9a829ed5ba 100644 --- a/src/gpu/effects/GrDisableColorXP.h +++ b/src/gpu/effects/GrDisableColorXP.h @@ -24,12 +24,13 @@ public: private: constexpr GrDisableColorXPFactory() {} - bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override { - return false; + AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&, + const GrPipelineAnalysisCoverage&, + const GrCaps&) const override { + return AnalysisProperties::kCompatibleWithAlphaAsCoverage | + AnalysisProperties::kIgnoresInputColor; } - bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const override { return true; } - GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, const FragmentProcessorAnalysis&, bool hasMixedSamples, diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp index aa416e0d1b..98268a2c5f 100644 --- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp +++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp @@ -83,7 +83,7 @@ public: (SecondaryOut >= kModulate_OutputType && GR_BLEND_COEFF_REFS_SRC2(DstCoeff)) ? kUsesInputColor_Property : 0) | // We assert later that SrcCoeff doesn't ref src2. - (kModulate_OutputType == PrimaryOut && + ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) && kNone_OutputType == SecondaryOut && GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(BlendEquation, SrcCoeff, DstCoeff) ? kCanTweakAlphaForCoverage_Property : 0))> { @@ -349,8 +349,6 @@ public: BlendFormula getBlendFormula() const { return fBlendFormula; } private: - GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override; - void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); } @@ -445,24 +443,6 @@ GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const { return new GLPorterDuffXferProcessor; } -GrXferProcessor::OptFlags PorterDuffXferProcessor::onGetOptimizations( - const FragmentProcessorAnalysis& analysis) const { - GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags; - if (!fBlendFormula.modifiesDst()) { - optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag | - GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag); - } else { - if (!fBlendFormula.usesInputColor()) { - optFlags |= GrXferProcessor::kIgnoreColor_OptFlag; - } - if (analysis.isCompatibleWithCoverageAsAlpha() && - fBlendFormula.canTweakAlphaForCoverage()) { - optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; - } - } - return optFlags; -} - /////////////////////////////////////////////////////////////////////////////// class ShaderPDXferProcessor : public GrXferProcessor { @@ -482,10 +462,6 @@ public: SkBlendMode getXfermode() const { return fXfermode; } private: - GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override { - return kNone_OptFlags; - } - void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; bool onIsEqual(const GrXferProcessor& xpBase) const override { @@ -558,8 +534,6 @@ public: private: PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha); - GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override; - void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { @@ -655,11 +629,6 @@ GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const { return new GLPDLCDXferProcessor(*this); } -GrXferProcessor::OptFlags PDLCDXferProcessor::onGetOptimizations( - const FragmentProcessorAnalysis&) const { - return GrXferProcessor::kIgnoreColor_OptFlag; -} - /////////////////////////////////////////////////////////////////////////////// constexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode) @@ -758,42 +727,53 @@ GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor( return new PorterDuffXferProcessor(blendFormula); } -bool GrPorterDuffXPFactory::canCombineOverlappedStencilAndCover(bool colorIsOpaque) const { - // Ignore the effect of coverage here. - BlendFormula colorFormula = gBlendTable[colorIsOpaque][0][(int)fBlendMode]; - SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation); - return !colorFormula.usesDstColor(); -} - -bool GrPorterDuffXPFactory::willReadDstInShader(const GrCaps& caps, - const FragmentProcessorAnalysis& analysis) const { - 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 (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) { - if (SkBlendMode::kSrcOver == fBlendMode && analysis.hasKnownOutputColor() && - !caps.shaderCaps()->dstReadInShaderSupport()) { - return false; +static inline GrXPFactory::AnalysisProperties analysis_properties( + const GrPipelineAnalysisColor& color, const GrPipelineAnalysisCoverage& coverage, + const GrCaps& caps, SkBlendMode mode) { + using AnalysisProperties = GrXPFactory::AnalysisProperties; + AnalysisProperties props = AnalysisProperties::kNone; + bool hasCoverage = GrPipelineAnalysisCoverage::kNone != coverage; + auto formula = gBlendTable[color.isOpaque()][hasCoverage][(int)mode]; + if (formula.canTweakAlphaForCoverage()) { + 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 (GrPipelineAnalysisCoverage::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()) { + props |= AnalysisProperties::kIgnoresInputColor; + } else { + if (get_lcd_blend_formula(mode).hasSecondaryOutput()) { + props |= AnalysisProperties::kReadsDstInShader; + } + } + } else if (formula.hasSecondaryOutput()) { + props |= AnalysisProperties::kReadsDstInShader; } - return get_lcd_blend_formula(fBlendMode).hasSecondaryOutput(); } - - // We fallback on the shader XP when the blend formula would use dual source blending but we - // don't have support for it. - static const bool kHasMixedSamples = false; - SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending. - auto formula = get_blend_formula(analysis.isOutputColorOpaque(), analysis.hasCoverage(), - kHasMixedSamples, fBlendMode); - return formula.hasSecondaryOutput(); + if (!formula.modifiesDst() || !formula.usesInputColor()) { + props |= AnalysisProperties::kIgnoresInputColor; + } + // Ignore the effect of coverage here for overlap stencil and cover property + auto colorFormula = gBlendTable[color.isOpaque()][0][(int)mode]; + SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation); + if (!colorFormula.usesDstColor()) { + props |= AnalysisProperties::kCanCombineOverlappedStencilAndCover; + } + return props; } -bool GrPorterDuffXPFactory::compatibleWithCoverageAsAlpha(bool colorIsOpaque) const { - // We assume we have coverage (or else this doesn't matter). - return gBlendTable[colorIsOpaque][1][(int)fBlendMode].canTweakAlphaForCoverage(); +GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties( + const GrPipelineAnalysisColor& color, + const GrPipelineAnalysisCoverage& coverage, + const GrCaps& caps) const { + return analysis_properties(color, coverage, caps, fBlendMode); } GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); @@ -869,31 +849,9 @@ sk_sp<GrXferProcessor> GrPorterDuffXPFactory::CreateNoCoverageXP(SkBlendMode ble return sk_make_sp<PorterDuffXferProcessor>(formula); } -bool GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(const GrCaps& caps, - const FragmentProcessorAnalysis& analysis) { - if (caps.shaderCaps()->dstReadInShaderSupport() || - 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 (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) { - if (analysis.hasKnownOutputColor() && !caps.shaderCaps()->dstReadInShaderSupport()) { - return false; - } - auto formula = get_lcd_blend_formula(SkBlendMode::kSrcOver); - return formula.hasSecondaryOutput(); - } - - // We fallback on the shader XP when the blend formula would use dual source blending but we - // don't have support for it. - static const bool kHasMixedSamples = false; - bool isOpaque = analysis.isOutputColorOpaque(); - bool hasCoverage = analysis.hasCoverage(); - SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending. - auto formula = - get_blend_formula(isOpaque, hasCoverage, kHasMixedSamples, SkBlendMode::kSrcOver); - return formula.hasSecondaryOutput(); +GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties( + const GrPipelineAnalysisColor& color, + const GrPipelineAnalysisCoverage& coverage, + const GrCaps& caps) { + return analysis_properties(color, coverage, caps, SkBlendMode::kSrcOver); } diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.h b/src/gpu/effects/GrPorterDuffXferProcessor.h index 23f1e9c5c5..81e8261724 100644 --- a/src/gpu/effects/GrPorterDuffXferProcessor.h +++ b/src/gpu/effects/GrPorterDuffXferProcessor.h @@ -35,25 +35,21 @@ public: by reference because it is global and its ref-cnting methods are not thread safe. */ static const GrXferProcessor& SimpleSrcOverXP(); - static bool WillSrcOverNeedDstTexture(const GrCaps&, const FragmentProcessorAnalysis&); - static bool SrcOverIsCompatibleWithCoverageAsAlpha() { return true; } - static bool SrcOverCanCombineOverlappedStencilAndCover(bool colorIsOpaque) { - return colorIsOpaque; - } + static AnalysisProperties SrcOverAnalysisProperties(const GrPipelineAnalysisColor&, + const GrPipelineAnalysisCoverage&, + const GrCaps&); private: constexpr GrPorterDuffXPFactory(SkBlendMode); - bool canCombineOverlappedStencilAndCover(bool colorIsOpaque) const override; - GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, const FragmentProcessorAnalysis&, bool hasMixedSamples, const DstTexture*) const override; - bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override; - - bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const override; + AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&, + const GrPipelineAnalysisCoverage&, + const GrCaps&) const override; GR_DECLARE_XP_FACTORY_TEST; static void TestGetXPOutputTypes(const GrXferProcessor*, int* outPrimary, int* outSecondary); |