aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/effects
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/effects')
-rw-r--r--src/gpu/effects/GrCoverageSetOpXP.cpp8
-rw-r--r--src/gpu/effects/GrCoverageSetOpXP.h7
-rw-r--r--src/gpu/effects/GrCustomXfermode.cpp141
-rw-r--r--src/gpu/effects/GrDisableColorXP.cpp4
-rw-r--r--src/gpu/effects/GrDisableColorXP.h9
-rw-r--r--src/gpu/effects/GrPorterDuffXferProcessor.cpp140
-rw-r--r--src/gpu/effects/GrPorterDuffXferProcessor.h16
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);