blob: 90188ea788fefd598adc1d1c7d6a02e94f68c2d7 [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
11void GrDrawState::setFromPaint(const GrPaint& paint) {
bsalomon@google.com88becf42012-10-05 14:54:42 +000012 for (int i = 0; i < GrPaint::kMaxColorStages; ++i) {
13 int s = i + GrPaint::kFirstColorStage;
14 if (paint.isColorStageEnabled(i)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +000015 fStages[s] = paint.getColorStage(i);
16 } else {
17 fStages[s].setEffect(NULL);
bsalomon@google.comaf84e742012-10-05 13:23:24 +000018 }
19 }
20
bsalomon@google.com88becf42012-10-05 14:54:42 +000021 this->setFirstCoverageStage(GrPaint::kFirstCoverageStage);
bsalomon@google.comaf84e742012-10-05 13:23:24 +000022
bsalomon@google.com88becf42012-10-05 14:54:42 +000023 for (int i = 0; i < GrPaint::kMaxCoverageStages; ++i) {
24 int s = i + GrPaint::kFirstCoverageStage;
25 if (paint.isCoverageStageEnabled(i)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +000026 fStages[s] = paint.getCoverageStage(i);
27 } else {
28 fStages[s].setEffect(NULL);
bsalomon@google.comaf84e742012-10-05 13:23:24 +000029 }
30 }
31
32 // disable all stages not accessible via the paint
33 for (int s = GrPaint::kTotalStages; s < GrDrawState::kNumStages; ++s) {
34 this->disableStage(s);
35 }
36
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000037 this->setColor(paint.getColor());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000038
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000039 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
40 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000041
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000042 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
43 this->setColorFilter(paint.getColorFilterColor(), paint.getColorFilterMode());
44 this->setCoverage(paint.getCoverage());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000045}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +000046
47////////////////////////////////////////////////////////////////////////////////
48
jvanverth@google.com9b855c72013-03-01 18:21:22 +000049static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
50 // this works as long as we're 4 byte-aligned
51#if GR_DEBUG
52 uint32_t overlapCheck = 0;
53#endif
jvanverth@google.com054ae992013-04-01 20:06:51 +000054 GrAssert(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000055 size_t size = 0;
56 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +000057 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000058 size += attribSize;
59#if GR_DEBUG
60 size_t dwordCount = attribSize >> 2;
61 uint32_t mask = (1 << dwordCount)-1;
62 size_t offsetShift = attribs[index].fOffset >> 2;
63 GrAssert(!(overlapCheck & (mask << offsetShift)));
64 overlapCheck |= (mask << offsetShift);
65#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +000066 }
67 return size;
68}
69
jvanverth@google.com9b855c72013-03-01 18:21:22 +000070size_t GrDrawState::getVertexSize() const {
robertphillips@google.com42903302013-04-20 12:26:07 +000071 return vertex_size(fCommon.fVAPtr, fCommon.fVACount);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000072}
73
jvanverth@google.comcc782382013-01-28 20:39:48 +000074////////////////////////////////////////////////////////////////////////////////
75
jvanverth@google.com9b855c72013-03-01 18:21:22 +000076void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
jvanverth@google.com054ae992013-04-01 20:06:51 +000077 GrAssert(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +000078
79 fCommon.fVAPtr = attribs;
80 fCommon.fVACount = count;
jvanverth@google.com054ae992013-04-01 20:06:51 +000081
82 // Set all the indices to -1
83 memset(fCommon.fFixedFunctionVertexAttribIndices,
84 0xff,
85 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
86#if GR_DEBUG
87 uint32_t overlapCheck = 0;
88#endif
89 for (int i = 0; i < count; ++i) {
90 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
91 // The fixed function attribs can only be specified once
92 GrAssert(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
93 GrAssert(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
94 GrVertexAttribTypeVectorCount(attribs[i].fType));
95 fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
96 }
97#if GR_DEBUG
98 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
99 uint32_t mask = (1 << dwordCount)-1;
100 size_t offsetShift = attribs[i].fOffset >> 2;
101 GrAssert(!(overlapCheck & (mask << offsetShift)));
102 overlapCheck |= (mask << offsetShift);
103#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000104 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000105 // Positions must be specified.
106 GrAssert(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000107}
108
109////////////////////////////////////////////////////////////////////////////////
110
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000111void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000112 static const GrVertexAttrib kPositionAttrib =
113 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000114
115 fCommon.fVAPtr = &kPositionAttrib;
116 fCommon.fVACount = 1;
117
jvanverth@google.com054ae992013-04-01 20:06:51 +0000118 // set all the fixed function indices to -1 except position.
119 memset(fCommon.fFixedFunctionVertexAttribIndices,
120 0xff,
121 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
122 fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000123}
124
125////////////////////////////////////////////////////////////////////////////////
126
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000127bool GrDrawState::validateVertexAttribs() const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000128 // check consistency of effects and attributes
129 GrSLType slTypes[kMaxVertexAttribCnt];
130 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
131 slTypes[i] = static_cast<GrSLType>(-1);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000132 }
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000133 for (int s = 0; s < kNumStages; ++s) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000134 if (this->isStageEnabled(s)) {
135 const GrEffectStage& stage = fStages[s];
136 const GrEffectRef* effect = stage.getEffect();
137 // make sure that any attribute indices have the correct binding type, that the attrib
138 // type and effect's shader lang type are compatible, and that attributes shared by
139 // multiple effects use the same shader lang type.
140 const int* attributeIndices = stage.getVertexAttribIndices();
141 int numAttributes = stage.getVertexAttribIndexCount();
142 for (int i = 0; i < numAttributes; ++i) {
143 int attribIndex = attributeIndices[i];
robertphillips@google.com42903302013-04-20 12:26:07 +0000144 if (attribIndex >= fCommon.fVACount ||
145 kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000146 return false;
147 }
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000148
jvanverth@google.com054ae992013-04-01 20:06:51 +0000149 GrSLType effectSLType = (*effect)->vertexAttribType(i);
robertphillips@google.com42903302013-04-20 12:26:07 +0000150 GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000151 int slVecCount = GrSLTypeVectorCount(effectSLType);
152 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
153 if (slVecCount != attribVecCount ||
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000154 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
robertphillips@google.com2c5ddb62013-04-01 23:24:15 +0000155 slTypes[attribIndex] != effectSLType)) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000156 return false;
157 }
158 slTypes[attribIndex] = effectSLType;
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000159 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000160 }
161 }
162
163 return true;
164}
165
jvanverth@google.comcc782382013-01-28 20:39:48 +0000166////////////////////////////////////////////////////////////////////////////////
167
jvanverth@google.com054ae992013-04-01 20:06:51 +0000168bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000169 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000170 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000171 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000172 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000173 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000174 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000175 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000176 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000177 color = this->getColor();
178 }
179
180 // Run through the color stages
181 int stageCnt = getFirstCoverageStage();
182 for (int s = 0; s < stageCnt; ++s) {
183 const GrEffectRef* effect = this->getStage(s).getEffect();
184 if (NULL != effect) {
185 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
186 }
187 }
188
189 // Check if the color filter could introduce an alpha.
190 // We could skip the above work when this is true, but it is rare and the right fix is to make
191 // the color filter a GrEffect and implement getConstantColorComponents() for it.
192 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
193 validComponentFlags = 0;
194 }
195
196 // Check whether coverage is treated as color. If so we run through the coverage computation.
197 if (this->isCoverageDrawing()) {
198 GrColor coverageColor = this->getCoverage();
199 GrColor oldColor = color;
200 color = 0;
201 for (int c = 0; c < 4; ++c) {
202 if (validComponentFlags & (1 << c)) {
203 U8CPU a = (oldColor >> (c * 8)) & 0xff;
204 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
205 color |= (SkMulDiv255Round(a, b) << (c * 8));
206 }
207 }
208 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
209 const GrEffectRef* effect = this->getStage(s).getEffect();
210 if (NULL != effect) {
211 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
212 }
213 }
214 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000215 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000216}
217
jvanverth@google.com054ae992013-04-01 20:06:51 +0000218bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000219 // If we're drawing coverage directly then coverage is effectively treated as color.
220 if (this->isCoverageDrawing()) {
221 return true;
222 }
223
224 GrColor coverage;
225 uint32_t validComponentFlags;
226 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000227 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000228 validComponentFlags = 0;
229 } else {
230 coverage = fCommon.fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000231 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000232 }
233
234 // Run through the coverage stages and see if the coverage will be all ones at the end.
235 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
236 const GrEffectRef* effect = this->getStage(s).getEffect();
237 if (NULL != effect) {
238 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
239 }
240 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000241 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000242}
243
jvanverth@google.comcc782382013-01-28 20:39:48 +0000244////////////////////////////////////////////////////////////////////////////////
245
bsalomon@google.com2b446732013-02-12 16:47:41 +0000246// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
247// others will blend incorrectly.
248bool GrDrawState::canTweakAlphaForCoverage() const {
249 /*
250 The fractional coverage is f.
251 The src and dst coeffs are Cs and Cd.
252 The dst and src colors are S and D.
253 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
254 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
255 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
256 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
257 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
258 color by definition.
259 */
260 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
261 kISA_GrBlendCoeff == fCommon.fDstBlend ||
262 kISC_GrBlendCoeff == fCommon.fDstBlend ||
263 this->isCoverageDrawing();
264}
265
266GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
267 GrBlendCoeff* srcCoeff,
268 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000269
270 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
271 if (NULL == srcCoeff) {
272 srcCoeff = &bogusSrcCoeff;
273 }
274 *srcCoeff = this->getSrcBlendCoeff();
275
276 if (NULL == dstCoeff) {
277 dstCoeff = &bogusDstCoeff;
278 }
279 *dstCoeff = this->getDstBlendCoeff();
280
281 if (this->isColorWriteDisabled()) {
282 *srcCoeff = kZero_GrBlendCoeff;
283 *dstCoeff = kOne_GrBlendCoeff;
284 }
285
jvanverth@google.com054ae992013-04-01 20:06:51 +0000286 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000287 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
288 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
289 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
290 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
291
292 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000293 !this->hasCoverageVertexAttribute() &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000294 0 == this->getCoverage();
295 // When coeffs are (0,1) there is no reason to draw at all, unless
296 // stenciling is enabled. Having color writes disabled is effectively
297 // (0,1). The same applies when coverage is known to be 0.
298 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
299 if (this->getStencil().doesWrite()) {
300 return kDisableBlend_BlendOptFlag |
301 kEmitTransBlack_BlendOptFlag;
302 } else {
303 return kSkipDraw_BlendOptFlag;
304 }
305 }
306
bsalomon@google.com4647f902013-03-26 14:45:27 +0000307 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000308 bool hasCoverage = forceCoverage ||
309 0xffffffff != this->getCoverage() ||
jvanverth@google.com054ae992013-04-01 20:06:51 +0000310 this->hasCoverageVertexAttribute();
311 for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000312 if (this->isStageEnabled(s)) {
313 hasCoverage = true;
314 }
315 }
316
317 // if we don't have coverage we can check whether the dst
318 // has to read at all. If not, we'll disable blending.
319 if (!hasCoverage) {
320 if (dstCoeffIsZero) {
321 if (kOne_GrBlendCoeff == *srcCoeff) {
322 // if there is no coverage and coeffs are (1,0) then we
323 // won't need to read the dst at all, it gets replaced by src
324 return kDisableBlend_BlendOptFlag;
325 } else if (kZero_GrBlendCoeff == *srcCoeff) {
326 // if the op is "clear" then we don't need to emit a color
327 // or blend, just write transparent black into the dst.
328 *srcCoeff = kOne_GrBlendCoeff;
329 *dstCoeff = kZero_GrBlendCoeff;
330 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
331 }
332 }
333 } else if (this->isCoverageDrawing()) {
334 // we have coverage but we aren't distinguishing it from alpha by request.
335 return kCoverageAsAlpha_BlendOptFlag;
336 } else {
337 // check whether coverage can be safely rolled into alpha
338 // of if we can skip color computation and just emit coverage
339 if (this->canTweakAlphaForCoverage()) {
340 return kCoverageAsAlpha_BlendOptFlag;
341 }
342 if (dstCoeffIsZero) {
343 if (kZero_GrBlendCoeff == *srcCoeff) {
344 // the source color is not included in the blend
345 // the dst coeff is effectively zero so blend works out to:
346 // (c)(0)D + (1-c)D = (1-c)D.
347 *dstCoeff = kISA_GrBlendCoeff;
348 return kEmitCoverage_BlendOptFlag;
349 } else if (srcAIsOne) {
350 // the dst coeff is effectively zero so blend works out to:
351 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
352 // If Sa is 1 then we can replace Sa with c
353 // and set dst coeff to 1-Sa.
354 *dstCoeff = kISA_GrBlendCoeff;
355 return kCoverageAsAlpha_BlendOptFlag;
356 }
357 } else if (dstCoeffIsOne) {
358 // the dst coeff is effectively one so blend works out to:
359 // cS + (c)(1)D + (1-c)D = cS + D.
360 *dstCoeff = kOne_GrBlendCoeff;
361 return kCoverageAsAlpha_BlendOptFlag;
362 }
363 }
364 return kNone_BlendOpt;
365}
366
367////////////////////////////////////////////////////////////////////////////////
368
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000369void GrDrawState::AutoViewMatrixRestore::restore() {
370 if (NULL != fDrawState) {
371 fDrawState->setViewMatrix(fViewMatrix);
372 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
373 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000374 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000375 }
376 }
377 }
378 fDrawState = NULL;
379}
380
381void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000382 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000383 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000384
385 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000386 if (NULL == drawState) {
387 return;
388 }
389
390 fRestoreMask = 0;
391 fViewMatrix = drawState->getViewMatrix();
392 drawState->preConcatViewMatrix(preconcatMatrix);
393 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000394 if (drawState->isStageEnabled(s)) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000395 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000396 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000397 drawState->fStages[s].localCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000398 }
399 }
400}
401
402////////////////////////////////////////////////////////////////////////////////
403
404void GrDrawState::AutoDeviceCoordDraw::restore() {
405 if (NULL != fDrawState) {
406 fDrawState->setViewMatrix(fViewMatrix);
407 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
408 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000409 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000410 }
411 }
412 }
413 fDrawState = NULL;
414}
415
bsalomon@google.comc7818882013-03-20 19:19:53 +0000416bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000417 GrAssert(NULL != drawState);
418
419 this->restore();
420
421 fDrawState = drawState;
422 if (NULL == fDrawState) {
423 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000424 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000425
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000426 fViewMatrix = drawState->getViewMatrix();
427 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000428 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000429 bool inverted = false;
430
431 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000432 if (drawState->isStageEnabled(s)) {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000433 if (!inverted && !fViewMatrix.invert(&invVM)) {
434 // sad trombone sound
435 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000436 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000437 } else {
438 inverted = true;
439 }
440 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000441 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000442 stage->saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000443 stage->localCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000444 }
445 }
446 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000447 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000448}