blob: 21bff8b668faeafdb1e1d97d87dd14ad0862bd92 [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 ||
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000149 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
robertphillips@google.com2c5ddb62013-04-01 23:24:15 +0000150 slTypes[attribIndex] != effectSLType)) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000151 return false;
152 }
153 slTypes[attribIndex] = effectSLType;
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000154 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000155 }
156 }
157
158 return true;
159}
160
jvanverth@google.comcc782382013-01-28 20:39:48 +0000161////////////////////////////////////////////////////////////////////////////////
162
jvanverth@google.com054ae992013-04-01 20:06:51 +0000163bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000164 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000165 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000166 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000167 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000168 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000169 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000170 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000171 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000172 color = this->getColor();
173 }
174
175 // Run through the color stages
176 int stageCnt = getFirstCoverageStage();
177 for (int s = 0; s < stageCnt; ++s) {
178 const GrEffectRef* effect = this->getStage(s).getEffect();
179 if (NULL != effect) {
180 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
181 }
182 }
183
184 // Check if the color filter could introduce an alpha.
185 // We could skip the above work when this is true, but it is rare and the right fix is to make
186 // the color filter a GrEffect and implement getConstantColorComponents() for it.
187 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
188 validComponentFlags = 0;
189 }
190
191 // Check whether coverage is treated as color. If so we run through the coverage computation.
192 if (this->isCoverageDrawing()) {
193 GrColor coverageColor = this->getCoverage();
194 GrColor oldColor = color;
195 color = 0;
196 for (int c = 0; c < 4; ++c) {
197 if (validComponentFlags & (1 << c)) {
198 U8CPU a = (oldColor >> (c * 8)) & 0xff;
199 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
200 color |= (SkMulDiv255Round(a, b) << (c * 8));
201 }
202 }
203 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
204 const GrEffectRef* effect = this->getStage(s).getEffect();
205 if (NULL != effect) {
206 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
207 }
208 }
209 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000210 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000211}
212
jvanverth@google.com054ae992013-04-01 20:06:51 +0000213bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000214 // If we're drawing coverage directly then coverage is effectively treated as color.
215 if (this->isCoverageDrawing()) {
216 return true;
217 }
218
219 GrColor coverage;
220 uint32_t validComponentFlags;
221 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000222 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000223 validComponentFlags = 0;
224 } else {
225 coverage = fCommon.fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000226 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000227 }
228
229 // Run through the coverage stages and see if the coverage will be all ones at the end.
230 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
231 const GrEffectRef* effect = this->getStage(s).getEffect();
232 if (NULL != effect) {
233 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
234 }
235 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000236 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000237}
238
jvanverth@google.comcc782382013-01-28 20:39:48 +0000239////////////////////////////////////////////////////////////////////////////////
240
bsalomon@google.com2b446732013-02-12 16:47:41 +0000241// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
242// others will blend incorrectly.
243bool GrDrawState::canTweakAlphaForCoverage() const {
244 /*
245 The fractional coverage is f.
246 The src and dst coeffs are Cs and Cd.
247 The dst and src colors are S and D.
248 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
249 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
250 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
251 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
252 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
253 color by definition.
254 */
255 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
256 kISA_GrBlendCoeff == fCommon.fDstBlend ||
257 kISC_GrBlendCoeff == fCommon.fDstBlend ||
258 this->isCoverageDrawing();
259}
260
261GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
262 GrBlendCoeff* srcCoeff,
263 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000264
265 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
266 if (NULL == srcCoeff) {
267 srcCoeff = &bogusSrcCoeff;
268 }
269 *srcCoeff = this->getSrcBlendCoeff();
270
271 if (NULL == dstCoeff) {
272 dstCoeff = &bogusDstCoeff;
273 }
274 *dstCoeff = this->getDstBlendCoeff();
275
276 if (this->isColorWriteDisabled()) {
277 *srcCoeff = kZero_GrBlendCoeff;
278 *dstCoeff = kOne_GrBlendCoeff;
279 }
280
jvanverth@google.com054ae992013-04-01 20:06:51 +0000281 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000282 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
283 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
284 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
285 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
286
287 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000288 !this->hasCoverageVertexAttribute() &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000289 0 == this->getCoverage();
290 // When coeffs are (0,1) there is no reason to draw at all, unless
291 // stenciling is enabled. Having color writes disabled is effectively
292 // (0,1). The same applies when coverage is known to be 0.
293 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
294 if (this->getStencil().doesWrite()) {
295 return kDisableBlend_BlendOptFlag |
296 kEmitTransBlack_BlendOptFlag;
297 } else {
298 return kSkipDraw_BlendOptFlag;
299 }
300 }
301
bsalomon@google.com4647f902013-03-26 14:45:27 +0000302 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000303 bool hasCoverage = forceCoverage ||
304 0xffffffff != this->getCoverage() ||
jvanverth@google.com054ae992013-04-01 20:06:51 +0000305 this->hasCoverageVertexAttribute();
306 for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000307 if (this->isStageEnabled(s)) {
308 hasCoverage = true;
309 }
310 }
311
312 // if we don't have coverage we can check whether the dst
313 // has to read at all. If not, we'll disable blending.
314 if (!hasCoverage) {
315 if (dstCoeffIsZero) {
316 if (kOne_GrBlendCoeff == *srcCoeff) {
317 // if there is no coverage and coeffs are (1,0) then we
318 // won't need to read the dst at all, it gets replaced by src
319 return kDisableBlend_BlendOptFlag;
320 } else if (kZero_GrBlendCoeff == *srcCoeff) {
321 // if the op is "clear" then we don't need to emit a color
322 // or blend, just write transparent black into the dst.
323 *srcCoeff = kOne_GrBlendCoeff;
324 *dstCoeff = kZero_GrBlendCoeff;
325 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
326 }
327 }
328 } else if (this->isCoverageDrawing()) {
329 // we have coverage but we aren't distinguishing it from alpha by request.
330 return kCoverageAsAlpha_BlendOptFlag;
331 } else {
332 // check whether coverage can be safely rolled into alpha
333 // of if we can skip color computation and just emit coverage
334 if (this->canTweakAlphaForCoverage()) {
335 return kCoverageAsAlpha_BlendOptFlag;
336 }
337 if (dstCoeffIsZero) {
338 if (kZero_GrBlendCoeff == *srcCoeff) {
339 // the source color is not included in the blend
340 // the dst coeff is effectively zero so blend works out to:
341 // (c)(0)D + (1-c)D = (1-c)D.
342 *dstCoeff = kISA_GrBlendCoeff;
343 return kEmitCoverage_BlendOptFlag;
344 } else if (srcAIsOne) {
345 // the dst coeff is effectively zero so blend works out to:
346 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
347 // If Sa is 1 then we can replace Sa with c
348 // and set dst coeff to 1-Sa.
349 *dstCoeff = kISA_GrBlendCoeff;
350 return kCoverageAsAlpha_BlendOptFlag;
351 }
352 } else if (dstCoeffIsOne) {
353 // the dst coeff is effectively one so blend works out to:
354 // cS + (c)(1)D + (1-c)D = cS + D.
355 *dstCoeff = kOne_GrBlendCoeff;
356 return kCoverageAsAlpha_BlendOptFlag;
357 }
358 }
359 return kNone_BlendOpt;
360}
361
362////////////////////////////////////////////////////////////////////////////////
363
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000364void GrDrawState::AutoViewMatrixRestore::restore() {
365 if (NULL != fDrawState) {
366 fDrawState->setViewMatrix(fViewMatrix);
367 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
368 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000369 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000370 }
371 }
372 }
373 fDrawState = NULL;
374}
375
376void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000377 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000378 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000379
380 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000381 if (NULL == drawState) {
382 return;
383 }
384
385 fRestoreMask = 0;
386 fViewMatrix = drawState->getViewMatrix();
387 drawState->preConcatViewMatrix(preconcatMatrix);
388 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000389 if (drawState->isStageEnabled(s)) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000390 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000391 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000392 drawState->fStages[s].localCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000393 }
394 }
395}
396
397////////////////////////////////////////////////////////////////////////////////
398
399void GrDrawState::AutoDeviceCoordDraw::restore() {
400 if (NULL != fDrawState) {
401 fDrawState->setViewMatrix(fViewMatrix);
402 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
403 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000404 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000405 }
406 }
407 }
408 fDrawState = NULL;
409}
410
bsalomon@google.comc7818882013-03-20 19:19:53 +0000411bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000412 GrAssert(NULL != drawState);
413
414 this->restore();
415
416 fDrawState = drawState;
417 if (NULL == fDrawState) {
418 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000419 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000420
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000421 fViewMatrix = drawState->getViewMatrix();
422 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000423 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000424 bool inverted = false;
425
426 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000427 if (drawState->isStageEnabled(s)) {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000428 if (!inverted && !fViewMatrix.invert(&invVM)) {
429 // sad trombone sound
430 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000431 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000432 } else {
433 inverted = true;
434 }
435 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000436 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000437 stage->saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000438 stage->localCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000439 }
440 }
441 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000442 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000443}