Perform coverage blend with the dst in the shader when using a dst-reading xfermode.
Review URL: https://codereview.chromium.org/14233006
git-svn-id: http://skia.googlecode.com/svn/trunk@8762 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 0b338f2..1b4baa4 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -96,24 +96,28 @@
void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
GrBlendCoeff* dstCoeff) const {
- switch (fDesc.fDualSrcOutput) {
- case GrGLProgramDesc::kNone_DualSrcOutput:
+ switch (fDesc.fCoverageOutput) {
+ case GrGLProgramDesc::kModulate_CoverageOutput:
break;
- // the prog will write a coverage value to the secondary
+ // The prog will write a coverage value to the secondary
// output and the dst is blended by one minus that value.
- case GrGLProgramDesc::kCoverage_DualSrcOutput:
- case GrGLProgramDesc::kCoverageISA_DualSrcOutput:
- case GrGLProgramDesc::kCoverageISC_DualSrcOutput:
- *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
- break;
+ case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
+ case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
+ case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
+ *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
+ break;
+ case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
+ // We should only have set this if the blend was specified as (1, 0)
+ GrAssert(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
+ break;
default:
- GrCrash("Unexpected dual source blend output");
+ GrCrash("Unexpected coverage output");
break;
}
}
namespace {
-// given two blend coeffecients determine whether the src
+// given two blend coefficients determine whether the src
// and/or dst computation can be omitted.
inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
SkXfermode::Coeff dstCoeff,
@@ -375,6 +379,20 @@
return compile_shader(gl, type, 1, &str, &length);
}
+void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
+ GrAssert(string->isEmpty() == (vec != kNone_GrSLConstantVec));
+ switch (vec) {
+ case kNone_GrSLConstantVec:
+ break;
+ case kZeros_GrSLConstantVec:
+ *string = GrGLSLZerosVecf(4);
+ break;
+ case kOnes_GrSLConstantVec:
+ *string = GrGLSLOnesVecf(4);
+ break;
+ }
+}
+
}
// compiles all the shaders from builder and stores the shader IDs
@@ -564,14 +582,16 @@
}
}
- if (GrGLProgramDesc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
+ GrGLProgramDesc::CoverageOutput coverageOutput =
+ static_cast<GrGLProgramDesc::CoverageOutput>(fDesc.fCoverageOutput);
+ if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(coverageOutput)) {
builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kOut_TypeModifier,
dual_source_output_name());
// default coeff to ones for kCoverage_DualSrcOutput
SkString coeff;
GrSLConstantVec knownCoeffValue = kOnes_GrSLConstantVec;
- if (GrGLProgramDesc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) {
+ if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == fDesc.fCoverageOutput) {
// Get (1-A) into coeff
SkString inColorAlpha;
GrGLSLGetComponent4f(&inColorAlpha,
@@ -585,7 +605,7 @@
kOnes_GrSLConstantVec,
knownColorValue,
true);
- } else if (GrGLProgramDesc::kCoverageISC_DualSrcOutput == fDesc.fDualSrcOutput) {
+ } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == coverageOutput) {
// Get (1-RGBA) into coeff
knownCoeffValue = GrGLSLSubtractf<4>(&coeff,
NULL,
@@ -609,15 +629,42 @@
///////////////////////////////////////////////////////////////////////////
// combine color and coverage as frag color
- // Get color * coverage into modulate and write that to frag shader's output.
- SkString modulate;
- GrGLSLModulatef<4>(&modulate,
- inColor.c_str(),
- inCoverage.c_str(),
- knownColorValue,
- knownCoverageValue,
- false);
- builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), modulate.c_str());
+ // Get "color * coverage" into fragColor
+ SkString fragColor;
+ GrSLConstantVec knownFragColorValue = GrGLSLModulatef<4>(&fragColor,
+ inColor.c_str(),
+ inCoverage.c_str(),
+ knownColorValue,
+ knownCoverageValue,
+ true);
+ // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
+ if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == coverageOutput) {
+ SkString dstCoeff;
+ GrSLConstantVec knownDstCoeffValue = GrGLSLSubtractf<4>(&dstCoeff,
+ NULL,
+ inCoverage.c_str(),
+ kOnes_GrSLConstantVec,
+ knownCoverageValue,
+ true);
+ SkString dstContribution;
+ GrSLConstantVec knownDstContributionValue = GrGLSLModulatef<4>(&dstContribution,
+ dstCoeff.c_str(),
+ builder.dstColor(),
+ knownDstCoeffValue,
+ kNone_GrSLConstantVec,
+ true);
+ SkString oldFragColor = fragColor;
+ fragColor.reset();
+ GrGLSLAddf<4>(&fragColor,
+ oldFragColor.c_str(),
+ dstContribution.c_str(),
+ knownFragColorValue,
+ knownDstContributionValue,
+ false);
+ } else {
+ expand_known_value4f(&fragColor, knownFragColorValue);
+ }
+ builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), fragColor.c_str());
///////////////////////////////////////////////////////////////////////////
// insert GS