blob: 6558b0d5facc8785587116f9c19b255b3a40fc86 [file] [log] [blame]
bsalomon@google.comaf84e742012-10-05 13:23:24 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrDrawState.h"
egdaniel3658f382014-09-15 07:01:59 -07009
egdanielb1cff032014-11-13 06:19:25 -080010#include "GrBlend.h"
egdaniel3658f382014-09-15 07:01:59 -070011#include "GrOptDrawState.h"
12#include "GrPaint.h"
egdanielb6cbc382014-11-13 11:00:34 -080013#include "GrProcOptInfo.h"
egdaniel3658f382014-09-15 07:01:59 -070014
15//////////////////////////////////////////////////////////////////////////////s
16
egdaniel89af44a2014-09-26 06:15:04 -070017bool GrDrawState::isEqual(const GrDrawState& that) const {
18 bool usingVertexColors = this->hasColorVertexAttribute();
19 if (!usingVertexColors && this->fColor != that.fColor) {
20 return false;
21 }
22
23 if (this->getRenderTarget() != that.getRenderTarget() ||
24 this->fColorStages.count() != that.fColorStages.count() ||
25 this->fCoverageStages.count() != that.fCoverageStages.count() ||
26 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
27 this->fSrcBlend != that.fSrcBlend ||
28 this->fDstBlend != that.fDstBlend ||
29 this->fBlendConstant != that.fBlendConstant ||
30 this->fFlagBits != that.fFlagBits ||
31 this->fVACount != that.fVACount ||
32 this->fVAStride != that.fVAStride ||
33 memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
34 this->fStencilSettings != that.fStencilSettings ||
35 this->fDrawFace != that.fDrawFace) {
36 return false;
37 }
38
39 bool usingVertexCoverage = this->hasCoverageVertexAttribute();
40 if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
41 return false;
42 }
43
44 bool explicitLocalCoords = this->hasLocalCoordAttribute();
45 if (this->hasGeometryProcessor()) {
46 if (!that.hasGeometryProcessor()) {
47 return false;
joshualitta5305a12014-10-10 17:47:00 -070048 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -070049 return false;
50 }
51 } else if (that.hasGeometryProcessor()) {
52 return false;
53 }
54
55 for (int i = 0; i < this->numColorStages(); i++) {
joshualitta5305a12014-10-10 17:47:00 -070056 if (!GrFragmentStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
egdaniel89af44a2014-09-26 06:15:04 -070057 explicitLocalCoords)) {
58 return false;
59 }
60 }
61 for (int i = 0; i < this->numCoverageStages(); i++) {
joshualitta5305a12014-10-10 17:47:00 -070062 if (!GrFragmentStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
egdaniel89af44a2014-09-26 06:15:04 -070063 explicitLocalCoords)) {
64 return false;
65 }
66 }
67
68 SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
69 that.fFixedFunctionVertexAttribIndices,
70 sizeof(this->fFixedFunctionVertexAttribIndices)));
71
72 return true;
73}
74
bsalomon8f727332014-08-05 07:50:06 -070075GrDrawState::CombinedState GrDrawState::CombineIfPossible(
bsalomon62c447d2014-08-08 08:08:50 -070076 const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
bsalomon8f727332014-08-05 07:50:06 -070077
egdaniel21aed572014-08-26 12:24:06 -070078 if (!a.isEqual(b)) {
bsalomon8f727332014-08-05 07:50:06 -070079 return kIncompatible_CombinedState;
80 }
81
egdaniel21aed572014-08-26 12:24:06 -070082 // If the general draw states are equal (from check above) we know hasColorVertexAttribute()
83 // is equivalent for both a and b
84 if (a.hasColorVertexAttribute()) {
bsalomon62c447d2014-08-08 08:08:50 -070085 // If one is opaque and the other is not then the combined state is not opaque. Moreover,
86 // if the opaqueness affects the ability to get color/coverage blending correct then we
87 // don't combine the draw states.
88 bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
89 bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
90 if (aIsOpaque != bIsOpaque) {
91 const GrDrawState* opaque;
92 const GrDrawState* nonOpaque;
93 if (aIsOpaque) {
94 opaque = &a;
95 nonOpaque = &b;
96 } else {
97 opaque = &b;
98 nonOpaque = &a;
99 }
100 if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
101 SkASSERT(!nonOpaque->hasSolidCoverage());
102 if (!nonOpaque->couldApplyCoverage(caps)) {
103 return kIncompatible_CombinedState;
104 }
105 }
106 return aIsOpaque ? kB_CombinedState : kA_CombinedState;
107 }
108 }
bsalomon8f727332014-08-05 07:50:06 -0700109 return kAOrB_CombinedState;
110}
111
bsalomon8f727332014-08-05 07:50:06 -0700112//////////////////////////////////////////////////////////////////////////////s
113
egdaniel69bb90c2014-11-11 07:32:45 -0800114GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
bsalomon8f727332014-08-05 07:50:06 -0700115 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
116 *this = state;
117 if (!preConcatMatrix.isIdentity()) {
egdaniel776bdbd2014-08-06 11:07:02 -0700118 for (int i = 0; i < this->numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700119 fColorStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -0700120 }
egdaniel776bdbd2014-08-06 11:07:02 -0700121 for (int i = 0; i < this->numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700122 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -0700123 }
bsalomon8f727332014-08-05 07:50:06 -0700124 }
125}
126
127GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
128 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700129 SkASSERT(!that.fRenderTarget.ownsPendingIO());
130 SkASSERT(!this->fRenderTarget.ownsPendingIO());
131 this->setRenderTarget(that.getRenderTarget());
bsalomon8f727332014-08-05 07:50:06 -0700132 fColor = that.fColor;
133 fViewMatrix = that.fViewMatrix;
egdaniel8cbf3d52014-08-21 06:27:22 -0700134 fSrcBlend = that.fSrcBlend;
135 fDstBlend = that.fDstBlend;
bsalomon8f727332014-08-05 07:50:06 -0700136 fBlendConstant = that.fBlendConstant;
137 fFlagBits = that.fFlagBits;
138 fVACount = that.fVACount;
139 fVAPtr = that.fVAPtr;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700140 fVAStride = that.fVAStride;
bsalomon8f727332014-08-05 07:50:06 -0700141 fStencilSettings = that.fStencilSettings;
142 fCoverage = that.fCoverage;
143 fDrawFace = that.fDrawFace;
joshualittbd769d02014-09-04 08:56:46 -0700144 if (that.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700145 fGeometryProcessor.initAndRef(that.fGeometryProcessor);
joshualittbd769d02014-09-04 08:56:46 -0700146 } else {
147 fGeometryProcessor.reset(NULL);
148 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700149 fColorStages = that.fColorStages;
150 fCoverageStages = that.fCoverageStages;
bsalomon8f727332014-08-05 07:50:06 -0700151
bsalomon62c447d2014-08-08 08:08:50 -0700152 fHints = that.fHints;
egdaniel776bdbd2014-08-06 11:07:02 -0700153
egdanielb6cbc382014-11-13 11:00:34 -0800154 fColorProcInfoValid = that.fColorProcInfoValid;
155 fCoverageProcInfoValid = that.fCoverageProcInfoValid;
156 if (fColorProcInfoValid) {
157 fColorProcInfo = that.fColorProcInfo;
158 }
159 if (fCoverageProcInfoValid) {
160 fCoverageProcInfo = that.fCoverageProcInfo;
161 }
162
bsalomon8f727332014-08-05 07:50:06 -0700163 memcpy(fFixedFunctionVertexAttribIndices,
164 that.fFixedFunctionVertexAttribIndices,
165 sizeof(fFixedFunctionVertexAttribIndices));
166 return *this;
167}
168
169void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
170 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700171 SkASSERT(!fRenderTarget.ownsPendingIO());
172
joshualittbd769d02014-09-04 08:56:46 -0700173 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700174 fColorStages.reset();
175 fCoverageStages.reset();
bsalomon8f727332014-08-05 07:50:06 -0700176
bsalomon2a9ca782014-09-05 14:27:43 -0700177 fRenderTarget.reset();
bsalomon8f727332014-08-05 07:50:06 -0700178
179 this->setDefaultVertexAttribs();
180
181 fColor = 0xffffffff;
182 if (NULL == initialViewMatrix) {
183 fViewMatrix.reset();
184 } else {
185 fViewMatrix = *initialViewMatrix;
186 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700187 fSrcBlend = kOne_GrBlendCoeff;
188 fDstBlend = kZero_GrBlendCoeff;
bsalomon8f727332014-08-05 07:50:06 -0700189 fBlendConstant = 0x0;
190 fFlagBits = 0x0;
191 fStencilSettings.setDisabled();
egdaniel8cbf3d52014-08-21 06:27:22 -0700192 fCoverage = 0xff;
bsalomon8f727332014-08-05 07:50:06 -0700193 fDrawFace = kBoth_DrawFace;
194
bsalomon62c447d2014-08-08 08:08:50 -0700195 fHints = 0;
egdanielb6cbc382014-11-13 11:00:34 -0800196
197 fColorProcInfoValid = false;
198 fCoverageProcInfoValid = false;
bsalomon8f727332014-08-05 07:50:06 -0700199}
200
bsalomon@google.com137f1342013-05-29 21:27:53 +0000201bool GrDrawState::setIdentityViewMatrix() {
joshualitt4dd99882014-11-11 08:51:30 -0800202 if (this->numFragmentStages()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000203 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -0700204 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000205 // sad trombone sound
206 return false;
207 }
egdaniel776bdbd2014-08-06 11:07:02 -0700208 for (int s = 0; s < this->numColorStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700209 fColorStages[s].localCoordChange(invVM);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000210 }
egdaniel776bdbd2014-08-06 11:07:02 -0700211 for (int s = 0; s < this->numCoverageStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700212 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000213 }
214 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700215 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000216 return true;
217}
218
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000219void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000220 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000221
joshualittbd769d02014-09-04 08:56:46 -0700222 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700223 fColorStages.reset();
224 fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000225
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000226 for (int i = 0; i < paint.numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700227 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000228 }
229
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000230 for (int i = 0; i < paint.numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700231 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000232 }
233
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000234 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000235
bsalomon2ed5ef82014-07-07 08:44:05 -0700236 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000237
238 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -0700239 fBlendConstant = 0x0;
240 fDrawFace = kBoth_DrawFace;
241 fStencilSettings.setDisabled();
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000242 this->resetStateFlags();
bsalomon62c447d2014-08-08 08:08:50 -0700243 fHints = 0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000244
bsalomon@google.com21c10c52013-06-13 17:44:07 +0000245 // Enable the clip bit
246 this->enableState(GrDrawState::kClip_StateBit);
247
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000248 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000249 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
250 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000251
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000252 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
joshualitt4052a8e2014-11-11 13:46:30 -0800253 this->setCoverage(0xFF);
egdanielb6cbc382014-11-13 11:00:34 -0800254 fColorProcInfoValid = false;
255 fCoverageProcInfoValid = false;
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000256}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000257
258////////////////////////////////////////////////////////////////////////////////
259
egdaniel89af44a2014-09-26 06:15:04 -0700260bool GrDrawState::validateVertexAttribs() const {
261 // check consistency of effects and attributes
262 GrSLType slTypes[kMaxVertexAttribCnt];
263 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
264 slTypes[i] = static_cast<GrSLType>(-1);
265 }
266
267 if (this->hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700268 const GrGeometryProcessor* gp = this->getGeometryProcessor();
egdaniel89af44a2014-09-26 06:15:04 -0700269 // make sure that any attribute indices have the correct binding type, that the attrib
270 // type and effect's shader lang type are compatible, and that attributes shared by
271 // multiple effects use the same shader lang type.
272 const GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
273
274 int effectIndex = 0;
275 for (int index = 0; index < fVACount; index++) {
276 if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
277 // we only care about effect bindings
278 continue;
279 }
280 SkASSERT(effectIndex < s.count());
281 GrSLType effectSLType = s[effectIndex].getType();
282 GrVertexAttribType attribType = fVAPtr[index].fType;
283 int slVecCount = GrSLTypeVectorCount(effectSLType);
284 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
285 if (slVecCount != attribVecCount ||
286 (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
287 return false;
288 }
289 slTypes[index] = effectSLType;
290 effectIndex++;
291 }
292 // Make sure all attributes are consumed and we were able to find everything
293 SkASSERT(s.count() == effectIndex);
294 }
295
296 return true;
297}
298
299////////////////////////////////////////////////////////////////////////////////
300
egdaniel7b3d5ee2014-08-28 05:41:14 -0700301static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000302 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000303#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000304 uint32_t overlapCheck = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700305 SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000306 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000307 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
egdaniel7b3d5ee2014-08-28 05:41:14 -0700308 size_t attribOffset = attribs[index].fOffset;
309 SkASSERT(attribOffset + attribSize <= stride);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000310 size_t dwordCount = attribSize >> 2;
311 uint32_t mask = (1 << dwordCount)-1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700312 size_t offsetShift = attribOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000313 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000314 overlapCheck |= (mask << offsetShift);
djsollenea81ced2014-08-27 13:07:34 -0700315 }
egdaniel7b3d5ee2014-08-28 05:41:14 -0700316#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000317}
318
319////////////////////////////////////////////////////////////////////////////////
320
egdaniel7b3d5ee2014-08-28 05:41:14 -0700321void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count,
322 size_t stride) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000323 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000324
bsalomon2ed5ef82014-07-07 08:44:05 -0700325 fVAPtr = attribs;
326 fVACount = count;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700327 fVAStride = stride;
328 validate_vertex_attribs(fVAPtr, fVACount, fVAStride);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000329
330 // Set all the indices to -1
bsalomon2ed5ef82014-07-07 08:44:05 -0700331 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000332 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700333 sizeof(fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000334#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000335 uint32_t overlapCheck = 0;
336#endif
337 for (int i = 0; i < count; ++i) {
338 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
339 // The fixed function attribs can only be specified once
bsalomon2ed5ef82014-07-07 08:44:05 -0700340 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000341 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000342 GrVertexAttribTypeVectorCount(attribs[i].fType));
bsalomon2ed5ef82014-07-07 08:44:05 -0700343 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000344 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000345#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000346 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
347 uint32_t mask = (1 << dwordCount)-1;
348 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000349 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000350 overlapCheck |= (mask << offsetShift);
351#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000352 }
egdanielb6cbc382014-11-13 11:00:34 -0800353 fColorProcInfoValid = false;
354 fCoverageProcInfoValid = false;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000355 // Positions must be specified.
bsalomon2ed5ef82014-07-07 08:44:05 -0700356 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000357}
358
359////////////////////////////////////////////////////////////////////////////////
360
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000361void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000362 static const GrVertexAttrib kPositionAttrib =
363 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000364
bsalomon2ed5ef82014-07-07 08:44:05 -0700365 fVAPtr = &kPositionAttrib;
366 fVACount = 1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700367 fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
robertphillips@google.com42903302013-04-20 12:26:07 +0000368
jvanverth@google.com054ae992013-04-01 20:06:51 +0000369 // set all the fixed function indices to -1 except position.
bsalomon2ed5ef82014-07-07 08:44:05 -0700370 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000371 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700372 sizeof(fFixedFunctionVertexAttribIndices));
373 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
egdanielb6cbc382014-11-13 11:00:34 -0800374 fColorProcInfoValid = false;
375 fCoverageProcInfoValid = false;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000376}
377
378////////////////////////////////////////////////////////////////////////////////
379
bsalomon62c447d2014-08-08 08:08:50 -0700380bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
381 if (caps.dualSourceBlendingSupport()) {
382 return true;
383 }
384 // we can correctly apply coverage if a) we have dual source blending
385 // or b) one of our blend optimizations applies
386 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
387 GrBlendCoeff srcCoeff;
388 GrBlendCoeff dstCoeff;
egdaniel170f90b2014-09-16 12:54:40 -0700389 BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
egdaniel89af44a2014-09-26 06:15:04 -0700390 return GrDrawState::kNone_BlendOpt != flag ||
bsalomon62c447d2014-08-08 08:08:50 -0700391 (this->willEffectReadDstColor() &&
392 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
393}
394
egdaniel89af44a2014-09-26 06:15:04 -0700395bool GrDrawState::hasSolidCoverage() const {
396 // If we're drawing coverage directly then coverage is effectively treated as color.
397 if (this->isCoverageDrawing()) {
398 return true;
399 }
400
joshualitt4dd99882014-11-11 08:51:30 -0800401 if (this->numCoverageStages() > 0) {
402 return false;
403 }
404
egdanielb6cbc382014-11-13 11:00:34 -0800405 this->calcCoverageInvariantOutput();
406 return fCoverageProcInfo.isSolidWhite();
egdaniel89af44a2014-09-26 06:15:04 -0700407}
408
egdaniel21aed572014-08-26 12:24:06 -0700409//////////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000410
egdaniel3658f382014-09-15 07:01:59 -0700411GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
bsalomon49f085d2014-09-05 13:34:00 -0700412 SkASSERT(drawState);
egdaniel21aed572014-08-26 12:24:06 -0700413 fDrawState = drawState;
414 fVAPtr = drawState->fVAPtr;
415 fVACount = drawState->fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700416 fVAStride = drawState->fVAStride;
egdaniel21aed572014-08-26 12:24:06 -0700417 fDrawState->setDefaultVertexAttribs();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000418}
419
egdaniel21aed572014-08-26 12:24:06 -0700420//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000421
egdaniel89af44a2014-09-26 06:15:04 -0700422bool GrDrawState::willEffectReadDstColor() const {
423 if (!this->isColorWriteDisabled()) {
egdanielb6cbc382014-11-13 11:00:34 -0800424 this->calcColorInvariantOutput();
425 if (fColorProcInfo.readsDst()) {
egdaniel89af44a2014-09-26 06:15:04 -0700426 return true;
427 }
428 }
egdanielb6cbc382014-11-13 11:00:34 -0800429 this->calcCoverageInvariantOutput();
430 return fCoverageProcInfo.readsDst();
egdaniel89af44a2014-09-26 06:15:04 -0700431}
432
egdaniel21aed572014-08-26 12:24:06 -0700433void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700434 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700435 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700436 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700437 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700438 } else {
joshualitta5305a12014-10-10 17:47:00 -0700439 SkASSERT(fDrawState->getGeometryProcessor()->getUniqueID() ==
bsalomon52e9d632014-09-05 12:23:12 -0700440 fOriginalGPID);
441 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700442 }
joshualittbd769d02014-09-04 08:56:46 -0700443
egdaniel21aed572014-08-26 12:24:06 -0700444 int m = fDrawState->numColorStages() - fColorEffectCnt;
445 SkASSERT(m >= 0);
446 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000447
egdaniel21aed572014-08-26 12:24:06 -0700448 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
449 SkASSERT(n >= 0);
450 fDrawState->fCoverageStages.pop_back_n(n);
egdanielb6cbc382014-11-13 11:00:34 -0800451 if (m + n > 0) {
452 fDrawState->fColorProcInfoValid = false;
453 fDrawState->fCoverageProcInfoValid = false;
454 }
egdaniel21aed572014-08-26 12:24:06 -0700455 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000456 }
egdaniel21aed572014-08-26 12:24:06 -0700457 fDrawState = ds;
458 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700459 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700460 if (NULL != ds->getGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700461 fOriginalGPID = ds->getGeometryProcessor()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700462 }
egdaniel21aed572014-08-26 12:24:06 -0700463 fColorEffectCnt = ds->numColorStages();
464 fCoverageEffectCnt = ds->numCoverageStages();
465 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
466 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000467}
468
jvanverth@google.comcc782382013-01-28 20:39:48 +0000469////////////////////////////////////////////////////////////////////////////////
470
egdaniel89af44a2014-09-26 06:15:04 -0700471// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
472// others will blend incorrectly.
473bool GrDrawState::canTweakAlphaForCoverage() const {
474 /*
475 The fractional coverage is f.
476 The src and dst coeffs are Cs and Cd.
477 The dst and src colors are S and D.
478 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
479 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
480 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
481 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
482 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
483 color by definition.
484 */
485 return kOne_GrBlendCoeff == fDstBlend ||
486 kISA_GrBlendCoeff == fDstBlend ||
487 kISC_GrBlendCoeff == fDstBlend ||
488 this->isCoverageDrawing();
489}
490
491////////////////////////////////////////////////////////////////////////////////
492
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000493void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700494 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000495 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700496 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000497 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000498 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000499 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000500
501 int i = 0;
502 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700503 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000504 }
505 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700506 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000507 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000508 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000509 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000510}
511
512void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000513 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000514 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000515
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000516 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000517 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000518 return;
519 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000520 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000521
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000522 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700523 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000524
525 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000526 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000527}
528
bsalomon@google.com137f1342013-05-29 21:27:53 +0000529bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000530 this->restore();
531
bsalomon@google.com137f1342013-05-29 21:27:53 +0000532 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000533 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000534 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000535
bsalomon@google.com137f1342013-05-29 21:27:53 +0000536 if (drawState->getViewMatrix().isIdentity()) {
537 return true;
538 }
539
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000540 fViewMatrix = drawState->getViewMatrix();
joshualitt4dd99882014-11-11 08:51:30 -0800541 if (0 == drawState->numFragmentStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700542 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000543 fDrawState = drawState;
544 fNumColorStages = 0;
545 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000546 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000547 return true;
548 } else {
549 SkMatrix inv;
550 if (!fViewMatrix.invert(&inv)) {
551 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000552 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700553 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000554 fDrawState = drawState;
555 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000556 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000557 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000558 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000559}
560
561void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
joshualitt4dd99882014-11-11 08:51:30 -0800562 fSavedCoordChanges.reset(fDrawState->numFragmentStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000563 int i = 0;
564
565 fNumColorStages = fDrawState->numColorStages();
566 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700567 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700568 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000569 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000570
571 int numCoverageStages = fDrawState->numCoverageStages();
572 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700573 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700574 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000575 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000576}
egdaniel21aed572014-08-26 12:24:06 -0700577
egdaniel170f90b2014-09-16 12:54:40 -0700578////////////////////////////////////////////////////////////////////////////////
579
egdaniel89af44a2014-09-26 06:15:04 -0700580void GrDrawState::convertToPendingExec() {
581 fRenderTarget.markPendingIO();
582 fRenderTarget.removeRef();
583 for (int i = 0; i < fColorStages.count(); ++i) {
584 fColorStages[i].convertToPendingExec();
585 }
586 if (fGeometryProcessor) {
joshualitta5305a12014-10-10 17:47:00 -0700587 fGeometryProcessor.convertToPendingExec();
egdaniel89af44a2014-09-26 06:15:04 -0700588 }
589 for (int i = 0; i < fCoverageStages.count(); ++i) {
590 fCoverageStages[i].convertToPendingExec();
591 }
592}
593
594////////////////////////////////////////////////////////////////////////////////
595
egdaniel170f90b2014-09-16 12:54:40 -0700596GrDrawState::~GrDrawState() {
egdaniel170f90b2014-09-16 12:54:40 -0700597 SkASSERT(0 == fBlockEffectRemovalCnt);
598}
599
egdaniel89af44a2014-09-26 06:15:04 -0700600////////////////////////////////////////////////////////////////////////////////
601
602GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
joshualitt65171342014-10-09 07:25:36 -0700603 GrBlendCoeff* srcCoeff,
604 GrBlendCoeff* dstCoeff) const {
egdaniel89af44a2014-09-26 06:15:04 -0700605 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
606 if (NULL == srcCoeff) {
607 srcCoeff = &bogusSrcCoeff;
608 }
609 if (NULL == dstCoeff) {
610 dstCoeff = &bogusDstCoeff;
611 }
612
613 *srcCoeff = this->getSrcBlendCoeff();
614 *dstCoeff = this->getDstBlendCoeff();
615
616 if (this->isColorWriteDisabled()) {
617 *srcCoeff = kZero_GrBlendCoeff;
618 *dstCoeff = kOne_GrBlendCoeff;
619 }
620
621 bool srcAIsOne = this->srcAlphaWillBeOne();
622 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
623 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
624 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
625 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
626
627 // When coeffs are (0,1) there is no reason to draw at all, unless
628 // stenciling is enabled. Having color writes disabled is effectively
629 // (0,1).
630 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
631 if (this->getStencil().doesWrite()) {
632 return kEmitCoverage_BlendOptFlag;
633 } else {
634 *dstCoeff = kOne_GrBlendCoeff;
635 return kSkipDraw_BlendOptFlag;
636 }
637 }
638
639 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
640
641 // if we don't have coverage we can check whether the dst
642 // has to read at all. If not, we'll disable blending.
643 if (!hasCoverage) {
644 if (dstCoeffIsZero) {
645 if (kOne_GrBlendCoeff == *srcCoeff) {
646 // if there is no coverage and coeffs are (1,0) then we
647 // won't need to read the dst at all, it gets replaced by src
648 *dstCoeff = kZero_GrBlendCoeff;
649 return kNone_BlendOpt;
650 } else if (kZero_GrBlendCoeff == *srcCoeff) {
651 // if the op is "clear" then we don't need to emit a color
652 // or blend, just write transparent black into the dst.
653 *srcCoeff = kOne_GrBlendCoeff;
654 *dstCoeff = kZero_GrBlendCoeff;
655 return kEmitTransBlack_BlendOptFlag;
656 }
657 }
658 } else if (this->isCoverageDrawing()) {
659 // we have coverage but we aren't distinguishing it from alpha by request.
660 return kCoverageAsAlpha_BlendOptFlag;
661 } else {
662 // check whether coverage can be safely rolled into alpha
663 // of if we can skip color computation and just emit coverage
664 if (this->canTweakAlphaForCoverage()) {
665 return kCoverageAsAlpha_BlendOptFlag;
666 }
667 if (dstCoeffIsZero) {
668 if (kZero_GrBlendCoeff == *srcCoeff) {
669 // the source color is not included in the blend
670 // the dst coeff is effectively zero so blend works out to:
671 // (c)(0)D + (1-c)D = (1-c)D.
672 *dstCoeff = kISA_GrBlendCoeff;
673 return kEmitCoverage_BlendOptFlag;
674 } else if (srcAIsOne) {
675 // the dst coeff is effectively zero so blend works out to:
676 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
677 // If Sa is 1 then we can replace Sa with c
678 // and set dst coeff to 1-Sa.
679 *dstCoeff = kISA_GrBlendCoeff;
680 return kCoverageAsAlpha_BlendOptFlag;
681 }
682 } else if (dstCoeffIsOne) {
683 // the dst coeff is effectively one so blend works out to:
684 // cS + (c)(1)D + (1-c)D = cS + D.
685 *dstCoeff = kOne_GrBlendCoeff;
686 return kCoverageAsAlpha_BlendOptFlag;
687 }
688 }
689
690 return kNone_BlendOpt;
691}
692
egdaniel89af44a2014-09-26 06:15:04 -0700693bool GrDrawState::srcAlphaWillBeOne() const {
egdanielb6cbc382014-11-13 11:00:34 -0800694 this->calcColorInvariantOutput();
egdaniel89af44a2014-09-26 06:15:04 -0700695 if (this->isCoverageDrawing()) {
egdanielb6cbc382014-11-13 11:00:34 -0800696 this->calcCoverageInvariantOutput();
697 return (fColorProcInfo.isOpaque() && fCoverageProcInfo.isOpaque());
egdaniel89af44a2014-09-26 06:15:04 -0700698 }
egdanielb6cbc382014-11-13 11:00:34 -0800699 return fColorProcInfo.isOpaque();
egdaniel89af44a2014-09-26 06:15:04 -0700700}
701
egdanielcd8b6302014-11-11 14:46:05 -0800702bool GrDrawState::willBlendWithDst() const {
703 if (!this->hasSolidCoverage()) {
704 return true;
705 }
706
egdanielb1cff032014-11-13 06:19:25 -0800707 if (this->willEffectReadDstColor()) {
708 return true;
egdanielcd8b6302014-11-11 14:46:05 -0800709 }
egdanielb1cff032014-11-13 06:19:25 -0800710
711 if (GrBlendCoeffRefsDst(this->getSrcBlendCoeff())) {
712 return true;
713 }
714
715 GrBlendCoeff dstCoeff = this->getDstBlendCoeff();
716 if (!(kZero_GrBlendCoeff == dstCoeff ||
717 (kISA_GrBlendCoeff == dstCoeff && this->srcAlphaWillBeOne()))) {
egdanielcd8b6302014-11-11 14:46:05 -0800718 return true;
719 }
720
721 return false;
722}
723
egdanielb6cbc382014-11-13 11:00:34 -0800724void GrDrawState::calcColorInvariantOutput() const {
725 if (!fColorProcInfoValid) {
726 GrColor color;
727 GrColorComponentFlags flags;
728 if (this->hasColorVertexAttribute()) {
729 if (fHints & kVertexColorsAreOpaque_Hint) {
730 flags = kA_GrColorComponentFlag;
731 color = 0xFF << GrColor_SHIFT_A;
732 } else {
733 flags = static_cast<GrColorComponentFlags>(0);
734 color = 0;
735 }
736 } else {
737 flags = kRGBA_GrColorComponentFlags;
738 color = this->getColor();
739 }
740 fColorProcInfo.calcWithInitialValues(fColorStages.begin(), this->numColorStages(),
741 color, flags, false);
742 fColorProcInfoValid = true;
743 }
744}
745
746void GrDrawState::calcCoverageInvariantOutput() const {
747 if (!fCoverageProcInfoValid) {
748 GrColor color;
749 GrColorComponentFlags flags;
750 // Check if per-vertex or constant color may have partial alpha
751 if (this->hasCoverageVertexAttribute()) {
752 flags = static_cast<GrColorComponentFlags>(0);
753 color = 0;
754 } else {
755 flags = kRGBA_GrColorComponentFlags;
756 color = this->getCoverageColor();
757 }
758 fCoverageProcInfo.calcWithInitialValues(fCoverageStages.begin(), this->numCoverageStages(),
759 color, flags, true, fGeometryProcessor.get());
760 fCoverageProcInfoValid = true;
761 }
762}
763