Make it possible to query GrXPFactory for dst texture without GrPipelineAnalysis.
authorBrian Salomon <bsalomon@google.com>
Fri, 20 Jan 2017 16:30:37 +0000 (11:30 -0500)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Fri, 20 Jan 2017 17:20:34 +0000 (17:20 +0000)
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>
include/gpu/GrXferProcessor.h
include/gpu/effects/GrCoverageSetOpXP.h
include/gpu/effects/GrPorterDuffXferProcessor.h
src/gpu/GrXferProcessor.cpp
src/gpu/effects/GrCustomXfermode.cpp
src/gpu/effects/GrDisableColorXP.h
src/gpu/effects/GrPorterDuffXferProcessor.cpp

index 17cd2c7..353c682 100644 (file)
@@ -307,6 +307,16 @@ GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
 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 @@ public:
     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
index ca71abc..385cad8 100644 (file)
@@ -40,9 +40,7 @@ private:
                                            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;
 
index ca14275..028cac6 100644 (file)
@@ -63,7 +63,7 @@ private:
                                            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);
index 7de0d77..d88259d 100644 (file)
@@ -180,6 +180,40 @@ SkString GrXferProcessor::BlendInfo::dump() const {
 
 ///////////////////////////////////////////////////////////////////////////////
 
+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 @@ GrXferProcessor* GrXPFactory::createXferProcessor(const GrPipelineAnalysis& anal
 }
 
 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);
 }
index 070fa2f..f8af7db 100644 (file)
@@ -54,15 +54,16 @@ static constexpr GrBlendEquation hw_blend_equation(SkBlendMode mode) {
 }
 
 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 @@ private:
                                            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 @@ GrXferProcessor* CustomXPFactory::onCreateXferProcessor(const GrCaps& caps,
                                                         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,
index 9f56ae5..f027e3c 100644 (file)
@@ -32,15 +32,13 @@ public:
 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;
index 7f40906..59710eb 100644 (file)
@@ -320,21 +320,17 @@ static const BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] =
     /* 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 @@ GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps
             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 @@ void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorP
     }
 }
 
-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 @@ bool GrPorterDuffXPFactory::onWillReadDstColor(const GrCaps& caps,
     // 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 @@ GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
     }
 
     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 @@ bool GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(const GrCaps& caps,
             !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();
 }