blob: 6d7969f024797b6a94fce235df4289c84c3e540c [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 {
jvanverth@google.com054ae992013-04-01 20:06:51 +000071 return vertex_size(fCommon.fVertexAttribs.begin(), fCommon.fVertexAttribs.count());
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);
78 fCommon.fVertexAttribs.reset(attribs, count);
79
80 // Set all the indices to -1
81 memset(fCommon.fFixedFunctionVertexAttribIndices,
82 0xff,
83 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
84#if GR_DEBUG
85 uint32_t overlapCheck = 0;
86#endif
87 for (int i = 0; i < count; ++i) {
88 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
89 // The fixed function attribs can only be specified once
90 GrAssert(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
91 GrAssert(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
92 GrVertexAttribTypeVectorCount(attribs[i].fType));
93 fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
94 }
95#if GR_DEBUG
96 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
97 uint32_t mask = (1 << dwordCount)-1;
98 size_t offsetShift = attribs[i].fOffset >> 2;
99 GrAssert(!(overlapCheck & (mask << offsetShift)));
100 overlapCheck |= (mask << offsetShift);
101#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000102 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000103 // Positions must be specified.
104 GrAssert(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000105}
106
107////////////////////////////////////////////////////////////////////////////////
108
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000109void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000110 static const GrVertexAttrib kPositionAttrib =
111 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
112 fCommon.fVertexAttribs.reset(&kPositionAttrib, 1);
113 // set all the fixed function indices to -1 except position.
114 memset(fCommon.fFixedFunctionVertexAttribIndices,
115 0xff,
116 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
117 fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000118}
119
120////////////////////////////////////////////////////////////////////////////////
121
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000122bool GrDrawState::validateVertexAttribs() const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000123 // check consistency of effects and attributes
124 GrSLType slTypes[kMaxVertexAttribCnt];
125 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
126 slTypes[i] = static_cast<GrSLType>(-1);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000127 }
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000128 for (int s = 0; s < kNumStages; ++s) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000129 if (this->isStageEnabled(s)) {
130 const GrEffectStage& stage = fStages[s];
131 const GrEffectRef* effect = stage.getEffect();
132 // make sure that any attribute indices have the correct binding type, that the attrib
133 // type and effect's shader lang type are compatible, and that attributes shared by
134 // multiple effects use the same shader lang type.
135 const int* attributeIndices = stage.getVertexAttribIndices();
136 int numAttributes = stage.getVertexAttribIndexCount();
137 for (int i = 0; i < numAttributes; ++i) {
138 int attribIndex = attributeIndices[i];
139 if (attribIndex >= fCommon.fVertexAttribs.count() ||
140 kEffect_GrVertexAttribBinding != fCommon.fVertexAttribs[attribIndex].fBinding) {
141 return false;
142 }
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000143
jvanverth@google.com054ae992013-04-01 20:06:51 +0000144 GrSLType effectSLType = (*effect)->vertexAttribType(i);
145 GrVertexAttribType attribType = fCommon.fVertexAttribs[attribIndex].fType;
146 int slVecCount = GrSLTypeVectorCount(effectSLType);
147 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
148 if (slVecCount != attribVecCount ||
149 (-1 != slTypes[attribIndex] && slTypes[attribIndex] != effectSLType)) {
150 return false;
151 }
152 slTypes[attribIndex] = effectSLType;
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000153 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000154 }
155 }
156
157 return true;
158}
159
jvanverth@google.comcc782382013-01-28 20:39:48 +0000160////////////////////////////////////////////////////////////////////////////////
161
jvanverth@google.com054ae992013-04-01 20:06:51 +0000162bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000163 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000164 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000165 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000166 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000167 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000168 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000169 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000170 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000171 color = this->getColor();
172 }
173
174 // Run through the color stages
175 int stageCnt = getFirstCoverageStage();
176 for (int s = 0; s < stageCnt; ++s) {
177 const GrEffectRef* effect = this->getStage(s).getEffect();
178 if (NULL != effect) {
179 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
180 }
181 }
182
183 // Check if the color filter could introduce an alpha.
184 // We could skip the above work when this is true, but it is rare and the right fix is to make
185 // the color filter a GrEffect and implement getConstantColorComponents() for it.
186 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
187 validComponentFlags = 0;
188 }
189
190 // Check whether coverage is treated as color. If so we run through the coverage computation.
191 if (this->isCoverageDrawing()) {
192 GrColor coverageColor = this->getCoverage();
193 GrColor oldColor = color;
194 color = 0;
195 for (int c = 0; c < 4; ++c) {
196 if (validComponentFlags & (1 << c)) {
197 U8CPU a = (oldColor >> (c * 8)) & 0xff;
198 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
199 color |= (SkMulDiv255Round(a, b) << (c * 8));
200 }
201 }
202 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
203 const GrEffectRef* effect = this->getStage(s).getEffect();
204 if (NULL != effect) {
205 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
206 }
207 }
208 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000209 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000210}
211
jvanverth@google.com054ae992013-04-01 20:06:51 +0000212bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000213 // If we're drawing coverage directly then coverage is effectively treated as color.
214 if (this->isCoverageDrawing()) {
215 return true;
216 }
217
218 GrColor coverage;
219 uint32_t validComponentFlags;
220 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000221 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000222 validComponentFlags = 0;
223 } else {
224 coverage = fCommon.fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000225 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000226 }
227
228 // Run through the coverage stages and see if the coverage will be all ones at the end.
229 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
230 const GrEffectRef* effect = this->getStage(s).getEffect();
231 if (NULL != effect) {
232 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
233 }
234 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000235 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000236}
237
jvanverth@google.comcc782382013-01-28 20:39:48 +0000238////////////////////////////////////////////////////////////////////////////////
239
bsalomon@google.com2b446732013-02-12 16:47:41 +0000240// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
241// others will blend incorrectly.
242bool GrDrawState::canTweakAlphaForCoverage() const {
243 /*
244 The fractional coverage is f.
245 The src and dst coeffs are Cs and Cd.
246 The dst and src colors are S and D.
247 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
248 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
249 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
250 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
251 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
252 color by definition.
253 */
254 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
255 kISA_GrBlendCoeff == fCommon.fDstBlend ||
256 kISC_GrBlendCoeff == fCommon.fDstBlend ||
257 this->isCoverageDrawing();
258}
259
260GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
261 GrBlendCoeff* srcCoeff,
262 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000263
264 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
265 if (NULL == srcCoeff) {
266 srcCoeff = &bogusSrcCoeff;
267 }
268 *srcCoeff = this->getSrcBlendCoeff();
269
270 if (NULL == dstCoeff) {
271 dstCoeff = &bogusDstCoeff;
272 }
273 *dstCoeff = this->getDstBlendCoeff();
274
275 if (this->isColorWriteDisabled()) {
276 *srcCoeff = kZero_GrBlendCoeff;
277 *dstCoeff = kOne_GrBlendCoeff;
278 }
279
jvanverth@google.com054ae992013-04-01 20:06:51 +0000280 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000281 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
282 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
283 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
284 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
285
286 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000287 !this->hasCoverageVertexAttribute() &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000288 0 == this->getCoverage();
289 // When coeffs are (0,1) there is no reason to draw at all, unless
290 // stenciling is enabled. Having color writes disabled is effectively
291 // (0,1). The same applies when coverage is known to be 0.
292 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
293 if (this->getStencil().doesWrite()) {
294 return kDisableBlend_BlendOptFlag |
295 kEmitTransBlack_BlendOptFlag;
296 } else {
297 return kSkipDraw_BlendOptFlag;
298 }
299 }
300
bsalomon@google.com4647f902013-03-26 14:45:27 +0000301 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000302 bool hasCoverage = forceCoverage ||
303 0xffffffff != this->getCoverage() ||
jvanverth@google.com054ae992013-04-01 20:06:51 +0000304 this->hasCoverageVertexAttribute();
305 for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000306 if (this->isStageEnabled(s)) {
307 hasCoverage = true;
308 }
309 }
310
311 // if we don't have coverage we can check whether the dst
312 // has to read at all. If not, we'll disable blending.
313 if (!hasCoverage) {
314 if (dstCoeffIsZero) {
315 if (kOne_GrBlendCoeff == *srcCoeff) {
316 // if there is no coverage and coeffs are (1,0) then we
317 // won't need to read the dst at all, it gets replaced by src
318 return kDisableBlend_BlendOptFlag;
319 } else if (kZero_GrBlendCoeff == *srcCoeff) {
320 // if the op is "clear" then we don't need to emit a color
321 // or blend, just write transparent black into the dst.
322 *srcCoeff = kOne_GrBlendCoeff;
323 *dstCoeff = kZero_GrBlendCoeff;
324 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
325 }
326 }
327 } else if (this->isCoverageDrawing()) {
328 // we have coverage but we aren't distinguishing it from alpha by request.
329 return kCoverageAsAlpha_BlendOptFlag;
330 } else {
331 // check whether coverage can be safely rolled into alpha
332 // of if we can skip color computation and just emit coverage
333 if (this->canTweakAlphaForCoverage()) {
334 return kCoverageAsAlpha_BlendOptFlag;
335 }
336 if (dstCoeffIsZero) {
337 if (kZero_GrBlendCoeff == *srcCoeff) {
338 // the source color is not included in the blend
339 // the dst coeff is effectively zero so blend works out to:
340 // (c)(0)D + (1-c)D = (1-c)D.
341 *dstCoeff = kISA_GrBlendCoeff;
342 return kEmitCoverage_BlendOptFlag;
343 } else if (srcAIsOne) {
344 // the dst coeff is effectively zero so blend works out to:
345 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
346 // If Sa is 1 then we can replace Sa with c
347 // and set dst coeff to 1-Sa.
348 *dstCoeff = kISA_GrBlendCoeff;
349 return kCoverageAsAlpha_BlendOptFlag;
350 }
351 } else if (dstCoeffIsOne) {
352 // the dst coeff is effectively one so blend works out to:
353 // cS + (c)(1)D + (1-c)D = cS + D.
354 *dstCoeff = kOne_GrBlendCoeff;
355 return kCoverageAsAlpha_BlendOptFlag;
356 }
357 }
358 return kNone_BlendOpt;
359}
360
361////////////////////////////////////////////////////////////////////////////////
362
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000363void GrDrawState::AutoViewMatrixRestore::restore() {
364 if (NULL != fDrawState) {
365 fDrawState->setViewMatrix(fViewMatrix);
366 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
367 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000368 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000369 }
370 }
371 }
372 fDrawState = NULL;
373}
374
375void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000376 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000377 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000378
379 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000380 if (NULL == drawState) {
381 return;
382 }
383
384 fRestoreMask = 0;
385 fViewMatrix = drawState->getViewMatrix();
386 drawState->preConcatViewMatrix(preconcatMatrix);
387 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000388 if (drawState->isStageEnabled(s)) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000389 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000390 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000391 drawState->fStages[s].localCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000392 }
393 }
394}
395
396////////////////////////////////////////////////////////////////////////////////
397
398void GrDrawState::AutoDeviceCoordDraw::restore() {
399 if (NULL != fDrawState) {
400 fDrawState->setViewMatrix(fViewMatrix);
401 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
402 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000403 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000404 }
405 }
406 }
407 fDrawState = NULL;
408}
409
bsalomon@google.comc7818882013-03-20 19:19:53 +0000410bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000411 GrAssert(NULL != drawState);
412
413 this->restore();
414
415 fDrawState = drawState;
416 if (NULL == fDrawState) {
417 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000418 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000419
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000420 fViewMatrix = drawState->getViewMatrix();
421 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000422 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000423 bool inverted = false;
424
425 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000426 if (drawState->isStageEnabled(s)) {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000427 if (!inverted && !fViewMatrix.invert(&invVM)) {
428 // sad trombone sound
429 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000430 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000431 } else {
432 inverted = true;
433 }
434 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000435 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000436 stage->saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000437 stage->localCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000438 }
439 }
440 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000441 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000442}