1 /*
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"
9
10 #include "GrGpuVertex.h"
11 #include "GrPaint.h"
12
setFromPaint(const GrPaint & paint)13 void GrDrawState::setFromPaint(const GrPaint& paint) {
14 for (int i = 0; i < GrPaint::kMaxColorStages; ++i) {
15 int s = i + GrPaint::kFirstColorStage;
16 if (paint.isColorStageEnabled(i)) {
17 fStages[s] = paint.getColorStage(i);
18 } else {
19 fStages[s].setEffect(NULL);
20 }
21 }
22
23 this->setFirstCoverageStage(GrPaint::kFirstCoverageStage);
24
25 for (int i = 0; i < GrPaint::kMaxCoverageStages; ++i) {
26 int s = i + GrPaint::kFirstCoverageStage;
27 if (paint.isCoverageStageEnabled(i)) {
28 fStages[s] = paint.getCoverageStage(i);
29 } else {
30 fStages[s].setEffect(NULL);
31 }
32 }
33
34 // disable all stages not accessible via the paint
35 for (int s = GrPaint::kTotalStages; s < GrDrawState::kNumStages; ++s) {
36 this->disableStage(s);
37 }
38
39 this->setColor(paint.getColor());
40
41 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
42 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
43
44 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
45 this->setColorFilter(paint.getColorFilterColor(), paint.getColorFilterMode());
46 this->setCoverage(paint.getCoverage());
47 }
48
49 ////////////////////////////////////////////////////////////////////////////////
50
51 namespace {
52
53 /**
54 * This function generates some masks that we like to have known at compile
55 * time. When the number of stages or tex coords is bumped or the way bits
56 * are defined in GrDrawState.h changes this function should be rerun to
57 * generate the new masks. (We attempted to force the compiler to generate the
58 * masks using recursive templates but always wound up with static initializers
59 * under gcc, even if they were just a series of immediate->memory moves.)
60 *
61 */
gen_mask_arrays(GrVertexLayout * stageTexCoordMasks,GrVertexLayout * texCoordMasks)62 void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks,
63 GrVertexLayout* texCoordMasks) {
64 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
65 stageTexCoordMasks[s] = 0;
66 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
67 stageTexCoordMasks[s] |= GrDrawState::StageTexCoordVertexLayoutBit(s, t);
68 }
69 }
70 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
71 texCoordMasks[t] = 0;
72 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
73 texCoordMasks[t] |= GrDrawState::StageTexCoordVertexLayoutBit(s, t);
74 }
75 }
76 }
77
78 /**
79 * Uncomment and run the gen_globals function to generate
80 * the code that declares the global masks.
81 *
82 * #if 0'ed out to avoid unused function warning.
83 */
84
85 #if 0
86 void gen_globals() {
87 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
88 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
89 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
90
91 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
92 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
93 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
94 }
95 GrPrintf("};\n");
96 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
97 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
98 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
99 GrPrintf(" 0x%x,\n", texCoordMasks[t]);
100 }
101 GrPrintf("};\n");
102 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
103 }
104 #endif
105
106 /* These values were generated by the above function */
107
108 const GrVertexLayout gStageTexCoordMasks[] = {
109 0x108421,
110 0x210842,
111 0x421084,
112 0x842108,
113 0x1084210,
114 };
115 GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
116
117 const GrVertexLayout gTexCoordMasks[] = {
118 0x1f,
119 0x3e0,
120 0x7c00,
121 0xf8000,
122 0x1f00000,
123 };
124 GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
125
126 #ifdef SK_DEBUG
check_layout(GrVertexLayout layout)127 bool check_layout(GrVertexLayout layout) {
128 // can only have 1 or 0 bits set for each stage.
129 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
130 int stageBits = layout & gStageTexCoordMasks[s];
131 if (stageBits && !GrIsPow2(stageBits)) {
132 return false;
133 }
134 }
135 return true;
136 }
137 #endif
138
num_tex_coords(GrVertexLayout layout)139 int num_tex_coords(GrVertexLayout layout) {
140 int cnt = 0;
141 // figure out how many tex coordinates are present
142 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
143 if (gTexCoordMasks[t] & layout) {
144 ++cnt;
145 }
146 }
147 return cnt;
148 }
149
150 } //unnamed namespace
151
VertexSize(GrVertexLayout vertexLayout)152 size_t GrDrawState::VertexSize(GrVertexLayout vertexLayout) {
153 GrAssert(check_layout(vertexLayout));
154
155 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
156 sizeof(GrGpuTextVertex) :
157 sizeof(GrPoint);
158
159 size_t size = vecSize; // position
160 size += num_tex_coords(vertexLayout) * vecSize;
161 if (vertexLayout & kColor_VertexLayoutBit) {
162 size += sizeof(GrColor);
163 }
164 if (vertexLayout & kCoverage_VertexLayoutBit) {
165 size += sizeof(GrColor);
166 }
167 if (vertexLayout & kEdge_VertexLayoutBit) {
168 size += 4 * sizeof(SkScalar);
169 }
170 return size;
171 }
172
173 ////////////////////////////////////////////////////////////////////////////////
174
175 /**
176 * Functions for computing offsets of various components from the layout
177 * bitfield.
178 *
179 * Order of vertex components:
180 * Position
181 * Tex Coord 0
182 * ...
183 * Tex Coord GrDrawState::kMaxTexCoords-1
184 * Color
185 * Coverage
186 */
187
VertexStageCoordOffset(int stageIdx,GrVertexLayout vertexLayout)188 int GrDrawState::VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout) {
189 GrAssert(check_layout(vertexLayout));
190
191 if (!StageUsesTexCoords(vertexLayout, stageIdx)) {
192 return 0;
193 }
194 int tcIdx = VertexTexCoordsForStage(stageIdx, vertexLayout);
195 if (tcIdx >= 0) {
196
197 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
198 sizeof(GrGpuTextVertex) :
199 sizeof(GrPoint);
200 int offset = vecSize; // position
201 // figure out how many tex coordinates are present and precede this one.
202 for (int t = 0; t < tcIdx; ++t) {
203 if (gTexCoordMasks[t] & vertexLayout) {
204 offset += vecSize;
205 }
206 }
207 return offset;
208 }
209
210 return -1;
211 }
212
VertexColorOffset(GrVertexLayout vertexLayout)213 int GrDrawState::VertexColorOffset(GrVertexLayout vertexLayout) {
214 GrAssert(check_layout(vertexLayout));
215
216 if (vertexLayout & kColor_VertexLayoutBit) {
217 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
218 sizeof(GrGpuTextVertex) :
219 sizeof(GrPoint);
220 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
221 }
222 return -1;
223 }
224
VertexCoverageOffset(GrVertexLayout vertexLayout)225 int GrDrawState::VertexCoverageOffset(GrVertexLayout vertexLayout) {
226 GrAssert(check_layout(vertexLayout));
227
228 if (vertexLayout & kCoverage_VertexLayoutBit) {
229 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
230 sizeof(GrGpuTextVertex) :
231 sizeof(GrPoint);
232
233 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
234 if (vertexLayout & kColor_VertexLayoutBit) {
235 offset += sizeof(GrColor);
236 }
237 return offset;
238 }
239 return -1;
240 }
241
VertexEdgeOffset(GrVertexLayout vertexLayout)242 int GrDrawState::VertexEdgeOffset(GrVertexLayout vertexLayout) {
243 GrAssert(check_layout(vertexLayout));
244
245 // edge pts are after the pos, tex coords, and color
246 if (vertexLayout & kEdge_VertexLayoutBit) {
247 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
248 sizeof(GrGpuTextVertex) :
249 sizeof(GrPoint);
250 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
251 if (vertexLayout & kColor_VertexLayoutBit) {
252 offset += sizeof(GrColor);
253 }
254 if (vertexLayout & kCoverage_VertexLayoutBit) {
255 offset += sizeof(GrColor);
256 }
257 return offset;
258 }
259 return -1;
260 }
261
VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,int texCoordOffsetsByIdx[kMaxTexCoords],int * colorOffset,int * coverageOffset,int * edgeOffset)262 int GrDrawState::VertexSizeAndOffsetsByIdx(
263 GrVertexLayout vertexLayout,
264 int texCoordOffsetsByIdx[kMaxTexCoords],
265 int* colorOffset,
266 int* coverageOffset,
267 int* edgeOffset) {
268 GrAssert(check_layout(vertexLayout));
269
270 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
271 sizeof(GrGpuTextVertex) :
272 sizeof(GrPoint);
273 int size = vecSize; // position
274
275 for (int t = 0; t < kMaxTexCoords; ++t) {
276 if (gTexCoordMasks[t] & vertexLayout) {
277 if (NULL != texCoordOffsetsByIdx) {
278 texCoordOffsetsByIdx[t] = size;
279 }
280 size += vecSize;
281 } else {
282 if (NULL != texCoordOffsetsByIdx) {
283 texCoordOffsetsByIdx[t] = -1;
284 }
285 }
286 }
287 if (kColor_VertexLayoutBit & vertexLayout) {
288 if (NULL != colorOffset) {
289 *colorOffset = size;
290 }
291 size += sizeof(GrColor);
292 } else {
293 if (NULL != colorOffset) {
294 *colorOffset = -1;
295 }
296 }
297 if (kCoverage_VertexLayoutBit & vertexLayout) {
298 if (NULL != coverageOffset) {
299 *coverageOffset = size;
300 }
301 size += sizeof(GrColor);
302 } else {
303 if (NULL != coverageOffset) {
304 *coverageOffset = -1;
305 }
306 }
307 if (kEdge_VertexLayoutBit & vertexLayout) {
308 if (NULL != edgeOffset) {
309 *edgeOffset = size;
310 }
311 size += 4 * sizeof(SkScalar);
312 } else {
313 if (NULL != edgeOffset) {
314 *edgeOffset = -1;
315 }
316 }
317 return size;
318 }
319
VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,int texCoordOffsetsByStage[GrDrawState::kNumStages],int * colorOffset,int * coverageOffset,int * edgeOffset)320 int GrDrawState::VertexSizeAndOffsetsByStage(
321 GrVertexLayout vertexLayout,
322 int texCoordOffsetsByStage[GrDrawState::kNumStages],
323 int* colorOffset,
324 int* coverageOffset,
325 int* edgeOffset) {
326 GrAssert(check_layout(vertexLayout));
327
328 int texCoordOffsetsByIdx[kMaxTexCoords];
329 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
330 (NULL == texCoordOffsetsByStage) ?
331 NULL :
332 texCoordOffsetsByIdx,
333 colorOffset,
334 coverageOffset,
335 edgeOffset);
336 if (NULL != texCoordOffsetsByStage) {
337 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
338 int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
339 texCoordOffsetsByStage[s] =
340 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
341 }
342 }
343 return size;
344 }
345
346 ////////////////////////////////////////////////////////////////////////////////
347
VertexUsesTexCoordIdx(int coordIndex,GrVertexLayout vertexLayout)348 bool GrDrawState::VertexUsesTexCoordIdx(int coordIndex,
349 GrVertexLayout vertexLayout) {
350 GrAssert(coordIndex < kMaxTexCoords);
351 GrAssert(check_layout(vertexLayout));
352 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
353 }
354
VertexTexCoordsForStage(int stageIdx,GrVertexLayout vertexLayout)355 int GrDrawState::VertexTexCoordsForStage(int stageIdx,
356 GrVertexLayout vertexLayout) {
357 GrAssert(stageIdx < GrDrawState::kNumStages);
358 GrAssert(check_layout(vertexLayout));
359 int bit = vertexLayout & gStageTexCoordMasks[stageIdx];
360 if (bit) {
361 // figure out which set of texture coordates is used
362 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
363 // and start at bit 0.
364 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
365 return (32 - SkCLZ(bit) - 1) / GrDrawState::kNumStages;
366 }
367 return -1;
368 }
369
370 ////////////////////////////////////////////////////////////////////////////////
371
VertexLayoutUnitTest()372 void GrDrawState::VertexLayoutUnitTest() {
373 // Ensure that our globals mask arrays are correct
374 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
375 GrVertexLayout texCoordMasks[kMaxTexCoords];
376 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
377 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
378 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
379 }
380 for (int t = 0; t < kMaxTexCoords; ++t) {
381 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
382 }
383
384 // not necessarily exhaustive
385 static bool run;
386 if (!run) {
387 run = true;
388 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
389
390 GrVertexLayout stageMask = 0;
391 for (int t = 0; t < kMaxTexCoords; ++t) {
392 stageMask |= StageTexCoordVertexLayoutBit(s,t);
393 }
394 GrAssert(1 == kMaxTexCoords ||
395 !check_layout(stageMask));
396 GrAssert(gStageTexCoordMasks[s] == stageMask);
397 GrAssert(!check_layout(stageMask));
398 }
399 for (int t = 0; t < kMaxTexCoords; ++t) {
400 GrVertexLayout tcMask = 0;
401 GrAssert(!VertexUsesTexCoordIdx(t, 0));
402 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
403 tcMask |= StageTexCoordVertexLayoutBit(s,t);
404 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
405 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
406 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
407 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
408 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
409 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
410
411 #if GR_DEBUG
412 GrVertexLayout posAsTex = tcMask;
413 #endif
414 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
415 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
416 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
417 GrAssert(-1 == VertexEdgeOffset(posAsTex));
418 }
419 GrAssert(-1 == VertexEdgeOffset(tcMask));
420 GrAssert(-1 == VertexColorOffset(tcMask));
421 GrAssert(-1 == VertexCoverageOffset(tcMask));
422 #if GR_DEBUG
423 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
424 #endif
425 GrAssert(-1 == VertexCoverageOffset(withColor));
426 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
427 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
428 #if GR_DEBUG
429 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
430 #endif
431 GrAssert(-1 == VertexColorOffset(withEdge));
432 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
433 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
434 #if GR_DEBUG
435 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
436 #endif
437 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
438 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
439 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
440 #if GR_DEBUG
441 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
442 #endif
443 GrAssert(-1 == VertexColorOffset(withCoverage));
444 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
445 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
446 #if GR_DEBUG
447 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
448 kColor_VertexLayoutBit;
449 #endif
450 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
451 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
452 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
453 }
454 GrAssert(gTexCoordMasks[t] == tcMask);
455 GrAssert(check_layout(tcMask));
456
457 int stageOffsets[GrDrawState::kNumStages];
458 int colorOffset;
459 int edgeOffset;
460 int coverageOffset;
461 int size;
462 size = VertexSizeAndOffsetsByStage(tcMask,
463 stageOffsets, &colorOffset,
464 &coverageOffset, &edgeOffset);
465 GrAssert(2*sizeof(GrPoint) == size);
466 GrAssert(-1 == colorOffset);
467 GrAssert(-1 == coverageOffset);
468 GrAssert(-1 == edgeOffset);
469 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
470 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
471 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
472 }
473 }
474 }
475 }
476
477 ////////////////////////////////////////////////////////////////////////////////
478
StageUsesTexCoords(GrVertexLayout layout,int stageIdx)479 bool GrDrawState::StageUsesTexCoords(GrVertexLayout layout, int stageIdx) {
480 return SkToBool(layout & gStageTexCoordMasks[stageIdx]);
481 }
482
srcAlphaWillBeOne(GrVertexLayout layout) const483 bool GrDrawState::srcAlphaWillBeOne(GrVertexLayout layout) const {
484
485 uint32_t validComponentFlags;
486 GrColor color;
487 // Check if per-vertex or constant color may have partial alpha
488 if (layout & kColor_VertexLayoutBit) {
489 validComponentFlags = 0;
490 } else {
491 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
492 color = this->getColor();
493 }
494
495 // Run through the color stages
496 int stageCnt = getFirstCoverageStage();
497 for (int s = 0; s < stageCnt; ++s) {
498 const GrEffectRef* effect = this->getStage(s).getEffect();
499 if (NULL != effect) {
500 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
501 }
502 }
503
504 // Check if the color filter could introduce an alpha.
505 // We could skip the above work when this is true, but it is rare and the right fix is to make
506 // the color filter a GrEffect and implement getConstantColorComponents() for it.
507 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
508 validComponentFlags = 0;
509 }
510
511 // Check whether coverage is treated as color. If so we run through the coverage computation.
512 if (this->isCoverageDrawing()) {
513 GrColor coverageColor = this->getCoverage();
514 GrColor oldColor = color;
515 color = 0;
516 for (int c = 0; c < 4; ++c) {
517 if (validComponentFlags & (1 << c)) {
518 U8CPU a = (oldColor >> (c * 8)) & 0xff;
519 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
520 color |= (SkMulDiv255Round(a, b) << (c * 8));
521 }
522 }
523 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
524 const GrEffectRef* effect = this->getStage(s).getEffect();
525 if (NULL != effect) {
526 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
527 }
528 }
529 }
530 return (GrEffect::kA_ValidComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
531 }
532
hasSolidCoverage(GrVertexLayout layout) const533 bool GrDrawState::hasSolidCoverage(GrVertexLayout layout) const {
534 // If we're drawing coverage directly then coverage is effectively treated as color.
535 if (this->isCoverageDrawing()) {
536 return true;
537 }
538
539 GrColor coverage;
540 uint32_t validComponentFlags;
541 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
542 if (layout & kCoverage_VertexLayoutBit) {
543 validComponentFlags = 0;
544 } else {
545 coverage = fCommon.fCoverage;
546 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
547 }
548
549 // Run through the coverage stages and see if the coverage will be all ones at the end.
550 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
551 const GrEffectRef* effect = this->getStage(s).getEffect();
552 if (NULL != effect) {
553 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
554 }
555 }
556 return (GrEffect::kAll_ValidComponentFlags == validComponentFlags) && (0xffffffff == coverage);
557 }
558
559 ////////////////////////////////////////////////////////////////////////////////
560
restore()561 void GrDrawState::AutoViewMatrixRestore::restore() {
562 if (NULL != fDrawState) {
563 fDrawState->setViewMatrix(fViewMatrix);
564 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
565 if (fRestoreMask & (1 << s)) {
566 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
567 }
568 }
569 }
570 fDrawState = NULL;
571 }
572
set(GrDrawState * drawState,const SkMatrix & preconcatMatrix,uint32_t explicitCoordStageMask)573 void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
574 const SkMatrix& preconcatMatrix,
575 uint32_t explicitCoordStageMask) {
576 this->restore();
577
578 fDrawState = drawState;
579 if (NULL == drawState) {
580 return;
581 }
582
583 fRestoreMask = 0;
584 fViewMatrix = drawState->getViewMatrix();
585 drawState->preConcatViewMatrix(preconcatMatrix);
586 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
587 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
588 fRestoreMask |= (1 << s);
589 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
590 drawState->fStages[s].preConcatCoordChange(preconcatMatrix);
591 }
592 }
593 }
594
595 ////////////////////////////////////////////////////////////////////////////////
596
restore()597 void GrDrawState::AutoDeviceCoordDraw::restore() {
598 if (NULL != fDrawState) {
599 fDrawState->setViewMatrix(fViewMatrix);
600 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
601 if (fRestoreMask & (1 << s)) {
602 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
603 }
604 }
605 }
606 fDrawState = NULL;
607 }
608
set(GrDrawState * drawState,uint32_t explicitCoordStageMask)609 bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState,
610 uint32_t explicitCoordStageMask) {
611 GrAssert(NULL != drawState);
612
613 this->restore();
614
615 fDrawState = drawState;
616 if (NULL == fDrawState) {
617 return false;
618 }
619
620 fViewMatrix = drawState->getViewMatrix();
621 fRestoreMask = 0;
622 SkMatrix invVM;
623 bool inverted = false;
624
625 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
626 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
627 if (!inverted && !fViewMatrix.invert(&invVM)) {
628 // sad trombone sound
629 fDrawState = NULL;
630 return false;
631 } else {
632 inverted = true;
633 }
634 fRestoreMask |= (1 << s);
635 GrEffectStage* stage = drawState->fStages + s;
636 stage->saveCoordChange(&fSavedCoordChanges[s]);
637 stage->preConcatCoordChange(invVM);
638 }
639 }
640 drawState->viewMatrix()->reset();
641 return true;
642 }
643