blob: b4cf9c8b4106228fc45d57a72e8ec5e7a7a8b9dd [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
egdanielc0648242014-09-22 13:17:02 -070015GrOptDrawState* GrDrawState::createOptState(const GrDrawTargetCaps& caps) const {
16 if (NULL == fCachedOptState || caps.getUniqueID() != fCachedCapsID) {
egdaniel170f90b2014-09-16 12:54:40 -070017 GrBlendCoeff srcCoeff;
18 GrBlendCoeff dstCoeff;
egdaniel89af44a2014-09-26 06:15:04 -070019 GrOptDrawState::BlendOptFlags blendFlags =
20 (GrOptDrawState::BlendOptFlags) this->getBlendOpts(false, &srcCoeff, &dstCoeff);
egdanielc0648242014-09-22 13:17:02 -070021 fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this, blendFlags, srcCoeff, dstCoeff, caps));
22 fCachedCapsID = caps.getUniqueID();
egdaniel3658f382014-09-15 07:01:59 -070023 } else {
egdaniel170f90b2014-09-16 12:54:40 -070024#ifdef SK_DEBUG
25 GrBlendCoeff srcCoeff;
26 GrBlendCoeff dstCoeff;
egdaniel89af44a2014-09-26 06:15:04 -070027 GrOptDrawState::BlendOptFlags blendFlags =
28 (GrOptDrawState::BlendOptFlags) this->getBlendOpts(false, &srcCoeff, &dstCoeff);
egdanielc0648242014-09-22 13:17:02 -070029 SkASSERT(GrOptDrawState(*this, blendFlags, srcCoeff, dstCoeff, caps) == *fCachedOptState);
egdaniel170f90b2014-09-16 12:54:40 -070030#endif
egdaniel3658f382014-09-15 07:01:59 -070031 }
32 fCachedOptState->ref();
33 return fCachedOptState;
34}
bsalomon@google.comaf84e742012-10-05 13:23:24 +000035
bsalomon8f727332014-08-05 07:50:06 -070036//////////////////////////////////////////////////////////////////////////////s
37
egdaniel89af44a2014-09-26 06:15:04 -070038bool GrDrawState::isEqual(const GrDrawState& that) const {
39 bool usingVertexColors = this->hasColorVertexAttribute();
40 if (!usingVertexColors && this->fColor != that.fColor) {
41 return false;
42 }
43
44 if (this->getRenderTarget() != that.getRenderTarget() ||
45 this->fColorStages.count() != that.fColorStages.count() ||
46 this->fCoverageStages.count() != that.fCoverageStages.count() ||
47 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
48 this->fSrcBlend != that.fSrcBlend ||
49 this->fDstBlend != that.fDstBlend ||
50 this->fBlendConstant != that.fBlendConstant ||
51 this->fFlagBits != that.fFlagBits ||
52 this->fVACount != that.fVACount ||
53 this->fVAStride != that.fVAStride ||
54 memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
55 this->fStencilSettings != that.fStencilSettings ||
56 this->fDrawFace != that.fDrawFace) {
57 return false;
58 }
59
60 bool usingVertexCoverage = this->hasCoverageVertexAttribute();
61 if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
62 return false;
63 }
64
65 bool explicitLocalCoords = this->hasLocalCoordAttribute();
66 if (this->hasGeometryProcessor()) {
67 if (!that.hasGeometryProcessor()) {
68 return false;
69 } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
70 *that.getGeometryProcessor(),
71 explicitLocalCoords)) {
72 return false;
73 }
74 } else if (that.hasGeometryProcessor()) {
75 return false;
76 }
77
78 for (int i = 0; i < this->numColorStages(); i++) {
79 if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
80 explicitLocalCoords)) {
81 return false;
82 }
83 }
84 for (int i = 0; i < this->numCoverageStages(); i++) {
85 if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
86 explicitLocalCoords)) {
87 return false;
88 }
89 }
90
91 SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
92 that.fFixedFunctionVertexAttribIndices,
93 sizeof(this->fFixedFunctionVertexAttribIndices)));
94
95 return true;
96}
97
bsalomon8f727332014-08-05 07:50:06 -070098GrDrawState::CombinedState GrDrawState::CombineIfPossible(
bsalomon62c447d2014-08-08 08:08:50 -070099 const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
bsalomon8f727332014-08-05 07:50:06 -0700100
egdaniel21aed572014-08-26 12:24:06 -0700101 if (!a.isEqual(b)) {
bsalomon8f727332014-08-05 07:50:06 -0700102 return kIncompatible_CombinedState;
103 }
104
egdaniel21aed572014-08-26 12:24:06 -0700105 // If the general draw states are equal (from check above) we know hasColorVertexAttribute()
106 // is equivalent for both a and b
107 if (a.hasColorVertexAttribute()) {
bsalomon62c447d2014-08-08 08:08:50 -0700108 // If one is opaque and the other is not then the combined state is not opaque. Moreover,
109 // if the opaqueness affects the ability to get color/coverage blending correct then we
110 // don't combine the draw states.
111 bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
112 bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
113 if (aIsOpaque != bIsOpaque) {
114 const GrDrawState* opaque;
115 const GrDrawState* nonOpaque;
116 if (aIsOpaque) {
117 opaque = &a;
118 nonOpaque = &b;
119 } else {
120 opaque = &b;
121 nonOpaque = &a;
122 }
123 if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
124 SkASSERT(!nonOpaque->hasSolidCoverage());
125 if (!nonOpaque->couldApplyCoverage(caps)) {
126 return kIncompatible_CombinedState;
127 }
128 }
129 return aIsOpaque ? kB_CombinedState : kA_CombinedState;
130 }
131 }
bsalomon8f727332014-08-05 07:50:06 -0700132 return kAOrB_CombinedState;
133}
134
bsalomon8f727332014-08-05 07:50:06 -0700135//////////////////////////////////////////////////////////////////////////////s
136
egdaniel3658f382014-09-15 07:01:59 -0700137GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix)
138 : fCachedOptState(NULL) {
bsalomon8f727332014-08-05 07:50:06 -0700139 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
140 *this = state;
141 if (!preConcatMatrix.isIdentity()) {
joshualittbd769d02014-09-04 08:56:46 -0700142 if (this->hasGeometryProcessor()) {
143 fGeometryProcessor->localCoordChange(preConcatMatrix);
144 }
egdaniel776bdbd2014-08-06 11:07:02 -0700145 for (int i = 0; i < this->numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700146 fColorStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -0700147 }
egdaniel776bdbd2014-08-06 11:07:02 -0700148 for (int i = 0; i < this->numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700149 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon8f727332014-08-05 07:50:06 -0700150 }
egdaniel3658f382014-09-15 07:01:59 -0700151 this->invalidateOptState();
bsalomon8f727332014-08-05 07:50:06 -0700152 }
153}
154
155GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
156 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700157 SkASSERT(!that.fRenderTarget.ownsPendingIO());
158 SkASSERT(!this->fRenderTarget.ownsPendingIO());
159 this->setRenderTarget(that.getRenderTarget());
bsalomon8f727332014-08-05 07:50:06 -0700160 fColor = that.fColor;
161 fViewMatrix = that.fViewMatrix;
egdaniel8cbf3d52014-08-21 06:27:22 -0700162 fSrcBlend = that.fSrcBlend;
163 fDstBlend = that.fDstBlend;
bsalomon8f727332014-08-05 07:50:06 -0700164 fBlendConstant = that.fBlendConstant;
165 fFlagBits = that.fFlagBits;
166 fVACount = that.fVACount;
167 fVAPtr = that.fVAPtr;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700168 fVAStride = that.fVAStride;
bsalomon8f727332014-08-05 07:50:06 -0700169 fStencilSettings = that.fStencilSettings;
170 fCoverage = that.fCoverage;
171 fDrawFace = that.fDrawFace;
joshualittbd769d02014-09-04 08:56:46 -0700172 if (that.hasGeometryProcessor()) {
joshualittb0a8a372014-09-23 09:50:21 -0700173 fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*that.fGeometryProcessor.get())));
joshualittbd769d02014-09-04 08:56:46 -0700174 } else {
175 fGeometryProcessor.reset(NULL);
176 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700177 fColorStages = that.fColorStages;
178 fCoverageStages = that.fCoverageStages;
bsalomon8f727332014-08-05 07:50:06 -0700179
bsalomon62c447d2014-08-08 08:08:50 -0700180 fHints = that.fHints;
egdaniel776bdbd2014-08-06 11:07:02 -0700181
egdaniel3658f382014-09-15 07:01:59 -0700182 SkRefCnt_SafeAssign(fCachedOptState, that.fCachedOptState);
183
bsalomon8f727332014-08-05 07:50:06 -0700184 memcpy(fFixedFunctionVertexAttribIndices,
185 that.fFixedFunctionVertexAttribIndices,
186 sizeof(fFixedFunctionVertexAttribIndices));
187 return *this;
188}
189
190void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
191 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2a9ca782014-09-05 14:27:43 -0700192 SkASSERT(!fRenderTarget.ownsPendingIO());
193
joshualittbd769d02014-09-04 08:56:46 -0700194 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700195 fColorStages.reset();
196 fCoverageStages.reset();
bsalomon8f727332014-08-05 07:50:06 -0700197
bsalomon2a9ca782014-09-05 14:27:43 -0700198 fRenderTarget.reset();
bsalomon8f727332014-08-05 07:50:06 -0700199
200 this->setDefaultVertexAttribs();
201
202 fColor = 0xffffffff;
203 if (NULL == initialViewMatrix) {
204 fViewMatrix.reset();
205 } else {
206 fViewMatrix = *initialViewMatrix;
207 }
egdaniel8cbf3d52014-08-21 06:27:22 -0700208 fSrcBlend = kOne_GrBlendCoeff;
209 fDstBlend = kZero_GrBlendCoeff;
bsalomon8f727332014-08-05 07:50:06 -0700210 fBlendConstant = 0x0;
211 fFlagBits = 0x0;
212 fStencilSettings.setDisabled();
egdaniel8cbf3d52014-08-21 06:27:22 -0700213 fCoverage = 0xff;
bsalomon8f727332014-08-05 07:50:06 -0700214 fDrawFace = kBoth_DrawFace;
215
bsalomon62c447d2014-08-08 08:08:50 -0700216 fHints = 0;
217
egdaniel3658f382014-09-15 07:01:59 -0700218 this->invalidateOptState();
bsalomon8f727332014-08-05 07:50:06 -0700219}
220
bsalomon@google.com137f1342013-05-29 21:27:53 +0000221bool GrDrawState::setIdentityViewMatrix() {
egdaniel776bdbd2014-08-06 11:07:02 -0700222 if (this->numTotalStages()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000223 SkMatrix invVM;
bsalomon2ed5ef82014-07-07 08:44:05 -0700224 if (!fViewMatrix.invert(&invVM)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000225 // sad trombone sound
226 return false;
227 }
joshualittbd769d02014-09-04 08:56:46 -0700228 if (this->hasGeometryProcessor()) {
229 fGeometryProcessor->localCoordChange(invVM);
230 }
egdaniel776bdbd2014-08-06 11:07:02 -0700231 for (int s = 0; s < this->numColorStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700232 fColorStages[s].localCoordChange(invVM);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000233 }
egdaniel776bdbd2014-08-06 11:07:02 -0700234 for (int s = 0; s < this->numCoverageStages(); ++s) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700235 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000236 }
237 }
egdaniel3658f382014-09-15 07:01:59 -0700238 this->invalidateOptState();
bsalomon2ed5ef82014-07-07 08:44:05 -0700239 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000240 return true;
241}
242
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000243void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000244 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000245
joshualittbd769d02014-09-04 08:56:46 -0700246 fGeometryProcessor.reset(NULL);
egdaniel8cbf3d52014-08-21 06:27:22 -0700247 fColorStages.reset();
248 fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000249
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000250 for (int i = 0; i < paint.numColorStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700251 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000252 }
253
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000254 for (int i = 0; i < paint.numCoverageStages(); ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700255 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000256 }
257
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000258 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000259
bsalomon2ed5ef82014-07-07 08:44:05 -0700260 fViewMatrix = vm;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000261
262 // These have no equivalent in GrPaint, set them to defaults
bsalomon2ed5ef82014-07-07 08:44:05 -0700263 fBlendConstant = 0x0;
264 fDrawFace = kBoth_DrawFace;
265 fStencilSettings.setDisabled();
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000266 this->resetStateFlags();
bsalomon62c447d2014-08-08 08:08:50 -0700267 fHints = 0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000268
bsalomon@google.com21c10c52013-06-13 17:44:07 +0000269 // Enable the clip bit
270 this->enableState(GrDrawState::kClip_StateBit);
271
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +0000272 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000273 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
274 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000275
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000276 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +0000277 this->setCoverage(paint.getCoverage());
egdaniel3658f382014-09-15 07:01:59 -0700278 this->invalidateOptState();
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000279}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000280
281////////////////////////////////////////////////////////////////////////////////
282
egdaniel89af44a2014-09-26 06:15:04 -0700283bool GrDrawState::validateVertexAttribs() const {
284 // check consistency of effects and attributes
285 GrSLType slTypes[kMaxVertexAttribCnt];
286 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
287 slTypes[i] = static_cast<GrSLType>(-1);
288 }
289
290 if (this->hasGeometryProcessor()) {
291 const GrGeometryStage& stage = *this->getGeometryProcessor();
292 const GrGeometryProcessor* gp = stage.getGeometryProcessor();
293 SkASSERT(gp);
294 // make sure that any attribute indices have the correct binding type, that the attrib
295 // type and effect's shader lang type are compatible, and that attributes shared by
296 // multiple effects use the same shader lang type.
297 const GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
298
299 int effectIndex = 0;
300 for (int index = 0; index < fVACount; index++) {
301 if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
302 // we only care about effect bindings
303 continue;
304 }
305 SkASSERT(effectIndex < s.count());
306 GrSLType effectSLType = s[effectIndex].getType();
307 GrVertexAttribType attribType = fVAPtr[index].fType;
308 int slVecCount = GrSLTypeVectorCount(effectSLType);
309 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
310 if (slVecCount != attribVecCount ||
311 (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
312 return false;
313 }
314 slTypes[index] = effectSLType;
315 effectIndex++;
316 }
317 // Make sure all attributes are consumed and we were able to find everything
318 SkASSERT(s.count() == effectIndex);
319 }
320
321 return true;
322}
323
324////////////////////////////////////////////////////////////////////////////////
325
egdaniel7b3d5ee2014-08-28 05:41:14 -0700326static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000327 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000328#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000329 uint32_t overlapCheck = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700330 SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000331 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000332 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
egdaniel7b3d5ee2014-08-28 05:41:14 -0700333 size_t attribOffset = attribs[index].fOffset;
334 SkASSERT(attribOffset + attribSize <= stride);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000335 size_t dwordCount = attribSize >> 2;
336 uint32_t mask = (1 << dwordCount)-1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700337 size_t offsetShift = attribOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000338 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000339 overlapCheck |= (mask << offsetShift);
djsollenea81ced2014-08-27 13:07:34 -0700340 }
egdaniel7b3d5ee2014-08-28 05:41:14 -0700341#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000342}
343
344////////////////////////////////////////////////////////////////////////////////
345
egdaniel7b3d5ee2014-08-28 05:41:14 -0700346void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count,
347 size_t stride) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000348 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000349
bsalomon2ed5ef82014-07-07 08:44:05 -0700350 fVAPtr = attribs;
351 fVACount = count;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700352 fVAStride = stride;
353 validate_vertex_attribs(fVAPtr, fVACount, fVAStride);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000354
355 // Set all the indices to -1
bsalomon2ed5ef82014-07-07 08:44:05 -0700356 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000357 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700358 sizeof(fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000359#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000360 uint32_t overlapCheck = 0;
361#endif
362 for (int i = 0; i < count; ++i) {
363 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
364 // The fixed function attribs can only be specified once
bsalomon2ed5ef82014-07-07 08:44:05 -0700365 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000366 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000367 GrVertexAttribTypeVectorCount(attribs[i].fType));
bsalomon2ed5ef82014-07-07 08:44:05 -0700368 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000369 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000370#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000371 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
372 uint32_t mask = (1 << dwordCount)-1;
373 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000374 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000375 overlapCheck |= (mask << offsetShift);
376#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000377 }
egdaniel3658f382014-09-15 07:01:59 -0700378 this->invalidateOptState();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000379 // Positions must be specified.
bsalomon2ed5ef82014-07-07 08:44:05 -0700380 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000381}
382
383////////////////////////////////////////////////////////////////////////////////
384
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000385void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000386 static const GrVertexAttrib kPositionAttrib =
387 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000388
bsalomon2ed5ef82014-07-07 08:44:05 -0700389 fVAPtr = &kPositionAttrib;
390 fVACount = 1;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700391 fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
robertphillips@google.com42903302013-04-20 12:26:07 +0000392
jvanverth@google.com054ae992013-04-01 20:06:51 +0000393 // set all the fixed function indices to -1 except position.
bsalomon2ed5ef82014-07-07 08:44:05 -0700394 memset(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000395 0xff,
bsalomon2ed5ef82014-07-07 08:44:05 -0700396 sizeof(fFixedFunctionVertexAttribIndices));
397 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
egdaniel3658f382014-09-15 07:01:59 -0700398 this->invalidateOptState();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000399}
400
401////////////////////////////////////////////////////////////////////////////////
402
bsalomon62c447d2014-08-08 08:08:50 -0700403bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
404 if (caps.dualSourceBlendingSupport()) {
405 return true;
406 }
407 // we can correctly apply coverage if a) we have dual source blending
408 // or b) one of our blend optimizations applies
409 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
410 GrBlendCoeff srcCoeff;
411 GrBlendCoeff dstCoeff;
egdaniel170f90b2014-09-16 12:54:40 -0700412 BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
egdaniel89af44a2014-09-26 06:15:04 -0700413 return GrDrawState::kNone_BlendOpt != flag ||
bsalomon62c447d2014-08-08 08:08:50 -0700414 (this->willEffectReadDstColor() &&
415 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
416}
417
egdaniel89af44a2014-09-26 06:15:04 -0700418bool GrDrawState::hasSolidCoverage() const {
419 // If we're drawing coverage directly then coverage is effectively treated as color.
420 if (this->isCoverageDrawing()) {
421 return true;
422 }
423
egdaniel1a8ecdf2014-10-03 06:24:12 -0700424 GrProcessor::InvariantOutput inout;
425 inout.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700426 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
427 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700428 inout.fValidFlags = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700429 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700430 inout.fColor = fCoverage;
431 inout.fValidFlags = kRGBA_GrColorComponentFlags;
egdaniel89af44a2014-09-26 06:15:04 -0700432 }
433
434 // Run through the coverage stages and see if the coverage will be all ones at the end.
435 if (this->hasGeometryProcessor()) {
436 const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700437 gp->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700438 }
439 for (int s = 0; s < this->numCoverageStages(); ++s) {
440 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700441 processor->computeInvariantOutput(&inout);
egdaniel89af44a2014-09-26 06:15:04 -0700442 }
egdaniel1a8ecdf2014-10-03 06:24:12 -0700443 return inout.isSolidWhite();
egdaniel89af44a2014-09-26 06:15:04 -0700444}
445
egdaniel21aed572014-08-26 12:24:06 -0700446//////////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000447
egdaniel3658f382014-09-15 07:01:59 -0700448GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
bsalomon49f085d2014-09-05 13:34:00 -0700449 SkASSERT(drawState);
egdaniel21aed572014-08-26 12:24:06 -0700450 fDrawState = drawState;
451 fVAPtr = drawState->fVAPtr;
452 fVACount = drawState->fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700453 fVAStride = drawState->fVAStride;
egdaniel21aed572014-08-26 12:24:06 -0700454 fDrawState->setDefaultVertexAttribs();
jvanverth@google.comcc782382013-01-28 20:39:48 +0000455}
456
egdaniel21aed572014-08-26 12:24:06 -0700457//////////////////////////////////////////////////////////////////////////////s
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000458
egdaniel89af44a2014-09-26 06:15:04 -0700459bool GrDrawState::willEffectReadDstColor() const {
460 if (!this->isColorWriteDisabled()) {
461 for (int s = 0; s < this->numColorStages(); ++s) {
462 if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) {
463 return true;
464 }
465 }
466 }
467 for (int s = 0; s < this->numCoverageStages(); ++s) {
468 if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
469 return true;
470 }
471 }
472 return false;
473}
474
egdaniel21aed572014-08-26 12:24:06 -0700475void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
bsalomon49f085d2014-09-05 13:34:00 -0700476 if (fDrawState) {
bsalomon9b536522014-09-05 09:18:51 -0700477 // See the big comment on the class definition about GPs.
bsalomon52e9d632014-09-05 12:23:12 -0700478 if (SK_InvalidUniqueID == fOriginalGPID) {
bsalomon9b536522014-09-05 09:18:51 -0700479 fDrawState->fGeometryProcessor.reset(NULL);
bsalomon52e9d632014-09-05 12:23:12 -0700480 } else {
joshualittb0a8a372014-09-23 09:50:21 -0700481 SkASSERT(fDrawState->getGeometryProcessor()->getProcessor()->getUniqueID() ==
bsalomon52e9d632014-09-05 12:23:12 -0700482 fOriginalGPID);
483 fOriginalGPID = SK_InvalidUniqueID;
bsalomon9b536522014-09-05 09:18:51 -0700484 }
joshualittbd769d02014-09-04 08:56:46 -0700485
egdaniel21aed572014-08-26 12:24:06 -0700486 int m = fDrawState->numColorStages() - fColorEffectCnt;
487 SkASSERT(m >= 0);
488 fDrawState->fColorStages.pop_back_n(m);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000489
egdaniel21aed572014-08-26 12:24:06 -0700490 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
491 SkASSERT(n >= 0);
492 fDrawState->fCoverageStages.pop_back_n(n);
493 if (m + n > 0) {
egdaniel3658f382014-09-15 07:01:59 -0700494 fDrawState->invalidateOptState();
egdaniel21aed572014-08-26 12:24:06 -0700495 }
496 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000497 }
egdaniel21aed572014-08-26 12:24:06 -0700498 fDrawState = ds;
499 if (NULL != ds) {
bsalomon52e9d632014-09-05 12:23:12 -0700500 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
bsalomon9b536522014-09-05 09:18:51 -0700501 if (NULL != ds->getGeometryProcessor()) {
joshualittb0a8a372014-09-23 09:50:21 -0700502 fOriginalGPID = ds->getGeometryProcessor()->getProcessor()->getUniqueID();
joshualittbd769d02014-09-04 08:56:46 -0700503 }
egdaniel21aed572014-08-26 12:24:06 -0700504 fColorEffectCnt = ds->numColorStages();
505 fCoverageEffectCnt = ds->numCoverageStages();
506 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
507 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000508}
509
jvanverth@google.comcc782382013-01-28 20:39:48 +0000510////////////////////////////////////////////////////////////////////////////////
511
egdaniel89af44a2014-09-26 06:15:04 -0700512// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
513// others will blend incorrectly.
514bool GrDrawState::canTweakAlphaForCoverage() const {
515 /*
516 The fractional coverage is f.
517 The src and dst coeffs are Cs and Cd.
518 The dst and src colors are S and D.
519 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
520 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
521 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
522 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
523 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
524 color by definition.
525 */
526 return kOne_GrBlendCoeff == fDstBlend ||
527 kISA_GrBlendCoeff == fDstBlend ||
528 kISC_GrBlendCoeff == fDstBlend ||
529 this->isCoverageDrawing();
530}
531
532////////////////////////////////////////////////////////////////////////////////
533
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000534void GrDrawState::AutoViewMatrixRestore::restore() {
bsalomon49f085d2014-09-05 13:34:00 -0700535 if (fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000536 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon2ed5ef82014-07-07 08:44:05 -0700537 fDrawState->fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000538 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000539 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000540 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000541
542 int i = 0;
joshualittbd769d02014-09-04 08:56:46 -0700543 if (fHasGeometryProcessor) {
544 SkASSERT(fDrawState->hasGeometryProcessor());
545 fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]);
546 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000547 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700548 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000549 }
550 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel8cbf3d52014-08-21 06:27:22 -0700551 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000552 }
egdaniel3658f382014-09-15 07:01:59 -0700553 fDrawState->invalidateOptState();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000554 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000555 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000556}
557
558void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000559 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000560 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000561
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000562 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000563 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000564 return;
565 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000566 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000567
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000568 fViewMatrix = drawState->getViewMatrix();
bsalomon2ed5ef82014-07-07 08:44:05 -0700569 drawState->fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000570
571 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000572 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
egdaniel3658f382014-09-15 07:01:59 -0700573 drawState->invalidateOptState();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000574}
575
bsalomon@google.com137f1342013-05-29 21:27:53 +0000576bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000577 this->restore();
578
bsalomon@google.com137f1342013-05-29 21:27:53 +0000579 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000580 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000581 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000582
bsalomon@google.com137f1342013-05-29 21:27:53 +0000583 if (drawState->getViewMatrix().isIdentity()) {
584 return true;
585 }
586
egdaniel3658f382014-09-15 07:01:59 -0700587 drawState->invalidateOptState();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000588 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000589 if (0 == drawState->numTotalStages()) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700590 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000591 fDrawState = drawState;
joshualittbd769d02014-09-04 08:56:46 -0700592 fHasGeometryProcessor = false;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000593 fNumColorStages = 0;
594 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000595 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000596 return true;
597 } else {
598 SkMatrix inv;
599 if (!fViewMatrix.invert(&inv)) {
600 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000601 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700602 drawState->fViewMatrix.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000603 fDrawState = drawState;
604 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000605 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000606 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000607 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000608}
609
610void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
611 fSavedCoordChanges.reset(fDrawState->numTotalStages());
612 int i = 0;
613
joshualittbd769d02014-09-04 08:56:46 -0700614 fHasGeometryProcessor = false;
615 if (fDrawState->hasGeometryProcessor()) {
616 fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]);
617 fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix);
618 fHasGeometryProcessor = true;
619 }
620
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000621 fNumColorStages = fDrawState->numColorStages();
622 for (int s = 0; s < fNumColorStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700623 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700624 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000625 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000626
627 int numCoverageStages = fDrawState->numCoverageStages();
628 for (int s = 0; s < numCoverageStages; ++s, ++i) {
egdaniel776bdbd2014-08-06 11:07:02 -0700629 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
egdaniel8cbf3d52014-08-21 06:27:22 -0700630 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000631 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000632}
egdaniel21aed572014-08-26 12:24:06 -0700633
egdaniel170f90b2014-09-16 12:54:40 -0700634////////////////////////////////////////////////////////////////////////////////
635
egdaniel89af44a2014-09-26 06:15:04 -0700636void GrDrawState::convertToPendingExec() {
637 fRenderTarget.markPendingIO();
638 fRenderTarget.removeRef();
639 for (int i = 0; i < fColorStages.count(); ++i) {
640 fColorStages[i].convertToPendingExec();
641 }
642 if (fGeometryProcessor) {
643 fGeometryProcessor->convertToPendingExec();
644 }
645 for (int i = 0; i < fCoverageStages.count(); ++i) {
646 fCoverageStages[i].convertToPendingExec();
647 }
648}
649
650////////////////////////////////////////////////////////////////////////////////
651
egdaniel170f90b2014-09-16 12:54:40 -0700652void GrDrawState::invalidateOptState() const {
653 SkSafeSetNull(fCachedOptState);
654}
655
656////////////////////////////////////////////////////////////////////////////////
657
658GrDrawState::~GrDrawState() {
659 SkSafeUnref(fCachedOptState);
660 SkASSERT(0 == fBlockEffectRemovalCnt);
661}
662
egdaniel89af44a2014-09-26 06:15:04 -0700663////////////////////////////////////////////////////////////////////////////////
664
665GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
666 GrBlendCoeff* srcCoeff,
667 GrBlendCoeff* dstCoeff) const {
668 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
669 if (NULL == srcCoeff) {
670 srcCoeff = &bogusSrcCoeff;
671 }
672 if (NULL == dstCoeff) {
673 dstCoeff = &bogusDstCoeff;
674 }
675
676 *srcCoeff = this->getSrcBlendCoeff();
677 *dstCoeff = this->getDstBlendCoeff();
678
679 if (this->isColorWriteDisabled()) {
680 *srcCoeff = kZero_GrBlendCoeff;
681 *dstCoeff = kOne_GrBlendCoeff;
682 }
683
684 bool srcAIsOne = this->srcAlphaWillBeOne();
685 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
686 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
687 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
688 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
689
690 // When coeffs are (0,1) there is no reason to draw at all, unless
691 // stenciling is enabled. Having color writes disabled is effectively
692 // (0,1).
693 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
694 if (this->getStencil().doesWrite()) {
695 return kEmitCoverage_BlendOptFlag;
696 } else {
697 *dstCoeff = kOne_GrBlendCoeff;
698 return kSkipDraw_BlendOptFlag;
699 }
700 }
701
702 bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
703
704 // if we don't have coverage we can check whether the dst
705 // has to read at all. If not, we'll disable blending.
706 if (!hasCoverage) {
707 if (dstCoeffIsZero) {
708 if (kOne_GrBlendCoeff == *srcCoeff) {
709 // if there is no coverage and coeffs are (1,0) then we
710 // won't need to read the dst at all, it gets replaced by src
711 *dstCoeff = kZero_GrBlendCoeff;
712 return kNone_BlendOpt;
713 } else if (kZero_GrBlendCoeff == *srcCoeff) {
714 // if the op is "clear" then we don't need to emit a color
715 // or blend, just write transparent black into the dst.
716 *srcCoeff = kOne_GrBlendCoeff;
717 *dstCoeff = kZero_GrBlendCoeff;
718 return kEmitTransBlack_BlendOptFlag;
719 }
720 }
721 } else if (this->isCoverageDrawing()) {
722 // we have coverage but we aren't distinguishing it from alpha by request.
723 return kCoverageAsAlpha_BlendOptFlag;
724 } else {
725 // check whether coverage can be safely rolled into alpha
726 // of if we can skip color computation and just emit coverage
727 if (this->canTweakAlphaForCoverage()) {
728 return kCoverageAsAlpha_BlendOptFlag;
729 }
730 if (dstCoeffIsZero) {
731 if (kZero_GrBlendCoeff == *srcCoeff) {
732 // the source color is not included in the blend
733 // the dst coeff is effectively zero so blend works out to:
734 // (c)(0)D + (1-c)D = (1-c)D.
735 *dstCoeff = kISA_GrBlendCoeff;
736 return kEmitCoverage_BlendOptFlag;
737 } else if (srcAIsOne) {
738 // the dst coeff is effectively zero so blend works out to:
739 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
740 // If Sa is 1 then we can replace Sa with c
741 // and set dst coeff to 1-Sa.
742 *dstCoeff = kISA_GrBlendCoeff;
743 return kCoverageAsAlpha_BlendOptFlag;
744 }
745 } else if (dstCoeffIsOne) {
746 // the dst coeff is effectively one so blend works out to:
747 // cS + (c)(1)D + (1-c)D = cS + D.
748 *dstCoeff = kOne_GrBlendCoeff;
749 return kCoverageAsAlpha_BlendOptFlag;
750 }
751 }
752
753 return kNone_BlendOpt;
754}
755
756
757bool GrDrawState::srcAlphaWillBeOne() const {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700758 GrProcessor::InvariantOutput inoutColor;
759 inoutColor.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700760 // Check if per-vertex or constant color may have partial alpha
761 if (this->hasColorVertexAttribute()) {
762 if (fHints & kVertexColorsAreOpaque_Hint) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700763 inoutColor.fValidFlags = kA_GrColorComponentFlag;
764 inoutColor.fColor = 0xFF << GrColor_SHIFT_A;
egdaniel89af44a2014-09-26 06:15:04 -0700765 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700766 inoutColor.fValidFlags = 0;
767 // not strictly necessary but we get false alarms from tools about uninit.
768 inoutColor.fColor = 0;
egdaniel89af44a2014-09-26 06:15:04 -0700769 }
770 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700771 inoutColor.fValidFlags = kRGBA_GrColorComponentFlags;
772 inoutColor.fColor = this->getColor();
egdaniel89af44a2014-09-26 06:15:04 -0700773 }
774
775 // Run through the color stages
776 for (int s = 0; s < this->numColorStages(); ++s) {
777 const GrProcessor* processor = this->getColorStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700778 processor->computeInvariantOutput(&inoutColor);
egdaniel89af44a2014-09-26 06:15:04 -0700779 }
780
781 // Check whether coverage is treated as color. If so we run through the coverage computation.
782 if (this->isCoverageDrawing()) {
783 // The shader generated for coverage drawing runs the full coverage computation and then
784 // makes the shader output be the multiplication of color and coverage. We mirror that here.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700785 GrProcessor::InvariantOutput inoutCoverage;
786 inoutCoverage.fIsSingleComponent = false;
egdaniel89af44a2014-09-26 06:15:04 -0700787 if (this->hasCoverageVertexAttribute()) {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700788 inoutCoverage.fValidFlags = 0;
789 inoutCoverage.fColor = 0; // suppresses any warnings.
egdaniel89af44a2014-09-26 06:15:04 -0700790 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700791 inoutCoverage.fValidFlags = kRGBA_GrColorComponentFlags;
792 inoutCoverage.fColor = this->getCoverageColor();
egdaniel89af44a2014-09-26 06:15:04 -0700793 }
794
795 // Run through the coverage stages
796 for (int s = 0; s < this->numCoverageStages(); ++s) {
797 const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700798 processor->computeInvariantOutput(&inoutCoverage);
egdaniel89af44a2014-09-26 06:15:04 -0700799 }
800
801 // Since the shader will multiply coverage and color, the only way the final A==1 is if
802 // coverage and color both have A==1.
egdaniel1a8ecdf2014-10-03 06:24:12 -0700803 return (inoutColor.isOpaque() && inoutCoverage.isOpaque());
egdaniel89af44a2014-09-26 06:15:04 -0700804 }
805
egdaniel1a8ecdf2014-10-03 06:24:12 -0700806 return inoutColor.isOpaque();
egdaniel89af44a2014-09-26 06:15:04 -0700807}
808