blob: fddce41099e0fe1b829ab00baf9fba0e7f102a07 [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.com9b855c72013-03-01 18:21:22 +000060void gen_tex_coord_mask(GrAttribBindings* texCoordMask) {
jvanverth@google.com39768252013-02-14 15:25:44 +000061 *texCoordMask = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +000062 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +000063 *texCoordMask |= GrDrawState::ExplicitTexCoordAttribBindingsBit(s);
jvanverth@google.comcc782382013-01-28 20:39:48 +000064 }
65}
66
jvanverth@google.com9b855c72013-03-01 18:21:22 +000067const GrAttribBindings kTexCoord_AttribBindingsMask = (1 << GrDrawState::kNumStages)-1;
jvanverth@google.comcc782382013-01-28 20:39:48 +000068
69} //unnamed namespace
70
jvanverth@google.com9b855c72013-03-01 18:21:22 +000071const size_t GrDrawState::kVertexAttribSizes[kGrVertexAttribTypeCount] = {
72 sizeof(float), // kFloat_GrVertexAttribType
73 2*sizeof(float), // kVec2_GrVertexAttribType
74 3*sizeof(float), // kVec3_GrVertexAttribType
skia.committer@gmail.comf140f182013-03-02 07:01:56 +000075 4*sizeof(float), // kVec4_GrVertexAttribType
jvanverth@google.com9b855c72013-03-01 18:21:22 +000076 4*sizeof(char) // kCVec4_GrVertexAttribType
77};
bsalomon@google.com85983282013-02-07 22:00:29 +000078
jvanverth@google.com9b855c72013-03-01 18:21:22 +000079static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
80 // this works as long as we're 4 byte-aligned
81#if GR_DEBUG
82 uint32_t overlapCheck = 0;
83#endif
84 GrAssert(count <= GrDrawState::kAttribIndexCount);
85 size_t size = 0;
86 for (int index = 0; index < count; ++index) {
87 size_t attribSize = GrDrawState::kVertexAttribSizes[attribs[index].fType];
88 size += attribSize;
89#if GR_DEBUG
90 size_t dwordCount = attribSize >> 2;
91 uint32_t mask = (1 << dwordCount)-1;
92 size_t offsetShift = attribs[index].fOffset >> 2;
93 GrAssert(!(overlapCheck & (mask << offsetShift)));
94 overlapCheck |= (mask << offsetShift);
95#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +000096 }
97 return size;
98}
99
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000100size_t GrDrawState::getVertexSize() const {
101 return vertex_size(fVertexAttribs.begin(), fVertexAttribs.count());
102}
103
104const GrAttribBindings GrDrawState::kAttribIndexMasks[kAttribIndexCount] = {
105 0, // position is not reflected in the bindings
106 kColor_AttribBindingsBit,
107 kCoverage_AttribBindingsBit,
108 kEdge_AttribBindingsBit,
109 kTexCoord_AttribBindingsMask
110};
111
jvanverth@google.comcc782382013-01-28 20:39:48 +0000112////////////////////////////////////////////////////////////////////////////////
113
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000114void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
115 GrAssert(count <= GrDrawState::kAttribIndexCount);
116 fVertexAttribs.reset();
117 for (int index = 0; index < count; ++index) {
118 fVertexAttribs.push_back(attribs[index]);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000119 }
jvanverth@google.comcc782382013-01-28 20:39:48 +0000120}
121
122////////////////////////////////////////////////////////////////////////////////
123
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000124void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000125 static const GrVertexAttrib kPositionAttrib = {kVec2f_GrVertexAttribType, 0};
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000126 fVertexAttribs.reset();
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000127 fVertexAttribs.push_back(kPositionAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000128
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000129 fCommon.fAttribBindings = kDefault_AttribBindings;
130
131 fAttribIndices[kPosition_AttribIndex] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000132}
133
134////////////////////////////////////////////////////////////////////////////////
135
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000136bool GrDrawState::validateVertexAttribs() const {
137 // color and coverage can set indices beyond the standard count
138 static const int kMaxValidAttribIndex = kVertexAttribCnt+2;
139 int attributeTypes[kMaxValidAttribIndex];
140 for (int i = 0; i < kMaxValidAttribIndex; ++i) {
141 attributeTypes[i] = -1;
142 }
143
144 // sentinel to make sure effects don't try to use built-in attributes
145 static const int kBuiltInAttributeType = 10000;
146
147 // check our built-in indices
148 if (fAttribIndices[kPosition_AttribIndex] >= kVertexAttribCnt) {
149 return false;
150 }
151 attributeTypes[fAttribIndices[kPosition_AttribIndex]] = kBuiltInAttributeType;
152 for (int j = kColor_AttribIndex; j <= kCoverage_AttribIndex; ++j) {
153 if (fCommon.fAttribBindings & kAttribIndexMasks[j]) {
154 int attributeIndex = fAttribIndices[j];
155 if (attributeIndex >= kMaxValidAttribIndex) {
156 return false;
157 }
158 // they should not be shared at all
159 if (attributeTypes[attributeIndex] != -1) {
160 return false;
161 }
162 attributeTypes[attributeIndex] = kBuiltInAttributeType;
163 }
164 }
165 for (int j = kEdge_AttribIndex; j < kAttribIndexCount; ++j) {
166 if (fCommon.fAttribBindings & kAttribIndexMasks[j]) {
167 int attributeIndex = fAttribIndices[j];
168 if (attributeIndex >= kVertexAttribCnt) {
169 return false;
170 }
171 // they should not be shared at all
172 if (attributeTypes[attributeIndex] != -1) {
173 return false;
174 }
175 attributeTypes[attributeIndex] = kBuiltInAttributeType;
176 }
177 }
178
179 // now those set by effects
180 for (int s = 0; s < kNumStages; ++s) {
181 const GrEffectStage& stage = fStages[s];
182 const GrEffectRef* effect = stage.getEffect();
183 if (effect == NULL) {
184 continue;
185 }
186
187 // make sure that the count in the stage and the effect matches
188 int numAttributes = stage.getVertexAttribIndexCount();
189 if (numAttributes != effect->get()->numVertexAttribs()) {
190 return false;
191 }
192
193 // make sure that any shared indices have the same type
194 const int* attributeIndices = stage.getVertexAttribIndices();
195 for (int i = 0; i < numAttributes; ++i) {
196 int attributeIndex = attributeIndices[i];
197 if (attributeIndex >= kVertexAttribCnt) {
198 return false;
199 }
200
201 GrSLType attributeType = effect->get()->vertexAttribType(i);
202 if (attributeTypes[attributeIndex] != -1 &&
203 attributeTypes[attributeIndex] != attributeType) {
204 return false;
205 }
206 attributeTypes[attributeIndex] = attributeType;
207 }
208 }
209
210 return true;
211}
212
213////////////////////////////////////////////////////////////////////////////////
214
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000215bool GrDrawState::AttributesBindExplicitTexCoords(GrAttribBindings attribBindings) {
216 return SkToBool(kTexCoord_AttribBindingsMask & attribBindings);
217}
218
219////////////////////////////////////////////////////////////////////////////////
220
221void GrDrawState::VertexAttributesUnitTest() {
jvanverth@google.com39768252013-02-14 15:25:44 +0000222 // Ensure that our tex coord mask is correct
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000223 GrAttribBindings texCoordMask;
jvanverth@google.com39768252013-02-14 15:25:44 +0000224 gen_tex_coord_mask(&texCoordMask);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000225 GrAssert(texCoordMask == kTexCoord_AttribBindingsMask);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000226
227 // not necessarily exhaustive
228 static bool run;
229 if (!run) {
230 run = true;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000231
232 GrVertexAttribArray<6> attribs;
233 GrAssert(0 == vertex_size(attribs.begin(), attribs.count()));
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000234
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000235 GrVertexAttrib currAttrib = {kFloat_GrVertexAttribType, 0};
236 attribs.push_back(currAttrib);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000237 GrAssert(sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
238 attribs[0].fType = kVec2f_GrVertexAttribType;
239 GrAssert(2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
240 attribs[0].fType = kVec3f_GrVertexAttribType;
241 GrAssert(3*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
242 attribs[0].fType = kVec4f_GrVertexAttribType;
243 GrAssert(4*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
244 attribs[0].fType = kVec4ub_GrVertexAttribType;
245 GrAssert(4*sizeof(char) == vertex_size(attribs.begin(), attribs.count()));
246
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000247 currAttrib.set(kVec2f_GrVertexAttribType, attribs[0].fOffset + 4*sizeof(char));
248 attribs.push_back(currAttrib);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000249 GrAssert(4*sizeof(char) + 2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000250 currAttrib.set(kVec3f_GrVertexAttribType, attribs[1].fOffset + 2*sizeof(float));
251 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000252 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000253 vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000254 currAttrib.set(kFloat_GrVertexAttribType, attribs[2].fOffset + 3*sizeof(float));
255 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000256 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000257 vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000258 currAttrib.set(kVec4f_GrVertexAttribType, attribs[3].fOffset + sizeof(float));
259 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000260 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) + 4*sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000261 vertex_size(attribs.begin(), attribs.count()));
262
263 GrAttribBindings tcMask = 0;
264 GrAssert(!AttributesBindExplicitTexCoords(0));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000265 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000266 tcMask |= ExplicitTexCoordAttribBindingsBit(s);
267 GrAssert(AttributesBindExplicitTexCoords(tcMask));
268 GrAssert(StageBindsExplicitTexCoords(tcMask, s));
jvanverth@google.com39768252013-02-14 15:25:44 +0000269 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000270 GrAssert(!StageBindsExplicitTexCoords(tcMask, s2));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000271 }
jvanverth@google.comcc782382013-01-28 20:39:48 +0000272 }
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000273 GrAssert(kTexCoord_AttribBindingsMask == tcMask);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000274 }
275}
276
277////////////////////////////////////////////////////////////////////////////////
278
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000279bool GrDrawState::StageBindsExplicitTexCoords(GrAttribBindings bindings, int stageIdx) {
280 return SkToBool(bindings & ExplicitTexCoordAttribBindingsBit(stageIdx));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000281}
282
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000283bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000284
285 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000286 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000287 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000288 if (bindings & kColor_AttribBindingsBit) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000289 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000290 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000291 } else {
292 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
293 color = this->getColor();
294 }
295
296 // Run through the color stages
297 int stageCnt = getFirstCoverageStage();
298 for (int s = 0; s < stageCnt; ++s) {
299 const GrEffectRef* effect = this->getStage(s).getEffect();
300 if (NULL != effect) {
301 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
302 }
303 }
304
305 // Check if the color filter could introduce an alpha.
306 // We could skip the above work when this is true, but it is rare and the right fix is to make
307 // the color filter a GrEffect and implement getConstantColorComponents() for it.
308 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
309 validComponentFlags = 0;
310 }
311
312 // Check whether coverage is treated as color. If so we run through the coverage computation.
313 if (this->isCoverageDrawing()) {
314 GrColor coverageColor = this->getCoverage();
315 GrColor oldColor = color;
316 color = 0;
317 for (int c = 0; c < 4; ++c) {
318 if (validComponentFlags & (1 << c)) {
319 U8CPU a = (oldColor >> (c * 8)) & 0xff;
320 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
321 color |= (SkMulDiv255Round(a, b) << (c * 8));
322 }
323 }
324 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
325 const GrEffectRef* effect = this->getStage(s).getEffect();
326 if (NULL != effect) {
327 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
328 }
329 }
330 }
331 return (GrEffect::kA_ValidComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
332}
333
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000334bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000335 // If we're drawing coverage directly then coverage is effectively treated as color.
336 if (this->isCoverageDrawing()) {
337 return true;
338 }
339
340 GrColor coverage;
341 uint32_t validComponentFlags;
342 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000343 if (bindings & kCoverage_AttribBindingsBit) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000344 validComponentFlags = 0;
345 } else {
346 coverage = fCommon.fCoverage;
347 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
348 }
349
350 // Run through the coverage stages and see if the coverage will be all ones at the end.
351 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
352 const GrEffectRef* effect = this->getStage(s).getEffect();
353 if (NULL != effect) {
354 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
355 }
356 }
357 return (GrEffect::kAll_ValidComponentFlags == validComponentFlags) && (0xffffffff == coverage);
358}
359
jvanverth@google.comcc782382013-01-28 20:39:48 +0000360////////////////////////////////////////////////////////////////////////////////
361
bsalomon@google.com2b446732013-02-12 16:47:41 +0000362// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
363// others will blend incorrectly.
364bool GrDrawState::canTweakAlphaForCoverage() const {
365 /*
366 The fractional coverage is f.
367 The src and dst coeffs are Cs and Cd.
368 The dst and src colors are S and D.
369 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
370 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
371 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
372 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
373 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
374 color by definition.
375 */
376 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
377 kISA_GrBlendCoeff == fCommon.fDstBlend ||
378 kISC_GrBlendCoeff == fCommon.fDstBlend ||
379 this->isCoverageDrawing();
380}
381
382GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
383 GrBlendCoeff* srcCoeff,
384 GrBlendCoeff* dstCoeff) const {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000385 GrAttribBindings bindings = this->getAttribBindings();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000386
387 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
388 if (NULL == srcCoeff) {
389 srcCoeff = &bogusSrcCoeff;
390 }
391 *srcCoeff = this->getSrcBlendCoeff();
392
393 if (NULL == dstCoeff) {
394 dstCoeff = &bogusDstCoeff;
395 }
396 *dstCoeff = this->getDstBlendCoeff();
397
398 if (this->isColorWriteDisabled()) {
399 *srcCoeff = kZero_GrBlendCoeff;
400 *dstCoeff = kOne_GrBlendCoeff;
401 }
402
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000403 bool srcAIsOne = this->srcAlphaWillBeOne(bindings);
bsalomon@google.com2b446732013-02-12 16:47:41 +0000404 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
405 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
406 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
407 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
408
409 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000410 !(bindings & GrDrawState::kCoverage_AttribBindingsBit) &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000411 0 == this->getCoverage();
412 // When coeffs are (0,1) there is no reason to draw at all, unless
413 // stenciling is enabled. Having color writes disabled is effectively
414 // (0,1). The same applies when coverage is known to be 0.
415 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
416 if (this->getStencil().doesWrite()) {
417 return kDisableBlend_BlendOptFlag |
418 kEmitTransBlack_BlendOptFlag;
419 } else {
420 return kSkipDraw_BlendOptFlag;
421 }
422 }
423
424 // check for coverage due to constant coverage, per-vertex coverage,
425 // edge aa or coverage stage
426 bool hasCoverage = forceCoverage ||
427 0xffffffff != this->getCoverage() ||
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000428 (bindings & GrDrawState::kCoverage_AttribBindingsBit) ||
429 (bindings & GrDrawState::kEdge_AttribBindingsBit);
bsalomon@google.com2b446732013-02-12 16:47:41 +0000430 for (int s = this->getFirstCoverageStage();
431 !hasCoverage && s < GrDrawState::kNumStages;
432 ++s) {
433 if (this->isStageEnabled(s)) {
434 hasCoverage = true;
435 }
436 }
437
438 // if we don't have coverage we can check whether the dst
439 // has to read at all. If not, we'll disable blending.
440 if (!hasCoverage) {
441 if (dstCoeffIsZero) {
442 if (kOne_GrBlendCoeff == *srcCoeff) {
443 // if there is no coverage and coeffs are (1,0) then we
444 // won't need to read the dst at all, it gets replaced by src
445 return kDisableBlend_BlendOptFlag;
446 } else if (kZero_GrBlendCoeff == *srcCoeff) {
447 // if the op is "clear" then we don't need to emit a color
448 // or blend, just write transparent black into the dst.
449 *srcCoeff = kOne_GrBlendCoeff;
450 *dstCoeff = kZero_GrBlendCoeff;
451 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
452 }
453 }
454 } else if (this->isCoverageDrawing()) {
455 // we have coverage but we aren't distinguishing it from alpha by request.
456 return kCoverageAsAlpha_BlendOptFlag;
457 } else {
458 // check whether coverage can be safely rolled into alpha
459 // of if we can skip color computation and just emit coverage
460 if (this->canTweakAlphaForCoverage()) {
461 return kCoverageAsAlpha_BlendOptFlag;
462 }
463 if (dstCoeffIsZero) {
464 if (kZero_GrBlendCoeff == *srcCoeff) {
465 // the source color is not included in the blend
466 // the dst coeff is effectively zero so blend works out to:
467 // (c)(0)D + (1-c)D = (1-c)D.
468 *dstCoeff = kISA_GrBlendCoeff;
469 return kEmitCoverage_BlendOptFlag;
470 } else if (srcAIsOne) {
471 // the dst coeff is effectively zero so blend works out to:
472 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
473 // If Sa is 1 then we can replace Sa with c
474 // and set dst coeff to 1-Sa.
475 *dstCoeff = kISA_GrBlendCoeff;
476 return kCoverageAsAlpha_BlendOptFlag;
477 }
478 } else if (dstCoeffIsOne) {
479 // the dst coeff is effectively one so blend works out to:
480 // cS + (c)(1)D + (1-c)D = cS + D.
481 *dstCoeff = kOne_GrBlendCoeff;
482 return kCoverageAsAlpha_BlendOptFlag;
483 }
484 }
485 return kNone_BlendOpt;
486}
487
488////////////////////////////////////////////////////////////////////////////////
489
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000490void GrDrawState::AutoViewMatrixRestore::restore() {
491 if (NULL != fDrawState) {
492 fDrawState->setViewMatrix(fViewMatrix);
493 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
494 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000495 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000496 }
497 }
498 }
499 fDrawState = NULL;
500}
501
502void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000503 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000504 uint32_t explicitCoordStageMask) {
505 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000506
507 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000508 if (NULL == drawState) {
509 return;
510 }
511
512 fRestoreMask = 0;
513 fViewMatrix = drawState->getViewMatrix();
514 drawState->preConcatViewMatrix(preconcatMatrix);
515 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
516 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
517 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000518 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
519 drawState->fStages[s].preConcatCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000520 }
521 }
522}
523
524////////////////////////////////////////////////////////////////////////////////
525
526void GrDrawState::AutoDeviceCoordDraw::restore() {
527 if (NULL != fDrawState) {
528 fDrawState->setViewMatrix(fViewMatrix);
529 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
530 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000531 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000532 }
533 }
534 }
535 fDrawState = NULL;
536}
537
538bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState,
539 uint32_t explicitCoordStageMask) {
540 GrAssert(NULL != drawState);
541
542 this->restore();
543
544 fDrawState = drawState;
545 if (NULL == fDrawState) {
546 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000547 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000548
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000549 fViewMatrix = drawState->getViewMatrix();
550 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000551 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000552 bool inverted = false;
553
554 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
555 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
556 if (!inverted && !fViewMatrix.invert(&invVM)) {
557 // sad trombone sound
558 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000559 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000560 } else {
561 inverted = true;
562 }
563 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000564 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000565 stage->saveCoordChange(&fSavedCoordChanges[s]);
566 stage->preConcatCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000567 }
568 }
569 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000570 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000571}