blob: 79829357ba4d651a9c6179ca4069a2bc712fcc41 [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.com9b855c72013-03-01 18:21:22 +000049const size_t GrDrawState::kVertexAttribSizes[kGrVertexAttribTypeCount] = {
50 sizeof(float), // kFloat_GrVertexAttribType
51 2*sizeof(float), // kVec2_GrVertexAttribType
52 3*sizeof(float), // kVec3_GrVertexAttribType
skia.committer@gmail.comf140f182013-03-02 07:01:56 +000053 4*sizeof(float), // kVec4_GrVertexAttribType
jvanverth@google.com9b855c72013-03-01 18:21:22 +000054 4*sizeof(char) // kCVec4_GrVertexAttribType
55};
bsalomon@google.com85983282013-02-07 22:00:29 +000056
jvanverth@google.com9b855c72013-03-01 18:21:22 +000057static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
58 // this works as long as we're 4 byte-aligned
59#if GR_DEBUG
60 uint32_t overlapCheck = 0;
61#endif
62 GrAssert(count <= GrDrawState::kAttribIndexCount);
63 size_t size = 0;
64 for (int index = 0; index < count; ++index) {
65 size_t attribSize = GrDrawState::kVertexAttribSizes[attribs[index].fType];
66 size += attribSize;
67#if GR_DEBUG
68 size_t dwordCount = attribSize >> 2;
69 uint32_t mask = (1 << dwordCount)-1;
70 size_t offsetShift = attribs[index].fOffset >> 2;
71 GrAssert(!(overlapCheck & (mask << offsetShift)));
72 overlapCheck |= (mask << offsetShift);
73#endif
jvanverth@google.comcc782382013-01-28 20:39:48 +000074 }
75 return size;
76}
77
jvanverth@google.com9b855c72013-03-01 18:21:22 +000078size_t GrDrawState::getVertexSize() const {
79 return vertex_size(fVertexAttribs.begin(), fVertexAttribs.count());
80}
81
82const GrAttribBindings GrDrawState::kAttribIndexMasks[kAttribIndexCount] = {
83 0, // position is not reflected in the bindings
84 kColor_AttribBindingsBit,
85 kCoverage_AttribBindingsBit,
86 kEdge_AttribBindingsBit,
bsalomon@google.comc7818882013-03-20 19:19:53 +000087 kLocalCoords_AttribBindingsBit,
jvanverth@google.com9b855c72013-03-01 18:21:22 +000088};
89
jvanverth@google.comcc782382013-01-28 20:39:48 +000090////////////////////////////////////////////////////////////////////////////////
91
jvanverth@google.com9b855c72013-03-01 18:21:22 +000092void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
93 GrAssert(count <= GrDrawState::kAttribIndexCount);
94 fVertexAttribs.reset();
95 for (int index = 0; index < count; ++index) {
96 fVertexAttribs.push_back(attribs[index]);
jvanverth@google.comcc782382013-01-28 20:39:48 +000097 }
jvanverth@google.comcc782382013-01-28 20:39:48 +000098}
99
100////////////////////////////////////////////////////////////////////////////////
101
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000102void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000103 static const GrVertexAttrib kPositionAttrib = {kVec2f_GrVertexAttribType, 0};
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000104 fVertexAttribs.reset();
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000105 fVertexAttribs.push_back(kPositionAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000106
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000107 fCommon.fAttribBindings = kDefault_AttribBindings;
108
109 fAttribIndices[kPosition_AttribIndex] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000110}
111
112////////////////////////////////////////////////////////////////////////////////
113
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000114bool GrDrawState::validateVertexAttribs() const {
115 // color and coverage can set indices beyond the standard count
116 static const int kMaxValidAttribIndex = kVertexAttribCnt+2;
117 int attributeTypes[kMaxValidAttribIndex];
118 for (int i = 0; i < kMaxValidAttribIndex; ++i) {
119 attributeTypes[i] = -1;
120 }
121
122 // sentinel to make sure effects don't try to use built-in attributes
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000123 static const int kBuiltInAttributeType = 10000;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000124
125 // check our built-in indices
126 if (fAttribIndices[kPosition_AttribIndex] >= kVertexAttribCnt) {
127 return false;
128 }
129 attributeTypes[fAttribIndices[kPosition_AttribIndex]] = kBuiltInAttributeType;
130 for (int j = kColor_AttribIndex; j <= kCoverage_AttribIndex; ++j) {
131 if (fCommon.fAttribBindings & kAttribIndexMasks[j]) {
132 int attributeIndex = fAttribIndices[j];
133 if (attributeIndex >= kMaxValidAttribIndex) {
134 return false;
135 }
136 // they should not be shared at all
137 if (attributeTypes[attributeIndex] != -1) {
138 return false;
139 }
140 attributeTypes[attributeIndex] = kBuiltInAttributeType;
141 }
142 }
143 for (int j = kEdge_AttribIndex; j < kAttribIndexCount; ++j) {
144 if (fCommon.fAttribBindings & kAttribIndexMasks[j]) {
145 int attributeIndex = fAttribIndices[j];
146 if (attributeIndex >= kVertexAttribCnt) {
147 return false;
148 }
149 // they should not be shared at all
150 if (attributeTypes[attributeIndex] != -1) {
151 return false;
152 }
153 attributeTypes[attributeIndex] = kBuiltInAttributeType;
154 }
155 }
156
157 // now those set by effects
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000158 for (int s = 0; s < kNumStages; ++s) {
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000159 const GrEffectStage& stage = fStages[s];
160 const GrEffectRef* effect = stage.getEffect();
161 if (effect == NULL) {
162 continue;
163 }
164
165 // make sure that the count in the stage and the effect matches
166 int numAttributes = stage.getVertexAttribIndexCount();
167 if (numAttributes != effect->get()->numVertexAttribs()) {
168 return false;
169 }
170
171 // make sure that any shared indices have the same type
172 const int* attributeIndices = stage.getVertexAttribIndices();
173 for (int i = 0; i < numAttributes; ++i) {
174 int attributeIndex = attributeIndices[i];
175 if (attributeIndex >= kVertexAttribCnt) {
176 return false;
177 }
178
179 GrSLType attributeType = effect->get()->vertexAttribType(i);
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000180 if (attributeTypes[attributeIndex] != -1 &&
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000181 attributeTypes[attributeIndex] != attributeType) {
182 return false;
183 }
184 attributeTypes[attributeIndex] = attributeType;
185 }
186 }
187
188 return true;
189}
190
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000191
192void GrDrawState::VertexAttributesUnitTest() {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000193 // not necessarily exhaustive
194 static bool run;
195 if (!run) {
196 run = true;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000197
198 GrVertexAttribArray<6> attribs;
199 GrAssert(0 == vertex_size(attribs.begin(), attribs.count()));
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000200
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000201 GrVertexAttrib currAttrib = {kFloat_GrVertexAttribType, 0};
202 attribs.push_back(currAttrib);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000203 GrAssert(sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
204 attribs[0].fType = kVec2f_GrVertexAttribType;
205 GrAssert(2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
206 attribs[0].fType = kVec3f_GrVertexAttribType;
207 GrAssert(3*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
208 attribs[0].fType = kVec4f_GrVertexAttribType;
209 GrAssert(4*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
210 attribs[0].fType = kVec4ub_GrVertexAttribType;
211 GrAssert(4*sizeof(char) == vertex_size(attribs.begin(), attribs.count()));
212
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000213 currAttrib.set(kVec2f_GrVertexAttribType, attribs[0].fOffset + 4*sizeof(char));
214 attribs.push_back(currAttrib);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000215 GrAssert(4*sizeof(char) + 2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000216 currAttrib.set(kVec3f_GrVertexAttribType, attribs[1].fOffset + 2*sizeof(float));
217 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000218 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000219 vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000220 currAttrib.set(kFloat_GrVertexAttribType, attribs[2].fOffset + 3*sizeof(float));
221 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000222 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000223 vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000224 currAttrib.set(kVec4f_GrVertexAttribType, attribs[3].fOffset + sizeof(float));
225 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000226 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) + 4*sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000227 vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000228 }
229}
230
231////////////////////////////////////////////////////////////////////////////////
232
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000233bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000234
235 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000236 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000237 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000238 if (bindings & kColor_AttribBindingsBit) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000239 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000240 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000241 } else {
242 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
243 color = this->getColor();
244 }
245
246 // Run through the color stages
247 int stageCnt = getFirstCoverageStage();
248 for (int s = 0; s < stageCnt; ++s) {
249 const GrEffectRef* effect = this->getStage(s).getEffect();
250 if (NULL != effect) {
251 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
252 }
253 }
254
255 // Check if the color filter could introduce an alpha.
256 // We could skip the above work when this is true, but it is rare and the right fix is to make
257 // the color filter a GrEffect and implement getConstantColorComponents() for it.
258 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
259 validComponentFlags = 0;
260 }
261
262 // Check whether coverage is treated as color. If so we run through the coverage computation.
263 if (this->isCoverageDrawing()) {
264 GrColor coverageColor = this->getCoverage();
265 GrColor oldColor = color;
266 color = 0;
267 for (int c = 0; c < 4; ++c) {
268 if (validComponentFlags & (1 << c)) {
269 U8CPU a = (oldColor >> (c * 8)) & 0xff;
270 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
271 color |= (SkMulDiv255Round(a, b) << (c * 8));
272 }
273 }
274 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
275 const GrEffectRef* effect = this->getStage(s).getEffect();
276 if (NULL != effect) {
277 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
278 }
279 }
280 }
281 return (GrEffect::kA_ValidComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
282}
283
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000284bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000285 // If we're drawing coverage directly then coverage is effectively treated as color.
286 if (this->isCoverageDrawing()) {
287 return true;
288 }
289
290 GrColor coverage;
291 uint32_t validComponentFlags;
292 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000293 if (bindings & kCoverage_AttribBindingsBit) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000294 validComponentFlags = 0;
295 } else {
296 coverage = fCommon.fCoverage;
297 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
298 }
299
300 // Run through the coverage stages and see if the coverage will be all ones at the end.
301 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
302 const GrEffectRef* effect = this->getStage(s).getEffect();
303 if (NULL != effect) {
304 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
305 }
306 }
307 return (GrEffect::kAll_ValidComponentFlags == validComponentFlags) && (0xffffffff == coverage);
308}
309
jvanverth@google.comcc782382013-01-28 20:39:48 +0000310////////////////////////////////////////////////////////////////////////////////
311
bsalomon@google.com2b446732013-02-12 16:47:41 +0000312// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
313// others will blend incorrectly.
314bool GrDrawState::canTweakAlphaForCoverage() const {
315 /*
316 The fractional coverage is f.
317 The src and dst coeffs are Cs and Cd.
318 The dst and src colors are S and D.
319 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
320 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
321 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
322 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
323 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
324 color by definition.
325 */
326 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
327 kISA_GrBlendCoeff == fCommon.fDstBlend ||
328 kISC_GrBlendCoeff == fCommon.fDstBlend ||
329 this->isCoverageDrawing();
330}
331
332GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
333 GrBlendCoeff* srcCoeff,
334 GrBlendCoeff* dstCoeff) const {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000335 GrAttribBindings bindings = this->getAttribBindings();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000336
337 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
338 if (NULL == srcCoeff) {
339 srcCoeff = &bogusSrcCoeff;
340 }
341 *srcCoeff = this->getSrcBlendCoeff();
342
343 if (NULL == dstCoeff) {
344 dstCoeff = &bogusDstCoeff;
345 }
346 *dstCoeff = this->getDstBlendCoeff();
347
348 if (this->isColorWriteDisabled()) {
349 *srcCoeff = kZero_GrBlendCoeff;
350 *dstCoeff = kOne_GrBlendCoeff;
351 }
352
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000353 bool srcAIsOne = this->srcAlphaWillBeOne(bindings);
bsalomon@google.com2b446732013-02-12 16:47:41 +0000354 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
355 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
356 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
357 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
358
359 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000360 !(bindings & GrDrawState::kCoverage_AttribBindingsBit) &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000361 0 == this->getCoverage();
362 // When coeffs are (0,1) there is no reason to draw at all, unless
363 // stenciling is enabled. Having color writes disabled is effectively
364 // (0,1). The same applies when coverage is known to be 0.
365 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
366 if (this->getStencil().doesWrite()) {
367 return kDisableBlend_BlendOptFlag |
368 kEmitTransBlack_BlendOptFlag;
369 } else {
370 return kSkipDraw_BlendOptFlag;
371 }
372 }
373
374 // check for coverage due to constant coverage, per-vertex coverage,
375 // edge aa or coverage stage
376 bool hasCoverage = forceCoverage ||
377 0xffffffff != this->getCoverage() ||
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000378 (bindings & GrDrawState::kCoverage_AttribBindingsBit) ||
379 (bindings & GrDrawState::kEdge_AttribBindingsBit);
bsalomon@google.com2b446732013-02-12 16:47:41 +0000380 for (int s = this->getFirstCoverageStage();
381 !hasCoverage && s < GrDrawState::kNumStages;
382 ++s) {
383 if (this->isStageEnabled(s)) {
384 hasCoverage = true;
385 }
386 }
387
388 // if we don't have coverage we can check whether the dst
389 // has to read at all. If not, we'll disable blending.
390 if (!hasCoverage) {
391 if (dstCoeffIsZero) {
392 if (kOne_GrBlendCoeff == *srcCoeff) {
393 // if there is no coverage and coeffs are (1,0) then we
394 // won't need to read the dst at all, it gets replaced by src
395 return kDisableBlend_BlendOptFlag;
396 } else if (kZero_GrBlendCoeff == *srcCoeff) {
397 // if the op is "clear" then we don't need to emit a color
398 // or blend, just write transparent black into the dst.
399 *srcCoeff = kOne_GrBlendCoeff;
400 *dstCoeff = kZero_GrBlendCoeff;
401 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
402 }
403 }
404 } else if (this->isCoverageDrawing()) {
405 // we have coverage but we aren't distinguishing it from alpha by request.
406 return kCoverageAsAlpha_BlendOptFlag;
407 } else {
408 // check whether coverage can be safely rolled into alpha
409 // of if we can skip color computation and just emit coverage
410 if (this->canTweakAlphaForCoverage()) {
411 return kCoverageAsAlpha_BlendOptFlag;
412 }
413 if (dstCoeffIsZero) {
414 if (kZero_GrBlendCoeff == *srcCoeff) {
415 // the source color is not included in the blend
416 // the dst coeff is effectively zero so blend works out to:
417 // (c)(0)D + (1-c)D = (1-c)D.
418 *dstCoeff = kISA_GrBlendCoeff;
419 return kEmitCoverage_BlendOptFlag;
420 } else if (srcAIsOne) {
421 // the dst coeff is effectively zero so blend works out to:
422 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
423 // If Sa is 1 then we can replace Sa with c
424 // and set dst coeff to 1-Sa.
425 *dstCoeff = kISA_GrBlendCoeff;
426 return kCoverageAsAlpha_BlendOptFlag;
427 }
428 } else if (dstCoeffIsOne) {
429 // the dst coeff is effectively one so blend works out to:
430 // cS + (c)(1)D + (1-c)D = cS + D.
431 *dstCoeff = kOne_GrBlendCoeff;
432 return kCoverageAsAlpha_BlendOptFlag;
433 }
434 }
435 return kNone_BlendOpt;
436}
437
438////////////////////////////////////////////////////////////////////////////////
439
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000440void GrDrawState::AutoViewMatrixRestore::restore() {
441 if (NULL != fDrawState) {
442 fDrawState->setViewMatrix(fViewMatrix);
443 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
444 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000445 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000446 }
447 }
448 }
449 fDrawState = NULL;
450}
451
452void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000453 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000454 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000455
456 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000457 if (NULL == drawState) {
458 return;
459 }
460
461 fRestoreMask = 0;
462 fViewMatrix = drawState->getViewMatrix();
463 drawState->preConcatViewMatrix(preconcatMatrix);
464 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000465 if (drawState->isStageEnabled(s)) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000466 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000467 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000468 drawState->fStages[s].localCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000469 }
470 }
471}
472
473////////////////////////////////////////////////////////////////////////////////
474
475void GrDrawState::AutoDeviceCoordDraw::restore() {
476 if (NULL != fDrawState) {
477 fDrawState->setViewMatrix(fViewMatrix);
478 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
479 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000480 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000481 }
482 }
483 }
484 fDrawState = NULL;
485}
486
bsalomon@google.comc7818882013-03-20 19:19:53 +0000487bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000488 GrAssert(NULL != drawState);
489
490 this->restore();
491
492 fDrawState = drawState;
493 if (NULL == fDrawState) {
494 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000495 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000496
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000497 fViewMatrix = drawState->getViewMatrix();
498 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000499 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000500 bool inverted = false;
501
502 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000503 if (drawState->isStageEnabled(s)) {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000504 if (!inverted && !fViewMatrix.invert(&invVM)) {
505 // sad trombone sound
506 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000507 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000508 } else {
509 inverted = true;
510 }
511 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000512 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000513 stage->saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000514 stage->localCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000515 }
516 }
517 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000518 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000519}