blob: c4b8154852084847e1dbb205e5a0b367015f0a9a [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;
joshualitta5305a12014-10-10 17:47:00 -070046 } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
egdaniel89af44a2014-09-26 06:15:04 -070047 return false;
48 }
49 } else if (that.hasGeometryProcessor()) {
50 return false;
51 }
52
53 for (int i = 0; i < this->numColorStages(); i++) {
joshualitta5305a12014-10-10 17:47:00 -070054 if (!GrFragmentStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
egdaniel89af44a2014-09-26 06:15:04 -070055 explicitLocalCoords)) {
56 return false;
57 }
58 }
59 for (int i = 0; i < this->numCoverageStages(); i++) {
joshualitta5305a12014-10-10 17:47:00 -070060 if (!GrFragmentStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
egdaniel89af44a2014-09-26 06:15:04 -070061 explicitLocalCoords)) {
62 return false;
63 }
64 }
65
66 SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
67 that.fFixedFunctionVertexAttribIndices,
68 sizeof(this->fFixedFunctionVertexAttribIndices)));
69
70 return true;
71}
72
bsalomon8f727332014-08-05 07:50:06 -070073GrDrawState::CombinedState GrDrawState::CombineIfPossible(
bsalomon62c447d2014-08-08 08:08:50 -070074 const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
bsalomon8f727332014-08-05 07:50:06 -070075
egdaniel21aed572014-08-26 12:24:06 -070076 if (!a.isEqual(b)) {
bsalomon8f727332014-08-05 07:50:06 -070077 return kIncompatible_CombinedState;
78 }
79
egdaniel21aed572014-08-26 12:24:06 -070080 // If the general draw states are equal (from check above) we know hasColorVertexAttribute()
81 // is equivalent for both a and b
82 if (a.hasColorVertexAttribute()) {
bsalomon62c447d2014-08-08 08:08:50 -070083 // If one is opaque and the other is not then the combined state is not opaque. Moreover,
84 // if the opaqueness affects the ability to get color/coverage blending correct then we
85 // don't combine the draw states.
86 bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
87 bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
88 if (aIsOpaque != bIsOpaque) {
89 const GrDrawState* opaque;
90 const GrDrawState* nonOpaque;
91 if (aIsOpaque) {
92 opaque = &a;
93 nonOpaque = &b;
94 } else {
95 opaque = &b;
96 nonOpaque = &a;
97 }
98 if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
99 SkASSERT(!nonOpaque->hasSolidCoverage());
100 if (!nonOpaque->couldApplyCoverage(caps)) {
101 return kIncompatible_CombinedState;
102 }
103 }
104 return aIsOpaque ? kB_CombinedState : kA_CombinedState;
105 }
106 }
bsalomon8f727332014-08-05 07:50:06 -0700107 return kAOrB_CombinedState;
108}
109
bsalomon8f727332014-08-05 07:50:06 -0700110//////////////////////////////////////////////////////////////////////////////s
111
egdaniel3658f382014-09-15 07:01:59 -0700112GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix)
113 : fCachedOptState(NULL) {
bsalomon8f727332014-08-05 07:50:06 -0700114 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
115 *this = state;
116 if (!preConcatMatrix.isIdentity()) {
egdaniel776bdbd2014-08-06 11:07:02 -0700117 for (int i = 0; i < this->numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700118 fColorStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -0700119 }
egdaniel776bdbd2014-08-06 11:07:02 -0700120 for (int i = 0; i < this->numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700121 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -0700122 }
egdaniel3658f382014-09-15 07:01:59 -0700123 this->invalidateOptState();
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
egdaniel3658f382014-09-15 07:01:59 -0700154 SkRefCnt_SafeAssign(fCachedOptState, that.fCachedOptState);
155
bsalomon8f727332014-08-05 07:50:06 -0700156 memcpy(fFixedFunctionVertexAttribIndices,
157 that.fFixedFunctionVertexAttribIndices,
158 sizeof(fFixedFunctionVertexAttribIndices));
159 return *this;
160}
161
162void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
163 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700164 SkASSERT(!fRenderTarget.ownsPendingIO());
165
joshualittbd769d02014-09-04 08:56:46 -0700166 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700167 fColorStages.reset();
168 fCoverageStages.reset();
bsalomon8f727332014-08-05 07:50:06 -0700169
bsalomon2a9ca782014-09-05 14:27:43 -0700170 fRenderTarget.reset();
bsalomon8f727332014-08-05 07:50:06 -0700171
172 this->setDefaultVertexAttribs();
173
174 fColor = 0xffffffff;
175 if (NULL == initialViewMatrix) {
176 fViewMatrix.reset();
177 } else {
178 fViewMatrix = *initialViewMatrix;
179 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700180 fSrcBlend = kOne_GrBlendCoeff;
181 fDstBlend = kZero_GrBlendCoeff;
bsalomon8f727332014-08-05 07:50:06 -0700182 fBlendConstant = 0x0;
183 fFlagBits = 0x0;
184 fStencilSettings.setDisabled();
egdaniel8cbf3d52014-08-21 06:27:22 -0700185 fCoverage = 0xff;
bsalomon8f727332014-08-05 07:50:06 -0700186 fDrawFace = kBoth_DrawFace;
187
bsalomon62c447d2014-08-08 08:08:50 -0700188 fHints = 0;
189
egdaniel3658f382014-09-15 07:01:59 -0700190 this->invalidateOptState();
bsalomon8f727332014-08-05 07:50:06 -0700191}
192
bsalomon@google.com137f1342013-05-29 21:27:53 +0000193bool GrDrawState::setIdentityViewMatrix() {
egdaniel776bdbd2014-08-06 11:07:02 -0700194 if (this->numTotalStages()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000195 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -0700196 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000197 // sad trombone sound
198 return false;
199 }
egdaniel776bdbd2014-08-06 11:07:02 -0700200 for (int s = 0; s < this->numColorStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700201 fColorStages[s].localCoordChange(invVM);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000202 }
egdaniel776bdbd2014-08-06 11:07:02 -0700203 for (int s = 0; s < this->numCoverageStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700204 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000205 }
206 }
egdaniel3658f382014-09-15 07:01:59 -0700207 this->invalidateOptState();
bsalomon2ed5ef82014-07-07 08:44:05 -0700208 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000209 return true;
210}
211
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000212void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000213 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000214
joshualittbd769d02014-09-04 08:56:46 -0700215 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700216 fColorStages.reset();
217 fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000218
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000219 for (int i = 0; i < paint.numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700220 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000221 }
222
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000223 for (int i = 0; i < paint.numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700224 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000225 }
226
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000227 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000228
bsalomon2ed5ef82014-07-07 08:44:05 -0700229 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000230
231 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -0700232 fBlendConstant = 0x0;
233 fDrawFace = kBoth_DrawFace;
234 fStencilSettings.setDisabled();
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000235 this->resetStateFlags();
bsalomon62c447d2014-08-08 08:08:50 -0700236 fHints = 0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000237
bsalomon@google.com21c10c52013-06-13 17:44:07 +0000238 // Enable the clip bit
239 this->enableState(GrDrawState::kClip_StateBit);
240
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000241 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000242 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
243 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000244
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000245 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000246 this->setCoverage(paint.getCoverage());
egdaniel3658f382014-09-15 07:01:59 -0700247 this->invalidateOptState();
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000248}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000249
250////////////////////////////////////////////////////////////////////////////////
251
egdaniel89af44a2014-09-26 06:15:04 -0700252bool GrDrawState::validateVertexAttribs() const {
253 // check consistency of effects and attributes
254 GrSLType slTypes[kMaxVertexAttribCnt];
255 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
256 slTypes[i] = static_cast<GrSLType>(-1);
257 }
258
259 if (this->hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700260 const GrGeometryProcessor* gp = this->getGeometryProcessor();
egdaniel89af44a2014-09-26 06:15:04 -0700261 // make sure that any attribute indices have the correct binding type, that the attrib
262 // type and effect's shader lang type are compatible, and that attributes shared by
263 // multiple effects use the same shader lang type.
264 const GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
265
266 int effectIndex = 0;
267 for (int index = 0; index < fVACount; index++) {
268 if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
269 // we only care about effect bindings
270 continue;
271 }
272 SkASSERT(effectIndex < s.count());
273 GrSLType effectSLType = s[effectIndex].getType();
274 GrVertexAttribType attribType = fVAPtr[index].fType;
275 int slVecCount = GrSLTypeVectorCount(effectSLType);
276 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
277 if (slVecCount != attribVecCount ||
278 (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
279 return false;
280 }
281 slTypes[index] = effectSLType;
282 effectIndex++;
283 }
284 // Make sure all attributes are consumed and we were able to find everything
285 SkASSERT(s.count() == effectIndex);
286 }
287
288 return true;
289}
290
291////////////////////////////////////////////////////////////////////////////////
292
egdaniel7b3d5ee2014-08-28 05:41:14 -0700293static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000294 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000295#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000296 uint32_t overlapCheck = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700297 SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000298 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000299 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
egdaniel7b3d5ee2014-08-28 05:41:14 -0700300 size_t attribOffset = attribs[index].fOffset;
301 SkASSERT(attribOffset + attribSize <= stride);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000302 size_t dwordCount = attribSize >> 2;
303 uint32_t mask = (1 << dwordCount)-1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700304 size_t offsetShift = attribOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000305 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000306 overlapCheck |= (mask << offsetShift);
djsollenea81ced2014-08-27 13:07:34 -0700307 }
egdaniel7b3d5ee2014-08-28 05:41:14 -0700308#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000309}
310
311////////////////////////////////////////////////////////////////////////////////
312
egdaniel7b3d5ee2014-08-28 05:41:14 -0700313void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count,
314 size_t stride) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000315 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000316
bsalomon2ed5ef82014-07-07 08:44:05 -0700317 fVAPtr = attribs;
318 fVACount = count;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700319 fVAStride = stride;
320 validate_vertex_attribs(fVAPtr, fVACount, fVAStride);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000321
322 // Set all the indices to -1
bsalomon2ed5ef82014-07-07 08:44:05 -0700323 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000324 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700325 sizeof(fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000326#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000327 uint32_t overlapCheck = 0;
328#endif
329 for (int i = 0; i < count; ++i) {
330 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
331 // The fixed function attribs can only be specified once
bsalomon2ed5ef82014-07-07 08:44:05 -0700332 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000333 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000334 GrVertexAttribTypeVectorCount(attribs[i].fType));
bsalomon2ed5ef82014-07-07 08:44:05 -0700335 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000336 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000337#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000338 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
339 uint32_t mask = (1 << dwordCount)-1;
340 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000341 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000342 overlapCheck |= (mask << offsetShift);
343#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000344 }
egdaniel3658f382014-09-15 07:01:59 -0700345 this->invalidateOptState();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000346 // Positions must be specified.
bsalomon2ed5ef82014-07-07 08:44:05 -0700347 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000348}
349
350////////////////////////////////////////////////////////////////////////////////
351
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000352void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000353 static const GrVertexAttrib kPositionAttrib =
354 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000355
bsalomon2ed5ef82014-07-07 08:44:05 -0700356 fVAPtr = &kPositionAttrib;
357 fVACount = 1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700358 fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
robertphillips@google.com42903302013-04-20 12:26:07 +0000359
jvanverth@google.com054ae992013-04-01 20:06:51 +0000360 // set all the fixed function indices to -1 except position.
bsalomon2ed5ef82014-07-07 08:44:05 -0700361 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000362 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700363 sizeof(fFixedFunctionVertexAttribIndices));
364 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
egdaniel3658f382014-09-15 07:01:59 -0700365 this->invalidateOptState();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000366}
367
368////////////////////////////////////////////////////////////////////////////////
369
bsalomon62c447d2014-08-08 08:08:50 -0700370bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
371 if (caps.dualSourceBlendingSupport()) {
372 return true;
373 }
374 // we can correctly apply coverage if a) we have dual source blending
375 // or b) one of our blend optimizations applies
376 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
377 GrBlendCoeff srcCoeff;
378 GrBlendCoeff dstCoeff;
egdaniel170f90b2014-09-16 12:54:40 -0700379 BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
egdaniel89af44a2014-09-26 06:15:04 -0700380 return GrDrawState::kNone_BlendOpt != flag ||
bsalomon62c447d2014-08-08 08:08:50 -0700381 (this->willEffectReadDstColor() &&
382 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
383}
384
egdaniel89af44a2014-09-26 06:15:04 -0700385bool GrDrawState::hasSolidCoverage() const {
386 // If we're drawing coverage directly then coverage is effectively treated as color.
387 if (this->isCoverageDrawing()) {
388 return true;
389 }
390
egdaniel1a8ecdf2014-10-03 06:24:12 -0700391 GrProcessor::InvariantOutput inout;
392 inout.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700393 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
394 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700395 inout.fValidFlags = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700396 } else {
joshualitt65171342014-10-09 07:25:36 -0700397 inout.fColor = this->getCoverageColor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700398 inout.fValidFlags = kRGBA_GrColorComponentFlags;
egdaniel89af44a2014-09-26 06:15:04 -0700399 }
400
401 // Run through the coverage stages and see if the coverage will be all ones at the end.
402 if (this->hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700403 fGeometryProcessor->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700404 }
joshualitt65171342014-10-09 07:25:36 -0700405
egdaniel89af44a2014-09-26 06:15:04 -0700406 for (int s = 0; s < this->numCoverageStages(); ++s) {
407 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700408 processor->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700409 }
egdaniel1a8ecdf2014-10-03 06:24:12 -0700410 return inout.isSolidWhite();
egdaniel89af44a2014-09-26 06:15:04 -0700411}
412
egdaniel21aed572014-08-26 12:24:06 -0700413//////////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000414
egdaniel3658f382014-09-15 07:01:59 -0700415GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
bsalomon49f085d2014-09-05 13:34:00 -0700416 SkASSERT(drawState);
egdaniel21aed572014-08-26 12:24:06 -0700417 fDrawState = drawState;
418 fVAPtr = drawState->fVAPtr;
419 fVACount = drawState->fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700420 fVAStride = drawState->fVAStride;
egdaniel21aed572014-08-26 12:24:06 -0700421 fDrawState->setDefaultVertexAttribs();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000422}
423
egdaniel21aed572014-08-26 12:24:06 -0700424//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000425
egdaniel89af44a2014-09-26 06:15:04 -0700426bool GrDrawState::willEffectReadDstColor() const {
427 if (!this->isColorWriteDisabled()) {
428 for (int s = 0; s < this->numColorStages(); ++s) {
joshualitt47bb3822014-10-07 16:43:25 -0700429 if (this->getColorStage(s).getProcessor()->willReadDstColor()) {
egdaniel89af44a2014-09-26 06:15:04 -0700430 return true;
431 }
432 }
433 }
434 for (int s = 0; s < this->numCoverageStages(); ++s) {
joshualitt47bb3822014-10-07 16:43:25 -0700435 if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) {
egdaniel89af44a2014-09-26 06:15:04 -0700436 return true;
437 }
438 }
439 return false;
440}
441
egdaniel21aed572014-08-26 12:24:06 -0700442void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700443 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700444 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700445 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700446 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700447 } else {
joshualitta5305a12014-10-10 17:47:00 -0700448 SkASSERT(fDrawState->getGeometryProcessor()->getUniqueID() ==
bsalomon52e9d632014-09-05 12:23:12 -0700449 fOriginalGPID);
450 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700451 }
joshualittbd769d02014-09-04 08:56:46 -0700452
egdaniel21aed572014-08-26 12:24:06 -0700453 int m = fDrawState->numColorStages() - fColorEffectCnt;
454 SkASSERT(m >= 0);
455 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000456
egdaniel21aed572014-08-26 12:24:06 -0700457 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
458 SkASSERT(n >= 0);
459 fDrawState->fCoverageStages.pop_back_n(n);
460 if (m + n > 0) {
egdaniel3658f382014-09-15 07:01:59 -0700461 fDrawState->invalidateOptState();
egdaniel21aed572014-08-26 12:24:06 -0700462 }
463 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000464 }
egdaniel21aed572014-08-26 12:24:06 -0700465 fDrawState = ds;
466 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700467 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700468 if (NULL != ds->getGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700469 fOriginalGPID = ds->getGeometryProcessor()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700470 }
egdaniel21aed572014-08-26 12:24:06 -0700471 fColorEffectCnt = ds->numColorStages();
472 fCoverageEffectCnt = ds->numCoverageStages();
473 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
474 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000475}
476
jvanverth@google.comcc782382013-01-28 20:39:48 +0000477////////////////////////////////////////////////////////////////////////////////
478
egdaniel89af44a2014-09-26 06:15:04 -0700479// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
480// others will blend incorrectly.
481bool GrDrawState::canTweakAlphaForCoverage() const {
482 /*
483 The fractional coverage is f.
484 The src and dst coeffs are Cs and Cd.
485 The dst and src colors are S and D.
486 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
487 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
488 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
489 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
490 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
491 color by definition.
492 */
493 return kOne_GrBlendCoeff == fDstBlend ||
494 kISA_GrBlendCoeff == fDstBlend ||
495 kISC_GrBlendCoeff == fDstBlend ||
496 this->isCoverageDrawing();
497}
498
499////////////////////////////////////////////////////////////////////////////////
500
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000501void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700502 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000503 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700504 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000505 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000506 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000507 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000508
509 int i = 0;
510 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700511 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000512 }
513 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700514 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000515 }
egdaniel3658f382014-09-15 07:01:59 -0700516 fDrawState->invalidateOptState();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000517 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000518 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000519}
520
521void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000522 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000523 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000524
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000525 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000526 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000527 return;
528 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000529 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000530
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000531 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700532 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000533
534 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000535 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
egdaniel3658f382014-09-15 07:01:59 -0700536 drawState->invalidateOptState();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000537}
538
bsalomon@google.com137f1342013-05-29 21:27:53 +0000539bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000540 this->restore();
541
bsalomon@google.com137f1342013-05-29 21:27:53 +0000542 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000543 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000544 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000545
bsalomon@google.com137f1342013-05-29 21:27:53 +0000546 if (drawState->getViewMatrix().isIdentity()) {
547 return true;
548 }
549
egdaniel3658f382014-09-15 07:01:59 -0700550 drawState->invalidateOptState();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000551 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000552 if (0 == drawState->numTotalStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700553 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000554 fDrawState = drawState;
555 fNumColorStages = 0;
556 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000557 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000558 return true;
559 } else {
560 SkMatrix inv;
561 if (!fViewMatrix.invert(&inv)) {
562 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000563 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700564 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000565 fDrawState = drawState;
566 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000567 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000568 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000569 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000570}
571
572void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
573 fSavedCoordChanges.reset(fDrawState->numTotalStages());
574 int i = 0;
575
576 fNumColorStages = fDrawState->numColorStages();
577 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700578 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700579 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000580 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000581
582 int numCoverageStages = fDrawState->numCoverageStages();
583 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700584 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700585 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000586 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000587}
egdaniel21aed572014-08-26 12:24:06 -0700588
egdaniel170f90b2014-09-16 12:54:40 -0700589////////////////////////////////////////////////////////////////////////////////
590
egdaniel89af44a2014-09-26 06:15:04 -0700591void GrDrawState::convertToPendingExec() {
592 fRenderTarget.markPendingIO();
593 fRenderTarget.removeRef();
594 for (int i = 0; i < fColorStages.count(); ++i) {
595 fColorStages[i].convertToPendingExec();
596 }
597 if (fGeometryProcessor) {
joshualitta5305a12014-10-10 17:47:00 -0700598 fGeometryProcessor.convertToPendingExec();
egdaniel89af44a2014-09-26 06:15:04 -0700599 }
600 for (int i = 0; i < fCoverageStages.count(); ++i) {
601 fCoverageStages[i].convertToPendingExec();
602 }
603}
604
605////////////////////////////////////////////////////////////////////////////////
606
egdaniel170f90b2014-09-16 12:54:40 -0700607void GrDrawState::invalidateOptState() const {
608 SkSafeSetNull(fCachedOptState);
609}
610
611////////////////////////////////////////////////////////////////////////////////
612
613GrDrawState::~GrDrawState() {
614 SkSafeUnref(fCachedOptState);
615 SkASSERT(0 == fBlockEffectRemovalCnt);
616}
617
egdaniel89af44a2014-09-26 06:15:04 -0700618////////////////////////////////////////////////////////////////////////////////
619
620GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
joshualitt65171342014-10-09 07:25:36 -0700621 GrBlendCoeff* srcCoeff,
622 GrBlendCoeff* dstCoeff) const {
egdaniel89af44a2014-09-26 06:15:04 -0700623 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
624 if (NULL == srcCoeff) {
625 srcCoeff = &bogusSrcCoeff;
626 }
627 if (NULL == dstCoeff) {
628 dstCoeff = &bogusDstCoeff;
629 }
630
631 *srcCoeff = this->getSrcBlendCoeff();
632 *dstCoeff = this->getDstBlendCoeff();
633
634 if (this->isColorWriteDisabled()) {
635 *srcCoeff = kZero_GrBlendCoeff;
636 *dstCoeff = kOne_GrBlendCoeff;
637 }
638
639 bool srcAIsOne = this->srcAlphaWillBeOne();
640 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
641 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
642 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
643 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
644
645 // When coeffs are (0,1) there is no reason to draw at all, unless
646 // stenciling is enabled. Having color writes disabled is effectively
647 // (0,1).
648 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
649 if (this->getStencil().doesWrite()) {
650 return kEmitCoverage_BlendOptFlag;
651 } else {
652 *dstCoeff = kOne_GrBlendCoeff;
653 return kSkipDraw_BlendOptFlag;
654 }
655 }
656
657 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
658
659 // if we don't have coverage we can check whether the dst
660 // has to read at all. If not, we'll disable blending.
661 if (!hasCoverage) {
662 if (dstCoeffIsZero) {
663 if (kOne_GrBlendCoeff == *srcCoeff) {
664 // if there is no coverage and coeffs are (1,0) then we
665 // won't need to read the dst at all, it gets replaced by src
666 *dstCoeff = kZero_GrBlendCoeff;
667 return kNone_BlendOpt;
668 } else if (kZero_GrBlendCoeff == *srcCoeff) {
669 // if the op is "clear" then we don't need to emit a color
670 // or blend, just write transparent black into the dst.
671 *srcCoeff = kOne_GrBlendCoeff;
672 *dstCoeff = kZero_GrBlendCoeff;
673 return kEmitTransBlack_BlendOptFlag;
674 }
675 }
676 } else if (this->isCoverageDrawing()) {
677 // we have coverage but we aren't distinguishing it from alpha by request.
678 return kCoverageAsAlpha_BlendOptFlag;
679 } else {
680 // check whether coverage can be safely rolled into alpha
681 // of if we can skip color computation and just emit coverage
682 if (this->canTweakAlphaForCoverage()) {
683 return kCoverageAsAlpha_BlendOptFlag;
684 }
685 if (dstCoeffIsZero) {
686 if (kZero_GrBlendCoeff == *srcCoeff) {
687 // the source color is not included in the blend
688 // the dst coeff is effectively zero so blend works out to:
689 // (c)(0)D + (1-c)D = (1-c)D.
690 *dstCoeff = kISA_GrBlendCoeff;
691 return kEmitCoverage_BlendOptFlag;
692 } else if (srcAIsOne) {
693 // the dst coeff is effectively zero so blend works out to:
694 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
695 // If Sa is 1 then we can replace Sa with c
696 // and set dst coeff to 1-Sa.
697 *dstCoeff = kISA_GrBlendCoeff;
698 return kCoverageAsAlpha_BlendOptFlag;
699 }
700 } else if (dstCoeffIsOne) {
701 // the dst coeff is effectively one so blend works out to:
702 // cS + (c)(1)D + (1-c)D = cS + D.
703 *dstCoeff = kOne_GrBlendCoeff;
704 return kCoverageAsAlpha_BlendOptFlag;
705 }
706 }
707
708 return kNone_BlendOpt;
709}
710
711
712bool GrDrawState::srcAlphaWillBeOne() const {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700713 GrProcessor::InvariantOutput inoutColor;
714 inoutColor.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700715 // Check if per-vertex or constant color may have partial alpha
716 if (this->hasColorVertexAttribute()) {
717 if (fHints & kVertexColorsAreOpaque_Hint) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700718 inoutColor.fValidFlags = kA_GrColorComponentFlag;
719 inoutColor.fColor = 0xFF << GrColor_SHIFT_A;
egdaniel89af44a2014-09-26 06:15:04 -0700720 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700721 inoutColor.fValidFlags = 0;
722 // not strictly necessary but we get false alarms from tools about uninit.
723 inoutColor.fColor = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700724 }
725 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700726 inoutColor.fValidFlags = kRGBA_GrColorComponentFlags;
727 inoutColor.fColor = this->getColor();
egdaniel89af44a2014-09-26 06:15:04 -0700728 }
729
730 // Run through the color stages
731 for (int s = 0; s < this->numColorStages(); ++s) {
732 const GrProcessor* processor = this->getColorStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700733 processor->computeInvariantOutput(&inoutColor);
egdaniel89af44a2014-09-26 06:15:04 -0700734 }
735
736 // Check whether coverage is treated as color. If so we run through the coverage computation.
737 if (this->isCoverageDrawing()) {
738 // The shader generated for coverage drawing runs the full coverage computation and then
739 // makes the shader output be the multiplication of color and coverage. We mirror that here.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700740 GrProcessor::InvariantOutput inoutCoverage;
741 inoutCoverage.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700742 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700743 inoutCoverage.fValidFlags = 0;
744 inoutCoverage.fColor = 0; // suppresses any warnings.
egdaniel89af44a2014-09-26 06:15:04 -0700745 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700746 inoutCoverage.fValidFlags = kRGBA_GrColorComponentFlags;
747 inoutCoverage.fColor = this->getCoverageColor();
egdaniel89af44a2014-09-26 06:15:04 -0700748 }
749
egdaniela703b842014-10-28 07:06:36 -0700750 if (this->hasGeometryProcessor()) {
751 fGeometryProcessor->computeInvariantOutput(&inoutCoverage);
752 }
753
egdaniel89af44a2014-09-26 06:15:04 -0700754 // Run through the coverage stages
755 for (int s = 0; s < this->numCoverageStages(); ++s) {
756 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700757 processor->computeInvariantOutput(&inoutCoverage);
egdaniel89af44a2014-09-26 06:15:04 -0700758 }
759
760 // Since the shader will multiply coverage and color, the only way the final A==1 is if
761 // coverage and color both have A==1.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700762 return (inoutColor.isOpaque() && inoutCoverage.isOpaque());
egdaniel89af44a2014-09-26 06:15:04 -0700763 }
764
egdaniel1a8ecdf2014-10-03 06:24:12 -0700765 return inoutColor.isOpaque();
egdaniel89af44a2014-09-26 06:15:04 -0700766}
767