Index: src/gpu/effects/GrPorterDuffXferProcessor.cpp |
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp |
index 83c72f934255f9bd6ac674b77313bf52cb802e41..17bc912f87ce56c7791f9ece8107f8ed96b2f9c3 100644 |
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp |
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp |
@@ -9,6 +9,7 @@ |
#include "GrBlend.h" |
#include "GrCaps.h" |
+#include "GrPipelineBuilder.h" |
#include "GrProcessor.h" |
#include "GrProcOptInfo.h" |
#include "GrTypes.h" |
@@ -288,35 +289,32 @@ static const BlendFormula gBlendTable[2][2][SkXfermode::kLastCoeffMode + 1] = { |
/* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), |
}}}; |
-static BlendFormula get_blend_formula(SkXfermode::Mode xfermode, |
+static BlendFormula get_blend_formula(const GrPipelineBuilder& builder, |
const GrProcOptInfo& colorPOI, |
- const GrProcOptInfo& coveragePOI) { |
+ const GrProcOptInfo& coveragePOI, |
+ SkXfermode::Mode xfermode) { |
SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode); |
SkASSERT(!coveragePOI.isFourChannelOutput()); |
- return gBlendTable[colorPOI.isOpaque()][!coveragePOI.isSolidWhite()][xfermode]; |
+ bool conflatesCoverage = !coveragePOI.isSolidWhite() || builder.hasMixedSamples(); |
+ return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode]; |
} |
/////////////////////////////////////////////////////////////////////////////// |
class PorterDuffXferProcessor : public GrXferProcessor { |
public: |
- static GrXferProcessor* Create(BlendFormula blendFormula) { |
- return SkNEW_ARGS(PorterDuffXferProcessor, (blendFormula)); |
+ PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendFormula) { |
+ this->initClassID<PorterDuffXferProcessor>(); |
} |
const char* name() const override { return "Porter Duff"; } |
- bool hasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); } |
GrGLXferProcessor* createGLInstance() const override; |
BlendFormula getBlendFormula() const { return fBlendFormula; } |
private: |
- PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendFormula) { |
- this->initClassID<PorterDuffXferProcessor>(); |
- } |
- |
GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, |
const GrProcOptInfo& coveragePOI, |
bool doesStencilWrite, |
@@ -325,6 +323,8 @@ private: |
void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; |
+ bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); } |
+ |
void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { |
blendInfo->fEquation = fBlendFormula.fBlendEquation; |
blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff; |
@@ -352,6 +352,7 @@ static void append_color_output(const PorterDuffXferProcessor& xp, GrGLXPFragmen |
fsBuilder->codeAppendf("%s = vec4(0.0);", output); |
break; |
case BlendFormula::kCoverage_OutputType: |
+ // We can have a coverage formula while not reading coverage if there are mixed samples. |
fsBuilder->codeAppendf("%s = %s;", |
output, xp.readsCoverage() ? inCoverage : "vec4(1.0)"); |
break; |
@@ -454,24 +455,21 @@ PorterDuffXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI, |
class ShaderPDXferProcessor : public GrXferProcessor { |
public: |
- static GrXferProcessor* Create(SkXfermode::Mode xfermode, const DstTexture* dstTexture) { |
- return SkNEW_ARGS(ShaderPDXferProcessor, (xfermode, dstTexture)); |
+ ShaderPDXferProcessor(const GrPipelineBuilder& builder, |
+ const DstTexture* dstTexture, |
+ SkXfermode::Mode xfermode) |
+ : INHERITED(builder, dstTexture, true) |
+ , fXfermode(xfermode) { |
+ this->initClassID<ShaderPDXferProcessor>(); |
} |
const char* name() const override { return "Porter Duff Shader"; } |
- bool hasSecondaryOutput() const override { return false; } |
GrGLXferProcessor* createGLInstance() const override; |
SkXfermode::Mode getXfermode() const { return fXfermode; } |
private: |
- ShaderPDXferProcessor(SkXfermode::Mode xfermode, const DstTexture* dstTexture) |
- : INHERITED(dstTexture, true) |
- , fXfermode(xfermode) { |
- this->initClassID<ShaderPDXferProcessor>(); |
- } |
- |
GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo&, const GrProcOptInfo&, |
bool, GrColor*, const GrCaps&) override { |
return kNone_Opt; |
@@ -596,8 +594,6 @@ public: |
GrGLXferProcessor* createGLInstance() const override; |
- bool hasSecondaryOutput() const override { return false; } |
- |
private: |
PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha); |
@@ -745,6 +741,7 @@ GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode xfermode) { |
GrXferProcessor* |
GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps, |
+ const GrPipelineBuilder& builder, |
const GrProcOptInfo& colorPOI, |
const GrProcOptInfo& covPOI, |
const DstTexture* dstTexture) const { |
@@ -753,13 +750,13 @@ GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps, |
return PDLCDXferProcessor::Create(fXfermode, colorPOI); |
} |
- BlendFormula blendFormula = get_blend_formula(fXfermode, colorPOI, covPOI); |
+ BlendFormula blendFormula = get_blend_formula(builder, colorPOI, covPOI, fXfermode); |
if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) { |
- return ShaderPDXferProcessor::Create(fXfermode, dstTexture); |
+ return SkNEW_ARGS(ShaderPDXferProcessor, (builder, dstTexture, fXfermode)); |
} |
SkASSERT(!dstTexture || !dstTexture->texture()); |
- return PorterDuffXferProcessor::Create(blendFormula); |
+ return SkNEW_ARGS(PorterDuffXferProcessor, (blendFormula)); |
} |
bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, |
@@ -803,16 +800,18 @@ void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorP |
} |
bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps, |
+ const GrPipelineBuilder& builder, |
const GrProcOptInfo& colorPOI, |
const GrProcOptInfo& coveragePOI) const { |
+ if (caps.shaderCaps()->dualSourceBlendingSupport()) { |
+ return false; |
+ } |
if (coveragePOI.isFourChannelOutput()) { |
- return false; // The LCD XP never does a dst read. |
+ return false; // The LCD XP will abort rather than doing a dst read. |
} |
- |
// We fallback on the shader XP when the blend formula would use dual source blending but we |
// don't have support for it. |
- return !caps.shaderCaps()->dualSourceBlendingSupport() && |
- get_blend_formula(fXfermode, colorPOI, coveragePOI).hasSecondaryOutput(); |
+ return get_blend_formula(builder, colorPOI, coveragePOI, fXfermode).hasSecondaryOutput(); |
} |
GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); |