blob: 2a81e2619c1efdc1df5fbf85934025f719cf93a0 [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() {
12 SkMatrix invVM;
13 bool inverted = false;
14 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
15 if (this->isStageEnabled(s)) {
16 if (!inverted) {
17 if (!fCommon.fViewMatrix.invert(&invVM)) {
18 // sad trombone sound
19 return false;
20 }
21 inverted = true;
22 }
23 fStages[s].localCoordChange(invVM);
24 }
25 }
26 fCommon.fViewMatrix.reset();
27 return true;
28}
29
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000030void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
bsalomon@google.com88becf42012-10-05 14:54:42 +000031 for (int i = 0; i < GrPaint::kMaxColorStages; ++i) {
32 int s = i + GrPaint::kFirstColorStage;
33 if (paint.isColorStageEnabled(i)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +000034 fStages[s] = paint.getColorStage(i);
35 } else {
36 fStages[s].setEffect(NULL);
bsalomon@google.comaf84e742012-10-05 13:23:24 +000037 }
38 }
39
bsalomon@google.com88becf42012-10-05 14:54:42 +000040 this->setFirstCoverageStage(GrPaint::kFirstCoverageStage);
bsalomon@google.comaf84e742012-10-05 13:23:24 +000041
bsalomon@google.com88becf42012-10-05 14:54:42 +000042 for (int i = 0; i < GrPaint::kMaxCoverageStages; ++i) {
43 int s = i + GrPaint::kFirstCoverageStage;
44 if (paint.isCoverageStageEnabled(i)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +000045 fStages[s] = paint.getCoverageStage(i);
46 } else {
47 fStages[s].setEffect(NULL);
bsalomon@google.comaf84e742012-10-05 13:23:24 +000048 }
49 }
50
51 // disable all stages not accessible via the paint
52 for (int s = GrPaint::kTotalStages; s < GrDrawState::kNumStages; ++s) {
53 this->disableStage(s);
54 }
55
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000056 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +000057
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000058 fCommon.fViewMatrix = vm;
59
60 // These have no equivalent in GrPaint, set them to defaults
61 fCommon.fBlendConstant = 0x0;
62 fCommon.fCoverage = 0xffffffff;
63 fCommon.fDrawFace = kBoth_DrawFace;
64 fCommon.fStencilSettings.setDisabled();
65 this->resetStateFlags();
66
bsalomon@google.com21c10c52013-06-13 17:44:07 +000067 // Enable the clip bit
68 this->enableState(GrDrawState::kClip_StateBit);
69
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000070 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000071 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
72 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000073
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000074 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
75 this->setColorFilter(paint.getColorFilterColor(), paint.getColorFilterMode());
76 this->setCoverage(paint.getCoverage());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000077}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +000078
79////////////////////////////////////////////////////////////////////////////////
80
jvanverth@google.com9b855c72013-03-01 18:21:22 +000081static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
82 // this works as long as we're 4 byte-aligned
83#if GR_DEBUG
84 uint32_t overlapCheck = 0;
85#endif
jvanverth@google.com054ae992013-04-01 20:06:51 +000086 GrAssert(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000087 size_t size = 0;
88 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +000089 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000090 size += attribSize;
91#if GR_DEBUG
92 size_t dwordCount = attribSize >> 2;
93 uint32_t mask = (1 << dwordCount)-1;
94 size_t offsetShift = attribs[index].fOffset >> 2;
95 GrAssert(!(overlapCheck & (mask << offsetShift)));
96 overlapCheck |= (mask << offsetShift);
97#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +000098 }
99 return size;
100}
101
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000102size_t GrDrawState::getVertexSize() const {
robertphillips@google.com42903302013-04-20 12:26:07 +0000103 return vertex_size(fCommon.fVAPtr, fCommon.fVACount);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000104}
105
jvanverth@google.comcc782382013-01-28 20:39:48 +0000106////////////////////////////////////////////////////////////////////////////////
107
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000108void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000109 GrAssert(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000110
111 fCommon.fVAPtr = attribs;
112 fCommon.fVACount = count;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000113
114 // Set all the indices to -1
115 memset(fCommon.fFixedFunctionVertexAttribIndices,
116 0xff,
117 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
118#if GR_DEBUG
119 uint32_t overlapCheck = 0;
120#endif
121 for (int i = 0; i < count; ++i) {
122 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
123 // The fixed function attribs can only be specified once
124 GrAssert(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
125 GrAssert(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
126 GrVertexAttribTypeVectorCount(attribs[i].fType));
127 fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
128 }
129#if GR_DEBUG
130 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
131 uint32_t mask = (1 << dwordCount)-1;
132 size_t offsetShift = attribs[i].fOffset >> 2;
133 GrAssert(!(overlapCheck & (mask << offsetShift)));
134 overlapCheck |= (mask << offsetShift);
135#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000136 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000137 // Positions must be specified.
138 GrAssert(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000139}
140
141////////////////////////////////////////////////////////////////////////////////
142
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000143void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000144 static const GrVertexAttrib kPositionAttrib =
145 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000146
147 fCommon.fVAPtr = &kPositionAttrib;
148 fCommon.fVACount = 1;
149
jvanverth@google.com054ae992013-04-01 20:06:51 +0000150 // set all the fixed function indices to -1 except position.
151 memset(fCommon.fFixedFunctionVertexAttribIndices,
152 0xff,
153 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
154 fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000155}
156
157////////////////////////////////////////////////////////////////////////////////
158
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000159bool GrDrawState::validateVertexAttribs() const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000160 // check consistency of effects and attributes
161 GrSLType slTypes[kMaxVertexAttribCnt];
162 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
163 slTypes[i] = static_cast<GrSLType>(-1);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000164 }
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000165 for (int s = 0; s < kNumStages; ++s) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000166 if (this->isStageEnabled(s)) {
167 const GrEffectStage& stage = fStages[s];
168 const GrEffectRef* effect = stage.getEffect();
169 // make sure that any attribute indices have the correct binding type, that the attrib
170 // type and effect's shader lang type are compatible, and that attributes shared by
171 // multiple effects use the same shader lang type.
172 const int* attributeIndices = stage.getVertexAttribIndices();
173 int numAttributes = stage.getVertexAttribIndexCount();
174 for (int i = 0; i < numAttributes; ++i) {
175 int attribIndex = attributeIndices[i];
robertphillips@google.com42903302013-04-20 12:26:07 +0000176 if (attribIndex >= fCommon.fVACount ||
177 kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000178 return false;
179 }
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000180
jvanverth@google.com054ae992013-04-01 20:06:51 +0000181 GrSLType effectSLType = (*effect)->vertexAttribType(i);
robertphillips@google.com42903302013-04-20 12:26:07 +0000182 GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000183 int slVecCount = GrSLTypeVectorCount(effectSLType);
184 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
185 if (slVecCount != attribVecCount ||
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000186 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
robertphillips@google.com2c5ddb62013-04-01 23:24:15 +0000187 slTypes[attribIndex] != effectSLType)) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000188 return false;
189 }
190 slTypes[attribIndex] = effectSLType;
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000191 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000192 }
193 }
194
195 return true;
196}
197
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000198bool GrDrawState::willEffectReadDstColor() const {
199 int startStage = this->isColorWriteDisabled() ? this->getFirstCoverageStage() : 0;
200 for (int s = startStage; s < kNumStages; ++s) {
201 if (this->isStageEnabled(s) && (*this->getStage(s).getEffect())->willReadDstColor()) {
202 return true;
203 }
204 }
205 return false;
206}
207
jvanverth@google.comcc782382013-01-28 20:39:48 +0000208////////////////////////////////////////////////////////////////////////////////
209
jvanverth@google.com054ae992013-04-01 20:06:51 +0000210bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000211 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000212 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000213 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000214 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000215 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000216 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000217 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000218 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000219 color = this->getColor();
220 }
221
222 // Run through the color stages
223 int stageCnt = getFirstCoverageStage();
224 for (int s = 0; s < stageCnt; ++s) {
225 const GrEffectRef* effect = this->getStage(s).getEffect();
226 if (NULL != effect) {
227 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
228 }
229 }
230
231 // Check if the color filter could introduce an alpha.
232 // We could skip the above work when this is true, but it is rare and the right fix is to make
233 // the color filter a GrEffect and implement getConstantColorComponents() for it.
234 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
235 validComponentFlags = 0;
236 }
237
238 // Check whether coverage is treated as color. If so we run through the coverage computation.
239 if (this->isCoverageDrawing()) {
240 GrColor coverageColor = this->getCoverage();
241 GrColor oldColor = color;
242 color = 0;
243 for (int c = 0; c < 4; ++c) {
244 if (validComponentFlags & (1 << c)) {
245 U8CPU a = (oldColor >> (c * 8)) & 0xff;
246 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
247 color |= (SkMulDiv255Round(a, b) << (c * 8));
248 }
249 }
250 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
251 const GrEffectRef* effect = this->getStage(s).getEffect();
252 if (NULL != effect) {
253 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
254 }
255 }
256 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000257 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000258}
259
jvanverth@google.com054ae992013-04-01 20:06:51 +0000260bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000261 // If we're drawing coverage directly then coverage is effectively treated as color.
262 if (this->isCoverageDrawing()) {
263 return true;
264 }
265
266 GrColor coverage;
267 uint32_t validComponentFlags;
268 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000269 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000270 validComponentFlags = 0;
271 } else {
272 coverage = fCommon.fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000273 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000274 }
275
276 // Run through the coverage stages and see if the coverage will be all ones at the end.
277 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
278 const GrEffectRef* effect = this->getStage(s).getEffect();
279 if (NULL != effect) {
280 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
281 }
282 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000283 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000284}
285
jvanverth@google.comcc782382013-01-28 20:39:48 +0000286////////////////////////////////////////////////////////////////////////////////
287
bsalomon@google.com2b446732013-02-12 16:47:41 +0000288// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
289// others will blend incorrectly.
290bool GrDrawState::canTweakAlphaForCoverage() const {
291 /*
292 The fractional coverage is f.
293 The src and dst coeffs are Cs and Cd.
294 The dst and src colors are S and D.
295 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
296 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
297 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
298 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
299 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
300 color by definition.
301 */
302 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
303 kISA_GrBlendCoeff == fCommon.fDstBlend ||
304 kISC_GrBlendCoeff == fCommon.fDstBlend ||
305 this->isCoverageDrawing();
306}
307
308GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
309 GrBlendCoeff* srcCoeff,
310 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000311
312 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
313 if (NULL == srcCoeff) {
314 srcCoeff = &bogusSrcCoeff;
315 }
316 *srcCoeff = this->getSrcBlendCoeff();
317
318 if (NULL == dstCoeff) {
319 dstCoeff = &bogusDstCoeff;
320 }
321 *dstCoeff = this->getDstBlendCoeff();
322
323 if (this->isColorWriteDisabled()) {
324 *srcCoeff = kZero_GrBlendCoeff;
325 *dstCoeff = kOne_GrBlendCoeff;
326 }
327
jvanverth@google.com054ae992013-04-01 20:06:51 +0000328 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000329 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
330 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
331 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
332 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
333
334 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000335 !this->hasCoverageVertexAttribute() &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000336 0 == this->getCoverage();
337 // When coeffs are (0,1) there is no reason to draw at all, unless
338 // stenciling is enabled. Having color writes disabled is effectively
339 // (0,1). The same applies when coverage is known to be 0.
340 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
341 if (this->getStencil().doesWrite()) {
342 return kDisableBlend_BlendOptFlag |
343 kEmitTransBlack_BlendOptFlag;
344 } else {
345 return kSkipDraw_BlendOptFlag;
346 }
347 }
348
bsalomon@google.com4647f902013-03-26 14:45:27 +0000349 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000350 bool hasCoverage = forceCoverage ||
351 0xffffffff != this->getCoverage() ||
jvanverth@google.com054ae992013-04-01 20:06:51 +0000352 this->hasCoverageVertexAttribute();
353 for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000354 if (this->isStageEnabled(s)) {
355 hasCoverage = true;
356 }
357 }
358
359 // if we don't have coverage we can check whether the dst
360 // has to read at all. If not, we'll disable blending.
361 if (!hasCoverage) {
362 if (dstCoeffIsZero) {
363 if (kOne_GrBlendCoeff == *srcCoeff) {
364 // if there is no coverage and coeffs are (1,0) then we
365 // won't need to read the dst at all, it gets replaced by src
366 return kDisableBlend_BlendOptFlag;
367 } else if (kZero_GrBlendCoeff == *srcCoeff) {
368 // if the op is "clear" then we don't need to emit a color
369 // or blend, just write transparent black into the dst.
370 *srcCoeff = kOne_GrBlendCoeff;
371 *dstCoeff = kZero_GrBlendCoeff;
372 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
373 }
374 }
375 } else if (this->isCoverageDrawing()) {
376 // we have coverage but we aren't distinguishing it from alpha by request.
377 return kCoverageAsAlpha_BlendOptFlag;
378 } else {
379 // check whether coverage can be safely rolled into alpha
380 // of if we can skip color computation and just emit coverage
381 if (this->canTweakAlphaForCoverage()) {
382 return kCoverageAsAlpha_BlendOptFlag;
383 }
384 if (dstCoeffIsZero) {
385 if (kZero_GrBlendCoeff == *srcCoeff) {
386 // the source color is not included in the blend
387 // the dst coeff is effectively zero so blend works out to:
388 // (c)(0)D + (1-c)D = (1-c)D.
389 *dstCoeff = kISA_GrBlendCoeff;
390 return kEmitCoverage_BlendOptFlag;
391 } else if (srcAIsOne) {
392 // the dst coeff is effectively zero so blend works out to:
393 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
394 // If Sa is 1 then we can replace Sa with c
395 // and set dst coeff to 1-Sa.
396 *dstCoeff = kISA_GrBlendCoeff;
397 return kCoverageAsAlpha_BlendOptFlag;
398 }
399 } else if (dstCoeffIsOne) {
400 // the dst coeff is effectively one so blend works out to:
401 // cS + (c)(1)D + (1-c)D = cS + D.
402 *dstCoeff = kOne_GrBlendCoeff;
403 return kCoverageAsAlpha_BlendOptFlag;
404 }
405 }
bsalomon@google.com0c89db22013-05-15 17:53:04 +0000406 if (kOne_GrBlendCoeff == *srcCoeff &&
407 kZero_GrBlendCoeff == *dstCoeff &&
408 this->willEffectReadDstColor()) {
409 // In this case the shader will fully resolve the color, coverage, and dst and we don't
410 // need blending.
411 return kDisableBlend_BlendOptFlag;
412 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000413 return kNone_BlendOpt;
414}
415
416////////////////////////////////////////////////////////////////////////////////
417
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000418void GrDrawState::AutoViewMatrixRestore::restore() {
419 if (NULL != fDrawState) {
bsalomon@google.com137f1342013-05-29 21:27:53 +0000420 fDrawState->fCommon.fViewMatrix = fViewMatrix;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000421 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
422 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000423 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000424 }
425 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000426 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000427 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000428}
429
430void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000431 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000432 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000433
bsalomon@google.com137f1342013-05-29 21:27:53 +0000434 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000435 return;
436 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000437 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000438
439 fRestoreMask = 0;
440 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000441 drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000442 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000443 if (drawState->isStageEnabled(s)) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000444 fRestoreMask |= (1 << s);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000445 drawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000446 drawState->fStages[s].localCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000447 }
448 }
449}
450
bsalomon@google.com137f1342013-05-29 21:27:53 +0000451bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000452 this->restore();
453
bsalomon@google.com137f1342013-05-29 21:27:53 +0000454 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000455 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000456 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000457
bsalomon@google.com137f1342013-05-29 21:27:53 +0000458 if (drawState->getViewMatrix().isIdentity()) {
459 return true;
460 }
461
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000462 fViewMatrix = drawState->getViewMatrix();
463 fRestoreMask = 0;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000464 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000465 if (drawState->isStageEnabled(s)) {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000466 fRestoreMask |= (1 << s);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000467 drawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000468 }
469 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000470 if (!drawState->setIdentityViewMatrix()) {
471 return false;
472 }
473 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000474 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000475}