blob: 7c68543479f1a898396fd3487aca9ee2f824ad0b [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() {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000012 if (fColorStages.count() || fCoverageStages.count()) {
13 SkMatrix invVM;
14 if (!fCommon.fViewMatrix.invert(&invVM)) {
15 // sad trombone sound
16 return false;
17 }
18 for (int s = 0; s < fColorStages.count(); ++s) {
19 fColorStages[s].localCoordChange(invVM);
20 }
21 for (int s = 0; s < fCoverageStages.count(); ++s) {
22 fCoverageStages[s].localCoordChange(invVM);
bsalomon@google.com137f1342013-05-29 21:27:53 +000023 }
24 }
25 fCommon.fViewMatrix.reset();
26 return true;
27}
28
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000029void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000030 GrAssert(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
31
32 fColorStages.reset();
33 fCoverageStages.reset();
34
bsalomon@google.com88becf42012-10-05 14:54:42 +000035 for (int i = 0; i < GrPaint::kMaxColorStages; ++i) {
bsalomon@google.com88becf42012-10-05 14:54:42 +000036 if (paint.isColorStageEnabled(i)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000037 fColorStages.push_back(paint.getColorStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +000038 }
39 }
40
bsalomon@google.com88becf42012-10-05 14:54:42 +000041 for (int i = 0; i < GrPaint::kMaxCoverageStages; ++i) {
bsalomon@google.com88becf42012-10-05 14:54:42 +000042 if (paint.isCoverageStageEnabled(i)) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000043 fCoverageStages.push_back(paint.getCoverageStage(i));
bsalomon@google.comaf84e742012-10-05 13:23:24 +000044 }
45 }
46
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000047 this->setRenderTarget(rt);
bsalomon@google.comaf84e742012-10-05 13:23:24 +000048
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000049 fCommon.fViewMatrix = vm;
50
51 // These have no equivalent in GrPaint, set them to defaults
52 fCommon.fBlendConstant = 0x0;
53 fCommon.fCoverage = 0xffffffff;
54 fCommon.fDrawFace = kBoth_DrawFace;
55 fCommon.fStencilSettings.setDisabled();
56 this->resetStateFlags();
57
bsalomon@google.com21c10c52013-06-13 17:44:07 +000058 // Enable the clip bit
59 this->enableState(GrDrawState::kClip_StateBit);
60
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000061 this->setColor(paint.getColor());
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000062 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
63 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000064
bsalomon@google.comc7448ce2012-10-05 19:04:13 +000065 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
66 this->setColorFilter(paint.getColorFilterColor(), paint.getColorFilterMode());
67 this->setCoverage(paint.getCoverage());
bsalomon@google.comaf84e742012-10-05 13:23:24 +000068}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +000069
70////////////////////////////////////////////////////////////////////////////////
71
jvanverth@google.com9b855c72013-03-01 18:21:22 +000072static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
73 // this works as long as we're 4 byte-aligned
74#if GR_DEBUG
75 uint32_t overlapCheck = 0;
76#endif
jvanverth@google.com054ae992013-04-01 20:06:51 +000077 GrAssert(count <= GrDrawState::kMaxVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000078 size_t size = 0;
79 for (int index = 0; index < count; ++index) {
jvanverth@google.com054ae992013-04-01 20:06:51 +000080 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000081 size += attribSize;
82#if GR_DEBUG
83 size_t dwordCount = attribSize >> 2;
84 uint32_t mask = (1 << dwordCount)-1;
85 size_t offsetShift = attribs[index].fOffset >> 2;
86 GrAssert(!(overlapCheck & (mask << offsetShift)));
87 overlapCheck |= (mask << offsetShift);
88#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +000089 }
90 return size;
91}
92
jvanverth@google.com9b855c72013-03-01 18:21:22 +000093size_t GrDrawState::getVertexSize() const {
robertphillips@google.com42903302013-04-20 12:26:07 +000094 return vertex_size(fCommon.fVAPtr, fCommon.fVACount);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000095}
96
jvanverth@google.comcc782382013-01-28 20:39:48 +000097////////////////////////////////////////////////////////////////////////////////
98
jvanverth@google.com9b855c72013-03-01 18:21:22 +000099void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000100 GrAssert(count <= kMaxVertexAttribCnt);
robertphillips@google.com42903302013-04-20 12:26:07 +0000101
102 fCommon.fVAPtr = attribs;
103 fCommon.fVACount = count;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000104
105 // Set all the indices to -1
106 memset(fCommon.fFixedFunctionVertexAttribIndices,
107 0xff,
108 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
109#if GR_DEBUG
110 uint32_t overlapCheck = 0;
111#endif
112 for (int i = 0; i < count; ++i) {
113 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
114 // The fixed function attribs can only be specified once
115 GrAssert(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
116 GrAssert(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
117 GrVertexAttribTypeVectorCount(attribs[i].fType));
118 fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
119 }
120#if GR_DEBUG
121 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
122 uint32_t mask = (1 << dwordCount)-1;
123 size_t offsetShift = attribs[i].fOffset >> 2;
124 GrAssert(!(overlapCheck & (mask << offsetShift)));
125 overlapCheck |= (mask << offsetShift);
126#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +0000127 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000128 // Positions must be specified.
129 GrAssert(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000130}
131
132////////////////////////////////////////////////////////////////////////////////
133
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000134void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000135 static const GrVertexAttrib kPositionAttrib =
136 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
robertphillips@google.com42903302013-04-20 12:26:07 +0000137
138 fCommon.fVAPtr = &kPositionAttrib;
139 fCommon.fVACount = 1;
140
jvanverth@google.com054ae992013-04-01 20:06:51 +0000141 // set all the fixed function indices to -1 except position.
142 memset(fCommon.fFixedFunctionVertexAttribIndices,
143 0xff,
144 sizeof(fCommon.fFixedFunctionVertexAttribIndices));
145 fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000146}
147
148////////////////////////////////////////////////////////////////////////////////
149
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000150bool GrDrawState::validateVertexAttribs() const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000151 // check consistency of effects and attributes
152 GrSLType slTypes[kMaxVertexAttribCnt];
153 for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
154 slTypes[i] = static_cast<GrSLType>(-1);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000155 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000156 int totalStages = fColorStages.count() + fCoverageStages.count();
157 for (int s = 0; s < totalStages; ++s) {
158 int covIdx = s - fColorStages.count();
159 const GrEffectStage& stage = covIdx < 0 ? fColorStages[s] : fCoverageStages[covIdx];
160 const GrEffectRef* effect = stage.getEffect();
161 GrAssert(NULL != effect);
162 // make sure that any attribute indices have the correct binding type, that the attrib
163 // type and effect's shader lang type are compatible, and that attributes shared by
164 // multiple effects use the same shader lang type.
165 const int* attributeIndices = stage.getVertexAttribIndices();
166 int numAttributes = stage.getVertexAttribIndexCount();
167 for (int i = 0; i < numAttributes; ++i) {
168 int attribIndex = attributeIndices[i];
169 if (attribIndex >= fCommon.fVACount ||
170 kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
171 return false;
jvanverth@google.comc7bf2962013-04-01 19:29:32 +0000172 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000173
174 GrSLType effectSLType = (*effect)->vertexAttribType(i);
175 GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
176 int slVecCount = GrSLTypeVectorCount(effectSLType);
177 int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
178 if (slVecCount != attribVecCount ||
179 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
180 slTypes[attribIndex] != effectSLType)) {
181 return false;
182 }
183 slTypes[attribIndex] = effectSLType;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000184 }
185 }
186
187 return true;
188}
189
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000190bool GrDrawState::willEffectReadDstColor() const {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000191 if (!this->isColorWriteDisabled()) {
192 for (int s = 0; s < fColorStages.count(); ++s) {
193 if ((*fColorStages[s].getEffect())->willReadDstColor()) {
194 return true;
195 }
196 }
197 }
198 for (int s = 0; s < fCoverageStages.count(); ++s) {
199 if ((*fCoverageStages[s].getEffect())->willReadDstColor()) {
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000200 return true;
201 }
202 }
203 return false;
204}
205
jvanverth@google.comcc782382013-01-28 20:39:48 +0000206////////////////////////////////////////////////////////////////////////////////
207
jvanverth@google.com054ae992013-04-01 20:06:51 +0000208bool GrDrawState::srcAlphaWillBeOne() const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000209 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000210 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000211 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com054ae992013-04-01 20:06:51 +0000212 if (this->hasColorVertexAttribute()) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000213 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000214 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000215 } else {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000216 validComponentFlags = kRGBA_GrColorComponentFlags;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000217 color = this->getColor();
218 }
219
220 // Run through the color stages
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000221 for (int s = 0; s < fColorStages.count(); ++s) {
222 const GrEffectRef* effect = fColorStages[s].getEffect();
223 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000224 }
225
226 // Check if the color filter could introduce an alpha.
227 // We could skip the above work when this is true, but it is rare and the right fix is to make
228 // the color filter a GrEffect and implement getConstantColorComponents() for it.
229 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
230 validComponentFlags = 0;
231 }
232
233 // Check whether coverage is treated as color. If so we run through the coverage computation.
234 if (this->isCoverageDrawing()) {
235 GrColor coverageColor = this->getCoverage();
236 GrColor oldColor = color;
237 color = 0;
238 for (int c = 0; c < 4; ++c) {
239 if (validComponentFlags & (1 << c)) {
240 U8CPU a = (oldColor >> (c * 8)) & 0xff;
241 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
242 color |= (SkMulDiv255Round(a, b) << (c * 8));
243 }
244 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000245 for (int s = 0; s < fCoverageStages.count(); ++s) {
246 const GrEffectRef* effect = fCoverageStages[s].getEffect();
247 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000248 }
249 }
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000250 return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000251}
252
jvanverth@google.com054ae992013-04-01 20:06:51 +0000253bool GrDrawState::hasSolidCoverage() const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000254 // If we're drawing coverage directly then coverage is effectively treated as color.
255 if (this->isCoverageDrawing()) {
256 return true;
257 }
258
259 GrColor coverage;
260 uint32_t validComponentFlags;
261 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com054ae992013-04-01 20:06:51 +0000262 if (this->hasCoverageVertexAttribute()) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000263 validComponentFlags = 0;
264 } else {
265 coverage = fCommon.fCoverage;
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000266 validComponentFlags = kRGBA_GrColorComponentFlags;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000267 }
268
269 // Run through the coverage stages and see if the coverage will be all ones at the end.
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000270 for (int s = 0; s < fCoverageStages.count(); ++s) {
271 const GrEffectRef* effect = fCoverageStages[s].getEffect();
272 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000273 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000274 return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000275}
276
jvanverth@google.comcc782382013-01-28 20:39:48 +0000277////////////////////////////////////////////////////////////////////////////////
278
bsalomon@google.com2b446732013-02-12 16:47:41 +0000279// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
280// others will blend incorrectly.
281bool GrDrawState::canTweakAlphaForCoverage() const {
282 /*
283 The fractional coverage is f.
284 The src and dst coeffs are Cs and Cd.
285 The dst and src colors are S and D.
286 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
287 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
288 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
289 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
290 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
291 color by definition.
292 */
293 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
294 kISA_GrBlendCoeff == fCommon.fDstBlend ||
295 kISC_GrBlendCoeff == fCommon.fDstBlend ||
296 this->isCoverageDrawing();
297}
298
299GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
300 GrBlendCoeff* srcCoeff,
301 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000302
303 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
304 if (NULL == srcCoeff) {
305 srcCoeff = &bogusSrcCoeff;
306 }
307 *srcCoeff = this->getSrcBlendCoeff();
308
309 if (NULL == dstCoeff) {
310 dstCoeff = &bogusDstCoeff;
311 }
312 *dstCoeff = this->getDstBlendCoeff();
313
314 if (this->isColorWriteDisabled()) {
315 *srcCoeff = kZero_GrBlendCoeff;
316 *dstCoeff = kOne_GrBlendCoeff;
317 }
318
jvanverth@google.com054ae992013-04-01 20:06:51 +0000319 bool srcAIsOne = this->srcAlphaWillBeOne();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000320 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
321 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
322 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
323 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
324
325 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000326 !this->hasCoverageVertexAttribute() &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000327 0 == this->getCoverage();
328 // When coeffs are (0,1) there is no reason to draw at all, unless
329 // stenciling is enabled. Having color writes disabled is effectively
330 // (0,1). The same applies when coverage is known to be 0.
331 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
332 if (this->getStencil().doesWrite()) {
333 return kDisableBlend_BlendOptFlag |
334 kEmitTransBlack_BlendOptFlag;
335 } else {
336 return kSkipDraw_BlendOptFlag;
337 }
338 }
339
bsalomon@google.com4647f902013-03-26 14:45:27 +0000340 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000341 bool hasCoverage = forceCoverage ||
342 0xffffffff != this->getCoverage() ||
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000343 this->hasCoverageVertexAttribute() ||
344 fCoverageStages.count() > 0;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000345
346 // if we don't have coverage we can check whether the dst
347 // has to read at all. If not, we'll disable blending.
348 if (!hasCoverage) {
349 if (dstCoeffIsZero) {
350 if (kOne_GrBlendCoeff == *srcCoeff) {
351 // if there is no coverage and coeffs are (1,0) then we
352 // won't need to read the dst at all, it gets replaced by src
353 return kDisableBlend_BlendOptFlag;
354 } else if (kZero_GrBlendCoeff == *srcCoeff) {
355 // if the op is "clear" then we don't need to emit a color
356 // or blend, just write transparent black into the dst.
357 *srcCoeff = kOne_GrBlendCoeff;
358 *dstCoeff = kZero_GrBlendCoeff;
359 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
360 }
361 }
362 } else if (this->isCoverageDrawing()) {
363 // we have coverage but we aren't distinguishing it from alpha by request.
364 return kCoverageAsAlpha_BlendOptFlag;
365 } else {
366 // check whether coverage can be safely rolled into alpha
367 // of if we can skip color computation and just emit coverage
368 if (this->canTweakAlphaForCoverage()) {
369 return kCoverageAsAlpha_BlendOptFlag;
370 }
371 if (dstCoeffIsZero) {
372 if (kZero_GrBlendCoeff == *srcCoeff) {
373 // the source color is not included in the blend
374 // the dst coeff is effectively zero so blend works out to:
375 // (c)(0)D + (1-c)D = (1-c)D.
376 *dstCoeff = kISA_GrBlendCoeff;
377 return kEmitCoverage_BlendOptFlag;
378 } else if (srcAIsOne) {
379 // the dst coeff is effectively zero so blend works out to:
380 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
381 // If Sa is 1 then we can replace Sa with c
382 // and set dst coeff to 1-Sa.
383 *dstCoeff = kISA_GrBlendCoeff;
384 return kCoverageAsAlpha_BlendOptFlag;
385 }
386 } else if (dstCoeffIsOne) {
387 // the dst coeff is effectively one so blend works out to:
388 // cS + (c)(1)D + (1-c)D = cS + D.
389 *dstCoeff = kOne_GrBlendCoeff;
390 return kCoverageAsAlpha_BlendOptFlag;
391 }
392 }
bsalomon@google.com0c89db22013-05-15 17:53:04 +0000393 if (kOne_GrBlendCoeff == *srcCoeff &&
394 kZero_GrBlendCoeff == *dstCoeff &&
395 this->willEffectReadDstColor()) {
396 // In this case the shader will fully resolve the color, coverage, and dst and we don't
397 // need blending.
398 return kDisableBlend_BlendOptFlag;
399 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000400 return kNone_BlendOpt;
401}
402
403////////////////////////////////////////////////////////////////////////////////
404
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000405void GrDrawState::AutoViewMatrixRestore::restore() {
406 if (NULL != fDrawState) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000407 GR_DEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com137f1342013-05-29 21:27:53 +0000408 fDrawState->fCommon.fViewMatrix = fViewMatrix;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000409 GrAssert(fDrawState->numColorStages() >= fNumColorStages);
410 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
411 GrAssert(fDrawState->numCoverageStages() >= numCoverageStages);
412
413 int i = 0;
414 for (int s = 0; s < fNumColorStages; ++s, ++i) {
415 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
416 }
417 for (int s = 0; s < numCoverageStages; ++s, ++i) {
418 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000419 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000420 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000421 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000422}
423
424void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000425 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000426 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000427
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000428 GrAssert(NULL == fDrawState);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000429 if (NULL == drawState || preconcatMatrix.isIdentity()) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000430 return;
431 }
bsalomon@google.com137f1342013-05-29 21:27:53 +0000432 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000433
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000434 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000435 drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000436
437 this->doEffectCoordChanges(preconcatMatrix);
438 GR_DEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000439}
440
bsalomon@google.com137f1342013-05-29 21:27:53 +0000441bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000442 this->restore();
443
bsalomon@google.com137f1342013-05-29 21:27:53 +0000444 if (NULL == drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000445 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000446 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000447
bsalomon@google.com137f1342013-05-29 21:27:53 +0000448 if (drawState->getViewMatrix().isIdentity()) {
449 return true;
450 }
451
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000452 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000453 if (0 == drawState->numTotalStages()) {
454 drawState->fCommon.fViewMatrix.reset();
455 fDrawState = drawState;
456 fNumColorStages = 0;
457 fSavedCoordChanges.reset(0);
458 GR_DEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
459 return true;
460 } else {
461 SkMatrix inv;
462 if (!fViewMatrix.invert(&inv)) {
463 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000464 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000465 drawState->fCommon.fViewMatrix.reset();
466 fDrawState = drawState;
467 this->doEffectCoordChanges(inv);
468 GR_DEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
469 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000470 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000471}
472
473void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
474 fSavedCoordChanges.reset(fDrawState->numTotalStages());
475 int i = 0;
476
477 fNumColorStages = fDrawState->numColorStages();
478 for (int s = 0; s < fNumColorStages; ++s, ++i) {
479 fDrawState->fColorStages[s].saveCoordChange(&fSavedCoordChanges[i]);
480 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000481 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000482
483 int numCoverageStages = fDrawState->numCoverageStages();
484 for (int s = 0; s < numCoverageStages; ++s, ++i) {
485 fDrawState->fCoverageStages[s].saveCoordChange(&fSavedCoordChanges[i]);
486 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
487 }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000488}