blob: f967a6fa76182d536bd9aba26221c685335c7896 [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();
joshualittdb0d3ca2014-10-07 12:42:26 -0700269 const GrGeometryProcessor* gp = stage.getGeometryProcessor();
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 {
joshualittd9097592014-10-07 08:37:36 -0700407 inout.fColor = fCoverage;
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()) {
joshualittdb0d3ca2014-10-07 12:42:26 -0700413 const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700414 gp->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700415 }
416 for (int s = 0; s < this->numCoverageStages(); ++s) {
417 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700418 processor->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700419 }
egdaniel1a8ecdf2014-10-03 06:24:12 -0700420 return inout.isSolidWhite();
egdaniel89af44a2014-09-26 06:15:04 -0700421}
422
egdaniel21aed572014-08-26 12:24:06 -0700423//////////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000424
egdaniel3658f382014-09-15 07:01:59 -0700425GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
bsalomon49f085d2014-09-05 13:34:00 -0700426 SkASSERT(drawState);
egdaniel21aed572014-08-26 12:24:06 -0700427 fDrawState = drawState;
428 fVAPtr = drawState->fVAPtr;
429 fVACount = drawState->fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700430 fVAStride = drawState->fVAStride;
egdaniel21aed572014-08-26 12:24:06 -0700431 fDrawState->setDefaultVertexAttribs();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000432}
433
egdaniel21aed572014-08-26 12:24:06 -0700434//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000435
egdaniel89af44a2014-09-26 06:15:04 -0700436bool GrDrawState::willEffectReadDstColor() const {
437 if (!this->isColorWriteDisabled()) {
438 for (int s = 0; s < this->numColorStages(); ++s) {
joshualittdb0d3ca2014-10-07 12:42:26 -0700439 if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) {
egdaniel89af44a2014-09-26 06:15:04 -0700440 return true;
441 }
442 }
443 }
444 for (int s = 0; s < this->numCoverageStages(); ++s) {
joshualittdb0d3ca2014-10-07 12:42:26 -0700445 if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
egdaniel89af44a2014-09-26 06:15:04 -0700446 return true;
447 }
448 }
449 return false;
450}
451
egdaniel21aed572014-08-26 12:24:06 -0700452void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700453 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700454 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700455 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700456 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700457 } else {
joshualittb0a8a372014-09-23 09:50:21 -0700458 SkASSERT(fDrawState->getGeometryProcessor()->getProcessor()->getUniqueID() ==
bsalomon52e9d632014-09-05 12:23:12 -0700459 fOriginalGPID);
460 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700461 }
joshualittbd769d02014-09-04 08:56:46 -0700462
egdaniel21aed572014-08-26 12:24:06 -0700463 int m = fDrawState->numColorStages() - fColorEffectCnt;
464 SkASSERT(m >= 0);
465 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000466
egdaniel21aed572014-08-26 12:24:06 -0700467 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
468 SkASSERT(n >= 0);
469 fDrawState->fCoverageStages.pop_back_n(n);
470 if (m + n > 0) {
egdaniel3658f382014-09-15 07:01:59 -0700471 fDrawState->invalidateOptState();
egdaniel21aed572014-08-26 12:24:06 -0700472 }
473 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000474 }
egdaniel21aed572014-08-26 12:24:06 -0700475 fDrawState = ds;
476 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700477 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700478 if (NULL != ds->getGeometryProcessor()) {
joshualittb0a8a372014-09-23 09:50:21 -0700479 fOriginalGPID = ds->getGeometryProcessor()->getProcessor()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700480 }
egdaniel21aed572014-08-26 12:24:06 -0700481 fColorEffectCnt = ds->numColorStages();
482 fCoverageEffectCnt = ds->numCoverageStages();
483 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
484 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000485}
486
jvanverth@google.comcc782382013-01-28 20:39:48 +0000487////////////////////////////////////////////////////////////////////////////////
488
egdaniel89af44a2014-09-26 06:15:04 -0700489// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
490// others will blend incorrectly.
491bool GrDrawState::canTweakAlphaForCoverage() const {
492 /*
493 The fractional coverage is f.
494 The src and dst coeffs are Cs and Cd.
495 The dst and src colors are S and D.
496 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
497 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
498 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
499 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
500 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
501 color by definition.
502 */
503 return kOne_GrBlendCoeff == fDstBlend ||
504 kISA_GrBlendCoeff == fDstBlend ||
505 kISC_GrBlendCoeff == fDstBlend ||
506 this->isCoverageDrawing();
507}
508
509////////////////////////////////////////////////////////////////////////////////
510
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000511void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700512 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000513 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700514 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000515 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000516 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000517 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000518
519 int i = 0;
joshualittbd769d02014-09-04 08:56:46 -0700520 if (fHasGeometryProcessor) {
521 SkASSERT(fDrawState->hasGeometryProcessor());
522 fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]);
523 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000524 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700525 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000526 }
527 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700528 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000529 }
egdaniel3658f382014-09-15 07:01:59 -0700530 fDrawState->invalidateOptState();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000531 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000532 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000533}
534
535void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000536 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000537 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000538
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000539 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000540 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000541 return;
542 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000543 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000544
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000545 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700546 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000547
548 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000549 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
egdaniel3658f382014-09-15 07:01:59 -0700550 drawState->invalidateOptState();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000551}
552
bsalomon@google.com137f1342013-05-29 21:27:53 +0000553bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000554 this->restore();
555
bsalomon@google.com137f1342013-05-29 21:27:53 +0000556 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000557 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000558 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000559
bsalomon@google.com137f1342013-05-29 21:27:53 +0000560 if (drawState->getViewMatrix().isIdentity()) {
561 return true;
562 }
563
egdaniel3658f382014-09-15 07:01:59 -0700564 drawState->invalidateOptState();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000565 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000566 if (0 == drawState->numTotalStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700567 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000568 fDrawState = drawState;
joshualittbd769d02014-09-04 08:56:46 -0700569 fHasGeometryProcessor = false;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000570 fNumColorStages = 0;
571 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000572 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000573 return true;
574 } else {
575 SkMatrix inv;
576 if (!fViewMatrix.invert(&inv)) {
577 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000578 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700579 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000580 fDrawState = drawState;
581 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000582 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000583 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000584 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000585}
586
587void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
588 fSavedCoordChanges.reset(fDrawState->numTotalStages());
589 int i = 0;
590
joshualittbd769d02014-09-04 08:56:46 -0700591 fHasGeometryProcessor = false;
592 if (fDrawState->hasGeometryProcessor()) {
593 fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]);
594 fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix);
595 fHasGeometryProcessor = true;
596 }
597
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000598 fNumColorStages = fDrawState->numColorStages();
599 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700600 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700601 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000602 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000603
604 int numCoverageStages = fDrawState->numCoverageStages();
605 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700606 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700607 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000608 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000609}
egdaniel21aed572014-08-26 12:24:06 -0700610
egdaniel170f90b2014-09-16 12:54:40 -0700611////////////////////////////////////////////////////////////////////////////////
612
egdaniel89af44a2014-09-26 06:15:04 -0700613void GrDrawState::convertToPendingExec() {
614 fRenderTarget.markPendingIO();
615 fRenderTarget.removeRef();
616 for (int i = 0; i < fColorStages.count(); ++i) {
617 fColorStages[i].convertToPendingExec();
618 }
619 if (fGeometryProcessor) {
620 fGeometryProcessor->convertToPendingExec();
621 }
622 for (int i = 0; i < fCoverageStages.count(); ++i) {
623 fCoverageStages[i].convertToPendingExec();
624 }
625}
626
627////////////////////////////////////////////////////////////////////////////////
628
egdaniel170f90b2014-09-16 12:54:40 -0700629void GrDrawState::invalidateOptState() const {
630 SkSafeSetNull(fCachedOptState);
631}
632
633////////////////////////////////////////////////////////////////////////////////
634
635GrDrawState::~GrDrawState() {
636 SkSafeUnref(fCachedOptState);
637 SkASSERT(0 == fBlockEffectRemovalCnt);
638}
639
egdaniel89af44a2014-09-26 06:15:04 -0700640////////////////////////////////////////////////////////////////////////////////
641
642GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
joshualittd9097592014-10-07 08:37:36 -0700643 GrBlendCoeff* srcCoeff,
644 GrBlendCoeff* dstCoeff) const {
egdaniel89af44a2014-09-26 06:15:04 -0700645 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
646 if (NULL == srcCoeff) {
647 srcCoeff = &bogusSrcCoeff;
648 }
649 if (NULL == dstCoeff) {
650 dstCoeff = &bogusDstCoeff;
651 }
652
653 *srcCoeff = this->getSrcBlendCoeff();
654 *dstCoeff = this->getDstBlendCoeff();
655
656 if (this->isColorWriteDisabled()) {
657 *srcCoeff = kZero_GrBlendCoeff;
658 *dstCoeff = kOne_GrBlendCoeff;
659 }
660
661 bool srcAIsOne = this->srcAlphaWillBeOne();
662 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
663 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
664 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
665 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
666
667 // When coeffs are (0,1) there is no reason to draw at all, unless
668 // stenciling is enabled. Having color writes disabled is effectively
669 // (0,1).
670 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
671 if (this->getStencil().doesWrite()) {
672 return kEmitCoverage_BlendOptFlag;
673 } else {
674 *dstCoeff = kOne_GrBlendCoeff;
675 return kSkipDraw_BlendOptFlag;
676 }
677 }
678
679 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
680
681 // if we don't have coverage we can check whether the dst
682 // has to read at all. If not, we'll disable blending.
683 if (!hasCoverage) {
684 if (dstCoeffIsZero) {
685 if (kOne_GrBlendCoeff == *srcCoeff) {
686 // if there is no coverage and coeffs are (1,0) then we
687 // won't need to read the dst at all, it gets replaced by src
688 *dstCoeff = kZero_GrBlendCoeff;
689 return kNone_BlendOpt;
690 } else if (kZero_GrBlendCoeff == *srcCoeff) {
691 // if the op is "clear" then we don't need to emit a color
692 // or blend, just write transparent black into the dst.
693 *srcCoeff = kOne_GrBlendCoeff;
694 *dstCoeff = kZero_GrBlendCoeff;
695 return kEmitTransBlack_BlendOptFlag;
696 }
697 }
698 } else if (this->isCoverageDrawing()) {
699 // we have coverage but we aren't distinguishing it from alpha by request.
700 return kCoverageAsAlpha_BlendOptFlag;
701 } else {
702 // check whether coverage can be safely rolled into alpha
703 // of if we can skip color computation and just emit coverage
704 if (this->canTweakAlphaForCoverage()) {
705 return kCoverageAsAlpha_BlendOptFlag;
706 }
707 if (dstCoeffIsZero) {
708 if (kZero_GrBlendCoeff == *srcCoeff) {
709 // the source color is not included in the blend
710 // the dst coeff is effectively zero so blend works out to:
711 // (c)(0)D + (1-c)D = (1-c)D.
712 *dstCoeff = kISA_GrBlendCoeff;
713 return kEmitCoverage_BlendOptFlag;
714 } else if (srcAIsOne) {
715 // the dst coeff is effectively zero so blend works out to:
716 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
717 // If Sa is 1 then we can replace Sa with c
718 // and set dst coeff to 1-Sa.
719 *dstCoeff = kISA_GrBlendCoeff;
720 return kCoverageAsAlpha_BlendOptFlag;
721 }
722 } else if (dstCoeffIsOne) {
723 // the dst coeff is effectively one so blend works out to:
724 // cS + (c)(1)D + (1-c)D = cS + D.
725 *dstCoeff = kOne_GrBlendCoeff;
726 return kCoverageAsAlpha_BlendOptFlag;
727 }
728 }
729
730 return kNone_BlendOpt;
731}
732
733
734bool GrDrawState::srcAlphaWillBeOne() const {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700735 GrProcessor::InvariantOutput inoutColor;
736 inoutColor.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700737 // Check if per-vertex or constant color may have partial alpha
738 if (this->hasColorVertexAttribute()) {
739 if (fHints & kVertexColorsAreOpaque_Hint) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700740 inoutColor.fValidFlags = kA_GrColorComponentFlag;
741 inoutColor.fColor = 0xFF << GrColor_SHIFT_A;
egdaniel89af44a2014-09-26 06:15:04 -0700742 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700743 inoutColor.fValidFlags = 0;
744 // not strictly necessary but we get false alarms from tools about uninit.
745 inoutColor.fColor = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700746 }
747 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700748 inoutColor.fValidFlags = kRGBA_GrColorComponentFlags;
749 inoutColor.fColor = this->getColor();
egdaniel89af44a2014-09-26 06:15:04 -0700750 }
751
752 // Run through the color stages
753 for (int s = 0; s < this->numColorStages(); ++s) {
754 const GrProcessor* processor = this->getColorStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700755 processor->computeInvariantOutput(&inoutColor);
egdaniel89af44a2014-09-26 06:15:04 -0700756 }
757
758 // Check whether coverage is treated as color. If so we run through the coverage computation.
759 if (this->isCoverageDrawing()) {
760 // The shader generated for coverage drawing runs the full coverage computation and then
761 // makes the shader output be the multiplication of color and coverage. We mirror that here.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700762 GrProcessor::InvariantOutput inoutCoverage;
763 inoutCoverage.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700764 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700765 inoutCoverage.fValidFlags = 0;
766 inoutCoverage.fColor = 0; // suppresses any warnings.
egdaniel89af44a2014-09-26 06:15:04 -0700767 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700768 inoutCoverage.fValidFlags = kRGBA_GrColorComponentFlags;
769 inoutCoverage.fColor = this->getCoverageColor();
egdaniel89af44a2014-09-26 06:15:04 -0700770 }
771
772 // Run through the coverage stages
773 for (int s = 0; s < this->numCoverageStages(); ++s) {
774 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700775 processor->computeInvariantOutput(&inoutCoverage);
egdaniel89af44a2014-09-26 06:15:04 -0700776 }
777
778 // Since the shader will multiply coverage and color, the only way the final A==1 is if
779 // coverage and color both have A==1.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700780 return (inoutColor.isOpaque() && inoutCoverage.isOpaque());
egdaniel89af44a2014-09-26 06:15:04 -0700781 }
782
egdaniel1a8ecdf2014-10-03 06:24:12 -0700783 return inoutColor.isOpaque();
egdaniel89af44a2014-09-26 06:15:04 -0700784}
785