blob: 3925bd9a9195538dd8a16409342b93d88a9778d3 [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/**
jvanverth@google.com39768252013-02-14 15:25:44 +000052 * This function generates a mask that we like to have known at compile
skia.committer@gmail.com044679e2013-02-15 07:16:57 +000053 * time. When the number of stages is bumped or the way bits are defined in
54 * GrDrawState.h changes this function should be rerun to generate the new mask.
55 * (We attempted to force the compiler to generate the mask using recursive
56 * templates but always wound up with static initializers under gcc, even if
jvanverth@google.com39768252013-02-14 15:25:44 +000057 * they were just a series of immediate->memory moves.)
jvanverth@google.comcc782382013-01-28 20:39:48 +000058 *
59 */
jvanverth@google.com39768252013-02-14 15:25:44 +000060void gen_tex_coord_mask(GrVertexLayout* texCoordMask) {
61 *texCoordMask = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +000062 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
jvanverth@google.com39768252013-02-14 15:25:44 +000063 *texCoordMask |= GrDrawState::StageTexCoordVertexLayoutBit(s);
jvanverth@google.comcc782382013-01-28 20:39:48 +000064 }
65}
66
jvanverth@google.com39768252013-02-14 15:25:44 +000067const GrVertexLayout kTexCoordMask = (1 << GrDrawState::kNumStages)-1;
jvanverth@google.comcc782382013-01-28 20:39:48 +000068
jvanverth@google.com39768252013-02-14 15:25:44 +000069inline int num_tex_coords(GrVertexLayout layout) {
70 return (kTexCoordMask & layout) ? 1 : 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +000071}
72
73} //unnamed namespace
74
bsalomon@google.com85983282013-02-07 22:00:29 +000075static const size_t kVec2Size = sizeof(GrPoint);
76
jvanverth@google.comcc782382013-01-28 20:39:48 +000077size_t GrDrawState::VertexSize(GrVertexLayout vertexLayout) {
bsalomon@google.com85983282013-02-07 22:00:29 +000078 size_t size = kVec2Size; // position
79 size += num_tex_coords(vertexLayout) * kVec2Size;
jvanverth@google.comcc782382013-01-28 20:39:48 +000080 if (vertexLayout & kColor_VertexLayoutBit) {
81 size += sizeof(GrColor);
82 }
83 if (vertexLayout & kCoverage_VertexLayoutBit) {
84 size += sizeof(GrColor);
85 }
86 if (vertexLayout & kEdge_VertexLayoutBit) {
87 size += 4 * sizeof(SkScalar);
88 }
89 return size;
90}
91
92////////////////////////////////////////////////////////////////////////////////
93
94/**
95 * Functions for computing offsets of various components from the layout
96 * bitfield.
97 *
98 * Order of vertex components:
99 * Position
skia.committer@gmail.com044679e2013-02-15 07:16:57 +0000100 * Tex Coord
jvanverth@google.comcc782382013-01-28 20:39:48 +0000101 * Color
102 * Coverage
103 */
104
105int GrDrawState::VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000106 if (!StageUsesTexCoords(vertexLayout, stageIdx)) {
107 return 0;
108 }
jvanverth@google.comcc782382013-01-28 20:39:48 +0000109
jvanverth@google.com39768252013-02-14 15:25:44 +0000110 return kVec2Size;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000111}
112
113int GrDrawState::VertexColorOffset(GrVertexLayout vertexLayout) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000114 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com85983282013-02-07 22:00:29 +0000115 return kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos
jvanverth@google.comcc782382013-01-28 20:39:48 +0000116 }
117 return -1;
118}
119
120int GrDrawState::VertexCoverageOffset(GrVertexLayout vertexLayout) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000121 if (vertexLayout & kCoverage_VertexLayoutBit) {
bsalomon@google.com85983282013-02-07 22:00:29 +0000122 int offset = kVec2Size * (num_tex_coords(vertexLayout) + 1);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000123 if (vertexLayout & kColor_VertexLayoutBit) {
124 offset += sizeof(GrColor);
125 }
126 return offset;
127 }
128 return -1;
129}
130
131int GrDrawState::VertexEdgeOffset(GrVertexLayout vertexLayout) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000132 // edge pts are after the pos, tex coords, and color
133 if (vertexLayout & kEdge_VertexLayoutBit) {
bsalomon@google.com85983282013-02-07 22:00:29 +0000134 int offset = kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos
jvanverth@google.comcc782382013-01-28 20:39:48 +0000135 if (vertexLayout & kColor_VertexLayoutBit) {
136 offset += sizeof(GrColor);
137 }
138 if (vertexLayout & kCoverage_VertexLayoutBit) {
139 offset += sizeof(GrColor);
140 }
141 return offset;
142 }
143 return -1;
144}
145
jvanverth@google.com39768252013-02-14 15:25:44 +0000146int GrDrawState::VertexSizeAndOffsets(
jvanverth@google.comcc782382013-01-28 20:39:48 +0000147 GrVertexLayout vertexLayout,
jvanverth@google.com39768252013-02-14 15:25:44 +0000148 int* texCoordOffset,
jvanverth@google.comcc782382013-01-28 20:39:48 +0000149 int* colorOffset,
150 int* coverageOffset,
151 int* edgeOffset) {
bsalomon@google.com85983282013-02-07 22:00:29 +0000152 int size = kVec2Size; // position
jvanverth@google.comcc782382013-01-28 20:39:48 +0000153
jvanverth@google.com39768252013-02-14 15:25:44 +0000154 if (kTexCoordMask & vertexLayout) {
155 if (NULL != texCoordOffset) {
156 *texCoordOffset = size;
157 }
158 size += kVec2Size;
159 } else {
160 if (NULL != texCoordOffset) {
161 *texCoordOffset = -1;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000162 }
163 }
164 if (kColor_VertexLayoutBit & vertexLayout) {
165 if (NULL != colorOffset) {
166 *colorOffset = size;
167 }
168 size += sizeof(GrColor);
169 } else {
170 if (NULL != colorOffset) {
171 *colorOffset = -1;
172 }
173 }
174 if (kCoverage_VertexLayoutBit & vertexLayout) {
175 if (NULL != coverageOffset) {
176 *coverageOffset = size;
177 }
178 size += sizeof(GrColor);
179 } else {
180 if (NULL != coverageOffset) {
181 *coverageOffset = -1;
182 }
183 }
184 if (kEdge_VertexLayoutBit & vertexLayout) {
185 if (NULL != edgeOffset) {
186 *edgeOffset = size;
187 }
188 size += 4 * sizeof(SkScalar);
189 } else {
190 if (NULL != edgeOffset) {
191 *edgeOffset = -1;
192 }
193 }
194 return size;
195}
196
197int GrDrawState::VertexSizeAndOffsetsByStage(
198 GrVertexLayout vertexLayout,
199 int texCoordOffsetsByStage[GrDrawState::kNumStages],
200 int* colorOffset,
201 int* coverageOffset,
202 int* edgeOffset) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000203
jvanverth@google.com39768252013-02-14 15:25:44 +0000204 int texCoordOffset;
205 int size = VertexSizeAndOffsets(vertexLayout,
206 &texCoordOffset,
207 colorOffset,
208 coverageOffset,
209 edgeOffset);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000210 if (NULL != texCoordOffsetsByStage) {
211 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
jvanverth@google.com39768252013-02-14 15:25:44 +0000212 texCoordOffsetsByStage[s] = StageUsesTexCoords(vertexLayout, s) ?
213 texCoordOffset : 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000214 }
215 }
216 return size;
217}
218
219////////////////////////////////////////////////////////////////////////////////
220
jvanverth@google.com39768252013-02-14 15:25:44 +0000221bool GrDrawState::VertexUsesTexCoords(GrVertexLayout vertexLayout) {
222 return SkToBool(kTexCoordMask & vertexLayout);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000223}
224
225////////////////////////////////////////////////////////////////////////////////
226
227void GrDrawState::VertexLayoutUnitTest() {
jvanverth@google.com39768252013-02-14 15:25:44 +0000228 // Ensure that our tex coord mask is correct
229 GrVertexLayout texCoordMask;
230 gen_tex_coord_mask(&texCoordMask);
231 GrAssert(texCoordMask == kTexCoordMask);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000232
233 // not necessarily exhaustive
234 static bool run;
235 if (!run) {
236 run = true;
jvanverth@google.com39768252013-02-14 15:25:44 +0000237 GrVertexLayout tcMask = 0;
238 GrAssert(!VertexUsesTexCoords(0));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000239 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
jvanverth@google.com39768252013-02-14 15:25:44 +0000240 tcMask |= StageTexCoordVertexLayoutBit(s);
241 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
242 GrAssert(VertexUsesTexCoords(tcMask));
243 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
244 GrAssert(StageUsesTexCoords(tcMask, s));
245 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
246 GrAssert(!StageUsesTexCoords(tcMask, s2));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000247
jvanverth@google.com39768252013-02-14 15:25:44 +0000248 #if GR_DEBUG
249 GrVertexLayout posAsTex = tcMask;
250 #endif
251 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
252 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
253 GrAssert(!StageUsesTexCoords(posAsTex, s2));
254 GrAssert(-1 == VertexEdgeOffset(posAsTex));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000255 }
jvanverth@google.com39768252013-02-14 15:25:44 +0000256 GrAssert(-1 == VertexEdgeOffset(tcMask));
257 GrAssert(-1 == VertexColorOffset(tcMask));
258 GrAssert(-1 == VertexCoverageOffset(tcMask));
259 #if GR_DEBUG
260 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
261 #endif
262 GrAssert(-1 == VertexCoverageOffset(withColor));
263 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
264 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
265 #if GR_DEBUG
266 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
267 #endif
268 GrAssert(-1 == VertexColorOffset(withEdge));
269 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
270 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
271 #if GR_DEBUG
272 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
273 #endif
274 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
275 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
276 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
277 #if GR_DEBUG
278 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
279 #endif
280 GrAssert(-1 == VertexColorOffset(withCoverage));
281 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
282 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
283 #if GR_DEBUG
284 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
285 kColor_VertexLayoutBit;
286 #endif
287 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
288 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
289 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000290 }
jvanverth@google.com39768252013-02-14 15:25:44 +0000291 GrAssert(kTexCoordMask == tcMask);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000292
jvanverth@google.com39768252013-02-14 15:25:44 +0000293 int stageOffsets[GrDrawState::kNumStages];
294 int colorOffset;
295 int edgeOffset;
296 int coverageOffset;
297 int size;
298 size = VertexSizeAndOffsetsByStage(tcMask,
299 stageOffsets, &colorOffset,
300 &coverageOffset, &edgeOffset);
301 GrAssert(2*sizeof(GrPoint) == size);
302 GrAssert(-1 == colorOffset);
303 GrAssert(-1 == coverageOffset);
304 GrAssert(-1 == edgeOffset);
305 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
306 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
307 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000308 }
309 }
310}
311
312////////////////////////////////////////////////////////////////////////////////
313
314bool GrDrawState::StageUsesTexCoords(GrVertexLayout layout, int stageIdx) {
jvanverth@google.com39768252013-02-14 15:25:44 +0000315 return SkToBool(layout & StageTexCoordVertexLayoutBit(stageIdx));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000316}
317
318bool GrDrawState::srcAlphaWillBeOne(GrVertexLayout layout) const {
319
320 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000321 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000322 // Check if per-vertex or constant color may have partial alpha
323 if (layout & kColor_VertexLayoutBit) {
324 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000325 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000326 } else {
327 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
328 color = this->getColor();
329 }
330
331 // Run through the color stages
332 int stageCnt = getFirstCoverageStage();
333 for (int s = 0; s < stageCnt; ++s) {
334 const GrEffectRef* effect = this->getStage(s).getEffect();
335 if (NULL != effect) {
336 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
337 }
338 }
339
340 // Check if the color filter could introduce an alpha.
341 // We could skip the above work when this is true, but it is rare and the right fix is to make
342 // the color filter a GrEffect and implement getConstantColorComponents() for it.
343 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
344 validComponentFlags = 0;
345 }
346
347 // Check whether coverage is treated as color. If so we run through the coverage computation.
348 if (this->isCoverageDrawing()) {
349 GrColor coverageColor = this->getCoverage();
350 GrColor oldColor = color;
351 color = 0;
352 for (int c = 0; c < 4; ++c) {
353 if (validComponentFlags & (1 << c)) {
354 U8CPU a = (oldColor >> (c * 8)) & 0xff;
355 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
356 color |= (SkMulDiv255Round(a, b) << (c * 8));
357 }
358 }
359 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
360 const GrEffectRef* effect = this->getStage(s).getEffect();
361 if (NULL != effect) {
362 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
363 }
364 }
365 }
366 return (GrEffect::kA_ValidComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
367}
368
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000369bool GrDrawState::hasSolidCoverage(GrVertexLayout layout) const {
370 // If we're drawing coverage directly then coverage is effectively treated as color.
371 if (this->isCoverageDrawing()) {
372 return true;
373 }
374
375 GrColor coverage;
376 uint32_t validComponentFlags;
377 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
378 if (layout & kCoverage_VertexLayoutBit) {
379 validComponentFlags = 0;
380 } else {
381 coverage = fCommon.fCoverage;
382 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
383 }
384
385 // Run through the coverage stages and see if the coverage will be all ones at the end.
386 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
387 const GrEffectRef* effect = this->getStage(s).getEffect();
388 if (NULL != effect) {
389 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
390 }
391 }
392 return (GrEffect::kAll_ValidComponentFlags == validComponentFlags) && (0xffffffff == coverage);
393}
394
jvanverth@google.comcc782382013-01-28 20:39:48 +0000395////////////////////////////////////////////////////////////////////////////////
396
bsalomon@google.com2b446732013-02-12 16:47:41 +0000397// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
398// others will blend incorrectly.
399bool GrDrawState::canTweakAlphaForCoverage() const {
400 /*
401 The fractional coverage is f.
402 The src and dst coeffs are Cs and Cd.
403 The dst and src colors are S and D.
404 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
405 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
406 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
407 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
408 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
409 color by definition.
410 */
411 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
412 kISA_GrBlendCoeff == fCommon.fDstBlend ||
413 kISC_GrBlendCoeff == fCommon.fDstBlend ||
414 this->isCoverageDrawing();
415}
416
417GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
418 GrBlendCoeff* srcCoeff,
419 GrBlendCoeff* dstCoeff) const {
420 GrVertexLayout layout = this->getVertexLayout();
421
422 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
423 if (NULL == srcCoeff) {
424 srcCoeff = &bogusSrcCoeff;
425 }
426 *srcCoeff = this->getSrcBlendCoeff();
427
428 if (NULL == dstCoeff) {
429 dstCoeff = &bogusDstCoeff;
430 }
431 *dstCoeff = this->getDstBlendCoeff();
432
433 if (this->isColorWriteDisabled()) {
434 *srcCoeff = kZero_GrBlendCoeff;
435 *dstCoeff = kOne_GrBlendCoeff;
436 }
437
438 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
439 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
440 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
441 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
442 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
443
444 bool covIsZero = !this->isCoverageDrawing() &&
445 !(layout & GrDrawState::kCoverage_VertexLayoutBit) &&
446 0 == this->getCoverage();
447 // When coeffs are (0,1) there is no reason to draw at all, unless
448 // stenciling is enabled. Having color writes disabled is effectively
449 // (0,1). The same applies when coverage is known to be 0.
450 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
451 if (this->getStencil().doesWrite()) {
452 return kDisableBlend_BlendOptFlag |
453 kEmitTransBlack_BlendOptFlag;
454 } else {
455 return kSkipDraw_BlendOptFlag;
456 }
457 }
458
459 // check for coverage due to constant coverage, per-vertex coverage,
460 // edge aa or coverage stage
461 bool hasCoverage = forceCoverage ||
462 0xffffffff != this->getCoverage() ||
463 (layout & GrDrawState::kCoverage_VertexLayoutBit) ||
464 (layout & GrDrawState::kEdge_VertexLayoutBit);
465 for (int s = this->getFirstCoverageStage();
466 !hasCoverage && s < GrDrawState::kNumStages;
467 ++s) {
468 if (this->isStageEnabled(s)) {
469 hasCoverage = true;
470 }
471 }
472
473 // if we don't have coverage we can check whether the dst
474 // has to read at all. If not, we'll disable blending.
475 if (!hasCoverage) {
476 if (dstCoeffIsZero) {
477 if (kOne_GrBlendCoeff == *srcCoeff) {
478 // if there is no coverage and coeffs are (1,0) then we
479 // won't need to read the dst at all, it gets replaced by src
480 return kDisableBlend_BlendOptFlag;
481 } else if (kZero_GrBlendCoeff == *srcCoeff) {
482 // if the op is "clear" then we don't need to emit a color
483 // or blend, just write transparent black into the dst.
484 *srcCoeff = kOne_GrBlendCoeff;
485 *dstCoeff = kZero_GrBlendCoeff;
486 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
487 }
488 }
489 } else if (this->isCoverageDrawing()) {
490 // we have coverage but we aren't distinguishing it from alpha by request.
491 return kCoverageAsAlpha_BlendOptFlag;
492 } else {
493 // check whether coverage can be safely rolled into alpha
494 // of if we can skip color computation and just emit coverage
495 if (this->canTweakAlphaForCoverage()) {
496 return kCoverageAsAlpha_BlendOptFlag;
497 }
498 if (dstCoeffIsZero) {
499 if (kZero_GrBlendCoeff == *srcCoeff) {
500 // the source color is not included in the blend
501 // the dst coeff is effectively zero so blend works out to:
502 // (c)(0)D + (1-c)D = (1-c)D.
503 *dstCoeff = kISA_GrBlendCoeff;
504 return kEmitCoverage_BlendOptFlag;
505 } else if (srcAIsOne) {
506 // the dst coeff is effectively zero so blend works out to:
507 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
508 // If Sa is 1 then we can replace Sa with c
509 // and set dst coeff to 1-Sa.
510 *dstCoeff = kISA_GrBlendCoeff;
511 return kCoverageAsAlpha_BlendOptFlag;
512 }
513 } else if (dstCoeffIsOne) {
514 // the dst coeff is effectively one so blend works out to:
515 // cS + (c)(1)D + (1-c)D = cS + D.
516 *dstCoeff = kOne_GrBlendCoeff;
517 return kCoverageAsAlpha_BlendOptFlag;
518 }
519 }
520 return kNone_BlendOpt;
521}
522
523////////////////////////////////////////////////////////////////////////////////
524
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000525void GrDrawState::AutoViewMatrixRestore::restore() {
526 if (NULL != fDrawState) {
527 fDrawState->setViewMatrix(fViewMatrix);
528 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
529 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000530 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000531 }
532 }
533 }
534 fDrawState = NULL;
535}
536
537void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000538 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000539 uint32_t explicitCoordStageMask) {
540 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000541
542 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000543 if (NULL == drawState) {
544 return;
545 }
546
547 fRestoreMask = 0;
548 fViewMatrix = drawState->getViewMatrix();
549 drawState->preConcatViewMatrix(preconcatMatrix);
550 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
551 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
552 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000553 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
554 drawState->fStages[s].preConcatCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000555 }
556 }
557}
558
559////////////////////////////////////////////////////////////////////////////////
560
561void GrDrawState::AutoDeviceCoordDraw::restore() {
562 if (NULL != fDrawState) {
563 fDrawState->setViewMatrix(fViewMatrix);
564 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
565 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000566 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000567 }
568 }
569 }
570 fDrawState = NULL;
571}
572
573bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState,
574 uint32_t explicitCoordStageMask) {
575 GrAssert(NULL != drawState);
576
577 this->restore();
578
579 fDrawState = drawState;
580 if (NULL == fDrawState) {
581 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000582 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000583
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000584 fViewMatrix = drawState->getViewMatrix();
585 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000586 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000587 bool inverted = false;
588
589 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
590 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
591 if (!inverted && !fViewMatrix.invert(&invVM)) {
592 // sad trombone sound
593 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000594 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000595 } else {
596 inverted = true;
597 }
598 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000599 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000600 stage->saveCoordChange(&fSavedCoordChanges[s]);
601 stage->preConcatCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000602 }
603 }
604 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000605 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000606}