blob: 5e177b8b128b2220d701bbf8ce068ce6dd2f9786 [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
egdaniel3658f382014-09-15 07:01:59 -070010#include "GrOptDrawState.h"
11#include "GrPaint.h"
12
13//////////////////////////////////////////////////////////////////////////////s
14
egdaniel89af44a2014-09-26 06:15:04 -070015bool GrDrawState::isEqual(const GrDrawState& that) const {
16 bool usingVertexColors = this->hasColorVertexAttribute();
17 if (!usingVertexColors && this->fColor != that.fColor) {
18 return false;
19 }
20
21 if (this->getRenderTarget() != that.getRenderTarget() ||
22 this->fColorStages.count() != that.fColorStages.count() ||
23 this->fCoverageStages.count() != that.fCoverageStages.count() ||
24 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
25 this->fSrcBlend != that.fSrcBlend ||
26 this->fDstBlend != that.fDstBlend ||
27 this->fBlendConstant != that.fBlendConstant ||
28 this->fFlagBits != that.fFlagBits ||
29 this->fVACount != that.fVACount ||
30 this->fVAStride != that.fVAStride ||
31 memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
32 this->fStencilSettings != that.fStencilSettings ||
33 this->fDrawFace != that.fDrawFace) {
34 return false;
35 }
36
37 bool usingVertexCoverage = this->hasCoverageVertexAttribute();
38 if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
39 return false;
40 }
41
42 bool explicitLocalCoords = this->hasLocalCoordAttribute();
43 if (this->hasGeometryProcessor()) {
44 if (!that.hasGeometryProcessor()) {
45 return false;
46 } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
47 *that.getGeometryProcessor(),
48 explicitLocalCoords)) {
49 return false;
50 }
51 } else if (that.hasGeometryProcessor()) {
52 return false;
53 }
54
55 for (int i = 0; i < this->numColorStages(); i++) {
56 if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
57 explicitLocalCoords)) {
58 return false;
59 }
60 }
61 for (int i = 0; i < this->numCoverageStages(); i++) {
62 if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
63 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
egdaniel3658f382014-09-15 07:01:59 -0700114GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix)
115 : fCachedOptState(NULL) {
bsalomon8f727332014-08-05 07:50:06 -0700116 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
117 *this = state;
118 if (!preConcatMatrix.isIdentity()) {
joshualittbd769d02014-09-04 08:56:46 -0700119 if (this->hasGeometryProcessor()) {
120 fGeometryProcessor->localCoordChange(preConcatMatrix);
121 }
egdaniel776bdbd2014-08-06 11:07:02 -0700122 for (int i = 0; i < this->numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700123 fColorStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -0700124 }
egdaniel776bdbd2014-08-06 11:07:02 -0700125 for (int i = 0; i < this->numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700126 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -0700127 }
egdaniel3658f382014-09-15 07:01:59 -0700128 this->invalidateOptState();
bsalomon8f727332014-08-05 07:50:06 -0700129 }
130}
131
132GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
133 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700134 SkASSERT(!that.fRenderTarget.ownsPendingIO());
135 SkASSERT(!this->fRenderTarget.ownsPendingIO());
136 this->setRenderTarget(that.getRenderTarget());
bsalomon8f727332014-08-05 07:50:06 -0700137 fColor = that.fColor;
138 fViewMatrix = that.fViewMatrix;
egdaniel8cbf3d52014-08-21 06:27:22 -0700139 fSrcBlend = that.fSrcBlend;
140 fDstBlend = that.fDstBlend;
bsalomon8f727332014-08-05 07:50:06 -0700141 fBlendConstant = that.fBlendConstant;
142 fFlagBits = that.fFlagBits;
143 fVACount = that.fVACount;
144 fVAPtr = that.fVAPtr;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700145 fVAStride = that.fVAStride;
bsalomon8f727332014-08-05 07:50:06 -0700146 fStencilSettings = that.fStencilSettings;
147 fCoverage = that.fCoverage;
148 fDrawFace = that.fDrawFace;
joshualittbd769d02014-09-04 08:56:46 -0700149 if (that.hasGeometryProcessor()) {
joshualittb0a8a372014-09-23 09:50:21 -0700150 fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*that.fGeometryProcessor.get())));
joshualittbd769d02014-09-04 08:56:46 -0700151 } else {
152 fGeometryProcessor.reset(NULL);
153 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700154 fColorStages = that.fColorStages;
155 fCoverageStages = that.fCoverageStages;
bsalomon8f727332014-08-05 07:50:06 -0700156
bsalomon62c447d2014-08-08 08:08:50 -0700157 fHints = that.fHints;
egdaniel776bdbd2014-08-06 11:07:02 -0700158
egdaniel3658f382014-09-15 07:01:59 -0700159 SkRefCnt_SafeAssign(fCachedOptState, that.fCachedOptState);
160
bsalomon8f727332014-08-05 07:50:06 -0700161 memcpy(fFixedFunctionVertexAttribIndices,
162 that.fFixedFunctionVertexAttribIndices,
163 sizeof(fFixedFunctionVertexAttribIndices));
164 return *this;
165}
166
167void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
168 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700169 SkASSERT(!fRenderTarget.ownsPendingIO());
170
joshualittbd769d02014-09-04 08:56:46 -0700171 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700172 fColorStages.reset();
173 fCoverageStages.reset();
bsalomon8f727332014-08-05 07:50:06 -0700174
bsalomon2a9ca782014-09-05 14:27:43 -0700175 fRenderTarget.reset();
bsalomon8f727332014-08-05 07:50:06 -0700176
177 this->setDefaultVertexAttribs();
178
179 fColor = 0xffffffff;
180 if (NULL == initialViewMatrix) {
181 fViewMatrix.reset();
182 } else {
183 fViewMatrix = *initialViewMatrix;
184 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700185 fSrcBlend = kOne_GrBlendCoeff;
186 fDstBlend = kZero_GrBlendCoeff;
bsalomon8f727332014-08-05 07:50:06 -0700187 fBlendConstant = 0x0;
188 fFlagBits = 0x0;
189 fStencilSettings.setDisabled();
egdaniel8cbf3d52014-08-21 06:27:22 -0700190 fCoverage = 0xff;
bsalomon8f727332014-08-05 07:50:06 -0700191 fDrawFace = kBoth_DrawFace;
192
bsalomon62c447d2014-08-08 08:08:50 -0700193 fHints = 0;
194
egdaniel3658f382014-09-15 07:01:59 -0700195 this->invalidateOptState();
bsalomon8f727332014-08-05 07:50:06 -0700196}
197
bsalomon@google.com137f1342013-05-29 21:27:53 +0000198bool GrDrawState::setIdentityViewMatrix() {
egdaniel776bdbd2014-08-06 11:07:02 -0700199 if (this->numTotalStages()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000200 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -0700201 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000202 // sad trombone sound
203 return false;
204 }
joshualittbd769d02014-09-04 08:56:46 -0700205 if (this->hasGeometryProcessor()) {
206 fGeometryProcessor->localCoordChange(invVM);
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 }
egdaniel3658f382014-09-15 07:01:59 -0700215 this->invalidateOptState();
bsalomon2ed5ef82014-07-07 08:44:05 -0700216 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000217 return true;
218}
219
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000220void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000221 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000222
joshualittbd769d02014-09-04 08:56:46 -0700223 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700224 fColorStages.reset();
225 fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000226
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000227 for (int i = 0; i < paint.numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700228 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000229 }
230
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000231 for (int i = 0; i < paint.numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700232 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000233 }
234
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000235 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000236
bsalomon2ed5ef82014-07-07 08:44:05 -0700237 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000238
239 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -0700240 fBlendConstant = 0x0;
241 fDrawFace = kBoth_DrawFace;
242 fStencilSettings.setDisabled();
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000243 this->resetStateFlags();
bsalomon62c447d2014-08-08 08:08:50 -0700244 fHints = 0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000245
bsalomon@google.com21c10c52013-06-13 17:44:07 +0000246 // Enable the clip bit
247 this->enableState(GrDrawState::kClip_StateBit);
248
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000249 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000250 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
251 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000252
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000253 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000254 this->setCoverage(paint.getCoverage());
egdaniel3658f382014-09-15 07:01:59 -0700255 this->invalidateOptState();
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()) {
268 const GrGeometryStage& stage = *this->getGeometryProcessor();
joshualitt47bb3822014-10-07 16:43:25 -0700269 const GrGeometryProcessor* gp = stage.getProcessor();
egdaniel89af44a2014-09-26 06:15:04 -0700270 SkASSERT(gp);
271 // make sure that any attribute indices have the correct binding type, that the attrib
272 // type and effect's shader lang type are compatible, and that attributes shared by
273 // multiple effects use the same shader lang type.
274 const GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
275
276 int effectIndex = 0;
277 for (int index = 0; index < fVACount; index++) {
278 if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
279 // we only care about effect bindings
280 continue;
281 }
282 SkASSERT(effectIndex < s.count());
283 GrSLType effectSLType = s[effectIndex].getType();
284 GrVertexAttribType attribType = fVAPtr[index].fType;
285 int slVecCount = GrSLTypeVectorCount(effectSLType);
286 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
287 if (slVecCount != attribVecCount ||
288 (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
289 return false;
290 }
291 slTypes[index] = effectSLType;
292 effectIndex++;
293 }
294 // Make sure all attributes are consumed and we were able to find everything
295 SkASSERT(s.count() == effectIndex);
296 }
297
298 return true;
299}
300
301////////////////////////////////////////////////////////////////////////////////
302
egdaniel7b3d5ee2014-08-28 05:41:14 -0700303static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000304 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000305#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000306 uint32_t overlapCheck = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700307 SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000308 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000309 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
egdaniel7b3d5ee2014-08-28 05:41:14 -0700310 size_t attribOffset = attribs[index].fOffset;
311 SkASSERT(attribOffset + attribSize <= stride);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000312 size_t dwordCount = attribSize >> 2;
313 uint32_t mask = (1 << dwordCount)-1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700314 size_t offsetShift = attribOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000315 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000316 overlapCheck |= (mask << offsetShift);
djsollenea81ced2014-08-27 13:07:34 -0700317 }
egdaniel7b3d5ee2014-08-28 05:41:14 -0700318#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000319}
320
321////////////////////////////////////////////////////////////////////////////////
322
egdaniel7b3d5ee2014-08-28 05:41:14 -0700323void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count,
324 size_t stride) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000325 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000326
bsalomon2ed5ef82014-07-07 08:44:05 -0700327 fVAPtr = attribs;
328 fVACount = count;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700329 fVAStride = stride;
330 validate_vertex_attribs(fVAPtr, fVACount, fVAStride);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000331
332 // Set all the indices to -1
bsalomon2ed5ef82014-07-07 08:44:05 -0700333 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000334 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700335 sizeof(fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000336#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000337 uint32_t overlapCheck = 0;
338#endif
339 for (int i = 0; i < count; ++i) {
340 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
341 // The fixed function attribs can only be specified once
bsalomon2ed5ef82014-07-07 08:44:05 -0700342 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000343 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000344 GrVertexAttribTypeVectorCount(attribs[i].fType));
bsalomon2ed5ef82014-07-07 08:44:05 -0700345 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000346 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000347#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000348 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
349 uint32_t mask = (1 << dwordCount)-1;
350 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000351 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000352 overlapCheck |= (mask << offsetShift);
353#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000354 }
egdaniel3658f382014-09-15 07:01:59 -0700355 this->invalidateOptState();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000356 // Positions must be specified.
bsalomon2ed5ef82014-07-07 08:44:05 -0700357 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000358}
359
360////////////////////////////////////////////////////////////////////////////////
361
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000362void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000363 static const GrVertexAttrib kPositionAttrib =
364 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000365
bsalomon2ed5ef82014-07-07 08:44:05 -0700366 fVAPtr = &kPositionAttrib;
367 fVACount = 1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700368 fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
robertphillips@google.com42903302013-04-20 12:26:07 +0000369
jvanverth@google.com054ae992013-04-01 20:06:51 +0000370 // set all the fixed function indices to -1 except position.
bsalomon2ed5ef82014-07-07 08:44:05 -0700371 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000372 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700373 sizeof(fFixedFunctionVertexAttribIndices));
374 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
egdaniel3658f382014-09-15 07:01:59 -0700375 this->invalidateOptState();
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
egdaniel1a8ecdf2014-10-03 06:24:12 -0700401 GrProcessor::InvariantOutput inout;
402 inout.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700403 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
404 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700405 inout.fValidFlags = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700406 } else {
joshualitt65171342014-10-09 07:25:36 -0700407 inout.fColor = this->getCoverageColor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700408 inout.fValidFlags = kRGBA_GrColorComponentFlags;
egdaniel89af44a2014-09-26 06:15:04 -0700409 }
410
411 // Run through the coverage stages and see if the coverage will be all ones at the end.
412 if (this->hasGeometryProcessor()) {
joshualitt47bb3822014-10-07 16:43:25 -0700413 const GrGeometryProcessor* gp = fGeometryProcessor->getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700414 gp->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700415 }
joshualitt65171342014-10-09 07:25:36 -0700416
egdaniel89af44a2014-09-26 06:15:04 -0700417 for (int s = 0; s < this->numCoverageStages(); ++s) {
418 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700419 processor->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700420 }
egdaniel1a8ecdf2014-10-03 06:24:12 -0700421 return inout.isSolidWhite();
egdaniel89af44a2014-09-26 06:15:04 -0700422}
423
egdaniel21aed572014-08-26 12:24:06 -0700424//////////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000425
egdaniel3658f382014-09-15 07:01:59 -0700426GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
bsalomon49f085d2014-09-05 13:34:00 -0700427 SkASSERT(drawState);
egdaniel21aed572014-08-26 12:24:06 -0700428 fDrawState = drawState;
429 fVAPtr = drawState->fVAPtr;
430 fVACount = drawState->fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700431 fVAStride = drawState->fVAStride;
egdaniel21aed572014-08-26 12:24:06 -0700432 fDrawState->setDefaultVertexAttribs();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000433}
434
egdaniel21aed572014-08-26 12:24:06 -0700435//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000436
egdaniel89af44a2014-09-26 06:15:04 -0700437bool GrDrawState::willEffectReadDstColor() const {
438 if (!this->isColorWriteDisabled()) {
439 for (int s = 0; s < this->numColorStages(); ++s) {
joshualitt47bb3822014-10-07 16:43:25 -0700440 if (this->getColorStage(s).getProcessor()->willReadDstColor()) {
egdaniel89af44a2014-09-26 06:15:04 -0700441 return true;
442 }
443 }
444 }
445 for (int s = 0; s < this->numCoverageStages(); ++s) {
joshualitt47bb3822014-10-07 16:43:25 -0700446 if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) {
egdaniel89af44a2014-09-26 06:15:04 -0700447 return true;
448 }
449 }
450 return false;
451}
452
egdaniel21aed572014-08-26 12:24:06 -0700453void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700454 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700455 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700456 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700457 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700458 } else {
joshualittb0a8a372014-09-23 09:50:21 -0700459 SkASSERT(fDrawState->getGeometryProcessor()->getProcessor()->getUniqueID() ==
bsalomon52e9d632014-09-05 12:23:12 -0700460 fOriginalGPID);
461 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700462 }
joshualittbd769d02014-09-04 08:56:46 -0700463
egdaniel21aed572014-08-26 12:24:06 -0700464 int m = fDrawState->numColorStages() - fColorEffectCnt;
465 SkASSERT(m >= 0);
466 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000467
egdaniel21aed572014-08-26 12:24:06 -0700468 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
469 SkASSERT(n >= 0);
470 fDrawState->fCoverageStages.pop_back_n(n);
471 if (m + n > 0) {
egdaniel3658f382014-09-15 07:01:59 -0700472 fDrawState->invalidateOptState();
egdaniel21aed572014-08-26 12:24:06 -0700473 }
474 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000475 }
egdaniel21aed572014-08-26 12:24:06 -0700476 fDrawState = ds;
477 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700478 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700479 if (NULL != ds->getGeometryProcessor()) {
joshualittb0a8a372014-09-23 09:50:21 -0700480 fOriginalGPID = ds->getGeometryProcessor()->getProcessor()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700481 }
egdaniel21aed572014-08-26 12:24:06 -0700482 fColorEffectCnt = ds->numColorStages();
483 fCoverageEffectCnt = ds->numCoverageStages();
484 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
485 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000486}
487
jvanverth@google.comcc782382013-01-28 20:39:48 +0000488////////////////////////////////////////////////////////////////////////////////
489
egdaniel89af44a2014-09-26 06:15:04 -0700490// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
491// others will blend incorrectly.
492bool GrDrawState::canTweakAlphaForCoverage() const {
493 /*
494 The fractional coverage is f.
495 The src and dst coeffs are Cs and Cd.
496 The dst and src colors are S and D.
497 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
498 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
499 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
500 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
501 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
502 color by definition.
503 */
504 return kOne_GrBlendCoeff == fDstBlend ||
505 kISA_GrBlendCoeff == fDstBlend ||
506 kISC_GrBlendCoeff == fDstBlend ||
507 this->isCoverageDrawing();
508}
509
510////////////////////////////////////////////////////////////////////////////////
511
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000512void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700513 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000514 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700515 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000516 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000517 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000518 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000519
520 int i = 0;
joshualittbd769d02014-09-04 08:56:46 -0700521 if (fHasGeometryProcessor) {
522 SkASSERT(fDrawState->hasGeometryProcessor());
523 fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]);
524 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000525 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700526 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000527 }
528 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700529 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000530 }
egdaniel3658f382014-09-15 07:01:59 -0700531 fDrawState->invalidateOptState();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000532 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000533 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000534}
535
536void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000537 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000538 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000539
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000540 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000541 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000542 return;
543 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000544 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000545
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000546 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700547 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000548
549 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000550 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
egdaniel3658f382014-09-15 07:01:59 -0700551 drawState->invalidateOptState();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000552}
553
bsalomon@google.com137f1342013-05-29 21:27:53 +0000554bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000555 this->restore();
556
bsalomon@google.com137f1342013-05-29 21:27:53 +0000557 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000558 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000559 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000560
bsalomon@google.com137f1342013-05-29 21:27:53 +0000561 if (drawState->getViewMatrix().isIdentity()) {
562 return true;
563 }
564
egdaniel3658f382014-09-15 07:01:59 -0700565 drawState->invalidateOptState();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000566 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000567 if (0 == drawState->numTotalStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700568 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000569 fDrawState = drawState;
joshualittbd769d02014-09-04 08:56:46 -0700570 fHasGeometryProcessor = false;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000571 fNumColorStages = 0;
572 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000573 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000574 return true;
575 } else {
576 SkMatrix inv;
577 if (!fViewMatrix.invert(&inv)) {
578 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000579 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700580 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000581 fDrawState = drawState;
582 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000583 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000584 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000585 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000586}
587
588void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
589 fSavedCoordChanges.reset(fDrawState->numTotalStages());
590 int i = 0;
591
joshualittbd769d02014-09-04 08:56:46 -0700592 fHasGeometryProcessor = false;
593 if (fDrawState->hasGeometryProcessor()) {
594 fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]);
595 fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix);
596 fHasGeometryProcessor = true;
597 }
598
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000599 fNumColorStages = fDrawState->numColorStages();
600 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700601 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700602 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000603 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000604
605 int numCoverageStages = fDrawState->numCoverageStages();
606 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700607 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700608 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000609 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000610}
egdaniel21aed572014-08-26 12:24:06 -0700611
egdaniel170f90b2014-09-16 12:54:40 -0700612////////////////////////////////////////////////////////////////////////////////
613
egdaniel89af44a2014-09-26 06:15:04 -0700614void GrDrawState::convertToPendingExec() {
615 fRenderTarget.markPendingIO();
616 fRenderTarget.removeRef();
617 for (int i = 0; i < fColorStages.count(); ++i) {
618 fColorStages[i].convertToPendingExec();
619 }
620 if (fGeometryProcessor) {
621 fGeometryProcessor->convertToPendingExec();
622 }
623 for (int i = 0; i < fCoverageStages.count(); ++i) {
624 fCoverageStages[i].convertToPendingExec();
625 }
626}
627
628////////////////////////////////////////////////////////////////////////////////
629
egdaniel170f90b2014-09-16 12:54:40 -0700630void GrDrawState::invalidateOptState() const {
631 SkSafeSetNull(fCachedOptState);
632}
633
634////////////////////////////////////////////////////////////////////////////////
635
636GrDrawState::~GrDrawState() {
637 SkSafeUnref(fCachedOptState);
638 SkASSERT(0 == fBlockEffectRemovalCnt);
639}
640
egdaniel89af44a2014-09-26 06:15:04 -0700641////////////////////////////////////////////////////////////////////////////////
642
643GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
joshualitt65171342014-10-09 07:25:36 -0700644 GrBlendCoeff* srcCoeff,
645 GrBlendCoeff* dstCoeff) const {
egdaniel89af44a2014-09-26 06:15:04 -0700646 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
647 if (NULL == srcCoeff) {
648 srcCoeff = &bogusSrcCoeff;
649 }
650 if (NULL == dstCoeff) {
651 dstCoeff = &bogusDstCoeff;
652 }
653
654 *srcCoeff = this->getSrcBlendCoeff();
655 *dstCoeff = this->getDstBlendCoeff();
656
657 if (this->isColorWriteDisabled()) {
658 *srcCoeff = kZero_GrBlendCoeff;
659 *dstCoeff = kOne_GrBlendCoeff;
660 }
661
662 bool srcAIsOne = this->srcAlphaWillBeOne();
663 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
664 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
665 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
666 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
667
668 // When coeffs are (0,1) there is no reason to draw at all, unless
669 // stenciling is enabled. Having color writes disabled is effectively
670 // (0,1).
671 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
672 if (this->getStencil().doesWrite()) {
673 return kEmitCoverage_BlendOptFlag;
674 } else {
675 *dstCoeff = kOne_GrBlendCoeff;
676 return kSkipDraw_BlendOptFlag;
677 }
678 }
679
680 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
681
682 // if we don't have coverage we can check whether the dst
683 // has to read at all. If not, we'll disable blending.
684 if (!hasCoverage) {
685 if (dstCoeffIsZero) {
686 if (kOne_GrBlendCoeff == *srcCoeff) {
687 // if there is no coverage and coeffs are (1,0) then we
688 // won't need to read the dst at all, it gets replaced by src
689 *dstCoeff = kZero_GrBlendCoeff;
690 return kNone_BlendOpt;
691 } else if (kZero_GrBlendCoeff == *srcCoeff) {
692 // if the op is "clear" then we don't need to emit a color
693 // or blend, just write transparent black into the dst.
694 *srcCoeff = kOne_GrBlendCoeff;
695 *dstCoeff = kZero_GrBlendCoeff;
696 return kEmitTransBlack_BlendOptFlag;
697 }
698 }
699 } else if (this->isCoverageDrawing()) {
700 // we have coverage but we aren't distinguishing it from alpha by request.
701 return kCoverageAsAlpha_BlendOptFlag;
702 } else {
703 // check whether coverage can be safely rolled into alpha
704 // of if we can skip color computation and just emit coverage
705 if (this->canTweakAlphaForCoverage()) {
706 return kCoverageAsAlpha_BlendOptFlag;
707 }
708 if (dstCoeffIsZero) {
709 if (kZero_GrBlendCoeff == *srcCoeff) {
710 // the source color is not included in the blend
711 // the dst coeff is effectively zero so blend works out to:
712 // (c)(0)D + (1-c)D = (1-c)D.
713 *dstCoeff = kISA_GrBlendCoeff;
714 return kEmitCoverage_BlendOptFlag;
715 } else if (srcAIsOne) {
716 // the dst coeff is effectively zero so blend works out to:
717 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
718 // If Sa is 1 then we can replace Sa with c
719 // and set dst coeff to 1-Sa.
720 *dstCoeff = kISA_GrBlendCoeff;
721 return kCoverageAsAlpha_BlendOptFlag;
722 }
723 } else if (dstCoeffIsOne) {
724 // the dst coeff is effectively one so blend works out to:
725 // cS + (c)(1)D + (1-c)D = cS + D.
726 *dstCoeff = kOne_GrBlendCoeff;
727 return kCoverageAsAlpha_BlendOptFlag;
728 }
729 }
730
731 return kNone_BlendOpt;
732}
733
734
735bool GrDrawState::srcAlphaWillBeOne() const {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700736 GrProcessor::InvariantOutput inoutColor;
737 inoutColor.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700738 // Check if per-vertex or constant color may have partial alpha
739 if (this->hasColorVertexAttribute()) {
740 if (fHints & kVertexColorsAreOpaque_Hint) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700741 inoutColor.fValidFlags = kA_GrColorComponentFlag;
742 inoutColor.fColor = 0xFF << GrColor_SHIFT_A;
egdaniel89af44a2014-09-26 06:15:04 -0700743 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700744 inoutColor.fValidFlags = 0;
745 // not strictly necessary but we get false alarms from tools about uninit.
746 inoutColor.fColor = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700747 }
748 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700749 inoutColor.fValidFlags = kRGBA_GrColorComponentFlags;
750 inoutColor.fColor = this->getColor();
egdaniel89af44a2014-09-26 06:15:04 -0700751 }
752
753 // Run through the color stages
754 for (int s = 0; s < this->numColorStages(); ++s) {
755 const GrProcessor* processor = this->getColorStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700756 processor->computeInvariantOutput(&inoutColor);
egdaniel89af44a2014-09-26 06:15:04 -0700757 }
758
759 // Check whether coverage is treated as color. If so we run through the coverage computation.
760 if (this->isCoverageDrawing()) {
761 // The shader generated for coverage drawing runs the full coverage computation and then
762 // makes the shader output be the multiplication of color and coverage. We mirror that here.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700763 GrProcessor::InvariantOutput inoutCoverage;
764 inoutCoverage.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700765 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700766 inoutCoverage.fValidFlags = 0;
767 inoutCoverage.fColor = 0; // suppresses any warnings.
egdaniel89af44a2014-09-26 06:15:04 -0700768 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700769 inoutCoverage.fValidFlags = kRGBA_GrColorComponentFlags;
770 inoutCoverage.fColor = this->getCoverageColor();
egdaniel89af44a2014-09-26 06:15:04 -0700771 }
772
773 // Run through the coverage stages
774 for (int s = 0; s < this->numCoverageStages(); ++s) {
775 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700776 processor->computeInvariantOutput(&inoutCoverage);
egdaniel89af44a2014-09-26 06:15:04 -0700777 }
778
779 // Since the shader will multiply coverage and color, the only way the final A==1 is if
780 // coverage and color both have A==1.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700781 return (inoutColor.isOpaque() && inoutCoverage.isOpaque());
egdaniel89af44a2014-09-26 06:15:04 -0700782 }
783
egdaniel1a8ecdf2014-10-03 06:24:12 -0700784 return inoutColor.isOpaque();
egdaniel89af44a2014-09-26 06:15:04 -0700785}
786