blob: a3850b087e7abcabbdcc45ce65c07124a29bc3c2 [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
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000166bool GrDrawState::willEffectReadDstColor() const {
167 int startStage = this->isColorWriteDisabled() ? this->getFirstCoverageStage() : 0;
168 for (int s = startStage; s < kNumStages; ++s) {
169 if (this->isStageEnabled(s) && (*this->getStage(s).getEffect())->willReadDstColor()) {
170 return true;
171 }
172 }
173 return false;
174}
175
jvanverth@google.comcc782382013-01-28 20:39:48 +0000176////////////////////////////////////////////////////////////////////////////////
177
jvanverth@google.com054ae992013-04-01 20:06:51 +0000178bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000179 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000180 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000181 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000182 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000183 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000184 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000185 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000186 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000187 color = this->getColor();
188 }
189
190 // Run through the color stages
191 int stageCnt = getFirstCoverageStage();
192 for (int s = 0; s < stageCnt; ++s) {
193 const GrEffectRef* effect = this->getStage(s).getEffect();
194 if (NULL != effect) {
195 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
196 }
197 }
198
199 // Check if the color filter could introduce an alpha.
200 // We could skip the above work when this is true, but it is rare and the right fix is to make
201 // the color filter a GrEffect and implement getConstantColorComponents() for it.
202 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
203 validComponentFlags = 0;
204 }
205
206 // Check whether coverage is treated as color. If so we run through the coverage computation.
207 if (this->isCoverageDrawing()) {
208 GrColor coverageColor = this->getCoverage();
209 GrColor oldColor = color;
210 color = 0;
211 for (int c = 0; c < 4; ++c) {
212 if (validComponentFlags & (1 << c)) {
213 U8CPU a = (oldColor >> (c * 8)) & 0xff;
214 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
215 color |= (SkMulDiv255Round(a, b) << (c * 8));
216 }
217 }
218 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
219 const GrEffectRef* effect = this->getStage(s).getEffect();
220 if (NULL != effect) {
221 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
222 }
223 }
224 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000225 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000226}
227
jvanverth@google.com054ae992013-04-01 20:06:51 +0000228bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000229 // If we're drawing coverage directly then coverage is effectively treated as color.
230 if (this->isCoverageDrawing()) {
231 return true;
232 }
233
234 GrColor coverage;
235 uint32_t validComponentFlags;
236 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000237 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000238 validComponentFlags = 0;
239 } else {
240 coverage = fCommon.fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000241 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000242 }
243
244 // Run through the coverage stages and see if the coverage will be all ones at the end.
245 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
246 const GrEffectRef* effect = this->getStage(s).getEffect();
247 if (NULL != effect) {
248 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
249 }
250 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000251 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000252}
253
jvanverth@google.comcc782382013-01-28 20:39:48 +0000254////////////////////////////////////////////////////////////////////////////////
255
bsalomon@google.com2b446732013-02-12 16:47:41 +0000256// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
257// others will blend incorrectly.
258bool GrDrawState::canTweakAlphaForCoverage() const {
259 /*
260 The fractional coverage is f.
261 The src and dst coeffs are Cs and Cd.
262 The dst and src colors are S and D.
263 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
264 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
265 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
266 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
267 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
268 color by definition.
269 */
270 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
271 kISA_GrBlendCoeff == fCommon.fDstBlend ||
272 kISC_GrBlendCoeff == fCommon.fDstBlend ||
273 this->isCoverageDrawing();
274}
275
276GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
277 GrBlendCoeff* srcCoeff,
278 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000279
280 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
281 if (NULL == srcCoeff) {
282 srcCoeff = &bogusSrcCoeff;
283 }
284 *srcCoeff = this->getSrcBlendCoeff();
285
286 if (NULL == dstCoeff) {
287 dstCoeff = &bogusDstCoeff;
288 }
289 *dstCoeff = this->getDstBlendCoeff();
290
291 if (this->isColorWriteDisabled()) {
292 *srcCoeff = kZero_GrBlendCoeff;
293 *dstCoeff = kOne_GrBlendCoeff;
294 }
295
jvanverth@google.com054ae992013-04-01 20:06:51 +0000296 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000297 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
298 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
299 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
300 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
301
302 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000303 !this->hasCoverageVertexAttribute() &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000304 0 == this->getCoverage();
305 // When coeffs are (0,1) there is no reason to draw at all, unless
306 // stenciling is enabled. Having color writes disabled is effectively
307 // (0,1). The same applies when coverage is known to be 0.
308 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
309 if (this->getStencil().doesWrite()) {
310 return kDisableBlend_BlendOptFlag |
311 kEmitTransBlack_BlendOptFlag;
312 } else {
313 return kSkipDraw_BlendOptFlag;
314 }
315 }
316
bsalomon@google.com4647f902013-03-26 14:45:27 +0000317 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000318 bool hasCoverage = forceCoverage ||
319 0xffffffff != this->getCoverage() ||
jvanverth@google.com054ae992013-04-01 20:06:51 +0000320 this->hasCoverageVertexAttribute();
321 for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000322 if (this->isStageEnabled(s)) {
323 hasCoverage = true;
324 }
325 }
326
327 // if we don't have coverage we can check whether the dst
328 // has to read at all. If not, we'll disable blending.
329 if (!hasCoverage) {
330 if (dstCoeffIsZero) {
331 if (kOne_GrBlendCoeff == *srcCoeff) {
332 // if there is no coverage and coeffs are (1,0) then we
333 // won't need to read the dst at all, it gets replaced by src
334 return kDisableBlend_BlendOptFlag;
335 } else if (kZero_GrBlendCoeff == *srcCoeff) {
336 // if the op is "clear" then we don't need to emit a color
337 // or blend, just write transparent black into the dst.
338 *srcCoeff = kOne_GrBlendCoeff;
339 *dstCoeff = kZero_GrBlendCoeff;
340 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
341 }
342 }
343 } else if (this->isCoverageDrawing()) {
344 // we have coverage but we aren't distinguishing it from alpha by request.
345 return kCoverageAsAlpha_BlendOptFlag;
346 } else {
347 // check whether coverage can be safely rolled into alpha
348 // of if we can skip color computation and just emit coverage
349 if (this->canTweakAlphaForCoverage()) {
350 return kCoverageAsAlpha_BlendOptFlag;
351 }
352 if (dstCoeffIsZero) {
353 if (kZero_GrBlendCoeff == *srcCoeff) {
354 // the source color is not included in the blend
355 // the dst coeff is effectively zero so blend works out to:
356 // (c)(0)D + (1-c)D = (1-c)D.
357 *dstCoeff = kISA_GrBlendCoeff;
358 return kEmitCoverage_BlendOptFlag;
359 } else if (srcAIsOne) {
360 // the dst coeff is effectively zero so blend works out to:
361 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
362 // If Sa is 1 then we can replace Sa with c
363 // and set dst coeff to 1-Sa.
364 *dstCoeff = kISA_GrBlendCoeff;
365 return kCoverageAsAlpha_BlendOptFlag;
366 }
367 } else if (dstCoeffIsOne) {
368 // the dst coeff is effectively one so blend works out to:
369 // cS + (c)(1)D + (1-c)D = cS + D.
370 *dstCoeff = kOne_GrBlendCoeff;
371 return kCoverageAsAlpha_BlendOptFlag;
372 }
373 }
bsalomon@google.com0c89db22013-05-15 17:53:04 +0000374 if (kOne_GrBlendCoeff == *srcCoeff &&
375 kZero_GrBlendCoeff == *dstCoeff &&
376 this->willEffectReadDstColor()) {
377 // In this case the shader will fully resolve the color, coverage, and dst and we don't
378 // need blending.
379 return kDisableBlend_BlendOptFlag;
380 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000381 return kNone_BlendOpt;
382}
383
384////////////////////////////////////////////////////////////////////////////////
385
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000386void GrDrawState::AutoViewMatrixRestore::restore() {
387 if (NULL != fDrawState) {
388 fDrawState->setViewMatrix(fViewMatrix);
389 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
390 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000391 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000392 }
393 }
394 }
395 fDrawState = NULL;
396}
397
398void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000399 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000400 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000401
402 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000403 if (NULL == drawState) {
404 return;
405 }
406
407 fRestoreMask = 0;
408 fViewMatrix = drawState->getViewMatrix();
409 drawState->preConcatViewMatrix(preconcatMatrix);
410 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000411 if (drawState->isStageEnabled(s)) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000412 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000413 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000414 drawState->fStages[s].localCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000415 }
416 }
417}
418
419////////////////////////////////////////////////////////////////////////////////
420
421void GrDrawState::AutoDeviceCoordDraw::restore() {
422 if (NULL != fDrawState) {
423 fDrawState->setViewMatrix(fViewMatrix);
424 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
425 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000426 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000427 }
428 }
429 }
430 fDrawState = NULL;
431}
432
bsalomon@google.comc7818882013-03-20 19:19:53 +0000433bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000434 GrAssert(NULL != drawState);
435
436 this->restore();
437
438 fDrawState = drawState;
439 if (NULL == fDrawState) {
440 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000441 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000442
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000443 fViewMatrix = drawState->getViewMatrix();
444 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000445 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000446 bool inverted = false;
447
448 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000449 if (drawState->isStageEnabled(s)) {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000450 if (!inverted && !fViewMatrix.invert(&invVM)) {
451 // sad trombone sound
452 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000453 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000454 } else {
455 inverted = true;
456 }
457 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000458 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000459 stage->saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000460 stage->localCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000461 }
462 }
463 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000464 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000465}