if (SkXfermode::AsNewEffectOrCoeff(mode, dev->context(), &xferEffect, &sm, &dm)) {
if (NULL != xferEffect) {
grPaint->colorStage(kXfermodeEffectIdx)->setEffect(xferEffect)->unref();
- // This may not be the right place to have this logic but we set the GPU blend to
- // src-over so that fractional coverage will be accounted for correctly.
sm = SkXfermode::kOne_Coeff;
- dm = SkXfermode::kISA_Coeff;
+ dm = SkXfermode::kZero_Coeff;
}
} else {
//SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
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,
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
}
}
- 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,
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,
///////////////////////////////////////////////////////////////////////////
// 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
desc->fDstRead = 0;
}
- desc->fDualSrcOutput = kNone_DualSrcOutput;
+ desc->fCoverageOutput = kModulate_CoverageOutput;
// Currently the experimental GS will only work with triangle prims (and it doesn't do anything
// other than pass through values from the VS to the FS anyway).
GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
if (kZero_GrBlendCoeff == dstCoeff) {
// write the coverage value to second color
- desc->fDualSrcOutput = kCoverage_DualSrcOutput;
+ desc->fCoverageOutput = kSecondaryCoverage_CoverageOutput;
desc->fFirstCoverageStage = firstCoverageStage;
} else if (kSA_GrBlendCoeff == dstCoeff) {
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
- desc->fDualSrcOutput = kCoverageISA_DualSrcOutput;
+ desc->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
desc->fFirstCoverageStage = firstCoverageStage;
} else if (kSC_GrBlendCoeff == dstCoeff) {
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
- desc->fDualSrcOutput = kCoverageISC_DualSrcOutput;
+ desc->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
desc->fFirstCoverageStage = firstCoverageStage;
}
+ } else if (readsDst &&
+ kOne_GrBlendCoeff == drawState.getSrcBlendCoeff() &&
+ kZero_GrBlendCoeff == drawState.getDstBlendCoeff()) {
+ desc->fCoverageOutput = kCombineWithDst_CoverageOutput;
+ desc->fFirstCoverageStage = firstCoverageStage;
}
}
kColorInputCnt
};
- // Dual-src blending makes use of a secondary output color that can be
- // used as a per-pixel blend coefficient. This controls whether a
- // secondary source is output and what value it holds.
- enum DualSrcOutput {
- kNone_DualSrcOutput,
- kCoverage_DualSrcOutput,
- kCoverageISA_DualSrcOutput,
- kCoverageISC_DualSrcOutput,
-
- kDualSrcOutputCnt
+
+ enum CoverageOutput {
+ // modulate color and coverage, write result as the color output.
+ kModulate_CoverageOutput,
+ // Writes color*coverage as the primary color output and also writes coverage as the
+ // secondary output. Only set if dual source blending is supported.
+ kSecondaryCoverage_CoverageOutput,
+ // Writes color*coverage as the primary color output and also writes coverage * (1 - colorA)
+ // as the secondary output. Only set if dual source blending is supported.
+ kSecondaryCoverageISA_CoverageOutput,
+ // Writes color*coverage as the primary color output and also writes coverage *
+ // (1 - colorRGB) as the secondary output. Only set if dual source blending is supported.
+ kSecondaryCoverageISC_CoverageOutput,
+ // Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This
+ // can only be set if fDstRead is set.
+ kCombineWithDst_CoverageOutput,
+
+ kCoverageOutputCnt
};
+ static bool CoverageOutputUsesSecondaryOutput(CoverageOutput co) {
+ switch (co) {
+ case kSecondaryCoverage_CoverageOutput: // fallthru
+ case kSecondaryCoverageISA_CoverageOutput:
+ case kSecondaryCoverageISC_CoverageOutput:
+ return true;
+ default:
+ return false;
+ }
+ }
+
/** Non-zero if this stage has an effect */
GrGLEffect::EffectKey fEffectKeys[GrDrawState::kNumStages];
uint8_t fColorInput; // casts to enum ColorInput
uint8_t fCoverageInput; // casts to enum ColorInput
- uint8_t fDualSrcOutput; // casts to enum DualSrcOutput
+ uint8_t fCoverageOutput; // casts to enum CoverageOutput
int8_t fFirstCoverageStage;
SkBool8 fEmitsPointSize;
fDiscardIfZeroCoverage = random->nextBool();
- if (gpu->caps()->dualSourceBlendingSupport()) {
- fDualSrcOutput = random->nextULessThan(kDualSrcOutputCnt);
- } else {
- fDualSrcOutput = kNone_DualSrcOutput;
- }
-
bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1;
if (dstRead) {
this->fDstRead = GrGLShaderBuilder::KeyForDstRead(dstTexture, gpu->glCaps());
}
+
+ CoverageOutput coverageOutput;
+ bool illegalCoverageOutput;
+ do {
+ coverageOutput = static_cast<CoverageOutput>(random->nextULessThan(kCoverageOutputCnt));
+ illegalCoverageOutput = (!gpu->caps()->dualSourceBlendingSupport() &&
+ CoverageOutputUsesSecondaryOutput(coverageOutput)) ||
+ !dstRead && kCombineWithDst_CoverageOutput == coverageOutput;
+ } while (illegalCoverageOutput);
+
+ fCoverageOutput = coverageOutput;
}
bool GrGpuGL::programUnitTest(int maxStages) {