blob: f2c69778de7fb8e35769e4ec0d097ed0c8c1ccaa [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.comcc782382013-01-28 20:39:48 +000049namespace {
50
51/**
52 * This function generates some masks that we like to have known at compile
53 * time. When the number of stages or tex coords is bumped or the way bits
54 * are defined in GrDrawState.h changes this function should be rerun to
55 * generate the new masks. (We attempted to force the compiler to generate the
56 * masks using recursive templates but always wound up with static initializers
57 * under gcc, even if they were just a series of immediate->memory moves.)
58 *
59 */
60void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks,
61 GrVertexLayout* texCoordMasks) {
62 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
63 stageTexCoordMasks[s] = 0;
64 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
65 stageTexCoordMasks[s] |= GrDrawState::StageTexCoordVertexLayoutBit(s, t);
66 }
67 }
68 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
69 texCoordMasks[t] = 0;
70 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
71 texCoordMasks[t] |= GrDrawState::StageTexCoordVertexLayoutBit(s, t);
72 }
73 }
74}
75
76/**
77 * Uncomment and run the gen_globals function to generate
78 * the code that declares the global masks.
79 *
80 * #if 0'ed out to avoid unused function warning.
81 */
82
83#if 0
84void gen_globals() {
85 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
86 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
87 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
88
89 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
90 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
91 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
92 }
93 GrPrintf("};\n");
94 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
95 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
96 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
97 GrPrintf(" 0x%x,\n", texCoordMasks[t]);
98 }
99 GrPrintf("};\n");
100 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
101}
102#endif
103
104/* These values were generated by the above function */
105
106const GrVertexLayout gStageTexCoordMasks[] = {
107 0x108421,
108 0x210842,
109 0x421084,
110 0x842108,
111 0x1084210,
112};
113GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
114
115const GrVertexLayout gTexCoordMasks[] = {
116 0x1f,
117 0x3e0,
118 0x7c00,
119 0xf8000,
120 0x1f00000,
121};
122GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
123
124#ifdef SK_DEBUG
125bool check_layout(GrVertexLayout layout) {
126 // can only have 1 or 0 bits set for each stage.
127 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
128 int stageBits = layout & gStageTexCoordMasks[s];
129 if (stageBits && !GrIsPow2(stageBits)) {
130 return false;
131 }
132 }
133 return true;
134}
135#endif
136
137int num_tex_coords(GrVertexLayout layout) {
138 int cnt = 0;
139 // figure out how many tex coordinates are present
140 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
141 if (gTexCoordMasks[t] & layout) {
142 ++cnt;
143 }
144 }
145 return cnt;
146}
147
148} //unnamed namespace
149
bsalomon@google.com85983282013-02-07 22:00:29 +0000150static const size_t kVec2Size = sizeof(GrPoint);
151
jvanverth@google.comcc782382013-01-28 20:39:48 +0000152size_t GrDrawState::VertexSize(GrVertexLayout vertexLayout) {
153 GrAssert(check_layout(vertexLayout));
154
bsalomon@google.com85983282013-02-07 22:00:29 +0000155 size_t size = kVec2Size; // position
156 size += num_tex_coords(vertexLayout) * kVec2Size;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000157 if (vertexLayout & kColor_VertexLayoutBit) {
158 size += sizeof(GrColor);
159 }
160 if (vertexLayout & kCoverage_VertexLayoutBit) {
161 size += sizeof(GrColor);
162 }
163 if (vertexLayout & kEdge_VertexLayoutBit) {
164 size += 4 * sizeof(SkScalar);
165 }
166 return size;
167}
168
169////////////////////////////////////////////////////////////////////////////////
170
171/**
172 * Functions for computing offsets of various components from the layout
173 * bitfield.
174 *
175 * Order of vertex components:
176 * Position
177 * Tex Coord 0
178 * ...
179 * Tex Coord GrDrawState::kMaxTexCoords-1
180 * Color
181 * Coverage
182 */
183
184int GrDrawState::VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout) {
185 GrAssert(check_layout(vertexLayout));
186
187 if (!StageUsesTexCoords(vertexLayout, stageIdx)) {
188 return 0;
189 }
190 int tcIdx = VertexTexCoordsForStage(stageIdx, vertexLayout);
191 if (tcIdx >= 0) {
192
bsalomon@google.com85983282013-02-07 22:00:29 +0000193 int offset = kVec2Size; // position
jvanverth@google.comcc782382013-01-28 20:39:48 +0000194 // figure out how many tex coordinates are present and precede this one.
195 for (int t = 0; t < tcIdx; ++t) {
196 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com85983282013-02-07 22:00:29 +0000197 offset += kVec2Size;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000198 }
199 }
200 return offset;
201 }
202
203 return -1;
204}
205
206int GrDrawState::VertexColorOffset(GrVertexLayout vertexLayout) {
207 GrAssert(check_layout(vertexLayout));
208
209 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com85983282013-02-07 22:00:29 +0000210 return kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos
jvanverth@google.comcc782382013-01-28 20:39:48 +0000211 }
212 return -1;
213}
214
215int GrDrawState::VertexCoverageOffset(GrVertexLayout vertexLayout) {
216 GrAssert(check_layout(vertexLayout));
217
218 if (vertexLayout & kCoverage_VertexLayoutBit) {
bsalomon@google.com85983282013-02-07 22:00:29 +0000219 int offset = kVec2Size * (num_tex_coords(vertexLayout) + 1);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000220 if (vertexLayout & kColor_VertexLayoutBit) {
221 offset += sizeof(GrColor);
222 }
223 return offset;
224 }
225 return -1;
226}
227
228int GrDrawState::VertexEdgeOffset(GrVertexLayout vertexLayout) {
229 GrAssert(check_layout(vertexLayout));
230
231 // edge pts are after the pos, tex coords, and color
232 if (vertexLayout & kEdge_VertexLayoutBit) {
bsalomon@google.com85983282013-02-07 22:00:29 +0000233 int offset = kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos
jvanverth@google.comcc782382013-01-28 20:39:48 +0000234 if (vertexLayout & kColor_VertexLayoutBit) {
235 offset += sizeof(GrColor);
236 }
237 if (vertexLayout & kCoverage_VertexLayoutBit) {
238 offset += sizeof(GrColor);
239 }
240 return offset;
241 }
242 return -1;
243}
244
245int GrDrawState::VertexSizeAndOffsetsByIdx(
246 GrVertexLayout vertexLayout,
247 int texCoordOffsetsByIdx[kMaxTexCoords],
248 int* colorOffset,
249 int* coverageOffset,
250 int* edgeOffset) {
251 GrAssert(check_layout(vertexLayout));
252
bsalomon@google.com85983282013-02-07 22:00:29 +0000253 int size = kVec2Size; // position
jvanverth@google.comcc782382013-01-28 20:39:48 +0000254
255 for (int t = 0; t < kMaxTexCoords; ++t) {
256 if (gTexCoordMasks[t] & vertexLayout) {
257 if (NULL != texCoordOffsetsByIdx) {
258 texCoordOffsetsByIdx[t] = size;
259 }
bsalomon@google.com85983282013-02-07 22:00:29 +0000260 size += kVec2Size;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000261 } else {
262 if (NULL != texCoordOffsetsByIdx) {
263 texCoordOffsetsByIdx[t] = -1;
264 }
265 }
266 }
267 if (kColor_VertexLayoutBit & vertexLayout) {
268 if (NULL != colorOffset) {
269 *colorOffset = size;
270 }
271 size += sizeof(GrColor);
272 } else {
273 if (NULL != colorOffset) {
274 *colorOffset = -1;
275 }
276 }
277 if (kCoverage_VertexLayoutBit & vertexLayout) {
278 if (NULL != coverageOffset) {
279 *coverageOffset = size;
280 }
281 size += sizeof(GrColor);
282 } else {
283 if (NULL != coverageOffset) {
284 *coverageOffset = -1;
285 }
286 }
287 if (kEdge_VertexLayoutBit & vertexLayout) {
288 if (NULL != edgeOffset) {
289 *edgeOffset = size;
290 }
291 size += 4 * sizeof(SkScalar);
292 } else {
293 if (NULL != edgeOffset) {
294 *edgeOffset = -1;
295 }
296 }
297 return size;
298}
299
300int GrDrawState::VertexSizeAndOffsetsByStage(
301 GrVertexLayout vertexLayout,
302 int texCoordOffsetsByStage[GrDrawState::kNumStages],
303 int* colorOffset,
304 int* coverageOffset,
305 int* edgeOffset) {
306 GrAssert(check_layout(vertexLayout));
307
308 int texCoordOffsetsByIdx[kMaxTexCoords];
309 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
310 (NULL == texCoordOffsetsByStage) ?
311 NULL :
312 texCoordOffsetsByIdx,
313 colorOffset,
314 coverageOffset,
315 edgeOffset);
316 if (NULL != texCoordOffsetsByStage) {
317 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
318 int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
319 texCoordOffsetsByStage[s] =
320 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
321 }
322 }
323 return size;
324}
325
326////////////////////////////////////////////////////////////////////////////////
327
328bool GrDrawState::VertexUsesTexCoordIdx(int coordIndex,
329 GrVertexLayout vertexLayout) {
330 GrAssert(coordIndex < kMaxTexCoords);
331 GrAssert(check_layout(vertexLayout));
332 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
333}
334
335int GrDrawState::VertexTexCoordsForStage(int stageIdx,
336 GrVertexLayout vertexLayout) {
337 GrAssert(stageIdx < GrDrawState::kNumStages);
338 GrAssert(check_layout(vertexLayout));
339 int bit = vertexLayout & gStageTexCoordMasks[stageIdx];
340 if (bit) {
341 // figure out which set of texture coordates is used
342 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
343 // and start at bit 0.
344 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
345 return (32 - SkCLZ(bit) - 1) / GrDrawState::kNumStages;
346 }
347 return -1;
348}
349
350////////////////////////////////////////////////////////////////////////////////
351
352void GrDrawState::VertexLayoutUnitTest() {
353 // Ensure that our globals mask arrays are correct
354 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
355 GrVertexLayout texCoordMasks[kMaxTexCoords];
356 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
357 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
358 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
359 }
360 for (int t = 0; t < kMaxTexCoords; ++t) {
361 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
362 }
363
364 // not necessarily exhaustive
365 static bool run;
366 if (!run) {
367 run = true;
368 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
369
370 GrVertexLayout stageMask = 0;
371 for (int t = 0; t < kMaxTexCoords; ++t) {
372 stageMask |= StageTexCoordVertexLayoutBit(s,t);
373 }
374 GrAssert(1 == kMaxTexCoords ||
375 !check_layout(stageMask));
376 GrAssert(gStageTexCoordMasks[s] == stageMask);
377 GrAssert(!check_layout(stageMask));
378 }
379 for (int t = 0; t < kMaxTexCoords; ++t) {
380 GrVertexLayout tcMask = 0;
381 GrAssert(!VertexUsesTexCoordIdx(t, 0));
382 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
383 tcMask |= StageTexCoordVertexLayoutBit(s,t);
384 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
385 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
386 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
387 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
388 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
389 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
390
391 #if GR_DEBUG
392 GrVertexLayout posAsTex = tcMask;
393 #endif
394 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
395 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
396 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
397 GrAssert(-1 == VertexEdgeOffset(posAsTex));
398 }
399 GrAssert(-1 == VertexEdgeOffset(tcMask));
400 GrAssert(-1 == VertexColorOffset(tcMask));
401 GrAssert(-1 == VertexCoverageOffset(tcMask));
402 #if GR_DEBUG
403 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
404 #endif
405 GrAssert(-1 == VertexCoverageOffset(withColor));
406 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
407 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
408 #if GR_DEBUG
409 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
410 #endif
411 GrAssert(-1 == VertexColorOffset(withEdge));
412 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
413 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
414 #if GR_DEBUG
415 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
416 #endif
417 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
418 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
419 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
420 #if GR_DEBUG
421 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
422 #endif
423 GrAssert(-1 == VertexColorOffset(withCoverage));
424 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
425 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
426 #if GR_DEBUG
427 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
428 kColor_VertexLayoutBit;
429 #endif
430 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
431 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
432 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
433 }
434 GrAssert(gTexCoordMasks[t] == tcMask);
435 GrAssert(check_layout(tcMask));
436
437 int stageOffsets[GrDrawState::kNumStages];
438 int colorOffset;
439 int edgeOffset;
440 int coverageOffset;
441 int size;
442 size = VertexSizeAndOffsetsByStage(tcMask,
443 stageOffsets, &colorOffset,
444 &coverageOffset, &edgeOffset);
445 GrAssert(2*sizeof(GrPoint) == size);
446 GrAssert(-1 == colorOffset);
447 GrAssert(-1 == coverageOffset);
448 GrAssert(-1 == edgeOffset);
449 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
450 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
451 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
452 }
453 }
454 }
455}
456
457////////////////////////////////////////////////////////////////////////////////
458
459bool GrDrawState::StageUsesTexCoords(GrVertexLayout layout, int stageIdx) {
460 return SkToBool(layout & gStageTexCoordMasks[stageIdx]);
461}
462
463bool GrDrawState::srcAlphaWillBeOne(GrVertexLayout layout) const {
464
465 uint32_t validComponentFlags;
466 GrColor color;
467 // Check if per-vertex or constant color may have partial alpha
468 if (layout & kColor_VertexLayoutBit) {
469 validComponentFlags = 0;
470 } else {
471 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
472 color = this->getColor();
473 }
474
475 // Run through the color stages
476 int stageCnt = getFirstCoverageStage();
477 for (int s = 0; s < stageCnt; ++s) {
478 const GrEffectRef* effect = this->getStage(s).getEffect();
479 if (NULL != effect) {
480 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
481 }
482 }
483
484 // Check if the color filter could introduce an alpha.
485 // We could skip the above work when this is true, but it is rare and the right fix is to make
486 // the color filter a GrEffect and implement getConstantColorComponents() for it.
487 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
488 validComponentFlags = 0;
489 }
490
491 // Check whether coverage is treated as color. If so we run through the coverage computation.
492 if (this->isCoverageDrawing()) {
493 GrColor coverageColor = this->getCoverage();
494 GrColor oldColor = color;
495 color = 0;
496 for (int c = 0; c < 4; ++c) {
497 if (validComponentFlags & (1 << c)) {
498 U8CPU a = (oldColor >> (c * 8)) & 0xff;
499 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
500 color |= (SkMulDiv255Round(a, b) << (c * 8));
501 }
502 }
503 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
504 const GrEffectRef* effect = this->getStage(s).getEffect();
505 if (NULL != effect) {
506 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
507 }
508 }
509 }
510 return (GrEffect::kA_ValidComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
511}
512
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000513bool GrDrawState::hasSolidCoverage(GrVertexLayout layout) const {
514 // If we're drawing coverage directly then coverage is effectively treated as color.
515 if (this->isCoverageDrawing()) {
516 return true;
517 }
518
519 GrColor coverage;
520 uint32_t validComponentFlags;
521 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
522 if (layout & kCoverage_VertexLayoutBit) {
523 validComponentFlags = 0;
524 } else {
525 coverage = fCommon.fCoverage;
526 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
527 }
528
529 // Run through the coverage stages and see if the coverage will be all ones at the end.
530 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
531 const GrEffectRef* effect = this->getStage(s).getEffect();
532 if (NULL != effect) {
533 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
534 }
535 }
536 return (GrEffect::kAll_ValidComponentFlags == validComponentFlags) && (0xffffffff == coverage);
537}
538
jvanverth@google.comcc782382013-01-28 20:39:48 +0000539////////////////////////////////////////////////////////////////////////////////
540
bsalomon@google.com2b446732013-02-12 16:47:41 +0000541// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
542// others will blend incorrectly.
543bool GrDrawState::canTweakAlphaForCoverage() const {
544 /*
545 The fractional coverage is f.
546 The src and dst coeffs are Cs and Cd.
547 The dst and src colors are S and D.
548 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
549 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
550 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
551 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
552 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
553 color by definition.
554 */
555 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
556 kISA_GrBlendCoeff == fCommon.fDstBlend ||
557 kISC_GrBlendCoeff == fCommon.fDstBlend ||
558 this->isCoverageDrawing();
559}
560
561GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
562 GrBlendCoeff* srcCoeff,
563 GrBlendCoeff* dstCoeff) const {
564 GrVertexLayout layout = this->getVertexLayout();
565
566 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
567 if (NULL == srcCoeff) {
568 srcCoeff = &bogusSrcCoeff;
569 }
570 *srcCoeff = this->getSrcBlendCoeff();
571
572 if (NULL == dstCoeff) {
573 dstCoeff = &bogusDstCoeff;
574 }
575 *dstCoeff = this->getDstBlendCoeff();
576
577 if (this->isColorWriteDisabled()) {
578 *srcCoeff = kZero_GrBlendCoeff;
579 *dstCoeff = kOne_GrBlendCoeff;
580 }
581
582 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
583 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
584 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
585 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
586 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
587
588 bool covIsZero = !this->isCoverageDrawing() &&
589 !(layout & GrDrawState::kCoverage_VertexLayoutBit) &&
590 0 == this->getCoverage();
591 // When coeffs are (0,1) there is no reason to draw at all, unless
592 // stenciling is enabled. Having color writes disabled is effectively
593 // (0,1). The same applies when coverage is known to be 0.
594 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
595 if (this->getStencil().doesWrite()) {
596 return kDisableBlend_BlendOptFlag |
597 kEmitTransBlack_BlendOptFlag;
598 } else {
599 return kSkipDraw_BlendOptFlag;
600 }
601 }
602
603 // check for coverage due to constant coverage, per-vertex coverage,
604 // edge aa or coverage stage
605 bool hasCoverage = forceCoverage ||
606 0xffffffff != this->getCoverage() ||
607 (layout & GrDrawState::kCoverage_VertexLayoutBit) ||
608 (layout & GrDrawState::kEdge_VertexLayoutBit);
609 for (int s = this->getFirstCoverageStage();
610 !hasCoverage && s < GrDrawState::kNumStages;
611 ++s) {
612 if (this->isStageEnabled(s)) {
613 hasCoverage = true;
614 }
615 }
616
617 // if we don't have coverage we can check whether the dst
618 // has to read at all. If not, we'll disable blending.
619 if (!hasCoverage) {
620 if (dstCoeffIsZero) {
621 if (kOne_GrBlendCoeff == *srcCoeff) {
622 // if there is no coverage and coeffs are (1,0) then we
623 // won't need to read the dst at all, it gets replaced by src
624 return kDisableBlend_BlendOptFlag;
625 } else if (kZero_GrBlendCoeff == *srcCoeff) {
626 // if the op is "clear" then we don't need to emit a color
627 // or blend, just write transparent black into the dst.
628 *srcCoeff = kOne_GrBlendCoeff;
629 *dstCoeff = kZero_GrBlendCoeff;
630 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
631 }
632 }
633 } else if (this->isCoverageDrawing()) {
634 // we have coverage but we aren't distinguishing it from alpha by request.
635 return kCoverageAsAlpha_BlendOptFlag;
636 } else {
637 // check whether coverage can be safely rolled into alpha
638 // of if we can skip color computation and just emit coverage
639 if (this->canTweakAlphaForCoverage()) {
640 return kCoverageAsAlpha_BlendOptFlag;
641 }
642 if (dstCoeffIsZero) {
643 if (kZero_GrBlendCoeff == *srcCoeff) {
644 // the source color is not included in the blend
645 // the dst coeff is effectively zero so blend works out to:
646 // (c)(0)D + (1-c)D = (1-c)D.
647 *dstCoeff = kISA_GrBlendCoeff;
648 return kEmitCoverage_BlendOptFlag;
649 } else if (srcAIsOne) {
650 // the dst coeff is effectively zero so blend works out to:
651 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
652 // If Sa is 1 then we can replace Sa with c
653 // and set dst coeff to 1-Sa.
654 *dstCoeff = kISA_GrBlendCoeff;
655 return kCoverageAsAlpha_BlendOptFlag;
656 }
657 } else if (dstCoeffIsOne) {
658 // the dst coeff is effectively one so blend works out to:
659 // cS + (c)(1)D + (1-c)D = cS + D.
660 *dstCoeff = kOne_GrBlendCoeff;
661 return kCoverageAsAlpha_BlendOptFlag;
662 }
663 }
664 return kNone_BlendOpt;
665}
666
667////////////////////////////////////////////////////////////////////////////////
668
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000669void GrDrawState::AutoViewMatrixRestore::restore() {
670 if (NULL != fDrawState) {
671 fDrawState->setViewMatrix(fViewMatrix);
672 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
673 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000674 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000675 }
676 }
677 }
678 fDrawState = NULL;
679}
680
681void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000682 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000683 uint32_t explicitCoordStageMask) {
684 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000685
686 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000687 if (NULL == drawState) {
688 return;
689 }
690
691 fRestoreMask = 0;
692 fViewMatrix = drawState->getViewMatrix();
693 drawState->preConcatViewMatrix(preconcatMatrix);
694 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
695 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
696 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000697 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
698 drawState->fStages[s].preConcatCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000699 }
700 }
701}
702
703////////////////////////////////////////////////////////////////////////////////
704
705void GrDrawState::AutoDeviceCoordDraw::restore() {
706 if (NULL != fDrawState) {
707 fDrawState->setViewMatrix(fViewMatrix);
708 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
709 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000710 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000711 }
712 }
713 }
714 fDrawState = NULL;
715}
716
717bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState,
718 uint32_t explicitCoordStageMask) {
719 GrAssert(NULL != drawState);
720
721 this->restore();
722
723 fDrawState = drawState;
724 if (NULL == fDrawState) {
725 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000726 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000727
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000728 fViewMatrix = drawState->getViewMatrix();
729 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000730 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000731 bool inverted = false;
732
733 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
734 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
735 if (!inverted && !fViewMatrix.invert(&invVM)) {
736 // sad trombone sound
737 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000738 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000739 } else {
740 inverted = true;
741 }
742 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000743 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000744 stage->saveCoordChange(&fSavedCoordChanges[s]);
745 stage->preConcatCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000746 }
747 }
748 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000749 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000750}