Add in shader blending for CoverageSetOp XP
BUG=skia:
Review URL: https://codereview.chromium.org/1488213002
diff --git a/src/effects/SkArithmeticMode_gpu.cpp b/src/effects/SkArithmeticMode_gpu.cpp
index 994b073..a379324 100644
--- a/src/effects/SkArithmeticMode_gpu.cpp
+++ b/src/effects/SkArithmeticMode_gpu.cpp
@@ -213,8 +213,10 @@
void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb,
GrGLSLXPFragmentBuilder* fragBuilder,
const char* srcColor,
+ const char* srcCoverage,
const char* dstColor,
const char* outColor,
+ const char* outColorSecondary,
const GrXferProcessor& proc) override {
fKUni = pb->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, kDefault_GrSLPrecision,
@@ -222,6 +224,19 @@
const char* kUni = pb->getUniformCStr(fKUni);
add_arithmetic_code(fragBuilder, srcColor, dstColor, outColor, kUni, fEnforcePMColor);
+
+ // Apply coverage.
+ if (proc.dstReadUsesMixedSamples()) {
+ if (srcCoverage) {
+ fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage);
+ fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage);
+ } else {
+ fragBuilder->codeAppendf("%s = vec4(1.0);", outColorSecondary);
+ }
+ } else if (srcCoverage) {
+ fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;",
+ outColor, srcCoverage, outColor, srcCoverage, dstColor);
+ }
}
void onSetData(const GrGLSLProgramDataManager& pdman,
diff --git a/src/gpu/effects/GrCoverageSetOpXP.cpp b/src/gpu/effects/GrCoverageSetOpXP.cpp
index 43bb488..219ed0b 100644
--- a/src/gpu/effects/GrCoverageSetOpXP.cpp
+++ b/src/gpu/effects/GrCoverageSetOpXP.cpp
@@ -11,6 +11,7 @@
#include "GrColor.h"
#include "GrProcessor.h"
#include "GrProcOptInfo.h"
+#include "glsl/GrGLSLBlend.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLXferProcessor.h"
@@ -146,6 +147,96 @@
///////////////////////////////////////////////////////////////////////////////
+class ShaderCSOXferProcessor : public GrXferProcessor {
+public:
+ ShaderCSOXferProcessor(const DstTexture* dstTexture,
+ bool hasMixedSamples,
+ SkXfermode::Mode xfermode,
+ SkRegion::Op regionOp,
+ bool invertCoverage)
+ : INHERITED(dstTexture, true, hasMixedSamples)
+ , fRegionOp(regionOp)
+ , fInvertCoverage(invertCoverage) {
+ this->initClassID<ShaderCSOXferProcessor>();
+ }
+
+ const char* name() const override { return "Coverage Set Op Shader"; }
+
+ GrGLSLXferProcessor* createGLSLInstance() const override;
+
+ SkRegion::Op regionOp() const { return fRegionOp; }
+ bool invertCoverage() const { return fInvertCoverage; }
+
+private:
+ GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations&, bool, GrColor*,
+ const GrCaps&) const override {
+ // We never look at the color input
+ return GrXferProcessor::kIgnoreColor_OptFlag;
+ }
+
+ void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
+
+ bool onIsEqual(const GrXferProcessor& xpBase) const override {
+ const ShaderCSOXferProcessor& xp = xpBase.cast<ShaderCSOXferProcessor>();
+ return (fRegionOp == xp.fRegionOp &&
+ fInvertCoverage == xp.fInvertCoverage);
+ }
+
+ SkRegion::Op fRegionOp;
+ bool fInvertCoverage;
+
+ typedef GrXferProcessor INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class GLShaderCSOXferProcessor : public GrGLSLXferProcessor {
+public:
+ static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
+ const ShaderCSOXferProcessor& xp = processor.cast<ShaderCSOXferProcessor>();
+ b->add32(xp.regionOp());
+ uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
+ b->add32(key);
+ }
+
+private:
+ void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb,
+ GrGLSLXPFragmentBuilder* fragBuilder,
+ const char* srcColor,
+ const char* srcCoverage,
+ const char* dstColor,
+ const char* outColor,
+ const char* outColorSecondary,
+ const GrXferProcessor& proc) override {
+ const ShaderCSOXferProcessor& xp = proc.cast<ShaderCSOXferProcessor>();
+
+ if (xp.invertCoverage()) {
+ fragBuilder->codeAppendf("%s = 1.0 - %s;", outColor, srcCoverage);
+ } else {
+ fragBuilder->codeAppendf("%s = %s;", outColor, srcCoverage);
+ }
+
+ GrGLSLBlend::AppendRegionOp(fragBuilder, outColor, dstColor, outColor, xp.regionOp());
+ }
+
+ void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
+
+ typedef GrGLSLXferProcessor INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ShaderCSOXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
+ GrProcessorKeyBuilder* b) const {
+ GLShaderCSOXferProcessor::GenKey(*this, b);
+}
+
+GrGLSLXferProcessor* ShaderCSOXferProcessor::createGLSLInstance() const {
+ return new GLShaderCSOXferProcessor;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
: fRegionOp(regionOp)
, fInvertCoverage(invertCoverage) {
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index 93999dd..d2aff60 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -161,13 +161,28 @@
void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb,
GrGLSLXPFragmentBuilder* fragBuilder,
const char* srcColor,
+ const char* srcCoverage,
const char* dstColor,
const char* outColor,
+ const char* outColorSecondary,
const GrXferProcessor& proc) override {
const CustomXP& xp = proc.cast<CustomXP>();
SkASSERT(!xp.hasHWBlendEquation());
GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.mode());
+
+ // Apply coverage.
+ if (xp.dstReadUsesMixedSamples()) {
+ if (srcCoverage) {
+ fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage);
+ fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage);
+ } else {
+ fragBuilder->codeAppendf("%s = vec4(1.0);", outColorSecondary);
+ }
+ } else if (srcCoverage) {
+ fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;",
+ outColor, srcCoverage, outColor, srcCoverage, dstColor);
+ }
}
void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index e288f0c..42a9631 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -548,12 +548,27 @@
void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb,
GrGLSLXPFragmentBuilder* fragBuilder,
const char* srcColor,
+ const char* srcCoverage,
const char* dstColor,
const char* outColor,
+ const char* outColorSecondary,
const GrXferProcessor& proc) override {
const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>();
GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode());
+
+ // Apply coverage.
+ if (xp.dstReadUsesMixedSamples()) {
+ if (srcCoverage) {
+ fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage);
+ fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage);
+ } else {
+ fragBuilder->codeAppendf("%s = vec4(1.0);", outColorSecondary);
+ }
+ } else if (srcCoverage) {
+ fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;",
+ outColor, srcCoverage, outColor, srcCoverage, dstColor);
+ }
}
void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
diff --git a/src/gpu/glsl/GrGLSLBlend.cpp b/src/gpu/glsl/GrGLSLBlend.cpp
index 3c83068..6937977 100644
--- a/src/gpu/glsl/GrGLSLBlend.cpp
+++ b/src/gpu/glsl/GrGLSLBlend.cpp
@@ -433,3 +433,50 @@
emit_advanced_xfermode_code(fsBuilder, srcColor, dstColor, outColor, mode);
}
}
+
+void GrGLSLBlend::AppendRegionOp(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
+ const char* dstColor, const char* outColor,
+ SkRegion::Op regionOp) {
+ SkXfermode::Coeff srcCoeff, dstCoeff;
+ switch (regionOp) {
+ case SkRegion::kReplace_Op:
+ srcCoeff = SkXfermode::kOne_Coeff;
+ dstCoeff = SkXfermode::kZero_Coeff;
+ break;
+ case SkRegion::kIntersect_Op:
+ srcCoeff = SkXfermode::kDC_Coeff;
+ dstCoeff = SkXfermode::kZero_Coeff;
+ break;
+ case SkRegion::kUnion_Op:
+ srcCoeff = SkXfermode::kOne_Coeff;
+ dstCoeff = SkXfermode::kISC_Coeff;
+ break;
+ case SkRegion::kXOR_Op:
+ srcCoeff = SkXfermode::kIDC_Coeff;
+ dstCoeff = SkXfermode::kISC_Coeff;
+ break;
+ case SkRegion::kDifference_Op:
+ srcCoeff = SkXfermode::kZero_Coeff;
+ dstCoeff = SkXfermode::kISC_Coeff;
+ break;
+ case SkRegion::kReverseDifference_Op:
+ srcCoeff = SkXfermode::kIDC_Coeff;
+ dstCoeff = SkXfermode::kZero_Coeff;
+ break;
+ default:
+ SkFAIL("Unsupported Op");
+ // We should never get here but to make compiler happy
+ srcCoeff = SkXfermode::kZero_Coeff;
+ dstCoeff = SkXfermode::kZero_Coeff;
+ }
+ fsBuilder->codeAppendf("%s = ", outColor);
+ // append src blend
+ bool didAppend = append_porterduff_term(fsBuilder, srcCoeff, srcColor, srcColor, dstColor,
+ false);
+ // append dst blend
+ if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstColor, didAppend)) {
+ fsBuilder->codeAppend("vec4(0, 0, 0, 0)");
+ }
+ fsBuilder->codeAppend(";");
+}
+
diff --git a/src/gpu/glsl/GrGLSLBlend.h b/src/gpu/glsl/GrGLSLBlend.h
index 25ae37b..c8047f8 100644
--- a/src/gpu/glsl/GrGLSLBlend.h
+++ b/src/gpu/glsl/GrGLSLBlend.h
@@ -8,6 +8,7 @@
#ifndef GrGLBlend_DEFINED
#define GrGLBlend_DEFINED
+#include "SkRegion.h"
#include "SkXfermode.h"
class GrGLSLFragmentBuilder;
@@ -19,6 +20,9 @@
*/
void AppendMode(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
const char* dstColor, const char* outColor, SkXfermode::Mode mode);
+
+ void AppendRegionOp(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
+ const char* dstColor, const char* outColor, SkRegion::Op regionOp);
};
#endif
diff --git a/src/gpu/glsl/GrGLSLXferProcessor.cpp b/src/gpu/glsl/GrGLSLXferProcessor.cpp
index 7382660..b6af968 100644
--- a/src/gpu/glsl/GrGLSLXferProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLXferProcessor.cpp
@@ -63,23 +63,11 @@
this->emitBlendCodeForDstRead(args.fPB,
fragBuilder,
args.fInputColor,
+ args.fInputCoverage,
dstColor,
args.fOutputPrimary,
+ args.fOutputSecondary,
args.fXP);
-
- // Apply coverage.
- if (args.fXP.dstReadUsesMixedSamples()) {
- if (args.fInputCoverage) {
- fragBuilder->codeAppendf("%s *= %s;", args.fOutputPrimary, args.fInputCoverage);
- fragBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, args.fInputCoverage);
- } else {
- fragBuilder->codeAppendf("%s = vec4(1.0);", args.fOutputSecondary);
- }
- } else if (args.fInputCoverage) {
- fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;",
- args.fOutputPrimary, args.fInputCoverage,
- args.fOutputPrimary, args.fInputCoverage, dstColor);
- }
}
void GrGLSLXferProcessor::setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) {
diff --git a/src/gpu/glsl/GrGLSLXferProcessor.h b/src/gpu/glsl/GrGLSLXferProcessor.h
index 46d775d..3707d93 100644
--- a/src/gpu/glsl/GrGLSLXferProcessor.h
+++ b/src/gpu/glsl/GrGLSLXferProcessor.h
@@ -85,8 +85,10 @@
virtual void emitBlendCodeForDstRead(GrGLSLXPBuilder*,
GrGLSLXPFragmentBuilder*,
const char* srcColor,
+ const char* srcCoverage,
const char* dstColor,
const char* outColor,
+ const char* outColorSecondary,
const GrXferProcessor&) {
SkFAIL("emitBlendCodeForDstRead not implemented.");
}