blob: 0aa4215d0d052b1acfa88ad68a04cff2d2240d00 [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"
bsalomon@google.comaf84e742012-10-05 13:23:24 +00009#include "GrPaint.h"
10
bsalomon@google.com137f1342013-05-29 21:27:53 +000011bool GrDrawState::setIdentityViewMatrix() {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000012 if (fColorStages.count() || fCoverageStages.count()) {
13 SkMatrix invVM;
14 if (!fCommon.fViewMatrix.invert(&invVM)) {
15 // sad trombone sound
16 return false;
17 }
18 for (int s = 0; s < fColorStages.count(); ++s) {
19 fColorStages[s].localCoordChange(invVM);
20 }
21 for (int s = 0; s < fCoverageStages.count(); ++s) {
22 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +000023 }
24 }
25 fCommon.fViewMatrix.reset();
26 return true;
27}
28
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000029void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000030 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000031
32 fColorStages.reset();
33 fCoverageStages.reset();
34
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +000035 for (int i = 0; i < paint.numColorStages(); ++i) {
36 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +000037 }
38
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +000039 for (int i = 0; i < paint.numCoverageStages(); ++i) {
40 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +000041 }
42
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000043 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +000044
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000045 fCommon.fViewMatrix = vm;
46
47 // These have no equivalent in GrPaint, set them to defaults
48 fCommon.fBlendConstant = 0x0;
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000049 fCommon.fDrawFace = kBoth_DrawFace;
50 fCommon.fStencilSettings.setDisabled();
51 this->resetStateFlags();
52
bsalomon@google.com21c10c52013-06-13 17:44:07 +000053 // Enable the clip bit
54 this->enableState(GrDrawState::kClip_StateBit);
55
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000056 this->setColor(paint.getColor());
bsalomon@google.com48bc7912013-08-02 19:54:28 +000057 this->setCoverage4(paint.getCoverage());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000058 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
59 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000060
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000061 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
62 this->setColorFilter(paint.getColorFilterColor(), paint.getColorFilterMode());
63 this->setCoverage(paint.getCoverage());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000064}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +000065
66////////////////////////////////////////////////////////////////////////////////
67
jvanverth@google.com9b855c72013-03-01 18:21:22 +000068static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
69 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000070#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +000071 uint32_t overlapCheck = 0;
72#endif
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000073 SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000074 size_t size = 0;
75 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +000076 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000077 size += attribSize;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000078#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +000079 size_t dwordCount = attribSize >> 2;
80 uint32_t mask = (1 << dwordCount)-1;
81 size_t offsetShift = attribs[index].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000082 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +000083 overlapCheck |= (mask << offsetShift);
84#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +000085 }
86 return size;
87}
88
jvanverth@google.com9b855c72013-03-01 18:21:22 +000089size_t GrDrawState::getVertexSize() const {
robertphillips@google.com42903302013-04-20 12:26:07 +000090 return vertex_size(fCommon.fVAPtr, fCommon.fVACount);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000091}
92
jvanverth@google.comcc782382013-01-28 20:39:48 +000093////////////////////////////////////////////////////////////////////////////////
94
jvanverth@google.com9b855c72013-03-01 18:21:22 +000095void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000096 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +000097
98 fCommon.fVAPtr = attribs;
99 fCommon.fVACount = count;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000100
101 // Set all the indices to -1
102 memset(fCommon.fFixedFunctionVertexAttribIndices,
103 0xff,
104 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000105#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000106 uint32_t overlapCheck = 0;
107#endif
108 for (int i = 0; i < count; ++i) {
109 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
110 // The fixed function attribs can only be specified once
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000111 SkASSERT(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
112 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000113 GrVertexAttribTypeVectorCount(attribs[i].fType));
114 fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
115 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000116#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000117 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
118 uint32_t mask = (1 << dwordCount)-1;
119 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000120 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000121 overlapCheck |= (mask << offsetShift);
122#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000123 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000124 // Positions must be specified.
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000125 SkASSERT(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000126}
127
128////////////////////////////////////////////////////////////////////////////////
129
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000130void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000131 static const GrVertexAttrib kPositionAttrib =
132 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000133
134 fCommon.fVAPtr = &kPositionAttrib;
135 fCommon.fVACount = 1;
136
jvanverth@google.com054ae992013-04-01 20:06:51 +0000137 // set all the fixed function indices to -1 except position.
138 memset(fCommon.fFixedFunctionVertexAttribIndices,
139 0xff,
140 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
141 fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000142}
143
144////////////////////////////////////////////////////////////////////////////////
145
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000146bool GrDrawState::validateVertexAttribs() const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000147 // check consistency of effects and attributes
148 GrSLType slTypes[kMaxVertexAttribCnt];
149 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
150 slTypes[i] = static_cast<GrSLType>(-1);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000151 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000152 int totalStages = fColorStages.count() + fCoverageStages.count();
153 for (int s = 0; s < totalStages; ++s) {
154 int covIdx = s - fColorStages.count();
155 const GrEffectStage& stage = covIdx < 0 ? fColorStages[s] : fCoverageStages[covIdx];
156 const GrEffectRef* effect = stage.getEffect();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000157 SkASSERT(NULL != effect);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000158 // make sure that any attribute indices have the correct binding type, that the attrib
159 // type and effect's shader lang type are compatible, and that attributes shared by
160 // multiple effects use the same shader lang type.
161 const int* attributeIndices = stage.getVertexAttribIndices();
162 int numAttributes = stage.getVertexAttribIndexCount();
163 for (int i = 0; i < numAttributes; ++i) {
164 int attribIndex = attributeIndices[i];
165 if (attribIndex >= fCommon.fVACount ||
166 kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
167 return false;
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000168 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000169
170 GrSLType effectSLType = (*effect)->vertexAttribType(i);
171 GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
172 int slVecCount = GrSLTypeVectorCount(effectSLType);
173 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
174 if (slVecCount != attribVecCount ||
175 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
176 slTypes[attribIndex] != effectSLType)) {
177 return false;
178 }
179 slTypes[attribIndex] = effectSLType;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000180 }
181 }
182
183 return true;
184}
185
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000186bool GrDrawState::willEffectReadDstColor() const {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000187 if (!this->isColorWriteDisabled()) {
188 for (int s = 0; s < fColorStages.count(); ++s) {
189 if ((*fColorStages[s].getEffect())->willReadDstColor()) {
190 return true;
191 }
192 }
193 }
194 for (int s = 0; s < fCoverageStages.count(); ++s) {
195 if ((*fCoverageStages[s].getEffect())->willReadDstColor()) {
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000196 return true;
197 }
198 }
199 return false;
200}
201
jvanverth@google.comcc782382013-01-28 20:39:48 +0000202////////////////////////////////////////////////////////////////////////////////
203
jvanverth@google.com054ae992013-04-01 20:06:51 +0000204bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000205 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000206 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000207 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000208 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000209 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000210 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000211 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000212 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000213 color = this->getColor();
214 }
215
216 // Run through the color stages
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000217 for (int s = 0; s < fColorStages.count(); ++s) {
218 const GrEffectRef* effect = fColorStages[s].getEffect();
219 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000220 }
221
222 // Check if the color filter could introduce an alpha.
223 // We could skip the above work when this is true, but it is rare and the right fix is to make
224 // the color filter a GrEffect and implement getConstantColorComponents() for it.
225 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
226 validComponentFlags = 0;
227 }
228
229 // Check whether coverage is treated as color. If so we run through the coverage computation.
230 if (this->isCoverageDrawing()) {
231 GrColor coverageColor = this->getCoverage();
232 GrColor oldColor = color;
233 color = 0;
234 for (int c = 0; c < 4; ++c) {
235 if (validComponentFlags & (1 << c)) {
236 U8CPU a = (oldColor >> (c * 8)) & 0xff;
237 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
238 color |= (SkMulDiv255Round(a, b) << (c * 8));
239 }
240 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000241 for (int s = 0; s < fCoverageStages.count(); ++s) {
242 const GrEffectRef* effect = fCoverageStages[s].getEffect();
243 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000244 }
245 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000246 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000247}
248
jvanverth@google.com054ae992013-04-01 20:06:51 +0000249bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000250 // If we're drawing coverage directly then coverage is effectively treated as color.
251 if (this->isCoverageDrawing()) {
252 return true;
253 }
254
255 GrColor coverage;
256 uint32_t validComponentFlags;
257 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000258 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000259 validComponentFlags = 0;
260 } else {
261 coverage = fCommon.fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000262 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000263 }
264
265 // Run through the coverage stages and see if the coverage will be all ones at the end.
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000266 for (int s = 0; s < fCoverageStages.count(); ++s) {
267 const GrEffectRef* effect = fCoverageStages[s].getEffect();
268 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000269 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000270 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000271}
272
jvanverth@google.comcc782382013-01-28 20:39:48 +0000273////////////////////////////////////////////////////////////////////////////////
274
bsalomon@google.com2b446732013-02-12 16:47:41 +0000275// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
276// others will blend incorrectly.
277bool GrDrawState::canTweakAlphaForCoverage() const {
278 /*
279 The fractional coverage is f.
280 The src and dst coeffs are Cs and Cd.
281 The dst and src colors are S and D.
282 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
283 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
284 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
285 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
286 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
287 color by definition.
288 */
289 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
290 kISA_GrBlendCoeff == fCommon.fDstBlend ||
291 kISC_GrBlendCoeff == fCommon.fDstBlend ||
292 this->isCoverageDrawing();
293}
294
295GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
296 GrBlendCoeff* srcCoeff,
297 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000298
299 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
300 if (NULL == srcCoeff) {
301 srcCoeff = &bogusSrcCoeff;
302 }
303 *srcCoeff = this->getSrcBlendCoeff();
304
305 if (NULL == dstCoeff) {
306 dstCoeff = &bogusDstCoeff;
307 }
308 *dstCoeff = this->getDstBlendCoeff();
309
310 if (this->isColorWriteDisabled()) {
311 *srcCoeff = kZero_GrBlendCoeff;
312 *dstCoeff = kOne_GrBlendCoeff;
313 }
314
jvanverth@google.com054ae992013-04-01 20:06:51 +0000315 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000316 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
317 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
318 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
319 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
320
321 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000322 !this->hasCoverageVertexAttribute() &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000323 0 == this->getCoverage();
324 // When coeffs are (0,1) there is no reason to draw at all, unless
325 // stenciling is enabled. Having color writes disabled is effectively
326 // (0,1). The same applies when coverage is known to be 0.
327 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
328 if (this->getStencil().doesWrite()) {
329 return kDisableBlend_BlendOptFlag |
commit-bot@chromium.orgbc98ff02013-08-15 18:16:41 +0000330 kEmitCoverage_BlendOptFlag;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000331 } else {
332 return kSkipDraw_BlendOptFlag;
333 }
334 }
335
bsalomon@google.com4647f902013-03-26 14:45:27 +0000336 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000337 bool hasCoverage = forceCoverage ||
338 0xffffffff != this->getCoverage() ||
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000339 this->hasCoverageVertexAttribute() ||
340 fCoverageStages.count() > 0;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000341
342 // if we don't have coverage we can check whether the dst
343 // has to read at all. If not, we'll disable blending.
344 if (!hasCoverage) {
345 if (dstCoeffIsZero) {
346 if (kOne_GrBlendCoeff == *srcCoeff) {
347 // if there is no coverage and coeffs are (1,0) then we
348 // won't need to read the dst at all, it gets replaced by src
349 return kDisableBlend_BlendOptFlag;
350 } else if (kZero_GrBlendCoeff == *srcCoeff) {
351 // if the op is "clear" then we don't need to emit a color
352 // or blend, just write transparent black into the dst.
353 *srcCoeff = kOne_GrBlendCoeff;
354 *dstCoeff = kZero_GrBlendCoeff;
355 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
356 }
357 }
358 } else if (this->isCoverageDrawing()) {
359 // we have coverage but we aren't distinguishing it from alpha by request.
360 return kCoverageAsAlpha_BlendOptFlag;
361 } else {
362 // check whether coverage can be safely rolled into alpha
363 // of if we can skip color computation and just emit coverage
364 if (this->canTweakAlphaForCoverage()) {
365 return kCoverageAsAlpha_BlendOptFlag;
366 }
367 if (dstCoeffIsZero) {
368 if (kZero_GrBlendCoeff == *srcCoeff) {
369 // the source color is not included in the blend
370 // the dst coeff is effectively zero so blend works out to:
371 // (c)(0)D + (1-c)D = (1-c)D.
372 *dstCoeff = kISA_GrBlendCoeff;
373 return kEmitCoverage_BlendOptFlag;
374 } else if (srcAIsOne) {
375 // the dst coeff is effectively zero so blend works out to:
376 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
377 // If Sa is 1 then we can replace Sa with c
378 // and set dst coeff to 1-Sa.
379 *dstCoeff = kISA_GrBlendCoeff;
380 return kCoverageAsAlpha_BlendOptFlag;
381 }
382 } else if (dstCoeffIsOne) {
383 // the dst coeff is effectively one so blend works out to:
384 // cS + (c)(1)D + (1-c)D = cS + D.
385 *dstCoeff = kOne_GrBlendCoeff;
386 return kCoverageAsAlpha_BlendOptFlag;
387 }
388 }
bsalomon@google.com0c89db22013-05-15 17:53:04 +0000389 if (kOne_GrBlendCoeff == *srcCoeff &&
390 kZero_GrBlendCoeff == *dstCoeff &&
391 this->willEffectReadDstColor()) {
392 // In this case the shader will fully resolve the color, coverage, and dst and we don't
393 // need blending.
394 return kDisableBlend_BlendOptFlag;
395 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000396 return kNone_BlendOpt;
397}
398
399////////////////////////////////////////////////////////////////////////////////
400
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000401void GrDrawState::AutoViewMatrixRestore::restore() {
402 if (NULL != fDrawState) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000403 GR_DEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com137f1342013-05-29 21:27:53 +0000404 fDrawState->fCommon.fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000405 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000406 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000407 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000408
409 int i = 0;
410 for (int s = 0; s < fNumColorStages; ++s, ++i) {
411 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
412 }
413 for (int s = 0; s < numCoverageStages; ++s, ++i) {
414 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000415 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000416 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000417 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000418}
419
420void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000421 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000422 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000423
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000424 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000425 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000426 return;
427 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000428 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000429
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000430 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000431 drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000432
433 this->doEffectCoordChanges(preconcatMatrix);
434 GR_DEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000435}
436
bsalomon@google.com137f1342013-05-29 21:27:53 +0000437bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000438 this->restore();
439
bsalomon@google.com137f1342013-05-29 21:27:53 +0000440 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000441 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000442 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000443
bsalomon@google.com137f1342013-05-29 21:27:53 +0000444 if (drawState->getViewMatrix().isIdentity()) {
445 return true;
446 }
447
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000448 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000449 if (0 == drawState->numTotalStages()) {
450 drawState->fCommon.fViewMatrix.reset();
451 fDrawState = drawState;
452 fNumColorStages = 0;
453 fSavedCoordChanges.reset(0);
454 GR_DEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
455 return true;
456 } else {
457 SkMatrix inv;
458 if (!fViewMatrix.invert(&inv)) {
459 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000460 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000461 drawState->fCommon.fViewMatrix.reset();
462 fDrawState = drawState;
463 this->doEffectCoordChanges(inv);
464 GR_DEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
465 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000466 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000467}
468
469void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
470 fSavedCoordChanges.reset(fDrawState->numTotalStages());
471 int i = 0;
472
473 fNumColorStages = fDrawState->numColorStages();
474 for (int s = 0; s < fNumColorStages; ++s, ++i) {
475 fDrawState->fColorStages[s].saveCoordChange(&fSavedCoordChanges[i]);
476 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000477 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000478
479 int numCoverageStages = fDrawState->numCoverageStages();
480 for (int s = 0; s < numCoverageStages; ++s, ++i) {
481 fDrawState->fCoverageStages[s].saveCoordChange(&fSavedCoordChanges[i]);
482 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
483 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000484}