blob: f114cccf8949d30eb18a8b8c3997c9d45a6926ba [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
67 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000068 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
69 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000070
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000071 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
72 this->setColorFilter(paint.getColorFilterColor(), paint.getColorFilterMode());
73 this->setCoverage(paint.getCoverage());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000074}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +000075
76////////////////////////////////////////////////////////////////////////////////
77
jvanverth@google.com9b855c72013-03-01 18:21:22 +000078static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
79 // this works as long as we're 4 byte-aligned
80#if GR_DEBUG
81 uint32_t overlapCheck = 0;
82#endif
jvanverth@google.com054ae992013-04-01 20:06:51 +000083 GrAssert(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000084 size_t size = 0;
85 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +000086 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000087 size += attribSize;
88#if GR_DEBUG
89 size_t dwordCount = attribSize >> 2;
90 uint32_t mask = (1 << dwordCount)-1;
91 size_t offsetShift = attribs[index].fOffset >> 2;
92 GrAssert(!(overlapCheck & (mask << offsetShift)));
93 overlapCheck |= (mask << offsetShift);
94#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +000095 }
96 return size;
97}
98
jvanverth@google.com9b855c72013-03-01 18:21:22 +000099size_t GrDrawState::getVertexSize() const {
robertphillips@google.com42903302013-04-20 12:26:07 +0000100 return vertex_size(fCommon.fVAPtr, fCommon.fVACount);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000101}
102
jvanverth@google.comcc782382013-01-28 20:39:48 +0000103////////////////////////////////////////////////////////////////////////////////
104
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000105void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000106 GrAssert(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000107
108 fCommon.fVAPtr = attribs;
109 fCommon.fVACount = count;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000110
111 // Set all the indices to -1
112 memset(fCommon.fFixedFunctionVertexAttribIndices,
113 0xff,
114 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
115#if GR_DEBUG
116 uint32_t overlapCheck = 0;
117#endif
118 for (int i = 0; i < count; ++i) {
119 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
120 // The fixed function attribs can only be specified once
121 GrAssert(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
122 GrAssert(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
123 GrVertexAttribTypeVectorCount(attribs[i].fType));
124 fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
125 }
126#if GR_DEBUG
127 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
128 uint32_t mask = (1 << dwordCount)-1;
129 size_t offsetShift = attribs[i].fOffset >> 2;
130 GrAssert(!(overlapCheck & (mask << offsetShift)));
131 overlapCheck |= (mask << offsetShift);
132#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000133 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000134 // Positions must be specified.
135 GrAssert(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000136}
137
138////////////////////////////////////////////////////////////////////////////////
139
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000140void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000141 static const GrVertexAttrib kPositionAttrib =
142 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000143
144 fCommon.fVAPtr = &kPositionAttrib;
145 fCommon.fVACount = 1;
146
jvanverth@google.com054ae992013-04-01 20:06:51 +0000147 // set all the fixed function indices to -1 except position.
148 memset(fCommon.fFixedFunctionVertexAttribIndices,
149 0xff,
150 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
151 fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000152}
153
154////////////////////////////////////////////////////////////////////////////////
155
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000156bool GrDrawState::validateVertexAttribs() const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000157 // check consistency of effects and attributes
158 GrSLType slTypes[kMaxVertexAttribCnt];
159 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
160 slTypes[i] = static_cast<GrSLType>(-1);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000161 }
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000162 for (int s = 0; s < kNumStages; ++s) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000163 if (this->isStageEnabled(s)) {
164 const GrEffectStage& stage = fStages[s];
165 const GrEffectRef* effect = stage.getEffect();
166 // make sure that any attribute indices have the correct binding type, that the attrib
167 // type and effect's shader lang type are compatible, and that attributes shared by
168 // multiple effects use the same shader lang type.
169 const int* attributeIndices = stage.getVertexAttribIndices();
170 int numAttributes = stage.getVertexAttribIndexCount();
171 for (int i = 0; i < numAttributes; ++i) {
172 int attribIndex = attributeIndices[i];
robertphillips@google.com42903302013-04-20 12:26:07 +0000173 if (attribIndex >= fCommon.fVACount ||
174 kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000175 return false;
176 }
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000177
jvanverth@google.com054ae992013-04-01 20:06:51 +0000178 GrSLType effectSLType = (*effect)->vertexAttribType(i);
robertphillips@google.com42903302013-04-20 12:26:07 +0000179 GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000180 int slVecCount = GrSLTypeVectorCount(effectSLType);
181 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
182 if (slVecCount != attribVecCount ||
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000183 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
robertphillips@google.com2c5ddb62013-04-01 23:24:15 +0000184 slTypes[attribIndex] != effectSLType)) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000185 return false;
186 }
187 slTypes[attribIndex] = effectSLType;
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000188 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000189 }
190 }
191
192 return true;
193}
194
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000195bool GrDrawState::willEffectReadDstColor() const {
196 int startStage = this->isColorWriteDisabled() ? this->getFirstCoverageStage() : 0;
197 for (int s = startStage; s < kNumStages; ++s) {
198 if (this->isStageEnabled(s) && (*this->getStage(s).getEffect())->willReadDstColor()) {
199 return true;
200 }
201 }
202 return false;
203}
204
jvanverth@google.comcc782382013-01-28 20:39:48 +0000205////////////////////////////////////////////////////////////////////////////////
206
jvanverth@google.com054ae992013-04-01 20:06:51 +0000207bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000208 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000209 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000210 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000211 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000212 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000213 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000214 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000215 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000216 color = this->getColor();
217 }
218
219 // Run through the color stages
220 int stageCnt = getFirstCoverageStage();
221 for (int s = 0; s < stageCnt; ++s) {
222 const GrEffectRef* effect = this->getStage(s).getEffect();
223 if (NULL != effect) {
224 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
225 }
226 }
227
228 // Check if the color filter could introduce an alpha.
229 // We could skip the above work when this is true, but it is rare and the right fix is to make
230 // the color filter a GrEffect and implement getConstantColorComponents() for it.
231 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
232 validComponentFlags = 0;
233 }
234
235 // Check whether coverage is treated as color. If so we run through the coverage computation.
236 if (this->isCoverageDrawing()) {
237 GrColor coverageColor = this->getCoverage();
238 GrColor oldColor = color;
239 color = 0;
240 for (int c = 0; c < 4; ++c) {
241 if (validComponentFlags & (1 << c)) {
242 U8CPU a = (oldColor >> (c * 8)) & 0xff;
243 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
244 color |= (SkMulDiv255Round(a, b) << (c * 8));
245 }
246 }
247 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
248 const GrEffectRef* effect = this->getStage(s).getEffect();
249 if (NULL != effect) {
250 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
251 }
252 }
253 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000254 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000255}
256
jvanverth@google.com054ae992013-04-01 20:06:51 +0000257bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000258 // If we're drawing coverage directly then coverage is effectively treated as color.
259 if (this->isCoverageDrawing()) {
260 return true;
261 }
262
263 GrColor coverage;
264 uint32_t validComponentFlags;
265 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000266 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000267 validComponentFlags = 0;
268 } else {
269 coverage = fCommon.fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000270 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000271 }
272
273 // Run through the coverage stages and see if the coverage will be all ones at the end.
274 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
275 const GrEffectRef* effect = this->getStage(s).getEffect();
276 if (NULL != effect) {
277 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
278 }
279 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000280 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000281}
282
jvanverth@google.comcc782382013-01-28 20:39:48 +0000283////////////////////////////////////////////////////////////////////////////////
284
bsalomon@google.com2b446732013-02-12 16:47:41 +0000285// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
286// others will blend incorrectly.
287bool GrDrawState::canTweakAlphaForCoverage() const {
288 /*
289 The fractional coverage is f.
290 The src and dst coeffs are Cs and Cd.
291 The dst and src colors are S and D.
292 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
293 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
294 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
295 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
296 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
297 color by definition.
298 */
299 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
300 kISA_GrBlendCoeff == fCommon.fDstBlend ||
301 kISC_GrBlendCoeff == fCommon.fDstBlend ||
302 this->isCoverageDrawing();
303}
304
305GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
306 GrBlendCoeff* srcCoeff,
307 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000308
309 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
310 if (NULL == srcCoeff) {
311 srcCoeff = &bogusSrcCoeff;
312 }
313 *srcCoeff = this->getSrcBlendCoeff();
314
315 if (NULL == dstCoeff) {
316 dstCoeff = &bogusDstCoeff;
317 }
318 *dstCoeff = this->getDstBlendCoeff();
319
320 if (this->isColorWriteDisabled()) {
321 *srcCoeff = kZero_GrBlendCoeff;
322 *dstCoeff = kOne_GrBlendCoeff;
323 }
324
jvanverth@google.com054ae992013-04-01 20:06:51 +0000325 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000326 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
327 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
328 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
329 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
330
331 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000332 !this->hasCoverageVertexAttribute() &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000333 0 == this->getCoverage();
334 // When coeffs are (0,1) there is no reason to draw at all, unless
335 // stenciling is enabled. Having color writes disabled is effectively
336 // (0,1). The same applies when coverage is known to be 0.
337 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
338 if (this->getStencil().doesWrite()) {
339 return kDisableBlend_BlendOptFlag |
340 kEmitTransBlack_BlendOptFlag;
341 } else {
342 return kSkipDraw_BlendOptFlag;
343 }
344 }
345
bsalomon@google.com4647f902013-03-26 14:45:27 +0000346 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000347 bool hasCoverage = forceCoverage ||
348 0xffffffff != this->getCoverage() ||
jvanverth@google.com054ae992013-04-01 20:06:51 +0000349 this->hasCoverageVertexAttribute();
350 for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000351 if (this->isStageEnabled(s)) {
352 hasCoverage = true;
353 }
354 }
355
356 // if we don't have coverage we can check whether the dst
357 // has to read at all. If not, we'll disable blending.
358 if (!hasCoverage) {
359 if (dstCoeffIsZero) {
360 if (kOne_GrBlendCoeff == *srcCoeff) {
361 // if there is no coverage and coeffs are (1,0) then we
362 // won't need to read the dst at all, it gets replaced by src
363 return kDisableBlend_BlendOptFlag;
364 } else if (kZero_GrBlendCoeff == *srcCoeff) {
365 // if the op is "clear" then we don't need to emit a color
366 // or blend, just write transparent black into the dst.
367 *srcCoeff = kOne_GrBlendCoeff;
368 *dstCoeff = kZero_GrBlendCoeff;
369 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
370 }
371 }
372 } else if (this->isCoverageDrawing()) {
373 // we have coverage but we aren't distinguishing it from alpha by request.
374 return kCoverageAsAlpha_BlendOptFlag;
375 } else {
376 // check whether coverage can be safely rolled into alpha
377 // of if we can skip color computation and just emit coverage
378 if (this->canTweakAlphaForCoverage()) {
379 return kCoverageAsAlpha_BlendOptFlag;
380 }
381 if (dstCoeffIsZero) {
382 if (kZero_GrBlendCoeff == *srcCoeff) {
383 // the source color is not included in the blend
384 // the dst coeff is effectively zero so blend works out to:
385 // (c)(0)D + (1-c)D = (1-c)D.
386 *dstCoeff = kISA_GrBlendCoeff;
387 return kEmitCoverage_BlendOptFlag;
388 } else if (srcAIsOne) {
389 // the dst coeff is effectively zero so blend works out to:
390 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
391 // If Sa is 1 then we can replace Sa with c
392 // and set dst coeff to 1-Sa.
393 *dstCoeff = kISA_GrBlendCoeff;
394 return kCoverageAsAlpha_BlendOptFlag;
395 }
396 } else if (dstCoeffIsOne) {
397 // the dst coeff is effectively one so blend works out to:
398 // cS + (c)(1)D + (1-c)D = cS + D.
399 *dstCoeff = kOne_GrBlendCoeff;
400 return kCoverageAsAlpha_BlendOptFlag;
401 }
402 }
bsalomon@google.com0c89db22013-05-15 17:53:04 +0000403 if (kOne_GrBlendCoeff == *srcCoeff &&
404 kZero_GrBlendCoeff == *dstCoeff &&
405 this->willEffectReadDstColor()) {
406 // In this case the shader will fully resolve the color, coverage, and dst and we don't
407 // need blending.
408 return kDisableBlend_BlendOptFlag;
409 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000410 return kNone_BlendOpt;
411}
412
413////////////////////////////////////////////////////////////////////////////////
414
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000415void GrDrawState::AutoViewMatrixRestore::restore() {
416 if (NULL != fDrawState) {
bsalomon@google.com137f1342013-05-29 21:27:53 +0000417 fDrawState->fCommon.fViewMatrix = fViewMatrix;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000418 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
419 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000420 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000421 }
422 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000423 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000424 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000425}
426
427void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000428 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000429 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000430
bsalomon@google.com137f1342013-05-29 21:27:53 +0000431 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000432 return;
433 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000434 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000435
436 fRestoreMask = 0;
437 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000438 drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000439 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000440 if (drawState->isStageEnabled(s)) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000441 fRestoreMask |= (1 << s);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000442 drawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000443 drawState->fStages[s].localCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000444 }
445 }
446}
447
bsalomon@google.com137f1342013-05-29 21:27:53 +0000448bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000449 this->restore();
450
bsalomon@google.com137f1342013-05-29 21:27:53 +0000451 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000452 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000453 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000454
bsalomon@google.com137f1342013-05-29 21:27:53 +0000455 if (drawState->getViewMatrix().isIdentity()) {
456 return true;
457 }
458
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000459 fViewMatrix = drawState->getViewMatrix();
460 fRestoreMask = 0;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000461 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000462 if (drawState->isStageEnabled(s)) {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000463 fRestoreMask |= (1 << s);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000464 drawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000465 }
466 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000467 if (!drawState->setIdentityViewMatrix()) {
468 return false;
469 }
470 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000471 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000472}