Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Unified Diff: src/gpu/effects/GrPorterDuffXferProcessor.cpp

Issue 914003003: Use dst copies in porter duffer XP to correctly render certain blends. (Closed) Base URL: https://skia.googlesource.com/skia.git@prePDDstCopy
Patch Set: Rebase Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/effects/GrDisableColorXP.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/effects/GrPorterDuffXferProcessor.cpp
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index a08776a20ff0668ebe11dc92d646f534dcdf3393..4453c8935d84ec84c190b7be33f0737c31539371 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -59,6 +59,10 @@ public:
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 {
@@ -87,11 +91,19 @@ public:
const GrDrawTargetCaps& caps) SK_OVERRIDE;
void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE {
- blendInfo->fSrcBlend = fSrcBlend;
- blendInfo->fDstBlend = fDstBlend;
+ if (!this->willReadDstColor()) {
+ blendInfo->fSrcBlend = fSrcBlend;
+ blendInfo->fDstBlend = fDstBlend;
+ } else {
+ blendInfo->fSrcBlend = kOne_GrBlendCoeff;
+ blendInfo->fDstBlend = kZero_GrBlendCoeff;
+ }
blendInfo->fBlendConstant = fBlendConstant;
}
+ GrBlendCoeff getSrcBlend() const { return fSrcBlend; }
+ GrBlendCoeff getDstBlend() const { return fDstBlend; }
+
private:
PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColor constant,
const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
@@ -128,6 +140,50 @@ private:
///////////////////////////////////////////////////////////////////////////////
+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&) {}
@@ -139,16 +195,24 @@ public:
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 (xp.hasSecondaryOutput()) {
+ if (PorterDuffXferProcessor::kCustom_PrimaryOutputType != xp.primaryOutputType()) {
+ SkASSERT(!xp.willReadDstColor());
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;",
@@ -163,24 +227,43 @@ private:
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");
+
+ 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);
}
}
@@ -196,7 +279,8 @@ PorterDuffXferProcessor::PorterDuffXferProcessor(GrBlendCoeff srcBlend,
GrColor constant,
const GrDeviceCoordTexture* dstCopy,
bool willReadDstColor)
- : fSrcBlend(srcBlend)
+ : INHERITED(dstCopy, willReadDstColor)
+ , fSrcBlend(srcBlend)
, fDstBlend(dstBlend)
, fBlendConstant(constant)
, fPrimaryOutputType(kModulate_PrimaryOutputType)
@@ -244,6 +328,11 @@ PorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
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;
@@ -284,11 +373,12 @@ GrXferProcessor::OptFlags
PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
bool doesStencilWrite) {
- bool srcAIsOne;
- bool hasCoverage;
+ if (this->willReadDstColor()) {
+ return GrXferProcessor::kNone_Opt;
+ }
- srcAIsOne = colorPOI.isOpaque();
- hasCoverage = !coveragePOI.isSolidWhite();
+ bool srcAIsOne = colorPOI.isOpaque();
+ bool hasCoverage = !coveragePOI.isSolidWhite();
bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend ||
(kSA_GrBlendCoeff == fDstBlend && srcAIsOne);
@@ -472,19 +562,20 @@ GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) {
}
GrXferProcessor*
-GrPorterDuffXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI,
+GrPorterDuffXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps,
+ const GrProcOptInfo& colorPOI,
const GrProcOptInfo& covPOI,
const GrDeviceCoordTexture* dstCopy) const {
if (!covPOI.isFourChannelOutput()) {
return PorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy,
- this->willReadDstColor(colorPOI, covPOI));
+ this->willReadDstColor(caps, 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(colorPOI, covPOI));
+ this->willReadDstColor(caps, colorPOI, covPOI));
} else {
return NULL;
}
@@ -500,39 +591,6 @@ bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/,
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;
-}
-
bool GrPorterDuffXPFactory::canTweakAlphaForCoverage() const {
return can_tweak_alpha_for_coverage(fDstCoeff);
}
@@ -606,9 +664,37 @@ void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
output->fWillBlendWithDst = false;
}
-bool GrPorterDuffXPFactory::willReadDstColor(const GrProcOptInfo& colorPOI,
+bool GrPorterDuffXPFactory::willReadDstColor(const GrDrawTargetCaps& caps,
+ const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const {
- return false;
+ // 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;
}
GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
« no previous file with comments | « src/gpu/effects/GrDisableColorXP.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698