OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrDrawState.h" | 8 #include "GrDrawState.h" |
9 #include "GrPaint.h" | 9 #include "GrPaint.h" |
| 10 #include "GrDrawTargetCaps.h" |
10 | 11 |
11 //////////////////////////////////////////////////////////////////////////////s | 12 //////////////////////////////////////////////////////////////////////////////s |
12 | 13 |
13 bool GrDrawState::State::HaveCompatibleState(const State& a, const State& b, | 14 bool GrDrawState::State::HaveCompatibleState(const State& a, const State& b, |
14 bool explicitLocalCoords) { | 15 bool explicitLocalCoords) { |
15 if (a.fColorStages.count() != b.fColorStages.count() || | 16 if (a.fColorStages.count() != b.fColorStages.count() || |
16 a.fCoverageStages.count() != b.fCoverageStages.count() || | 17 a.fCoverageStages.count() != b.fCoverageStages.count() || |
17 a.fSrcBlend != b.fSrcBlend || | 18 a.fSrcBlend != b.fSrcBlend || |
18 a.fDstBlend != b.fDstBlend) { | 19 a.fDstBlend != b.fDstBlend) { |
19 return false; | 20 return false; |
20 } | 21 } |
21 for (int i = 0; i < a.fColorStages.count(); i++) { | 22 for (int i = 0; i < a.fColorStages.count(); i++) { |
22 if (!GrEffectStage::AreCompatible(a.fColorStages[i], b.fColorStages[i], | 23 if (!GrEffectStage::AreCompatible(a.fColorStages[i], b.fColorStages[i], |
23 explicitLocalCoords)) { | 24 explicitLocalCoords)) { |
24 return false; | 25 return false; |
25 } | 26 } |
26 } | 27 } |
27 for (int i = 0; i < a.fCoverageStages.count(); i++) { | 28 for (int i = 0; i < a.fCoverageStages.count(); i++) { |
28 if (!GrEffectStage::AreCompatible(a.fCoverageStages[i], b.fCoverageStage
s[i], | 29 if (!GrEffectStage::AreCompatible(a.fCoverageStages[i], b.fCoverageStage
s[i], |
29 explicitLocalCoords)) { | 30 explicitLocalCoords)) { |
30 return false; | 31 return false; |
31 } | 32 } |
32 } | 33 } |
33 return true; | 34 return true; |
34 } | 35 } |
35 //////////////////////////////////////////////////////////////////////////////s | 36 //////////////////////////////////////////////////////////////////////////////s |
36 GrDrawState::CombinedState GrDrawState::CombineIfPossible( | 37 GrDrawState::CombinedState GrDrawState::CombineIfPossible( |
37 const GrDrawState& a, const GrDrawState& b) { | 38 const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) { |
38 | 39 |
39 bool usingVertexColors = a.hasColorVertexAttribute(); | 40 bool usingVertexColors = a.hasColorVertexAttribute(); |
40 if (!usingVertexColors && a.fColor != b.fColor) { | 41 if (!usingVertexColors && a.fColor != b.fColor) { |
41 return kIncompatible_CombinedState; | 42 return kIncompatible_CombinedState; |
42 } | 43 } |
43 | 44 |
44 if (a.fRenderTarget.get() != b.fRenderTarget.get() || | 45 if (a.fRenderTarget.get() != b.fRenderTarget.get() || |
45 !a.fViewMatrix.cheapEqualTo(b.fViewMatrix) || | 46 !a.fViewMatrix.cheapEqualTo(b.fViewMatrix) || |
46 a.fBlendConstant != b.fBlendConstant || | 47 a.fBlendConstant != b.fBlendConstant || |
47 a.fFlagBits != b.fFlagBits || | 48 a.fFlagBits != b.fFlagBits || |
(...skipping 10 matching lines...) Expand all Loading... |
58 } | 59 } |
59 | 60 |
60 bool explicitLocalCoords = a.hasLocalCoordAttribute(); | 61 bool explicitLocalCoords = a.hasLocalCoordAttribute(); |
61 | 62 |
62 SkASSERT(0 == memcmp(a.fFixedFunctionVertexAttribIndices, | 63 SkASSERT(0 == memcmp(a.fFixedFunctionVertexAttribIndices, |
63 b.fFixedFunctionVertexAttribIndices, | 64 b.fFixedFunctionVertexAttribIndices, |
64 sizeof(a.fFixedFunctionVertexAttribIndices))); | 65 sizeof(a.fFixedFunctionVertexAttribIndices))); |
65 if (!State::HaveCompatibleState(a.fState, b.fState, explicitLocalCoords)) { | 66 if (!State::HaveCompatibleState(a.fState, b.fState, explicitLocalCoords)) { |
66 return kIncompatible_CombinedState; | 67 return kIncompatible_CombinedState; |
67 } | 68 } |
| 69 |
| 70 if (usingVertexColors) { |
| 71 // If one is opaque and the other is not then the combined state is not
opaque. Moreover, |
| 72 // if the opaqueness affects the ability to get color/coverage blending
correct then we |
| 73 // don't combine the draw states. |
| 74 bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints); |
| 75 bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints); |
| 76 if (aIsOpaque != bIsOpaque) { |
| 77 const GrDrawState* opaque; |
| 78 const GrDrawState* nonOpaque; |
| 79 if (aIsOpaque) { |
| 80 opaque = &a; |
| 81 nonOpaque = &b; |
| 82 } else { |
| 83 opaque = &b; |
| 84 nonOpaque = &a; |
| 85 } |
| 86 if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps))
{ |
| 87 SkASSERT(!nonOpaque->hasSolidCoverage()); |
| 88 if (!nonOpaque->couldApplyCoverage(caps)) { |
| 89 return kIncompatible_CombinedState; |
| 90 } |
| 91 } |
| 92 return aIsOpaque ? kB_CombinedState : kA_CombinedState; |
| 93 } |
| 94 } |
68 return kAOrB_CombinedState; | 95 return kAOrB_CombinedState; |
69 } | 96 } |
70 | 97 |
71 | |
72 //////////////////////////////////////////////////////////////////////////////s | 98 //////////////////////////////////////////////////////////////////////////////s |
73 | 99 |
74 GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatr
ix) { | 100 GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatr
ix) { |
75 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;) | 101 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;) |
76 *this = state; | 102 *this = state; |
77 if (!preConcatMatrix.isIdentity()) { | 103 if (!preConcatMatrix.isIdentity()) { |
78 for (int i = 0; i < this->numColorStages(); ++i) { | 104 for (int i = 0; i < this->numColorStages(); ++i) { |
79 fState.fColorStages[i].localCoordChange(preConcatMatrix); | 105 fState.fColorStages[i].localCoordChange(preConcatMatrix); |
80 } | 106 } |
81 for (int i = 0; i < this->numCoverageStages(); ++i) { | 107 for (int i = 0; i < this->numCoverageStages(); ++i) { |
(...skipping 13 matching lines...) Expand all Loading... |
95 fVACount = that.fVACount; | 121 fVACount = that.fVACount; |
96 fVAPtr = that.fVAPtr; | 122 fVAPtr = that.fVAPtr; |
97 fStencilSettings = that.fStencilSettings; | 123 fStencilSettings = that.fStencilSettings; |
98 fCoverage = that.fCoverage; | 124 fCoverage = that.fCoverage; |
99 fDrawFace = that.fDrawFace; | 125 fDrawFace = that.fDrawFace; |
100 fOptSrcBlend = that.fOptSrcBlend; | 126 fOptSrcBlend = that.fOptSrcBlend; |
101 fOptDstBlend = that.fOptDstBlend; | 127 fOptDstBlend = that.fOptDstBlend; |
102 fBlendOptFlags = that.fBlendOptFlags; | 128 fBlendOptFlags = that.fBlendOptFlags; |
103 | 129 |
104 fState = that.fState; | 130 fState = that.fState; |
| 131 fHints = that.fHints; |
105 | 132 |
106 memcpy(fFixedFunctionVertexAttribIndices, | 133 memcpy(fFixedFunctionVertexAttribIndices, |
107 that.fFixedFunctionVertexAttribIndices, | 134 that.fFixedFunctionVertexAttribIndices, |
108 sizeof(fFixedFunctionVertexAttribIndices)); | 135 sizeof(fFixedFunctionVertexAttribIndices)); |
109 return *this; | 136 return *this; |
110 } | 137 } |
111 | 138 |
112 void GrDrawState::onReset(const SkMatrix* initialViewMatrix) { | 139 void GrDrawState::onReset(const SkMatrix* initialViewMatrix) { |
113 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages()); | 140 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages()); |
114 fState.reset(); | 141 fState.reset(); |
115 | 142 |
116 fRenderTarget.reset(NULL); | 143 fRenderTarget.reset(NULL); |
117 | 144 |
118 this->setDefaultVertexAttribs(); | 145 this->setDefaultVertexAttribs(); |
119 | 146 |
120 fColor = 0xffffffff; | 147 fColor = 0xffffffff; |
121 if (NULL == initialViewMatrix) { | 148 if (NULL == initialViewMatrix) { |
122 fViewMatrix.reset(); | 149 fViewMatrix.reset(); |
123 } else { | 150 } else { |
124 fViewMatrix = *initialViewMatrix; | 151 fViewMatrix = *initialViewMatrix; |
125 } | 152 } |
126 fBlendConstant = 0x0; | 153 fBlendConstant = 0x0; |
127 fFlagBits = 0x0; | 154 fFlagBits = 0x0; |
128 fStencilSettings.setDisabled(); | 155 fStencilSettings.setDisabled(); |
129 fCoverage = 0xffffffff; | 156 fCoverage = 0xffffffff; |
130 fDrawFace = kBoth_DrawFace; | 157 fDrawFace = kBoth_DrawFace; |
131 | 158 |
| 159 fHints = 0; |
| 160 |
132 this->invalidateBlendOptFlags(); | 161 this->invalidateBlendOptFlags(); |
133 } | 162 } |
134 | 163 |
135 bool GrDrawState::setIdentityViewMatrix() { | 164 bool GrDrawState::setIdentityViewMatrix() { |
136 if (this->numTotalStages()) { | 165 if (this->numTotalStages()) { |
137 SkMatrix invVM; | 166 SkMatrix invVM; |
138 if (!fViewMatrix.invert(&invVM)) { | 167 if (!fViewMatrix.invert(&invVM)) { |
139 // sad trombone sound | 168 // sad trombone sound |
140 return false; | 169 return false; |
141 } | 170 } |
(...skipping 23 matching lines...) Expand all Loading... |
165 | 194 |
166 this->setRenderTarget(rt); | 195 this->setRenderTarget(rt); |
167 | 196 |
168 fViewMatrix = vm; | 197 fViewMatrix = vm; |
169 | 198 |
170 // These have no equivalent in GrPaint, set them to defaults | 199 // These have no equivalent in GrPaint, set them to defaults |
171 fBlendConstant = 0x0; | 200 fBlendConstant = 0x0; |
172 fDrawFace = kBoth_DrawFace; | 201 fDrawFace = kBoth_DrawFace; |
173 fStencilSettings.setDisabled(); | 202 fStencilSettings.setDisabled(); |
174 this->resetStateFlags(); | 203 this->resetStateFlags(); |
| 204 fHints = 0; |
175 | 205 |
176 // Enable the clip bit | 206 // Enable the clip bit |
177 this->enableState(GrDrawState::kClip_StateBit); | 207 this->enableState(GrDrawState::kClip_StateBit); |
178 | 208 |
179 this->setColor(paint.getColor()); | 209 this->setColor(paint.getColor()); |
180 this->setState(GrDrawState::kDither_StateBit, paint.isDither()); | 210 this->setState(GrDrawState::kDither_StateBit, paint.isDither()); |
181 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias()); | 211 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias()); |
182 | 212 |
183 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff()); | 213 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff()); |
184 this->setCoverage(paint.getCoverage()); | 214 this->setCoverage(paint.getCoverage()); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 for (int s = 0; s < this->numCoverageStages(); ++s) { | 349 for (int s = 0; s < this->numCoverageStages(); ++s) { |
320 if (this->getCoverageStage(s).getEffect()->willReadDstColor()) { | 350 if (this->getCoverageStage(s).getEffect()->willReadDstColor()) { |
321 return true; | 351 return true; |
322 } | 352 } |
323 } | 353 } |
324 return false; | 354 return false; |
325 } | 355 } |
326 | 356 |
327 //////////////////////////////////////////////////////////////////////////////// | 357 //////////////////////////////////////////////////////////////////////////////// |
328 | 358 |
| 359 bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const { |
| 360 if (caps.dualSourceBlendingSupport()) { |
| 361 return true; |
| 362 } |
| 363 // we can correctly apply coverage if a) we have dual source blending |
| 364 // or b) one of our blend optimizations applies |
| 365 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color |
| 366 GrBlendCoeff srcCoeff; |
| 367 GrBlendCoeff dstCoeff; |
| 368 GrDrawState::BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCo
eff); |
| 369 return GrDrawState::kNone_BlendOpt != flag || |
| 370 (this->willEffectReadDstColor() && |
| 371 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff); |
| 372 } |
| 373 |
329 bool GrDrawState::srcAlphaWillBeOne() const { | 374 bool GrDrawState::srcAlphaWillBeOne() const { |
330 uint32_t validComponentFlags; | 375 uint32_t validComponentFlags; |
331 GrColor color; | 376 GrColor color; |
332 // Check if per-vertex or constant color may have partial alpha | 377 // Check if per-vertex or constant color may have partial alpha |
333 if (this->hasColorVertexAttribute()) { | 378 if (this->hasColorVertexAttribute()) { |
334 validComponentFlags = 0; | 379 if (fHints & kVertexColorsAreOpaque_Hint) { |
335 color = 0; // not strictly necessary but we get false alarms from tools
about uninit. | 380 validComponentFlags = kA_GrColorComponentFlag; |
| 381 color = 0xFF << GrColor_SHIFT_A; |
| 382 } else { |
| 383 validComponentFlags = 0; |
| 384 color = 0; // not strictly necessary but we get false alarms from to
ols about uninit. |
| 385 } |
336 } else { | 386 } else { |
337 validComponentFlags = kRGBA_GrColorComponentFlags; | 387 validComponentFlags = kRGBA_GrColorComponentFlags; |
338 color = this->getColor(); | 388 color = this->getColor(); |
339 } | 389 } |
340 | 390 |
341 // Run through the color stages | 391 // Run through the color stages |
342 for (int s = 0; s < this->numColorStages(); ++s) { | 392 for (int s = 0; s < this->numColorStages(); ++s) { |
343 const GrEffect* effect = this->getColorStage(s).getEffect(); | 393 const GrEffect* effect = this->getColorStage(s).getEffect(); |
344 effect->getConstantColorComponents(&color, &validComponentFlags); | 394 effect->getConstantColorComponents(&color, &validComponentFlags); |
345 } | 395 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 *srcCoeff = kZero_GrBlendCoeff; | 498 *srcCoeff = kZero_GrBlendCoeff; |
449 *dstCoeff = kOne_GrBlendCoeff; | 499 *dstCoeff = kOne_GrBlendCoeff; |
450 } | 500 } |
451 | 501 |
452 bool srcAIsOne = this->srcAlphaWillBeOne(); | 502 bool srcAIsOne = this->srcAlphaWillBeOne(); |
453 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff || | 503 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff || |
454 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne); | 504 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne); |
455 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff || | 505 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff || |
456 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne); | 506 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne); |
457 | 507 |
458 bool covIsZero = !this->isCoverageDrawing() && | |
459 !this->hasCoverageVertexAttribute() && | |
460 0 == this->getCoverageColor(); | |
461 // When coeffs are (0,1) there is no reason to draw at all, unless | 508 // When coeffs are (0,1) there is no reason to draw at all, unless |
462 // stenciling is enabled. Having color writes disabled is effectively | 509 // stenciling is enabled. Having color writes disabled is effectively |
463 // (0,1). The same applies when coverage is known to be 0. | 510 // (0,1). |
464 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) { | 511 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) { |
465 if (this->getStencil().doesWrite()) { | 512 if (this->getStencil().doesWrite()) { |
466 return kEmitCoverage_BlendOptFlag; | 513 return kEmitCoverage_BlendOptFlag; |
467 } else { | 514 } else { |
468 return kSkipDraw_BlendOptFlag; | 515 return kSkipDraw_BlendOptFlag; |
469 } | 516 } |
470 } | 517 } |
471 | 518 |
472 // check for coverage due to constant coverage, per-vertex coverage, or cove
rage stage | 519 bool hasCoverage = forceCoverage || !this->hasSolidCoverage(); |
473 bool hasCoverage = forceCoverage || | |
474 0xffffffff != this->getCoverageColor() || | |
475 this->hasCoverageVertexAttribute() || | |
476 this->numCoverageStages() > 0; | |
477 | 520 |
478 // if we don't have coverage we can check whether the dst | 521 // if we don't have coverage we can check whether the dst |
479 // has to read at all. If not, we'll disable blending. | 522 // has to read at all. If not, we'll disable blending. |
480 if (!hasCoverage) { | 523 if (!hasCoverage) { |
481 if (dstCoeffIsZero) { | 524 if (dstCoeffIsZero) { |
482 if (kOne_GrBlendCoeff == *srcCoeff) { | 525 if (kOne_GrBlendCoeff == *srcCoeff) { |
483 // if there is no coverage and coeffs are (1,0) then we | 526 // if there is no coverage and coeffs are (1,0) then we |
484 // won't need to read the dst at all, it gets replaced by src | 527 // won't need to read the dst at all, it gets replaced by src |
485 *dstCoeff = kZero_GrBlendCoeff; | 528 *dstCoeff = kZero_GrBlendCoeff; |
486 return kNone_BlendOpt; | 529 return kNone_BlendOpt; |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]); | 692 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]); |
650 fDrawState->fState.fColorStages[s].localCoordChange(coordChangeMatrix); | 693 fDrawState->fState.fColorStages[s].localCoordChange(coordChangeMatrix); |
651 } | 694 } |
652 | 695 |
653 int numCoverageStages = fDrawState->numCoverageStages(); | 696 int numCoverageStages = fDrawState->numCoverageStages(); |
654 for (int s = 0; s < numCoverageStages; ++s, ++i) { | 697 for (int s = 0; s < numCoverageStages; ++s, ++i) { |
655 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]); | 698 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]); |
656 fDrawState->fState.fCoverageStages[s].localCoordChange(coordChangeMatrix
); | 699 fDrawState->fState.fCoverageStages[s].localCoordChange(coordChangeMatrix
); |
657 } | 700 } |
658 } | 701 } |
OLD | NEW |