Move blend optimization functions to GrDrawState.
Review URL: https://codereview.appspot.com/7300089
git-svn-id: http://skia.googlecode.com/svn/trunk@7703 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 3282f13..c00a5ce 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -454,168 +454,24 @@
////////////////////////////////////////////////////////////////////////////////
-// Some blend modes allow folding a partial coverage value into the color's
-// alpha channel, while others will blend incorrectly.
-bool GrDrawTarget::canTweakAlphaForCoverage() const {
- /**
- * The fractional coverage is f
- * The src and dst coeffs are Cs and Cd
- * The dst and src colors are S and D
- * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
- * By tweaking the source color's alpha we're replacing S with S'=fS. It's
- * obvious that that first term will always be ok. The second term can be
- * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
- * for Cd we find that only 1, ISA, and ISC produce the correct depth
- * coefficient in terms of S' and D.
- */
- GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
- return kOne_GrBlendCoeff == dstCoeff ||
- kISA_GrBlendCoeff == dstCoeff ||
- kISC_GrBlendCoeff == dstCoeff ||
- this->getDrawState().isCoverageDrawing();
-}
-
-namespace {
-GrVertexLayout default_blend_opts_vertex_layout() {
- GrVertexLayout layout = 0;
- return layout;
-}
-}
-
-GrDrawTarget::BlendOptFlags
-GrDrawTarget::getBlendOpts(bool forceCoverage,
- GrBlendCoeff* srcCoeff,
- GrBlendCoeff* dstCoeff) const {
-
- const GrDrawState& drawState = this->getDrawState();
-
- GrVertexLayout layout;
- if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
- layout = default_blend_opts_vertex_layout();
- } else {
- layout = drawState.getVertexLayout();
- }
-
- GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
- if (NULL == srcCoeff) {
- srcCoeff = &bogusSrcCoeff;
- }
- *srcCoeff = drawState.getSrcBlendCoeff();
-
- if (NULL == dstCoeff) {
- dstCoeff = &bogusDstCoeff;
- }
- *dstCoeff = drawState.getDstBlendCoeff();
-
- if (drawState.isColorWriteDisabled()) {
- *srcCoeff = kZero_GrBlendCoeff;
- *dstCoeff = kOne_GrBlendCoeff;
- }
-
- bool srcAIsOne = drawState.srcAlphaWillBeOne(layout);
- bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
- (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
- bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
- (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
-
- bool covIsZero = !drawState.isCoverageDrawing() &&
- !(layout & GrDrawState::kCoverage_VertexLayoutBit) &&
- 0 == drawState.getCoverage();
- // When coeffs are (0,1) there is no reason to draw at all, unless
- // stenciling is enabled. Having color writes disabled is effectively
- // (0,1). The same applies when coverage is known to be 0.
- if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
- if (drawState.getStencil().doesWrite()) {
- return kDisableBlend_BlendOptFlag |
- kEmitTransBlack_BlendOptFlag;
- } else {
- return kSkipDraw_BlendOptFlag;
- }
- }
-
- // check for coverage due to constant coverage, per-vertex coverage,
- // edge aa or coverage stage
- bool hasCoverage = forceCoverage ||
- 0xffffffff != drawState.getCoverage() ||
- (layout & GrDrawState::kCoverage_VertexLayoutBit) ||
- (layout & GrDrawState::kEdge_VertexLayoutBit);
- for (int s = drawState.getFirstCoverageStage();
- !hasCoverage && s < GrDrawState::kNumStages;
- ++s) {
- if (drawState.isStageEnabled(s)) {
- hasCoverage = true;
- }
- }
-
- // if we don't have coverage we can check whether the dst
- // has to read at all. If not, we'll disable blending.
- if (!hasCoverage) {
- if (dstCoeffIsZero) {
- if (kOne_GrBlendCoeff == *srcCoeff) {
- // if there is no coverage and coeffs are (1,0) then we
- // won't need to read the dst at all, it gets replaced by src
- return kDisableBlend_BlendOptFlag;
- } else if (kZero_GrBlendCoeff == *srcCoeff) {
- // if the op is "clear" then we don't need to emit a color
- // or blend, just write transparent black into the dst.
- *srcCoeff = kOne_GrBlendCoeff;
- *dstCoeff = kZero_GrBlendCoeff;
- return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
- }
- }
- } else if (drawState.isCoverageDrawing()) {
- // we have coverage but we aren't distinguishing it from alpha by request.
- return kCoverageAsAlpha_BlendOptFlag;
- } else {
- // check whether coverage can be safely rolled into alpha
- // of if we can skip color computation and just emit coverage
- if (this->canTweakAlphaForCoverage()) {
- return kCoverageAsAlpha_BlendOptFlag;
- }
- if (dstCoeffIsZero) {
- if (kZero_GrBlendCoeff == *srcCoeff) {
- // the source color is not included in the blend
- // the dst coeff is effectively zero so blend works out to:
- // (c)(0)D + (1-c)D = (1-c)D.
- *dstCoeff = kISA_GrBlendCoeff;
- return kEmitCoverage_BlendOptFlag;
- } else if (srcAIsOne) {
- // the dst coeff is effectively zero so blend works out to:
- // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
- // If Sa is 1 then we can replace Sa with c
- // and set dst coeff to 1-Sa.
- *dstCoeff = kISA_GrBlendCoeff;
- return kCoverageAsAlpha_BlendOptFlag;
- }
- } else if (dstCoeffIsOne) {
- // the dst coeff is effectively one so blend works out to:
- // cS + (c)(1)D + (1-c)D = cS + D.
- *dstCoeff = kOne_GrBlendCoeff;
- return kCoverageAsAlpha_BlendOptFlag;
- }
- }
- return kNone_BlendOpt;
-}
-
bool GrDrawTarget::willUseHWAALines() const {
- // there is a conflict between using smooth lines and our use of
- // premultiplied alpha. Smooth lines tweak the incoming alpha value
- // but not in a premul-alpha way. So we only use them when our alpha
- // is 0xff and tweaking the color for partial coverage is OK
+ // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
+ // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
+ // our alpha is 0xff and tweaking the color for partial coverage is OK
if (!fCaps.hwAALineSupport() ||
!this->getDrawState().isHWAntialiasState()) {
return false;
}
- BlendOptFlags opts = this->getBlendOpts();
- return (kDisableBlend_BlendOptFlag & opts) &&
- (kCoverageAsAlpha_BlendOptFlag & opts);
+ GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts();
+ return (GrDrawState::kDisableBlend_BlendOptFlag & opts) &&
+ (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts);
}
bool GrDrawTarget::canApplyCoverage() const {
// we can correctly apply coverage if a) we have dual source blending
// or b) one of our blend optimizations applies.
return this->getCaps().dualSourceBlendingSupport() ||
- kNone_BlendOpt != this->getBlendOpts(true);
+ GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
}
////////////////////////////////////////////////////////////////////////////////