Make it possible to query GrXPFactory for dst texture without GrPipelineAnalysis.
Change-Id: I8c140eb4e3e5f2d21ecbf8f8f3c8533dc7f50e7c
Reviewed-on: https://skia-review.googlesource.com/7316
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/include/gpu/GrXferProcessor.h b/include/gpu/GrXferProcessor.h
index 17cd2c7..353c682 100644
--- a/include/gpu/GrXferProcessor.h
+++ b/include/gpu/GrXferProcessor.h
@@ -307,6 +307,16 @@
class GrXPFactory {
public:
typedef GrXferProcessor::DstTexture DstTexture;
+
+ /** Describes known properties of a draw's color input to the GrXferProcessor. */
+ enum class ColorType { kUnknown, kOpaqueConstant, kConstant, kOpaque };
+
+ /**
+ * Indicates whether a draw's coverage input to the GrXferProcessor is solid, single channel
+ * or LCD (four channel coverage).
+ */
+ enum class CoverageType { kNone, kSingleChannel, kLCD };
+
GrXferProcessor* createXferProcessor(const GrPipelineAnalysis&,
bool hasMixedSamples,
const DstTexture*,
@@ -329,24 +339,33 @@
virtual void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
InvariantBlendedColor*) const = 0;
- bool willNeedDstTexture(const GrCaps& caps, const GrPipelineAnalysis&) const;
+ bool willNeedDstTexture(const GrCaps& caps, const GrPipelineAnalysis& analysis) const;
protected:
constexpr GrXPFactory() {}
+ static bool ColorTypeIsOpaque(ColorType type) {
+ return ColorType::kOpaqueConstant == type || ColorType::kOpaque == type;
+ }
+
+ static bool ColorTypeIsConstant(ColorType type) {
+ return ColorType::kOpaqueConstant == type || ColorType::kConstant == type;
+ }
+
private:
virtual GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis&,
bool hasMixedSamples,
const DstTexture*) const = 0;
- bool willReadDstColor(const GrCaps&, const GrPipelineAnalysis&) const;
+ bool willReadDstColor(const GrCaps& caps, const GrPipelineAnalysis& analysis) const;
/**
* Returns true if the XP generated by this factory will explicitly read dst in the fragment
- * shader.
+ * shader. This will not be called for draws that read from PLS since the dst color is always
+ * available in such draws.
*/
- virtual bool onWillReadDstColor(const GrCaps&, const GrPipelineAnalysis&) const = 0;
+ virtual bool willReadDstColor(const GrCaps&, ColorType, CoverageType) const = 0;
};
#if defined(__GNUC__) || defined(__clang)
#pragma GCC diagnostic pop
diff --git a/include/gpu/effects/GrCoverageSetOpXP.h b/include/gpu/effects/GrCoverageSetOpXP.h
index ca71abc..385cad8 100644
--- a/include/gpu/effects/GrCoverageSetOpXP.h
+++ b/include/gpu/effects/GrCoverageSetOpXP.h
@@ -40,9 +40,7 @@
bool hasMixedSamples,
const DstTexture*) const override;
- bool onWillReadDstColor(const GrCaps&, const GrPipelineAnalysis&) const override {
- return false;
- }
+ bool willReadDstColor(const GrCaps&, ColorType, CoverageType) const override { return false; }
GR_DECLARE_XP_FACTORY_TEST;
diff --git a/include/gpu/effects/GrPorterDuffXferProcessor.h b/include/gpu/effects/GrPorterDuffXferProcessor.h
index ca14275..028cac6 100644
--- a/include/gpu/effects/GrPorterDuffXferProcessor.h
+++ b/include/gpu/effects/GrPorterDuffXferProcessor.h
@@ -63,7 +63,7 @@
bool hasMixedSamples,
const DstTexture*) const override;
- bool onWillReadDstColor(const GrCaps&, const GrPipelineAnalysis&) const override;
+ bool willReadDstColor(const GrCaps&, ColorType, CoverageType) const override;
GR_DECLARE_XP_FACTORY_TEST;
static void TestGetXPOutputTypes(const GrXferProcessor*, int* outPrimary, int* outSecondary);
diff --git a/src/gpu/GrXferProcessor.cpp b/src/gpu/GrXferProcessor.cpp
index 7de0d77..d88259d 100644
--- a/src/gpu/GrXferProcessor.cpp
+++ b/src/gpu/GrXferProcessor.cpp
@@ -180,6 +180,40 @@
///////////////////////////////////////////////////////////////////////////////
+using ColorType = GrXPFactory::ColorType;
+using CoverageType = GrXPFactory::CoverageType;
+
+ColorType analysis_color_type(const GrPipelineAnalysis& analysis) {
+ if (analysis.fColorPOI.validFlags() == kRGBA_GrColorComponentFlags) {
+ return GrColorIsOpaque(analysis.fColorPOI.color()) ? ColorType::kOpaqueConstant
+ : ColorType::kConstant;
+ }
+ if ((analysis.fColorPOI.validFlags() & kA_GrColorComponentFlag) &&
+ GrColorIsOpaque(analysis.fColorPOI.color())) {
+ return ColorType::kOpaque;
+ }
+ return ColorType::kUnknown;
+}
+
+CoverageType analysis_coverage_type(const GrPipelineAnalysis& analysis) {
+ if (analysis.fCoveragePOI.isSolidWhite()) {
+ return CoverageType::kNone;
+ }
+ if (analysis.fCoveragePOI.isLCDCoverage()) {
+ return CoverageType::kLCD;
+ }
+ return CoverageType::kSingleChannel;
+}
+
+bool GrXPFactory::willReadDstColor(const GrCaps& caps, const GrPipelineAnalysis& analysis) const {
+ if (analysis.fUsesPLSDstRead) {
+ return true;
+ }
+ ColorType colorType = analysis_color_type(analysis);
+ CoverageType coverageType = analysis_coverage_type(analysis);
+ return this->willReadDstColor(caps, colorType, coverageType);
+}
+
GrXferProcessor* GrXPFactory::createXferProcessor(const GrPipelineAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dstTexture,
@@ -200,9 +234,6 @@
}
bool GrXPFactory::willNeedDstTexture(const GrCaps& caps, const GrPipelineAnalysis& analysis) const {
- return (this->willReadDstColor(caps, analysis) && !caps.shaderCaps()->dstReadInShaderSupport());
-}
-
-bool GrXPFactory::willReadDstColor(const GrCaps& caps, const GrPipelineAnalysis& analysis) const {
- return analysis.fUsesPLSDstRead || this->onWillReadDstColor(caps, analysis);
+ return !analysis.fUsesPLSDstRead && !caps.shaderCaps()->dstReadInShaderSupport() &&
+ this->willReadDstColor(caps, analysis);
}
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index 070fa2f..f8af7db 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -54,15 +54,16 @@
}
static bool can_use_hw_blend_equation(GrBlendEquation equation,
- const GrPipelineAnalysis& analysis,
+ bool usePLSRead,
+ bool isLCDCoverage,
const GrCaps& caps) {
if (!caps.advancedBlendEquationSupport()) {
return false;
}
- if (analysis.fUsesPLSDstRead) {
+ if (usePLSRead) {
return false;
}
- if (analysis.fCoveragePOI.isLCDCoverage()) {
+ if (isLCDCoverage) {
return false; // LCD coverage must be applied after the blend equation.
}
if (caps.canUseAdvancedBlendEquation(equation)) {
@@ -340,8 +341,7 @@
bool hasMixedSamples,
const DstTexture*) const override;
- bool onWillReadDstColor(const GrCaps&, const GrPipelineAnalysis&) const override;
-
+ bool willReadDstColor(const GrCaps&, ColorType, CoverageType) const override;
GR_DECLARE_XP_FACTORY_TEST;
@@ -359,16 +359,20 @@
bool hasMixedSamples,
const DstTexture* dstTexture) const {
SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
- if (can_use_hw_blend_equation(fHWBlendEquation, analysis, caps)) {
+ if (can_use_hw_blend_equation(fHWBlendEquation, analysis.fUsesPLSDstRead,
+ analysis.fCoveragePOI.isLCDCoverage(), caps)) {
SkASSERT(!dstTexture || !dstTexture->texture());
return new CustomXP(fMode, fHWBlendEquation);
}
return new CustomXP(dstTexture, hasMixedSamples, fMode);
}
-bool CustomXPFactory::onWillReadDstColor(const GrCaps& caps,
- const GrPipelineAnalysis& analysis) const {
- return !can_use_hw_blend_equation(fHWBlendEquation, analysis, caps);
+bool CustomXPFactory::willReadDstColor(const GrCaps& caps, ColorType colorType,
+ CoverageType coverageType) const {
+ // This should not be called if we're using PLS dst read.
+ static constexpr bool kUsesPLSRead = false;
+ return !can_use_hw_blend_equation(fHWBlendEquation, kUsesPLSRead,
+ CoverageType::kLCD == coverageType, caps);
}
void CustomXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
diff --git a/src/gpu/effects/GrDisableColorXP.h b/src/gpu/effects/GrDisableColorXP.h
index 9f56ae5..f027e3c 100644
--- a/src/gpu/effects/GrDisableColorXP.h
+++ b/src/gpu/effects/GrDisableColorXP.h
@@ -32,15 +32,13 @@
private:
constexpr GrDisableColorXPFactory() {}
+ bool willReadDstColor(const GrCaps&, ColorType, CoverageType) const override { return false; }
+
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis&,
bool hasMixedSamples,
const DstTexture* dstTexture) const override;
- bool onWillReadDstColor(const GrCaps&, const GrPipelineAnalysis&) const override {
- return false;
- }
-
GR_DECLARE_XP_FACTORY_TEST;
typedef GrXPFactory INHERITED;
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index 7f40906..59710eb 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -320,21 +320,17 @@
/* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
};
-static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& coveragePOI,
+static BlendFormula get_blend_formula(bool isOpaque,
+ bool hasCoverage,
bool hasMixedSamples,
SkBlendMode xfermode) {
SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
- SkASSERT(!coveragePOI.isLCDCoverage());
-
- bool conflatesCoverage = !coveragePOI.isSolidWhite() || hasMixedSamples;
- return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][(int)xfermode];
+ bool conflatesCoverage = hasCoverage || hasMixedSamples;
+ return gBlendTable[isOpaque][conflatesCoverage][(int)xfermode];
}
-static BlendFormula get_lcd_blend_formula(const GrProcOptInfo& coveragePOI,
- SkBlendMode xfermode) {
+static BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) {
SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
- SkASSERT(coveragePOI.isLCDCoverage());
return gLCDBlendTable[(int)xfermode];
}
@@ -759,9 +755,10 @@
SkASSERT(!dstTexture || !dstTexture->texture());
return PDLCDXferProcessor::Create(fBlendMode, analysis.fColorPOI);
}
- blendFormula = get_lcd_blend_formula(analysis.fCoveragePOI, fBlendMode);
+ blendFormula = get_lcd_blend_formula(fBlendMode);
} else {
- blendFormula = get_blend_formula(analysis.fColorPOI, analysis.fCoveragePOI, hasMixedSamples,
+ blendFormula = get_blend_formula(analysis.fColorPOI.isOpaque(),
+ !analysis.fCoveragePOI.isSolidWhite(), hasMixedSamples,
fBlendMode);
}
@@ -804,8 +801,8 @@
}
}
-bool GrPorterDuffXPFactory::onWillReadDstColor(const GrCaps& caps,
- const GrPipelineAnalysis& analysis) const {
+bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps, ColorType colorType,
+ CoverageType coverageType) const {
if (caps.shaderCaps()->dualSourceBlendingSupport()) {
return false;
}
@@ -813,20 +810,20 @@
// 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.fCoveragePOI.isLCDCoverage()) {
- if (SkBlendMode::kSrcOver == fBlendMode &&
- kRGBA_GrColorComponentFlags == analysis.fColorPOI.validFlags() &&
+ if (CoverageType::kLCD == coverageType) {
+ if (SkBlendMode::kSrcOver == fBlendMode && ColorTypeIsConstant(colorType) &&
!caps.shaderCaps()->dstReadInShaderSupport()) {
return false;
}
- return get_lcd_blend_formula(analysis.fCoveragePOI, fBlendMode).hasSecondaryOutput();
+ 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.fColorPOI, analysis.fCoveragePOI, kHasMixedSamples,
+ auto formula = get_blend_formula(ColorTypeIsOpaque(colorType),
+ CoverageType::kSingleChannel == coverageType, kHasMixedSamples,
fBlendMode);
return formula.hasSecondaryOutput();
}
@@ -893,7 +890,7 @@
}
BlendFormula blendFormula;
- blendFormula = get_lcd_blend_formula(analysis.fCoveragePOI, SkBlendMode::kSrcOver);
+ blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkBlendMode::kSrcOver);
}
@@ -917,15 +914,17 @@
!caps.shaderCaps()->dstReadInShaderSupport()) {
return false;
}
- auto formula = get_lcd_blend_formula(analysis.fCoveragePOI, SkBlendMode::kSrcOver);
+ 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.fColorPOI.isOpaque();
+ bool hasCoverage = !analysis.fCoveragePOI.isSolidWhite();
SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
- auto formula = get_blend_formula(analysis.fColorPOI, analysis.fCoveragePOI, kHasMixedSamples,
- SkBlendMode::kSrcOver);
+ auto formula =
+ get_blend_formula(isOpaque, hasCoverage, kHasMixedSamples, SkBlendMode::kSrcOver);
return formula.hasSecondaryOutput();
}