blob: 288fa12730850316750b1992446ee7381a860d83 [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;
joshualitt89c7a2e2014-10-10 14:11:59 -070046 } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
47 *that.getGeometryProcessor(),
48 explicitLocalCoords)) {
egdaniel89af44a2014-09-26 06:15:04 -070049 return false;
50 }
51 } else if (that.hasGeometryProcessor()) {
52 return false;
53 }
54
55 for (int i = 0; i < this->numColorStages(); i++) {
joshualitt89c7a2e2014-10-10 14:11:59 -070056 if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
egdaniel89af44a2014-09-26 06:15:04 -070057 explicitLocalCoords)) {
58 return false;
59 }
60 }
61 for (int i = 0; i < this->numCoverageStages(); i++) {
joshualitt89c7a2e2014-10-10 14:11:59 -070062 if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
egdaniel89af44a2014-09-26 06:15:04 -070063 explicitLocalCoords)) {
64 return false;
65 }
66 }
67
68 SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
69 that.fFixedFunctionVertexAttribIndices,
70 sizeof(this->fFixedFunctionVertexAttribIndices)));
71
72 return true;
73}
74
bsalomon8f727332014-08-05 07:50:06 -070075GrDrawState::CombinedState GrDrawState::CombineIfPossible(
bsalomon62c447d2014-08-08 08:08:50 -070076 const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
bsalomon8f727332014-08-05 07:50:06 -070077
egdaniel21aed572014-08-26 12:24:06 -070078 if (!a.isEqual(b)) {
bsalomon8f727332014-08-05 07:50:06 -070079 return kIncompatible_CombinedState;
80 }
81
egdaniel21aed572014-08-26 12:24:06 -070082 // If the general draw states are equal (from check above) we know hasColorVertexAttribute()
83 // is equivalent for both a and b
84 if (a.hasColorVertexAttribute()) {
bsalomon62c447d2014-08-08 08:08:50 -070085 // If one is opaque and the other is not then the combined state is not opaque. Moreover,
86 // if the opaqueness affects the ability to get color/coverage blending correct then we
87 // don't combine the draw states.
88 bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
89 bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
90 if (aIsOpaque != bIsOpaque) {
91 const GrDrawState* opaque;
92 const GrDrawState* nonOpaque;
93 if (aIsOpaque) {
94 opaque = &a;
95 nonOpaque = &b;
96 } else {
97 opaque = &b;
98 nonOpaque = &a;
99 }
100 if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
101 SkASSERT(!nonOpaque->hasSolidCoverage());
102 if (!nonOpaque->couldApplyCoverage(caps)) {
103 return kIncompatible_CombinedState;
104 }
105 }
106 return aIsOpaque ? kB_CombinedState : kA_CombinedState;
107 }
108 }
bsalomon8f727332014-08-05 07:50:06 -0700109 return kAOrB_CombinedState;
110}
111
bsalomon8f727332014-08-05 07:50:06 -0700112//////////////////////////////////////////////////////////////////////////////s
113
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()) {
joshualitt89c7a2e2014-10-10 14:11:59 -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()) {
joshualitt89c7a2e2014-10-10 14:11:59 -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 }
joshualitt89c7a2e2014-10-10 14:11:59 -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()) {
joshualitt89c7a2e2014-10-10 14:11:59 -0700268 const GrGeometryStage& stage = *this->getGeometryProcessor();
269 const GrGeometryProcessor* gp = stage.getProcessor();
270 SkASSERT(gp);
egdaniel89af44a2014-09-26 06:15:04 -0700271 // make sure that any attribute indices have the correct binding type, that the attrib
272 // type and effect's shader lang type are compatible, and that attributes shared by
273 // multiple effects use the same shader lang type.
274 const GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
275
276 int effectIndex = 0;
277 for (int index = 0; index < fVACount; index++) {
278 if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
279 // we only care about effect bindings
280 continue;
281 }
282 SkASSERT(effectIndex < s.count());
283 GrSLType effectSLType = s[effectIndex].getType();
284 GrVertexAttribType attribType = fVAPtr[index].fType;
285 int slVecCount = GrSLTypeVectorCount(effectSLType);
286 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
287 if (slVecCount != attribVecCount ||
288 (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
289 return false;
290 }
291 slTypes[index] = effectSLType;
292 effectIndex++;
293 }
294 // Make sure all attributes are consumed and we were able to find everything
295 SkASSERT(s.count() == effectIndex);
296 }
297
298 return true;
299}
300
301////////////////////////////////////////////////////////////////////////////////
302
egdaniel7b3d5ee2014-08-28 05:41:14 -0700303static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000304 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000305#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000306 uint32_t overlapCheck = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700307 SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000308 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000309 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
egdaniel7b3d5ee2014-08-28 05:41:14 -0700310 size_t attribOffset = attribs[index].fOffset;
311 SkASSERT(attribOffset + attribSize <= stride);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000312 size_t dwordCount = attribSize >> 2;
313 uint32_t mask = (1 << dwordCount)-1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700314 size_t offsetShift = attribOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000315 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000316 overlapCheck |= (mask << offsetShift);
djsollenea81ced2014-08-27 13:07:34 -0700317 }
egdaniel7b3d5ee2014-08-28 05:41:14 -0700318#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000319}
320
321////////////////////////////////////////////////////////////////////////////////
322
egdaniel7b3d5ee2014-08-28 05:41:14 -0700323void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count,
324 size_t stride) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000325 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000326
bsalomon2ed5ef82014-07-07 08:44:05 -0700327 fVAPtr = attribs;
328 fVACount = count;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700329 fVAStride = stride;
330 validate_vertex_attribs(fVAPtr, fVACount, fVAStride);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000331
332 // Set all the indices to -1
bsalomon2ed5ef82014-07-07 08:44:05 -0700333 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000334 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700335 sizeof(fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000336#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000337 uint32_t overlapCheck = 0;
338#endif
339 for (int i = 0; i < count; ++i) {
340 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
341 // The fixed function attribs can only be specified once
bsalomon2ed5ef82014-07-07 08:44:05 -0700342 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000343 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000344 GrVertexAttribTypeVectorCount(attribs[i].fType));
bsalomon2ed5ef82014-07-07 08:44:05 -0700345 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000346 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000347#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000348 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
349 uint32_t mask = (1 << dwordCount)-1;
350 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000351 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000352 overlapCheck |= (mask << offsetShift);
353#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000354 }
egdaniel3658f382014-09-15 07:01:59 -0700355 this->invalidateOptState();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000356 // Positions must be specified.
bsalomon2ed5ef82014-07-07 08:44:05 -0700357 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000358}
359
360////////////////////////////////////////////////////////////////////////////////
361
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000362void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000363 static const GrVertexAttrib kPositionAttrib =
364 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000365
bsalomon2ed5ef82014-07-07 08:44:05 -0700366 fVAPtr = &kPositionAttrib;
367 fVACount = 1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700368 fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
robertphillips@google.com42903302013-04-20 12:26:07 +0000369
jvanverth@google.com054ae992013-04-01 20:06:51 +0000370 // set all the fixed function indices to -1 except position.
bsalomon2ed5ef82014-07-07 08:44:05 -0700371 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000372 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700373 sizeof(fFixedFunctionVertexAttribIndices));
374 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
egdaniel3658f382014-09-15 07:01:59 -0700375 this->invalidateOptState();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000376}
377
378////////////////////////////////////////////////////////////////////////////////
379
bsalomon62c447d2014-08-08 08:08:50 -0700380bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
381 if (caps.dualSourceBlendingSupport()) {
382 return true;
383 }
384 // we can correctly apply coverage if a) we have dual source blending
385 // or b) one of our blend optimizations applies
386 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
387 GrBlendCoeff srcCoeff;
388 GrBlendCoeff dstCoeff;
egdaniel170f90b2014-09-16 12:54:40 -0700389 BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
egdaniel89af44a2014-09-26 06:15:04 -0700390 return GrDrawState::kNone_BlendOpt != flag ||
bsalomon62c447d2014-08-08 08:08:50 -0700391 (this->willEffectReadDstColor() &&
392 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
393}
394
egdaniel89af44a2014-09-26 06:15:04 -0700395bool GrDrawState::hasSolidCoverage() const {
396 // If we're drawing coverage directly then coverage is effectively treated as color.
397 if (this->isCoverageDrawing()) {
398 return true;
399 }
400
egdaniel1a8ecdf2014-10-03 06:24:12 -0700401 GrProcessor::InvariantOutput inout;
402 inout.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700403 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
404 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700405 inout.fValidFlags = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700406 } else {
joshualitt65171342014-10-09 07:25:36 -0700407 inout.fColor = this->getCoverageColor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700408 inout.fValidFlags = kRGBA_GrColorComponentFlags;
egdaniel89af44a2014-09-26 06:15:04 -0700409 }
410
411 // Run through the coverage stages and see if the coverage will be all ones at the end.
412 if (this->hasGeometryProcessor()) {
joshualitt89c7a2e2014-10-10 14:11:59 -0700413 const GrGeometryProcessor* gp = fGeometryProcessor->getProcessor();
414 gp->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700415 }
joshualitt65171342014-10-09 07:25:36 -0700416
egdaniel89af44a2014-09-26 06:15:04 -0700417 for (int s = 0; s < this->numCoverageStages(); ++s) {
418 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700419 processor->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700420 }
egdaniel1a8ecdf2014-10-03 06:24:12 -0700421 return inout.isSolidWhite();
egdaniel89af44a2014-09-26 06:15:04 -0700422}
423
egdaniel21aed572014-08-26 12:24:06 -0700424//////////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000425
egdaniel3658f382014-09-15 07:01:59 -0700426GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
bsalomon49f085d2014-09-05 13:34:00 -0700427 SkASSERT(drawState);
egdaniel21aed572014-08-26 12:24:06 -0700428 fDrawState = drawState;
429 fVAPtr = drawState->fVAPtr;
430 fVACount = drawState->fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700431 fVAStride = drawState->fVAStride;
egdaniel21aed572014-08-26 12:24:06 -0700432 fDrawState->setDefaultVertexAttribs();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000433}
434
egdaniel21aed572014-08-26 12:24:06 -0700435//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000436
egdaniel89af44a2014-09-26 06:15:04 -0700437bool GrDrawState::willEffectReadDstColor() const {
438 if (!this->isColorWriteDisabled()) {
439 for (int s = 0; s < this->numColorStages(); ++s) {
joshualitt47bb3822014-10-07 16:43:25 -0700440 if (this->getColorStage(s).getProcessor()->willReadDstColor()) {
egdaniel89af44a2014-09-26 06:15:04 -0700441 return true;
442 }
443 }
444 }
445 for (int s = 0; s < this->numCoverageStages(); ++s) {
joshualitt47bb3822014-10-07 16:43:25 -0700446 if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) {
egdaniel89af44a2014-09-26 06:15:04 -0700447 return true;
448 }
449 }
450 return false;
451}
452
egdaniel21aed572014-08-26 12:24:06 -0700453void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700454 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700455 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700456 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700457 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700458 } else {
joshualitt89c7a2e2014-10-10 14:11:59 -0700459 SkASSERT(fDrawState->getGeometryProcessor()->getProcessor()->getUniqueID() ==
bsalomon52e9d632014-09-05 12:23:12 -0700460 fOriginalGPID);
461 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700462 }
joshualittbd769d02014-09-04 08:56:46 -0700463
egdaniel21aed572014-08-26 12:24:06 -0700464 int m = fDrawState->numColorStages() - fColorEffectCnt;
465 SkASSERT(m >= 0);
466 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000467
egdaniel21aed572014-08-26 12:24:06 -0700468 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
469 SkASSERT(n >= 0);
470 fDrawState->fCoverageStages.pop_back_n(n);
471 if (m + n > 0) {
egdaniel3658f382014-09-15 07:01:59 -0700472 fDrawState->invalidateOptState();
egdaniel21aed572014-08-26 12:24:06 -0700473 }
474 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000475 }
egdaniel21aed572014-08-26 12:24:06 -0700476 fDrawState = ds;
477 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700478 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700479 if (NULL != ds->getGeometryProcessor()) {
joshualitt89c7a2e2014-10-10 14:11:59 -0700480 fOriginalGPID = ds->getGeometryProcessor()->getProcessor()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700481 }
egdaniel21aed572014-08-26 12:24:06 -0700482 fColorEffectCnt = ds->numColorStages();
483 fCoverageEffectCnt = ds->numCoverageStages();
484 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
485 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000486}
487
jvanverth@google.comcc782382013-01-28 20:39:48 +0000488////////////////////////////////////////////////////////////////////////////////
489
egdaniel89af44a2014-09-26 06:15:04 -0700490// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
491// others will blend incorrectly.
492bool GrDrawState::canTweakAlphaForCoverage() const {
493 /*
494 The fractional coverage is f.
495 The src and dst coeffs are Cs and Cd.
496 The dst and src colors are S and D.
497 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
498 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
499 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
500 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
501 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
502 color by definition.
503 */
504 return kOne_GrBlendCoeff == fDstBlend ||
505 kISA_GrBlendCoeff == fDstBlend ||
506 kISC_GrBlendCoeff == fDstBlend ||
507 this->isCoverageDrawing();
508}
509
510////////////////////////////////////////////////////////////////////////////////
511
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000512void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700513 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000514 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700515 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000516 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000517 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
joshualitt89c7a2e2014-10-10 14:11:59 -0700518 numCoverageStages -= fHasGeometryProcessor ? 1 : 0;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000519 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000520
521 int i = 0;
joshualitt89c7a2e2014-10-10 14:11:59 -0700522 if (fHasGeometryProcessor) {
523 SkASSERT(fDrawState->hasGeometryProcessor());
524 fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]);
525 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000526 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700527 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000528 }
529 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700530 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000531 }
egdaniel3658f382014-09-15 07:01:59 -0700532 fDrawState->invalidateOptState();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000533 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000534 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000535}
536
537void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000538 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000539 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000540
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000541 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000542 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000543 return;
544 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000545 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000546
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000547 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700548 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000549
550 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000551 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
egdaniel3658f382014-09-15 07:01:59 -0700552 drawState->invalidateOptState();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000553}
554
bsalomon@google.com137f1342013-05-29 21:27:53 +0000555bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000556 this->restore();
557
bsalomon@google.com137f1342013-05-29 21:27:53 +0000558 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000559 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000560 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000561
bsalomon@google.com137f1342013-05-29 21:27:53 +0000562 if (drawState->getViewMatrix().isIdentity()) {
563 return true;
564 }
565
egdaniel3658f382014-09-15 07:01:59 -0700566 drawState->invalidateOptState();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000567 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000568 if (0 == drawState->numTotalStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700569 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000570 fDrawState = drawState;
joshualitt89c7a2e2014-10-10 14:11:59 -0700571 fHasGeometryProcessor = false;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000572 fNumColorStages = 0;
573 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000574 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000575 return true;
576 } else {
577 SkMatrix inv;
578 if (!fViewMatrix.invert(&inv)) {
579 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000580 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700581 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000582 fDrawState = drawState;
583 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000584 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000585 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000586 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000587}
588
589void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
590 fSavedCoordChanges.reset(fDrawState->numTotalStages());
591 int i = 0;
592
joshualitt89c7a2e2014-10-10 14:11:59 -0700593 fHasGeometryProcessor = false;
594 if (fDrawState->hasGeometryProcessor()) {
595 fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]);
596 fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix);
597 fHasGeometryProcessor = true;
598 }
599
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000600 fNumColorStages = fDrawState->numColorStages();
601 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700602 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700603 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000604 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000605
606 int numCoverageStages = fDrawState->numCoverageStages();
607 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700608 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700609 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000610 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000611}
egdaniel21aed572014-08-26 12:24:06 -0700612
egdaniel170f90b2014-09-16 12:54:40 -0700613////////////////////////////////////////////////////////////////////////////////
614
egdaniel89af44a2014-09-26 06:15:04 -0700615void GrDrawState::convertToPendingExec() {
616 fRenderTarget.markPendingIO();
617 fRenderTarget.removeRef();
618 for (int i = 0; i < fColorStages.count(); ++i) {
619 fColorStages[i].convertToPendingExec();
620 }
621 if (fGeometryProcessor) {
joshualitt89c7a2e2014-10-10 14:11:59 -0700622 fGeometryProcessor->convertToPendingExec();
egdaniel89af44a2014-09-26 06:15:04 -0700623 }
624 for (int i = 0; i < fCoverageStages.count(); ++i) {
625 fCoverageStages[i].convertToPendingExec();
626 }
627}
628
629////////////////////////////////////////////////////////////////////////////////
630
egdaniel170f90b2014-09-16 12:54:40 -0700631void GrDrawState::invalidateOptState() const {
632 SkSafeSetNull(fCachedOptState);
633}
634
635////////////////////////////////////////////////////////////////////////////////
636
637GrDrawState::~GrDrawState() {
638 SkSafeUnref(fCachedOptState);
639 SkASSERT(0 == fBlockEffectRemovalCnt);
640}
641
egdaniel89af44a2014-09-26 06:15:04 -0700642////////////////////////////////////////////////////////////////////////////////
643
644GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
joshualitt65171342014-10-09 07:25:36 -0700645 GrBlendCoeff* srcCoeff,
646 GrBlendCoeff* dstCoeff) const {
egdaniel89af44a2014-09-26 06:15:04 -0700647 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
648 if (NULL == srcCoeff) {
649 srcCoeff = &bogusSrcCoeff;
650 }
651 if (NULL == dstCoeff) {
652 dstCoeff = &bogusDstCoeff;
653 }
654
655 *srcCoeff = this->getSrcBlendCoeff();
656 *dstCoeff = this->getDstBlendCoeff();
657
658 if (this->isColorWriteDisabled()) {
659 *srcCoeff = kZero_GrBlendCoeff;
660 *dstCoeff = kOne_GrBlendCoeff;
661 }
662
663 bool srcAIsOne = this->srcAlphaWillBeOne();
664 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
665 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
666 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
667 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
668
669 // When coeffs are (0,1) there is no reason to draw at all, unless
670 // stenciling is enabled. Having color writes disabled is effectively
671 // (0,1).
672 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
673 if (this->getStencil().doesWrite()) {
674 return kEmitCoverage_BlendOptFlag;
675 } else {
676 *dstCoeff = kOne_GrBlendCoeff;
677 return kSkipDraw_BlendOptFlag;
678 }
679 }
680
681 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
682
683 // if we don't have coverage we can check whether the dst
684 // has to read at all. If not, we'll disable blending.
685 if (!hasCoverage) {
686 if (dstCoeffIsZero) {
687 if (kOne_GrBlendCoeff == *srcCoeff) {
688 // if there is no coverage and coeffs are (1,0) then we
689 // won't need to read the dst at all, it gets replaced by src
690 *dstCoeff = kZero_GrBlendCoeff;
691 return kNone_BlendOpt;
692 } else if (kZero_GrBlendCoeff == *srcCoeff) {
693 // if the op is "clear" then we don't need to emit a color
694 // or blend, just write transparent black into the dst.
695 *srcCoeff = kOne_GrBlendCoeff;
696 *dstCoeff = kZero_GrBlendCoeff;
697 return kEmitTransBlack_BlendOptFlag;
698 }
699 }
700 } else if (this->isCoverageDrawing()) {
701 // we have coverage but we aren't distinguishing it from alpha by request.
702 return kCoverageAsAlpha_BlendOptFlag;
703 } else {
704 // check whether coverage can be safely rolled into alpha
705 // of if we can skip color computation and just emit coverage
706 if (this->canTweakAlphaForCoverage()) {
707 return kCoverageAsAlpha_BlendOptFlag;
708 }
709 if (dstCoeffIsZero) {
710 if (kZero_GrBlendCoeff == *srcCoeff) {
711 // the source color is not included in the blend
712 // the dst coeff is effectively zero so blend works out to:
713 // (c)(0)D + (1-c)D = (1-c)D.
714 *dstCoeff = kISA_GrBlendCoeff;
715 return kEmitCoverage_BlendOptFlag;
716 } else if (srcAIsOne) {
717 // the dst coeff is effectively zero so blend works out to:
718 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
719 // If Sa is 1 then we can replace Sa with c
720 // and set dst coeff to 1-Sa.
721 *dstCoeff = kISA_GrBlendCoeff;
722 return kCoverageAsAlpha_BlendOptFlag;
723 }
724 } else if (dstCoeffIsOne) {
725 // the dst coeff is effectively one so blend works out to:
726 // cS + (c)(1)D + (1-c)D = cS + D.
727 *dstCoeff = kOne_GrBlendCoeff;
728 return kCoverageAsAlpha_BlendOptFlag;
729 }
730 }
731
732 return kNone_BlendOpt;
733}
734
735
736bool GrDrawState::srcAlphaWillBeOne() const {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700737 GrProcessor::InvariantOutput inoutColor;
738 inoutColor.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700739 // Check if per-vertex or constant color may have partial alpha
740 if (this->hasColorVertexAttribute()) {
741 if (fHints & kVertexColorsAreOpaque_Hint) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700742 inoutColor.fValidFlags = kA_GrColorComponentFlag;
743 inoutColor.fColor = 0xFF << GrColor_SHIFT_A;
egdaniel89af44a2014-09-26 06:15:04 -0700744 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700745 inoutColor.fValidFlags = 0;
746 // not strictly necessary but we get false alarms from tools about uninit.
747 inoutColor.fColor = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700748 }
749 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700750 inoutColor.fValidFlags = kRGBA_GrColorComponentFlags;
751 inoutColor.fColor = this->getColor();
egdaniel89af44a2014-09-26 06:15:04 -0700752 }
753
754 // Run through the color stages
755 for (int s = 0; s < this->numColorStages(); ++s) {
756 const GrProcessor* processor = this->getColorStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700757 processor->computeInvariantOutput(&inoutColor);
egdaniel89af44a2014-09-26 06:15:04 -0700758 }
759
760 // Check whether coverage is treated as color. If so we run through the coverage computation.
761 if (this->isCoverageDrawing()) {
762 // The shader generated for coverage drawing runs the full coverage computation and then
763 // makes the shader output be the multiplication of color and coverage. We mirror that here.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700764 GrProcessor::InvariantOutput inoutCoverage;
765 inoutCoverage.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700766 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700767 inoutCoverage.fValidFlags = 0;
768 inoutCoverage.fColor = 0; // suppresses any warnings.
egdaniel89af44a2014-09-26 06:15:04 -0700769 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700770 inoutCoverage.fValidFlags = kRGBA_GrColorComponentFlags;
771 inoutCoverage.fColor = this->getCoverageColor();
egdaniel89af44a2014-09-26 06:15:04 -0700772 }
773
774 // Run through the coverage stages
775 for (int s = 0; s < this->numCoverageStages(); ++s) {
776 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700777 processor->computeInvariantOutput(&inoutCoverage);
egdaniel89af44a2014-09-26 06:15:04 -0700778 }
779
780 // Since the shader will multiply coverage and color, the only way the final A==1 is if
781 // coverage and color both have A==1.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700782 return (inoutColor.isOpaque() && inoutCoverage.isOpaque());
egdaniel89af44a2014-09-26 06:15:04 -0700783 }
784
egdaniel1a8ecdf2014-10-03 06:24:12 -0700785 return inoutColor.isOpaque();
egdaniel89af44a2014-09-26 06:15:04 -0700786}
787