blob: 1743604a19a505a498309f229aa90f390f9353b8 [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());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000062 this->setCoverage(paint.getCoverage());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000063}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +000064
65////////////////////////////////////////////////////////////////////////////////
66
jvanverth@google.com9b855c72013-03-01 18:21:22 +000067static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
68 // this works as long as we're 4 byte-aligned
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000069#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +000070 uint32_t overlapCheck = 0;
71#endif
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000072 SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000073 size_t size = 0;
74 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +000075 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000076 size += attribSize;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000077#ifdef SK_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +000078 size_t dwordCount = attribSize >> 2;
79 uint32_t mask = (1 << dwordCount)-1;
80 size_t offsetShift = attribs[index].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000081 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com9b855c72013-03-01 18:21:22 +000082 overlapCheck |= (mask << offsetShift);
83#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +000084 }
85 return size;
86}
87
jvanverth@google.com9b855c72013-03-01 18:21:22 +000088size_t GrDrawState::getVertexSize() const {
robertphillips@google.com42903302013-04-20 12:26:07 +000089 return vertex_size(fCommon.fVAPtr, fCommon.fVACount);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000090}
91
jvanverth@google.comcc782382013-01-28 20:39:48 +000092////////////////////////////////////////////////////////////////////////////////
93
jvanverth@google.com9b855c72013-03-01 18:21:22 +000094void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000095 SkASSERT(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +000096
97 fCommon.fVAPtr = attribs;
98 fCommon.fVACount = count;
jvanverth@google.com054ae992013-04-01 20:06:51 +000099
100 // Set all the indices to -1
101 memset(fCommon.fFixedFunctionVertexAttribIndices,
102 0xff,
103 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000104#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000105 uint32_t overlapCheck = 0;
106#endif
107 for (int i = 0; i < count; ++i) {
108 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
109 // The fixed function attribs can only be specified once
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000110 SkASSERT(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
111 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
jvanverth@google.com054ae992013-04-01 20:06:51 +0000112 GrVertexAttribTypeVectorCount(attribs[i].fType));
113 fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
114 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000115#ifdef SK_DEBUG
jvanverth@google.com054ae992013-04-01 20:06:51 +0000116 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
117 uint32_t mask = (1 << dwordCount)-1;
118 size_t offsetShift = attribs[i].fOffset >> 2;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000119 SkASSERT(!(overlapCheck & (mask << offsetShift)));
jvanverth@google.com054ae992013-04-01 20:06:51 +0000120 overlapCheck |= (mask << offsetShift);
121#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000122 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000123 // Positions must be specified.
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000124 SkASSERT(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000125}
126
127////////////////////////////////////////////////////////////////////////////////
128
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000129void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000130 static const GrVertexAttrib kPositionAttrib =
131 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000132
133 fCommon.fVAPtr = &kPositionAttrib;
134 fCommon.fVACount = 1;
135
jvanverth@google.com054ae992013-04-01 20:06:51 +0000136 // set all the fixed function indices to -1 except position.
137 memset(fCommon.fFixedFunctionVertexAttribIndices,
138 0xff,
139 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
140 fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000141}
142
143////////////////////////////////////////////////////////////////////////////////
144
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000145bool GrDrawState::validateVertexAttribs() const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000146 // check consistency of effects and attributes
147 GrSLType slTypes[kMaxVertexAttribCnt];
148 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
149 slTypes[i] = static_cast<GrSLType>(-1);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000150 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000151 int totalStages = fColorStages.count() + fCoverageStages.count();
152 for (int s = 0; s < totalStages; ++s) {
153 int covIdx = s - fColorStages.count();
154 const GrEffectStage& stage = covIdx < 0 ? fColorStages[s] : fCoverageStages[covIdx];
155 const GrEffectRef* effect = stage.getEffect();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000156 SkASSERT(NULL != effect);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000157 // make sure that any attribute indices have the correct binding type, that the attrib
158 // type and effect's shader lang type are compatible, and that attributes shared by
159 // multiple effects use the same shader lang type.
160 const int* attributeIndices = stage.getVertexAttribIndices();
161 int numAttributes = stage.getVertexAttribIndexCount();
162 for (int i = 0; i < numAttributes; ++i) {
163 int attribIndex = attributeIndices[i];
164 if (attribIndex >= fCommon.fVACount ||
165 kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
166 return false;
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000167 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000168
169 GrSLType effectSLType = (*effect)->vertexAttribType(i);
170 GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
171 int slVecCount = GrSLTypeVectorCount(effectSLType);
172 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
173 if (slVecCount != attribVecCount ||
174 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
175 slTypes[attribIndex] != effectSLType)) {
176 return false;
177 }
178 slTypes[attribIndex] = effectSLType;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000179 }
180 }
181
182 return true;
183}
184
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000185bool GrDrawState::willEffectReadDstColor() const {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000186 if (!this->isColorWriteDisabled()) {
187 for (int s = 0; s < fColorStages.count(); ++s) {
188 if ((*fColorStages[s].getEffect())->willReadDstColor()) {
189 return true;
190 }
191 }
192 }
193 for (int s = 0; s < fCoverageStages.count(); ++s) {
194 if ((*fCoverageStages[s].getEffect())->willReadDstColor()) {
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000195 return true;
196 }
197 }
198 return false;
199}
200
jvanverth@google.comcc782382013-01-28 20:39:48 +0000201////////////////////////////////////////////////////////////////////////////////
202
jvanverth@google.com054ae992013-04-01 20:06:51 +0000203bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000204 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000205 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000206 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000207 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000208 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000209 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000210 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000211 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000212 color = this->getColor();
213 }
214
215 // Run through the color stages
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000216 for (int s = 0; s < fColorStages.count(); ++s) {
217 const GrEffectRef* effect = fColorStages[s].getEffect();
218 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000219 }
220
jvanverth@google.comcc782382013-01-28 20:39:48 +0000221 // Check whether coverage is treated as color. If so we run through the coverage computation.
222 if (this->isCoverageDrawing()) {
223 GrColor coverageColor = this->getCoverage();
224 GrColor oldColor = color;
225 color = 0;
226 for (int c = 0; c < 4; ++c) {
227 if (validComponentFlags & (1 << c)) {
228 U8CPU a = (oldColor >> (c * 8)) & 0xff;
229 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
230 color |= (SkMulDiv255Round(a, b) << (c * 8));
231 }
232 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000233 for (int s = 0; s < fCoverageStages.count(); ++s) {
234 const GrEffectRef* effect = fCoverageStages[s].getEffect();
235 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000236 }
237 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000238 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000239}
240
jvanverth@google.com054ae992013-04-01 20:06:51 +0000241bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000242 // If we're drawing coverage directly then coverage is effectively treated as color.
243 if (this->isCoverageDrawing()) {
244 return true;
245 }
246
247 GrColor coverage;
248 uint32_t validComponentFlags;
249 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000250 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000251 validComponentFlags = 0;
252 } else {
253 coverage = fCommon.fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000254 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000255 }
256
257 // 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 +0000258 for (int s = 0; s < fCoverageStages.count(); ++s) {
259 const GrEffectRef* effect = fCoverageStages[s].getEffect();
260 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000261 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000262 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000263}
264
jvanverth@google.comcc782382013-01-28 20:39:48 +0000265////////////////////////////////////////////////////////////////////////////////
266
bsalomon@google.com2b446732013-02-12 16:47:41 +0000267// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
268// others will blend incorrectly.
269bool GrDrawState::canTweakAlphaForCoverage() const {
270 /*
271 The fractional coverage is f.
272 The src and dst coeffs are Cs and Cd.
273 The dst and src colors are S and D.
274 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
275 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
276 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
277 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
278 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
279 color by definition.
280 */
281 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
282 kISA_GrBlendCoeff == fCommon.fDstBlend ||
283 kISC_GrBlendCoeff == fCommon.fDstBlend ||
284 this->isCoverageDrawing();
285}
286
287GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
288 GrBlendCoeff* srcCoeff,
289 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000290
291 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
292 if (NULL == srcCoeff) {
293 srcCoeff = &bogusSrcCoeff;
294 }
295 *srcCoeff = this->getSrcBlendCoeff();
296
297 if (NULL == dstCoeff) {
298 dstCoeff = &bogusDstCoeff;
299 }
300 *dstCoeff = this->getDstBlendCoeff();
301
302 if (this->isColorWriteDisabled()) {
303 *srcCoeff = kZero_GrBlendCoeff;
304 *dstCoeff = kOne_GrBlendCoeff;
305 }
306
jvanverth@google.com054ae992013-04-01 20:06:51 +0000307 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000308 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
309 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
310 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
311 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
312
313 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000314 !this->hasCoverageVertexAttribute() &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000315 0 == this->getCoverage();
316 // When coeffs are (0,1) there is no reason to draw at all, unless
317 // stenciling is enabled. Having color writes disabled is effectively
318 // (0,1). The same applies when coverage is known to be 0.
319 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
320 if (this->getStencil().doesWrite()) {
321 return kDisableBlend_BlendOptFlag |
commit-bot@chromium.orgbc98ff02013-08-15 18:16:41 +0000322 kEmitCoverage_BlendOptFlag;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000323 } else {
324 return kSkipDraw_BlendOptFlag;
325 }
326 }
327
bsalomon@google.com4647f902013-03-26 14:45:27 +0000328 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000329 bool hasCoverage = forceCoverage ||
330 0xffffffff != this->getCoverage() ||
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000331 this->hasCoverageVertexAttribute() ||
332 fCoverageStages.count() > 0;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000333
334 // if we don't have coverage we can check whether the dst
335 // has to read at all. If not, we'll disable blending.
336 if (!hasCoverage) {
337 if (dstCoeffIsZero) {
338 if (kOne_GrBlendCoeff == *srcCoeff) {
339 // if there is no coverage and coeffs are (1,0) then we
340 // won't need to read the dst at all, it gets replaced by src
341 return kDisableBlend_BlendOptFlag;
342 } else if (kZero_GrBlendCoeff == *srcCoeff) {
343 // if the op is "clear" then we don't need to emit a color
344 // or blend, just write transparent black into the dst.
345 *srcCoeff = kOne_GrBlendCoeff;
346 *dstCoeff = kZero_GrBlendCoeff;
347 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
348 }
349 }
350 } else if (this->isCoverageDrawing()) {
351 // we have coverage but we aren't distinguishing it from alpha by request.
352 return kCoverageAsAlpha_BlendOptFlag;
353 } else {
354 // check whether coverage can be safely rolled into alpha
355 // of if we can skip color computation and just emit coverage
356 if (this->canTweakAlphaForCoverage()) {
357 return kCoverageAsAlpha_BlendOptFlag;
358 }
359 if (dstCoeffIsZero) {
360 if (kZero_GrBlendCoeff == *srcCoeff) {
361 // the source color is not included in the blend
362 // the dst coeff is effectively zero so blend works out to:
363 // (c)(0)D + (1-c)D = (1-c)D.
364 *dstCoeff = kISA_GrBlendCoeff;
365 return kEmitCoverage_BlendOptFlag;
366 } else if (srcAIsOne) {
367 // the dst coeff is effectively zero so blend works out to:
368 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
369 // If Sa is 1 then we can replace Sa with c
370 // and set dst coeff to 1-Sa.
371 *dstCoeff = kISA_GrBlendCoeff;
372 return kCoverageAsAlpha_BlendOptFlag;
373 }
374 } else if (dstCoeffIsOne) {
375 // the dst coeff is effectively one so blend works out to:
376 // cS + (c)(1)D + (1-c)D = cS + D.
377 *dstCoeff = kOne_GrBlendCoeff;
378 return kCoverageAsAlpha_BlendOptFlag;
379 }
380 }
bsalomon@google.com0c89db22013-05-15 17:53:04 +0000381 if (kOne_GrBlendCoeff == *srcCoeff &&
382 kZero_GrBlendCoeff == *dstCoeff &&
383 this->willEffectReadDstColor()) {
384 // In this case the shader will fully resolve the color, coverage, and dst and we don't
385 // need blending.
386 return kDisableBlend_BlendOptFlag;
387 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000388 return kNone_BlendOpt;
389}
390
391////////////////////////////////////////////////////////////////////////////////
392
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000393void GrDrawState::AutoViewMatrixRestore::restore() {
394 if (NULL != fDrawState) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000395 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com137f1342013-05-29 21:27:53 +0000396 fDrawState->fCommon.fViewMatrix = fViewMatrix;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000397 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000398 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000399 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000400
401 int i = 0;
402 for (int s = 0; s < fNumColorStages; ++s, ++i) {
403 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
404 }
405 for (int s = 0; s < numCoverageStages; ++s, ++i) {
406 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000407 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000408 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000409 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000410}
411
412void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000413 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000414 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000415
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000416 SkASSERT(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000417 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000418 return;
419 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000420 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000421
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000422 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000423 drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000424
425 this->doEffectCoordChanges(preconcatMatrix);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000426 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000427}
428
bsalomon@google.com137f1342013-05-29 21:27:53 +0000429bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000430 this->restore();
431
bsalomon@google.com137f1342013-05-29 21:27:53 +0000432 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000433 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000434 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000435
bsalomon@google.com137f1342013-05-29 21:27:53 +0000436 if (drawState->getViewMatrix().isIdentity()) {
437 return true;
438 }
439
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000440 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000441 if (0 == drawState->numTotalStages()) {
442 drawState->fCommon.fViewMatrix.reset();
443 fDrawState = drawState;
444 fNumColorStages = 0;
445 fSavedCoordChanges.reset(0);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000446 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000447 return true;
448 } else {
449 SkMatrix inv;
450 if (!fViewMatrix.invert(&inv)) {
451 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000452 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000453 drawState->fCommon.fViewMatrix.reset();
454 fDrawState = drawState;
455 this->doEffectCoordChanges(inv);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000456 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000457 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000458 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000459}
460
461void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
462 fSavedCoordChanges.reset(fDrawState->numTotalStages());
463 int i = 0;
464
465 fNumColorStages = fDrawState->numColorStages();
466 for (int s = 0; s < fNumColorStages; ++s, ++i) {
467 fDrawState->fColorStages[s].saveCoordChange(&fSavedCoordChanges[i]);
468 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000469 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000470
471 int numCoverageStages = fDrawState->numCoverageStages();
472 for (int s = 0; s < numCoverageStages; ++s, ++i) {
473 fDrawState->fCoverageStages[s].saveCoordChange(&fSavedCoordChanges[i]);
474 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
475 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000476}