Index: src/gpu/effects/GrPorterDuffXferProcessor.cpp |
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp |
index 22029e1d1418a8d52cd4f9cca85bbf90a7661288..6f2b63f5cb2b53977041fef563d89e30be9ead65 100644 |
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp |
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp |
@@ -59,10 +59,6 @@ |
kCoverage_PrimaryOutputType, |
// Modulate color and coverage, write result as the color output. |
kModulate_PrimaryOutputType, |
- // Custom Porter-Duff output, used for when we explictly are reading the dst and blending |
- // in the shader. Secondary Output must be none if you use this. The custom blend uses the |
- // equation: cov * (coeffS * S + coeffD * D) + (1 - cov) * D |
- kCustom_PrimaryOutputType |
}; |
enum SecondaryOutputType { |
@@ -91,18 +87,10 @@ |
const GrDrawTargetCaps& caps) SK_OVERRIDE; |
void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE { |
- if (!this->willReadDstColor()) { |
- blendInfo->fSrcBlend = fSrcBlend; |
- blendInfo->fDstBlend = fDstBlend; |
- } else { |
- blendInfo->fSrcBlend = kOne_GrBlendCoeff; |
- blendInfo->fDstBlend = kZero_GrBlendCoeff; |
- } |
+ blendInfo->fSrcBlend = fSrcBlend; |
+ blendInfo->fDstBlend = fDstBlend; |
blendInfo->fBlendConstant = fBlendConstant; |
} |
- |
- GrBlendCoeff getSrcBlend() const { return fSrcBlend; } |
- GrBlendCoeff getDstBlend() const { return fDstBlend; } |
private: |
PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColor constant, |
@@ -140,50 +128,6 @@ |
/////////////////////////////////////////////////////////////////////////////// |
-bool append_porterduff_term(GrGLFPFragmentBuilder* fsBuilder, GrBlendCoeff coeff, |
- const char* colorName, const char* srcColorName, |
- const char* dstColorName, bool hasPrevious) { |
- if (kZero_GrBlendCoeff == coeff) { |
- return hasPrevious; |
- } else { |
- if (hasPrevious) { |
- fsBuilder->codeAppend(" + "); |
- } |
- fsBuilder->codeAppendf("%s", colorName); |
- switch (coeff) { |
- case kOne_GrBlendCoeff: |
- break; |
- case kSC_GrBlendCoeff: |
- fsBuilder->codeAppendf(" * %s", srcColorName); |
- break; |
- case kISC_GrBlendCoeff: |
- fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", srcColorName); |
- break; |
- case kDC_GrBlendCoeff: |
- fsBuilder->codeAppendf(" * %s", dstColorName); |
- break; |
- case kIDC_GrBlendCoeff: |
- fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", dstColorName); |
- break; |
- case kSA_GrBlendCoeff: |
- fsBuilder->codeAppendf(" * %s.a", srcColorName); |
- break; |
- case kISA_GrBlendCoeff: |
- fsBuilder->codeAppendf(" * (1.0 - %s.a)", srcColorName); |
- break; |
- case kDA_GrBlendCoeff: |
- fsBuilder->codeAppendf(" * %s.a", dstColorName); |
- break; |
- case kIDA_GrBlendCoeff: |
- fsBuilder->codeAppendf(" * (1.0 - %s.a)", dstColorName); |
- break; |
- default: |
- SkFAIL("Unsupported Blend Coeff"); |
- } |
- return true; |
- } |
-} |
- |
class GLPorterDuffXferProcessor : public GrGLXferProcessor { |
public: |
GLPorterDuffXferProcessor(const GrProcessor&) {} |
@@ -195,24 +139,16 @@ |
const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>(); |
b->add32(xp.primaryOutputType()); |
b->add32(xp.secondaryOutputType()); |
- if (xp.willReadDstColor()) { |
- b->add32(xp.getSrcBlend()); |
- b->add32(xp.getDstBlend()); |
- } |
}; |
private: |
void onEmitCode(const EmitArgs& args) SK_OVERRIDE { |
const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>(); |
GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
- if (PorterDuffXferProcessor::kCustom_PrimaryOutputType != xp.primaryOutputType()) { |
- SkASSERT(!xp.willReadDstColor()); |
+ if (xp.hasSecondaryOutput()) { |
switch(xp.secondaryOutputType()) { |
- case PorterDuffXferProcessor::kNone_SecondaryOutputType: |
- break; |
case PorterDuffXferProcessor::kCoverage_SecondaryOutputType: |
- fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, |
- args.fInputCoverage); |
+ fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, args.fInputCoverage); |
break; |
case PorterDuffXferProcessor::kCoverageISA_SecondaryOutputType: |
fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", |
@@ -227,43 +163,24 @@ |
default: |
SkFAIL("Unexpected Secondary Output"); |
} |
- |
- switch (xp.primaryOutputType()) { |
- case PorterDuffXferProcessor::kNone_PrimaryOutputType: |
- fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary); |
- break; |
- case PorterDuffXferProcessor::kColor_PrimaryOutputType: |
- fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputColor); |
- break; |
- case PorterDuffXferProcessor::kCoverage_PrimaryOutputType: |
- fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage); |
- break; |
- case PorterDuffXferProcessor::kModulate_PrimaryOutputType: |
- fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor, |
- args.fInputCoverage); |
- break; |
- default: |
- SkFAIL("Unexpected Primary Output"); |
- } |
- } else { |
- SkASSERT(xp.willReadDstColor()); |
- |
- const char* dstColor = fsBuilder->dstColor(); |
- |
- fsBuilder->codeAppend("vec4 colorBlend ="); |
- // append src blend |
- bool didAppend = append_porterduff_term(fsBuilder, xp.getSrcBlend(), |
- args.fInputColor, args.fInputColor, |
- dstColor, false); |
- // append dst blend |
- SkAssertResult(append_porterduff_term(fsBuilder, xp.getDstBlend(), |
- dstColor, args.fInputColor, |
- dstColor, didAppend)); |
- fsBuilder->codeAppend(";"); |
- |
- fsBuilder->codeAppendf("%s = %s * colorBlend + (vec4(1.0) - %s) * %s;", |
- args.fOutputPrimary, args.fInputCoverage, args.fInputCoverage, |
- dstColor); |
+ } |
+ |
+ switch (xp.primaryOutputType()) { |
+ case PorterDuffXferProcessor::kNone_PrimaryOutputType: |
+ fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary); |
+ break; |
+ case PorterDuffXferProcessor::kColor_PrimaryOutputType: |
+ fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputColor); |
+ break; |
+ case PorterDuffXferProcessor::kCoverage_PrimaryOutputType: |
+ fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage); |
+ break; |
+ case PorterDuffXferProcessor::kModulate_PrimaryOutputType: |
+ fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor, |
+ args.fInputCoverage); |
+ break; |
+ default: |
+ SkFAIL("Unexpected Primary Output"); |
} |
} |
@@ -279,8 +196,7 @@ |
GrColor constant, |
const GrDeviceCoordTexture* dstCopy, |
bool willReadDstColor) |
- : INHERITED(dstCopy, willReadDstColor) |
- , fSrcBlend(srcBlend) |
+ : fSrcBlend(srcBlend) |
, fDstBlend(dstBlend) |
, fBlendConstant(constant) |
, fPrimaryOutputType(kModulate_PrimaryOutputType) |
@@ -328,11 +244,6 @@ |
void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags, |
const GrDrawTargetCaps& caps, |
bool hasSolidCoverage) { |
- if (this->willReadDstColor()) { |
- fPrimaryOutputType = kCustom_PrimaryOutputType; |
- return; |
- } |
- |
if (optFlags & kIgnoreColor_OptFlag) { |
if (optFlags & kIgnoreCoverage_OptFlag) { |
fPrimaryOutputType = kNone_PrimaryOutputType; |
@@ -373,12 +284,11 @@ |
PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, |
const GrProcOptInfo& coveragePOI, |
bool doesStencilWrite) { |
- if (this->willReadDstColor()) { |
- return GrXferProcessor::kNone_Opt; |
- } |
- |
- bool srcAIsOne = colorPOI.isOpaque(); |
- bool hasCoverage = !coveragePOI.isSolidWhite(); |
+ bool srcAIsOne; |
+ bool hasCoverage; |
+ |
+ srcAIsOne = colorPOI.isOpaque(); |
+ hasCoverage = !coveragePOI.isSolidWhite(); |
bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || |
(kSA_GrBlendCoeff == fDstBlend && srcAIsOne); |
@@ -543,20 +453,19 @@ |
} |
GrXferProcessor* |
-GrPorterDuffXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps, |
- const GrProcOptInfo& colorPOI, |
+GrPorterDuffXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI, |
const GrProcOptInfo& covPOI, |
const GrDeviceCoordTexture* dstCopy) const { |
if (!covPOI.isFourChannelOutput()) { |
return PorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy, |
- this->willReadDstColor(caps, colorPOI, covPOI)); |
+ this->willReadDstColor(colorPOI, covPOI)); |
} else { |
if (this->supportsRGBCoverage(colorPOI.color(), colorPOI.validFlags())) { |
SkASSERT(kRGBA_GrColorComponentFlags == colorPOI.validFlags()); |
GrColor blendConstant = GrUnPreMulColor(colorPOI.color()); |
return PorterDuffXferProcessor::Create(kConstC_GrBlendCoeff, kISC_GrBlendCoeff, |
blendConstant, dstCopy, |
- this->willReadDstColor(caps, colorPOI, covPOI)); |
+ this->willReadDstColor(colorPOI, covPOI)); |
} else { |
return NULL; |
} |
@@ -569,6 +478,39 @@ |
kRGBA_GrColorComponentFlags == knownColorFlags) { |
return true; |
} |
+ return false; |
+} |
+ |
+bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI, |
+ const GrProcOptInfo& coveragePOI) const { |
+ bool srcAIsOne = colorPOI.isOpaque(); |
+ |
+ bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstCoeff || |
+ (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne); |
+ bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstCoeff || |
+ (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne); |
+ |
+ if ((kZero_GrBlendCoeff == fSrcCoeff && dstCoeffIsOne)) { |
+ return true; |
+ } |
+ |
+ // if we don't have coverage we can check whether the dst |
+ // has to read at all. |
+ // check whether coverage can be safely rolled into alpha |
+ // of if we can skip color computation and just emit coverage |
+ if (this->canTweakAlphaForCoverage()) { |
+ return true; |
+ } |
+ if (dstCoeffIsZero) { |
+ if (kZero_GrBlendCoeff == fSrcCoeff) { |
+ return true; |
+ } else if (srcAIsOne) { |
+ return true; |
+ } |
+ } else if (dstCoeffIsOne) { |
+ return true; |
+ } |
+ |
return false; |
} |
@@ -645,37 +587,9 @@ |
output->fWillBlendWithDst = false; |
} |
-bool GrPorterDuffXPFactory::willReadDstColor(const GrDrawTargetCaps& caps, |
- const GrProcOptInfo& colorPOI, |
+bool GrPorterDuffXPFactory::willReadDstColor(const GrProcOptInfo& colorPOI, |
const GrProcOptInfo& coveragePOI) const { |
- // We can always blend correctly if we have dual source blending. |
- if (caps.dualSourceBlendingSupport()) { |
- return false; |
- } |
- |
- if (this->canTweakAlphaForCoverage()) { |
- return false; |
- } |
- |
- bool srcAIsOne = colorPOI.isOpaque(); |
- |
- if (kZero_GrBlendCoeff == fDstCoeff) { |
- if (kZero_GrBlendCoeff == fSrcCoeff || srcAIsOne) { |
- return false; |
- } |
- } |
- |
- // Reduces to: coeffS * (Cov*S) + D |
- if (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne) { |
- return false; |
- } |
- |
- // We can always blend correctly if we have solid coverage. |
- if (coveragePOI.isSolidWhite()) { |
- return false; |
- } |
- |
- return true; |
+ return false; |
} |
GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); |