blob: 1f9f6967c2d717ce8c1a0083de8d3c1f3871ebea [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
egdaniel69bb90c2014-11-11 07:32:45 -0800112GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
bsalomon8f727332014-08-05 07:50:06 -0700113 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
114 *this = state;
115 if (!preConcatMatrix.isIdentity()) {
egdaniel776bdbd2014-08-06 11:07:02 -0700116 for (int i = 0; i < this->numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700117 fColorStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -0700118 }
egdaniel776bdbd2014-08-06 11:07:02 -0700119 for (int i = 0; i < this->numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700120 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -0700121 }
bsalomon8f727332014-08-05 07:50:06 -0700122 }
123}
124
125GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
126 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700127 SkASSERT(!that.fRenderTarget.ownsPendingIO());
128 SkASSERT(!this->fRenderTarget.ownsPendingIO());
129 this->setRenderTarget(that.getRenderTarget());
bsalomon8f727332014-08-05 07:50:06 -0700130 fColor = that.fColor;
131 fViewMatrix = that.fViewMatrix;
egdaniel8cbf3d52014-08-21 06:27:22 -0700132 fSrcBlend = that.fSrcBlend;
133 fDstBlend = that.fDstBlend;
bsalomon8f727332014-08-05 07:50:06 -0700134 fBlendConstant = that.fBlendConstant;
135 fFlagBits = that.fFlagBits;
136 fVACount = that.fVACount;
137 fVAPtr = that.fVAPtr;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700138 fVAStride = that.fVAStride;
bsalomon8f727332014-08-05 07:50:06 -0700139 fStencilSettings = that.fStencilSettings;
140 fCoverage = that.fCoverage;
141 fDrawFace = that.fDrawFace;
joshualittbd769d02014-09-04 08:56:46 -0700142 if (that.hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700143 fGeometryProcessor.initAndRef(that.fGeometryProcessor);
joshualittbd769d02014-09-04 08:56:46 -0700144 } else {
145 fGeometryProcessor.reset(NULL);
146 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700147 fColorStages = that.fColorStages;
148 fCoverageStages = that.fCoverageStages;
bsalomon8f727332014-08-05 07:50:06 -0700149
bsalomon62c447d2014-08-08 08:08:50 -0700150 fHints = that.fHints;
egdaniel776bdbd2014-08-06 11:07:02 -0700151
bsalomon8f727332014-08-05 07:50:06 -0700152 memcpy(fFixedFunctionVertexAttribIndices,
153 that.fFixedFunctionVertexAttribIndices,
154 sizeof(fFixedFunctionVertexAttribIndices));
155 return *this;
156}
157
158void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
159 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700160 SkASSERT(!fRenderTarget.ownsPendingIO());
161
joshualittbd769d02014-09-04 08:56:46 -0700162 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700163 fColorStages.reset();
164 fCoverageStages.reset();
bsalomon8f727332014-08-05 07:50:06 -0700165
bsalomon2a9ca782014-09-05 14:27:43 -0700166 fRenderTarget.reset();
bsalomon8f727332014-08-05 07:50:06 -0700167
168 this->setDefaultVertexAttribs();
169
170 fColor = 0xffffffff;
171 if (NULL == initialViewMatrix) {
172 fViewMatrix.reset();
173 } else {
174 fViewMatrix = *initialViewMatrix;
175 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700176 fSrcBlend = kOne_GrBlendCoeff;
177 fDstBlend = kZero_GrBlendCoeff;
bsalomon8f727332014-08-05 07:50:06 -0700178 fBlendConstant = 0x0;
179 fFlagBits = 0x0;
180 fStencilSettings.setDisabled();
egdaniel8cbf3d52014-08-21 06:27:22 -0700181 fCoverage = 0xff;
bsalomon8f727332014-08-05 07:50:06 -0700182 fDrawFace = kBoth_DrawFace;
183
bsalomon62c447d2014-08-08 08:08:50 -0700184 fHints = 0;
bsalomon8f727332014-08-05 07:50:06 -0700185}
186
bsalomon@google.com137f1342013-05-29 21:27:53 +0000187bool GrDrawState::setIdentityViewMatrix() {
joshualitt4dd99882014-11-11 08:51:30 -0800188 if (this->numFragmentStages()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000189 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -0700190 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000191 // sad trombone sound
192 return false;
193 }
egdaniel776bdbd2014-08-06 11:07:02 -0700194 for (int s = 0; s < this->numColorStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700195 fColorStages[s].localCoordChange(invVM);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000196 }
egdaniel776bdbd2014-08-06 11:07:02 -0700197 for (int s = 0; s < this->numCoverageStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700198 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000199 }
200 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700201 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000202 return true;
203}
204
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000205void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000206 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000207
joshualittbd769d02014-09-04 08:56:46 -0700208 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700209 fColorStages.reset();
210 fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000211
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000212 for (int i = 0; i < paint.numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700213 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000214 }
215
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000216 for (int i = 0; i < paint.numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700217 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000218 }
219
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000220 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000221
bsalomon2ed5ef82014-07-07 08:44:05 -0700222 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000223
224 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -0700225 fBlendConstant = 0x0;
226 fDrawFace = kBoth_DrawFace;
227 fStencilSettings.setDisabled();
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000228 this->resetStateFlags();
bsalomon62c447d2014-08-08 08:08:50 -0700229 fHints = 0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000230
bsalomon@google.com21c10c52013-06-13 17:44:07 +0000231 // Enable the clip bit
232 this->enableState(GrDrawState::kClip_StateBit);
233
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000234 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000235 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
236 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000237
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000238 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000239 this->setCoverage(paint.getCoverage());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000240}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000241
242////////////////////////////////////////////////////////////////////////////////
243
egdaniel89af44a2014-09-26 06:15:04 -0700244bool GrDrawState::validateVertexAttribs() const {
245 // check consistency of effects and attributes
246 GrSLType slTypes[kMaxVertexAttribCnt];
247 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
248 slTypes[i] = static_cast<GrSLType>(-1);
249 }
250
251 if (this->hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700252 const GrGeometryProcessor* gp = this->getGeometryProcessor();
egdaniel89af44a2014-09-26 06:15:04 -0700253 // make sure that any attribute indices have the correct binding type, that the attrib
254 // type and effect's shader lang type are compatible, and that attributes shared by
255 // multiple effects use the same shader lang type.
256 const GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
257
258 int effectIndex = 0;
259 for (int index = 0; index < fVACount; index++) {
260 if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
261 // we only care about effect bindings
262 continue;
263 }
264 SkASSERT(effectIndex < s.count());
265 GrSLType effectSLType = s[effectIndex].getType();
266 GrVertexAttribType attribType = fVAPtr[index].fType;
267 int slVecCount = GrSLTypeVectorCount(effectSLType);
268 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
269 if (slVecCount != attribVecCount ||
270 (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
271 return false;
272 }
273 slTypes[index] = effectSLType;
274 effectIndex++;
275 }
276 // Make sure all attributes are consumed and we were able to find everything
277 SkASSERT(s.count() == effectIndex);
278 }
279
280 return true;
281}
282
283////////////////////////////////////////////////////////////////////////////////
284
egdaniel7b3d5ee2014-08-28 05:41:14 -0700285static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000286 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000287#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000288 uint32_t overlapCheck = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700289 SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000290 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000291 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
egdaniel7b3d5ee2014-08-28 05:41:14 -0700292 size_t attribOffset = attribs[index].fOffset;
293 SkASSERT(attribOffset + attribSize <= stride);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000294 size_t dwordCount = attribSize >> 2;
295 uint32_t mask = (1 << dwordCount)-1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700296 size_t offsetShift = attribOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000297 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000298 overlapCheck |= (mask << offsetShift);
djsollenea81ced2014-08-27 13:07:34 -0700299 }
egdaniel7b3d5ee2014-08-28 05:41:14 -0700300#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000301}
302
303////////////////////////////////////////////////////////////////////////////////
304
egdaniel7b3d5ee2014-08-28 05:41:14 -0700305void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count,
306 size_t stride) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000307 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000308
bsalomon2ed5ef82014-07-07 08:44:05 -0700309 fVAPtr = attribs;
310 fVACount = count;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700311 fVAStride = stride;
312 validate_vertex_attribs(fVAPtr, fVACount, fVAStride);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000313
314 // Set all the indices to -1
bsalomon2ed5ef82014-07-07 08:44:05 -0700315 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000316 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700317 sizeof(fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000318#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000319 uint32_t overlapCheck = 0;
320#endif
321 for (int i = 0; i < count; ++i) {
322 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
323 // The fixed function attribs can only be specified once
bsalomon2ed5ef82014-07-07 08:44:05 -0700324 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000325 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000326 GrVertexAttribTypeVectorCount(attribs[i].fType));
bsalomon2ed5ef82014-07-07 08:44:05 -0700327 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000328 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000329#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000330 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
331 uint32_t mask = (1 << dwordCount)-1;
332 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000333 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000334 overlapCheck |= (mask << offsetShift);
335#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000336 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000337 // Positions must be specified.
bsalomon2ed5ef82014-07-07 08:44:05 -0700338 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000339}
340
341////////////////////////////////////////////////////////////////////////////////
342
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000343void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000344 static const GrVertexAttrib kPositionAttrib =
345 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000346
bsalomon2ed5ef82014-07-07 08:44:05 -0700347 fVAPtr = &kPositionAttrib;
348 fVACount = 1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700349 fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
robertphillips@google.com42903302013-04-20 12:26:07 +0000350
jvanverth@google.com054ae992013-04-01 20:06:51 +0000351 // set all the fixed function indices to -1 except position.
bsalomon2ed5ef82014-07-07 08:44:05 -0700352 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000353 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700354 sizeof(fFixedFunctionVertexAttribIndices));
355 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000356}
357
358////////////////////////////////////////////////////////////////////////////////
359
bsalomon62c447d2014-08-08 08:08:50 -0700360bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
361 if (caps.dualSourceBlendingSupport()) {
362 return true;
363 }
364 // we can correctly apply coverage if a) we have dual source blending
365 // or b) one of our blend optimizations applies
366 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
367 GrBlendCoeff srcCoeff;
368 GrBlendCoeff dstCoeff;
egdaniel170f90b2014-09-16 12:54:40 -0700369 BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
egdaniel89af44a2014-09-26 06:15:04 -0700370 return GrDrawState::kNone_BlendOpt != flag ||
bsalomon62c447d2014-08-08 08:08:50 -0700371 (this->willEffectReadDstColor() &&
372 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
373}
374
egdaniel89af44a2014-09-26 06:15:04 -0700375bool GrDrawState::hasSolidCoverage() const {
376 // If we're drawing coverage directly then coverage is effectively treated as color.
377 if (this->isCoverageDrawing()) {
378 return true;
379 }
380
joshualitt4dd99882014-11-11 08:51:30 -0800381 if (this->numCoverageStages() > 0) {
382 return false;
383 }
384
egdaniel1a8ecdf2014-10-03 06:24:12 -0700385 GrProcessor::InvariantOutput inout;
egdaniel37b4d862014-11-03 10:07:07 -0800386 inout.fIsSingleComponent = true;
egdaniel89af44a2014-09-26 06:15:04 -0700387 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
388 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700389 inout.fValidFlags = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700390 } else {
joshualitt65171342014-10-09 07:25:36 -0700391 inout.fColor = this->getCoverageColor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700392 inout.fValidFlags = kRGBA_GrColorComponentFlags;
egdaniel89af44a2014-09-26 06:15:04 -0700393 }
394
joshualitt4dd99882014-11-11 08:51:30 -0800395 // check the coverage output from the GP
egdaniel89af44a2014-09-26 06:15:04 -0700396 if (this->hasGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700397 fGeometryProcessor->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700398 }
joshualitt65171342014-10-09 07:25:36 -0700399
egdaniel1a8ecdf2014-10-03 06:24:12 -0700400 return inout.isSolidWhite();
egdaniel89af44a2014-09-26 06:15:04 -0700401}
402
egdaniel21aed572014-08-26 12:24:06 -0700403//////////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000404
egdaniel3658f382014-09-15 07:01:59 -0700405GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
bsalomon49f085d2014-09-05 13:34:00 -0700406 SkASSERT(drawState);
egdaniel21aed572014-08-26 12:24:06 -0700407 fDrawState = drawState;
408 fVAPtr = drawState->fVAPtr;
409 fVACount = drawState->fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700410 fVAStride = drawState->fVAStride;
egdaniel21aed572014-08-26 12:24:06 -0700411 fDrawState->setDefaultVertexAttribs();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000412}
413
egdaniel21aed572014-08-26 12:24:06 -0700414//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000415
egdaniel89af44a2014-09-26 06:15:04 -0700416bool GrDrawState::willEffectReadDstColor() const {
417 if (!this->isColorWriteDisabled()) {
418 for (int s = 0; s < this->numColorStages(); ++s) {
joshualitt47bb3822014-10-07 16:43:25 -0700419 if (this->getColorStage(s).getProcessor()->willReadDstColor()) {
egdaniel89af44a2014-09-26 06:15:04 -0700420 return true;
421 }
422 }
423 }
424 for (int s = 0; s < this->numCoverageStages(); ++s) {
joshualitt47bb3822014-10-07 16:43:25 -0700425 if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) {
egdaniel89af44a2014-09-26 06:15:04 -0700426 return true;
427 }
428 }
429 return false;
430}
431
egdaniel21aed572014-08-26 12:24:06 -0700432void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700433 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700434 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700435 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700436 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700437 } else {
joshualitta5305a12014-10-10 17:47:00 -0700438 SkASSERT(fDrawState->getGeometryProcessor()->getUniqueID() ==
bsalomon52e9d632014-09-05 12:23:12 -0700439 fOriginalGPID);
440 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700441 }
joshualittbd769d02014-09-04 08:56:46 -0700442
egdaniel21aed572014-08-26 12:24:06 -0700443 int m = fDrawState->numColorStages() - fColorEffectCnt;
444 SkASSERT(m >= 0);
445 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000446
egdaniel21aed572014-08-26 12:24:06 -0700447 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
448 SkASSERT(n >= 0);
449 fDrawState->fCoverageStages.pop_back_n(n);
egdaniel21aed572014-08-26 12:24:06 -0700450 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000451 }
egdaniel21aed572014-08-26 12:24:06 -0700452 fDrawState = ds;
453 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700454 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700455 if (NULL != ds->getGeometryProcessor()) {
joshualitta5305a12014-10-10 17:47:00 -0700456 fOriginalGPID = ds->getGeometryProcessor()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700457 }
egdaniel21aed572014-08-26 12:24:06 -0700458 fColorEffectCnt = ds->numColorStages();
459 fCoverageEffectCnt = ds->numCoverageStages();
460 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
461 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000462}
463
jvanverth@google.comcc782382013-01-28 20:39:48 +0000464////////////////////////////////////////////////////////////////////////////////
465
egdaniel89af44a2014-09-26 06:15:04 -0700466// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
467// others will blend incorrectly.
468bool GrDrawState::canTweakAlphaForCoverage() const {
469 /*
470 The fractional coverage is f.
471 The src and dst coeffs are Cs and Cd.
472 The dst and src colors are S and D.
473 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
474 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
475 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
476 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
477 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
478 color by definition.
479 */
480 return kOne_GrBlendCoeff == fDstBlend ||
481 kISA_GrBlendCoeff == fDstBlend ||
482 kISC_GrBlendCoeff == fDstBlend ||
483 this->isCoverageDrawing();
484}
485
486////////////////////////////////////////////////////////////////////////////////
487
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000488void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700489 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000490 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700491 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000492 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000493 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000494 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000495
496 int i = 0;
497 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700498 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000499 }
500 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700501 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000502 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000503 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000504 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000505}
506
507void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000508 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000509 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000510
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000511 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000512 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000513 return;
514 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000515 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000516
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000517 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700518 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000519
520 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000521 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000522}
523
bsalomon@google.com137f1342013-05-29 21:27:53 +0000524bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000525 this->restore();
526
bsalomon@google.com137f1342013-05-29 21:27:53 +0000527 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000528 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000529 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000530
bsalomon@google.com137f1342013-05-29 21:27:53 +0000531 if (drawState->getViewMatrix().isIdentity()) {
532 return true;
533 }
534
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000535 fViewMatrix = drawState->getViewMatrix();
joshualitt4dd99882014-11-11 08:51:30 -0800536 if (0 == drawState->numFragmentStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700537 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000538 fDrawState = drawState;
539 fNumColorStages = 0;
540 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000541 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000542 return true;
543 } else {
544 SkMatrix inv;
545 if (!fViewMatrix.invert(&inv)) {
546 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000547 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700548 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000549 fDrawState = drawState;
550 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000551 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000552 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000553 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000554}
555
556void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
joshualitt4dd99882014-11-11 08:51:30 -0800557 fSavedCoordChanges.reset(fDrawState->numFragmentStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000558 int i = 0;
559
560 fNumColorStages = fDrawState->numColorStages();
561 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700562 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700563 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000564 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000565
566 int numCoverageStages = fDrawState->numCoverageStages();
567 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700568 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700569 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000570 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000571}
egdaniel21aed572014-08-26 12:24:06 -0700572
egdaniel170f90b2014-09-16 12:54:40 -0700573////////////////////////////////////////////////////////////////////////////////
574
egdaniel89af44a2014-09-26 06:15:04 -0700575void GrDrawState::convertToPendingExec() {
576 fRenderTarget.markPendingIO();
577 fRenderTarget.removeRef();
578 for (int i = 0; i < fColorStages.count(); ++i) {
579 fColorStages[i].convertToPendingExec();
580 }
581 if (fGeometryProcessor) {
joshualitta5305a12014-10-10 17:47:00 -0700582 fGeometryProcessor.convertToPendingExec();
egdaniel89af44a2014-09-26 06:15:04 -0700583 }
584 for (int i = 0; i < fCoverageStages.count(); ++i) {
585 fCoverageStages[i].convertToPendingExec();
586 }
587}
588
589////////////////////////////////////////////////////////////////////////////////
590
egdaniel170f90b2014-09-16 12:54:40 -0700591GrDrawState::~GrDrawState() {
egdaniel170f90b2014-09-16 12:54:40 -0700592 SkASSERT(0 == fBlockEffectRemovalCnt);
593}
594
egdaniel89af44a2014-09-26 06:15:04 -0700595////////////////////////////////////////////////////////////////////////////////
596
597GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
joshualitt65171342014-10-09 07:25:36 -0700598 GrBlendCoeff* srcCoeff,
599 GrBlendCoeff* dstCoeff) const {
egdaniel89af44a2014-09-26 06:15:04 -0700600 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
601 if (NULL == srcCoeff) {
602 srcCoeff = &bogusSrcCoeff;
603 }
604 if (NULL == dstCoeff) {
605 dstCoeff = &bogusDstCoeff;
606 }
607
608 *srcCoeff = this->getSrcBlendCoeff();
609 *dstCoeff = this->getDstBlendCoeff();
610
611 if (this->isColorWriteDisabled()) {
612 *srcCoeff = kZero_GrBlendCoeff;
613 *dstCoeff = kOne_GrBlendCoeff;
614 }
615
616 bool srcAIsOne = this->srcAlphaWillBeOne();
617 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
618 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
619 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
620 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
621
622 // When coeffs are (0,1) there is no reason to draw at all, unless
623 // stenciling is enabled. Having color writes disabled is effectively
624 // (0,1).
625 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
626 if (this->getStencil().doesWrite()) {
627 return kEmitCoverage_BlendOptFlag;
628 } else {
629 *dstCoeff = kOne_GrBlendCoeff;
630 return kSkipDraw_BlendOptFlag;
631 }
632 }
633
634 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
635
636 // if we don't have coverage we can check whether the dst
637 // has to read at all. If not, we'll disable blending.
638 if (!hasCoverage) {
639 if (dstCoeffIsZero) {
640 if (kOne_GrBlendCoeff == *srcCoeff) {
641 // if there is no coverage and coeffs are (1,0) then we
642 // won't need to read the dst at all, it gets replaced by src
643 *dstCoeff = kZero_GrBlendCoeff;
644 return kNone_BlendOpt;
645 } else if (kZero_GrBlendCoeff == *srcCoeff) {
646 // if the op is "clear" then we don't need to emit a color
647 // or blend, just write transparent black into the dst.
648 *srcCoeff = kOne_GrBlendCoeff;
649 *dstCoeff = kZero_GrBlendCoeff;
650 return kEmitTransBlack_BlendOptFlag;
651 }
652 }
653 } else if (this->isCoverageDrawing()) {
654 // we have coverage but we aren't distinguishing it from alpha by request.
655 return kCoverageAsAlpha_BlendOptFlag;
656 } else {
657 // check whether coverage can be safely rolled into alpha
658 // of if we can skip color computation and just emit coverage
659 if (this->canTweakAlphaForCoverage()) {
660 return kCoverageAsAlpha_BlendOptFlag;
661 }
662 if (dstCoeffIsZero) {
663 if (kZero_GrBlendCoeff == *srcCoeff) {
664 // the source color is not included in the blend
665 // the dst coeff is effectively zero so blend works out to:
666 // (c)(0)D + (1-c)D = (1-c)D.
667 *dstCoeff = kISA_GrBlendCoeff;
668 return kEmitCoverage_BlendOptFlag;
669 } else if (srcAIsOne) {
670 // the dst coeff is effectively zero so blend works out to:
671 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
672 // If Sa is 1 then we can replace Sa with c
673 // and set dst coeff to 1-Sa.
674 *dstCoeff = kISA_GrBlendCoeff;
675 return kCoverageAsAlpha_BlendOptFlag;
676 }
677 } else if (dstCoeffIsOne) {
678 // the dst coeff is effectively one so blend works out to:
679 // cS + (c)(1)D + (1-c)D = cS + D.
680 *dstCoeff = kOne_GrBlendCoeff;
681 return kCoverageAsAlpha_BlendOptFlag;
682 }
683 }
684
685 return kNone_BlendOpt;
686}
687
688
689bool GrDrawState::srcAlphaWillBeOne() const {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700690 GrProcessor::InvariantOutput inoutColor;
691 inoutColor.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700692 // Check if per-vertex or constant color may have partial alpha
693 if (this->hasColorVertexAttribute()) {
694 if (fHints & kVertexColorsAreOpaque_Hint) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700695 inoutColor.fValidFlags = kA_GrColorComponentFlag;
696 inoutColor.fColor = 0xFF << GrColor_SHIFT_A;
egdaniel89af44a2014-09-26 06:15:04 -0700697 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700698 inoutColor.fValidFlags = 0;
699 // not strictly necessary but we get false alarms from tools about uninit.
700 inoutColor.fColor = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700701 }
702 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700703 inoutColor.fValidFlags = kRGBA_GrColorComponentFlags;
704 inoutColor.fColor = this->getColor();
egdaniel89af44a2014-09-26 06:15:04 -0700705 }
706
707 // Run through the color stages
708 for (int s = 0; s < this->numColorStages(); ++s) {
709 const GrProcessor* processor = this->getColorStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700710 processor->computeInvariantOutput(&inoutColor);
egdaniel89af44a2014-09-26 06:15:04 -0700711 }
712
713 // Check whether coverage is treated as color. If so we run through the coverage computation.
714 if (this->isCoverageDrawing()) {
715 // The shader generated for coverage drawing runs the full coverage computation and then
716 // makes the shader output be the multiplication of color and coverage. We mirror that here.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700717 GrProcessor::InvariantOutput inoutCoverage;
egdaniel37b4d862014-11-03 10:07:07 -0800718 inoutCoverage.fIsSingleComponent = true;
egdaniel89af44a2014-09-26 06:15:04 -0700719 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700720 inoutCoverage.fValidFlags = 0;
721 inoutCoverage.fColor = 0; // suppresses any warnings.
egdaniel89af44a2014-09-26 06:15:04 -0700722 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700723 inoutCoverage.fValidFlags = kRGBA_GrColorComponentFlags;
724 inoutCoverage.fColor = this->getCoverageColor();
egdaniel89af44a2014-09-26 06:15:04 -0700725 }
726
egdaniela703b842014-10-28 07:06:36 -0700727 if (this->hasGeometryProcessor()) {
728 fGeometryProcessor->computeInvariantOutput(&inoutCoverage);
729 }
730
egdaniel89af44a2014-09-26 06:15:04 -0700731 // Run through the coverage stages
732 for (int s = 0; s < this->numCoverageStages(); ++s) {
733 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700734 processor->computeInvariantOutput(&inoutCoverage);
egdaniel89af44a2014-09-26 06:15:04 -0700735 }
736
737 // Since the shader will multiply coverage and color, the only way the final A==1 is if
738 // coverage and color both have A==1.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700739 return (inoutColor.isOpaque() && inoutCoverage.isOpaque());
egdaniel89af44a2014-09-26 06:15:04 -0700740 }
741
egdaniel1a8ecdf2014-10-03 06:24:12 -0700742 return inoutColor.isOpaque();
egdaniel89af44a2014-09-26 06:15:04 -0700743}
744