blob: 591e157129af4aa7846cda18bf949ec4f8e04861 [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 }
374 return kNone_BlendOpt;
375}
376
377////////////////////////////////////////////////////////////////////////////////
378
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000379void GrDrawState::AutoViewMatrixRestore::restore() {
380 if (NULL != fDrawState) {
381 fDrawState->setViewMatrix(fViewMatrix);
382 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
383 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000384 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000385 }
386 }
387 }
388 fDrawState = NULL;
389}
390
391void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000392 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000393 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000394
395 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000396 if (NULL == drawState) {
397 return;
398 }
399
400 fRestoreMask = 0;
401 fViewMatrix = drawState->getViewMatrix();
402 drawState->preConcatViewMatrix(preconcatMatrix);
403 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000404 if (drawState->isStageEnabled(s)) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000405 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000406 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000407 drawState->fStages[s].localCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000408 }
409 }
410}
411
412////////////////////////////////////////////////////////////////////////////////
413
414void GrDrawState::AutoDeviceCoordDraw::restore() {
415 if (NULL != fDrawState) {
416 fDrawState->setViewMatrix(fViewMatrix);
417 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
418 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000419 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000420 }
421 }
422 }
423 fDrawState = NULL;
424}
425
bsalomon@google.comc7818882013-03-20 19:19:53 +0000426bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000427 GrAssert(NULL != drawState);
428
429 this->restore();
430
431 fDrawState = drawState;
432 if (NULL == fDrawState) {
433 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000434 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000435
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000436 fViewMatrix = drawState->getViewMatrix();
437 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000438 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000439 bool inverted = false;
440
441 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000442 if (drawState->isStageEnabled(s)) {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000443 if (!inverted && !fViewMatrix.invert(&invVM)) {
444 // sad trombone sound
445 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000446 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000447 } else {
448 inverted = true;
449 }
450 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000451 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000452 stage->saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000453 stage->localCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000454 }
455 }
456 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000457 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000458}