blob: e10899958bb4328239a41f89e02b9b143c636b00 [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
bsalomon@google.com4647f902013-03-26 14:45:27 +000062 GrAssert(count <= GrDrawState::kVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000063 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,
bsalomon@google.comc7818882013-03-20 19:19:53 +000086 kLocalCoords_AttribBindingsBit,
jvanverth@google.com9b855c72013-03-01 18:21:22 +000087};
88
jvanverth@google.comcc782382013-01-28 20:39:48 +000089////////////////////////////////////////////////////////////////////////////////
90
jvanverth@google.com9b855c72013-03-01 18:21:22 +000091void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
bsalomon@google.com4647f902013-03-26 14:45:27 +000092 GrAssert(count <= GrDrawState::kVertexAttribCnt);
jvanverth@google.com9b855c72013-03-01 18:21:22 +000093 fVertexAttribs.reset();
94 for (int index = 0; index < count; ++index) {
95 fVertexAttribs.push_back(attribs[index]);
jvanverth@google.comcc782382013-01-28 20:39:48 +000096 }
jvanverth@google.comcc782382013-01-28 20:39:48 +000097}
98
99////////////////////////////////////////////////////////////////////////////////
100
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000101void GrDrawState::setDefaultVertexAttribs() {
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000102 static const GrVertexAttrib kPositionAttrib = {kVec2f_GrVertexAttribType, 0};
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000103 fVertexAttribs.reset();
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000104 fVertexAttribs.push_back(kPositionAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000105
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000106 fCommon.fAttribBindings = kDefault_AttribBindings;
107
108 fAttribIndices[kPosition_AttribIndex] = 0;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000109}
110
111////////////////////////////////////////////////////////////////////////////////
112
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000113bool GrDrawState::validateVertexAttribs() const {
114 // color and coverage can set indices beyond the standard count
115 static const int kMaxValidAttribIndex = kVertexAttribCnt+2;
116 int attributeTypes[kMaxValidAttribIndex];
117 for (int i = 0; i < kMaxValidAttribIndex; ++i) {
118 attributeTypes[i] = -1;
119 }
120
121 // sentinel to make sure effects don't try to use built-in attributes
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000122 static const int kBuiltInAttributeType = 10000;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000123
124 // check our built-in indices
125 if (fAttribIndices[kPosition_AttribIndex] >= kVertexAttribCnt) {
126 return false;
127 }
128 attributeTypes[fAttribIndices[kPosition_AttribIndex]] = kBuiltInAttributeType;
129 for (int j = kColor_AttribIndex; j <= kCoverage_AttribIndex; ++j) {
130 if (fCommon.fAttribBindings & kAttribIndexMasks[j]) {
131 int attributeIndex = fAttribIndices[j];
132 if (attributeIndex >= kMaxValidAttribIndex) {
133 return false;
134 }
135 // they should not be shared at all
136 if (attributeTypes[attributeIndex] != -1) {
137 return false;
138 }
139 attributeTypes[attributeIndex] = kBuiltInAttributeType;
140 }
141 }
bsalomon@google.com4647f902013-03-26 14:45:27 +0000142 if (fCommon.fAttribBindings & kAttribIndexMasks[kLocalCoords_AttribIndex]) {
143 int attributeIndex = fAttribIndices[kLocalCoords_AttribIndex];
144 if (attributeIndex >= kVertexAttribCnt) {
145 return false;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000146 }
bsalomon@google.com4647f902013-03-26 14:45:27 +0000147 // they should not be shared at all
148 if (attributeTypes[attributeIndex] != -1) {
149 return false;
150 }
151 attributeTypes[attributeIndex] = kBuiltInAttributeType;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000152 }
153
154 // now those set by effects
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000155 for (int s = 0; s < kNumStages; ++s) {
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000156 const GrEffectStage& stage = fStages[s];
157 const GrEffectRef* effect = stage.getEffect();
158 if (effect == NULL) {
159 continue;
160 }
161
162 // make sure that the count in the stage and the effect matches
163 int numAttributes = stage.getVertexAttribIndexCount();
164 if (numAttributes != effect->get()->numVertexAttribs()) {
165 return false;
166 }
167
168 // make sure that any shared indices have the same type
169 const int* attributeIndices = stage.getVertexAttribIndices();
170 for (int i = 0; i < numAttributes; ++i) {
171 int attributeIndex = attributeIndices[i];
172 if (attributeIndex >= kVertexAttribCnt) {
173 return false;
174 }
175
176 GrSLType attributeType = effect->get()->vertexAttribType(i);
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000177 if (attributeTypes[attributeIndex] != -1 &&
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000178 attributeTypes[attributeIndex] != attributeType) {
179 return false;
180 }
181 attributeTypes[attributeIndex] = attributeType;
182 }
183 }
184
185 return true;
186}
187
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000188
189void GrDrawState::VertexAttributesUnitTest() {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000190 // not necessarily exhaustive
191 static bool run;
192 if (!run) {
193 run = true;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000194
195 GrVertexAttribArray<6> attribs;
196 GrAssert(0 == vertex_size(attribs.begin(), attribs.count()));
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000197
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000198 GrVertexAttrib currAttrib = {kFloat_GrVertexAttribType, 0};
199 attribs.push_back(currAttrib);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000200 GrAssert(sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
201 attribs[0].fType = kVec2f_GrVertexAttribType;
202 GrAssert(2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
203 attribs[0].fType = kVec3f_GrVertexAttribType;
204 GrAssert(3*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
205 attribs[0].fType = kVec4f_GrVertexAttribType;
206 GrAssert(4*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
207 attribs[0].fType = kVec4ub_GrVertexAttribType;
208 GrAssert(4*sizeof(char) == vertex_size(attribs.begin(), attribs.count()));
209
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000210 currAttrib.set(kVec2f_GrVertexAttribType, attribs[0].fOffset + 4*sizeof(char));
211 attribs.push_back(currAttrib);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000212 GrAssert(4*sizeof(char) + 2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000213 currAttrib.set(kVec3f_GrVertexAttribType, attribs[1].fOffset + 2*sizeof(float));
214 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000215 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000216 vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000217 currAttrib.set(kFloat_GrVertexAttribType, attribs[2].fOffset + 3*sizeof(float));
218 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000219 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000220 vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000221 currAttrib.set(kVec4f_GrVertexAttribType, attribs[3].fOffset + sizeof(float));
222 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000223 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) + 4*sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000224 vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000225 }
226}
227
228////////////////////////////////////////////////////////////////////////////////
229
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000230bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000231
232 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000233 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000234 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000235 if (bindings & kColor_AttribBindingsBit) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000236 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000237 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000238 } else {
239 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
240 color = this->getColor();
241 }
242
243 // Run through the color stages
244 int stageCnt = getFirstCoverageStage();
245 for (int s = 0; s < stageCnt; ++s) {
246 const GrEffectRef* effect = this->getStage(s).getEffect();
247 if (NULL != effect) {
248 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
249 }
250 }
251
252 // Check if the color filter could introduce an alpha.
253 // We could skip the above work when this is true, but it is rare and the right fix is to make
254 // the color filter a GrEffect and implement getConstantColorComponents() for it.
255 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
256 validComponentFlags = 0;
257 }
258
259 // Check whether coverage is treated as color. If so we run through the coverage computation.
260 if (this->isCoverageDrawing()) {
261 GrColor coverageColor = this->getCoverage();
262 GrColor oldColor = color;
263 color = 0;
264 for (int c = 0; c < 4; ++c) {
265 if (validComponentFlags & (1 << c)) {
266 U8CPU a = (oldColor >> (c * 8)) & 0xff;
267 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
268 color |= (SkMulDiv255Round(a, b) << (c * 8));
269 }
270 }
271 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
272 const GrEffectRef* effect = this->getStage(s).getEffect();
273 if (NULL != effect) {
274 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
275 }
276 }
277 }
278 return (GrEffect::kA_ValidComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
279}
280
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000281bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000282 // If we're drawing coverage directly then coverage is effectively treated as color.
283 if (this->isCoverageDrawing()) {
284 return true;
285 }
286
287 GrColor coverage;
288 uint32_t validComponentFlags;
289 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000290 if (bindings & kCoverage_AttribBindingsBit) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000291 validComponentFlags = 0;
292 } else {
293 coverage = fCommon.fCoverage;
294 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
295 }
296
297 // Run through the coverage stages and see if the coverage will be all ones at the end.
298 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
299 const GrEffectRef* effect = this->getStage(s).getEffect();
300 if (NULL != effect) {
301 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
302 }
303 }
304 return (GrEffect::kAll_ValidComponentFlags == validComponentFlags) && (0xffffffff == coverage);
305}
306
jvanverth@google.comcc782382013-01-28 20:39:48 +0000307////////////////////////////////////////////////////////////////////////////////
308
bsalomon@google.com2b446732013-02-12 16:47:41 +0000309// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
310// others will blend incorrectly.
311bool GrDrawState::canTweakAlphaForCoverage() const {
312 /*
313 The fractional coverage is f.
314 The src and dst coeffs are Cs and Cd.
315 The dst and src colors are S and D.
316 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
317 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
318 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
319 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
320 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
321 color by definition.
322 */
323 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
324 kISA_GrBlendCoeff == fCommon.fDstBlend ||
325 kISC_GrBlendCoeff == fCommon.fDstBlend ||
326 this->isCoverageDrawing();
327}
328
329GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
330 GrBlendCoeff* srcCoeff,
331 GrBlendCoeff* dstCoeff) const {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000332 GrAttribBindings bindings = this->getAttribBindings();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000333
334 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
335 if (NULL == srcCoeff) {
336 srcCoeff = &bogusSrcCoeff;
337 }
338 *srcCoeff = this->getSrcBlendCoeff();
339
340 if (NULL == dstCoeff) {
341 dstCoeff = &bogusDstCoeff;
342 }
343 *dstCoeff = this->getDstBlendCoeff();
344
345 if (this->isColorWriteDisabled()) {
346 *srcCoeff = kZero_GrBlendCoeff;
347 *dstCoeff = kOne_GrBlendCoeff;
348 }
349
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000350 bool srcAIsOne = this->srcAlphaWillBeOne(bindings);
bsalomon@google.com2b446732013-02-12 16:47:41 +0000351 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
352 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
353 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
354 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
355
356 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000357 !(bindings & GrDrawState::kCoverage_AttribBindingsBit) &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000358 0 == this->getCoverage();
359 // When coeffs are (0,1) there is no reason to draw at all, unless
360 // stenciling is enabled. Having color writes disabled is effectively
361 // (0,1). The same applies when coverage is known to be 0.
362 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
363 if (this->getStencil().doesWrite()) {
364 return kDisableBlend_BlendOptFlag |
365 kEmitTransBlack_BlendOptFlag;
366 } else {
367 return kSkipDraw_BlendOptFlag;
368 }
369 }
370
bsalomon@google.com4647f902013-03-26 14:45:27 +0000371 // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bsalomon@google.com2b446732013-02-12 16:47:41 +0000372 bool hasCoverage = forceCoverage ||
373 0xffffffff != this->getCoverage() ||
bsalomon@google.com4647f902013-03-26 14:45:27 +0000374 (bindings & GrDrawState::kCoverage_AttribBindingsBit);
bsalomon@google.com2b446732013-02-12 16:47:41 +0000375 for (int s = this->getFirstCoverageStage();
376 !hasCoverage && s < GrDrawState::kNumStages;
377 ++s) {
378 if (this->isStageEnabled(s)) {
379 hasCoverage = true;
380 }
381 }
382
383 // if we don't have coverage we can check whether the dst
384 // has to read at all. If not, we'll disable blending.
385 if (!hasCoverage) {
386 if (dstCoeffIsZero) {
387 if (kOne_GrBlendCoeff == *srcCoeff) {
388 // if there is no coverage and coeffs are (1,0) then we
389 // won't need to read the dst at all, it gets replaced by src
390 return kDisableBlend_BlendOptFlag;
391 } else if (kZero_GrBlendCoeff == *srcCoeff) {
392 // if the op is "clear" then we don't need to emit a color
393 // or blend, just write transparent black into the dst.
394 *srcCoeff = kOne_GrBlendCoeff;
395 *dstCoeff = kZero_GrBlendCoeff;
396 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
397 }
398 }
399 } else if (this->isCoverageDrawing()) {
400 // we have coverage but we aren't distinguishing it from alpha by request.
401 return kCoverageAsAlpha_BlendOptFlag;
402 } else {
403 // check whether coverage can be safely rolled into alpha
404 // of if we can skip color computation and just emit coverage
405 if (this->canTweakAlphaForCoverage()) {
406 return kCoverageAsAlpha_BlendOptFlag;
407 }
408 if (dstCoeffIsZero) {
409 if (kZero_GrBlendCoeff == *srcCoeff) {
410 // the source color is not included in the blend
411 // the dst coeff is effectively zero so blend works out to:
412 // (c)(0)D + (1-c)D = (1-c)D.
413 *dstCoeff = kISA_GrBlendCoeff;
414 return kEmitCoverage_BlendOptFlag;
415 } else if (srcAIsOne) {
416 // the dst coeff is effectively zero so blend works out to:
417 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
418 // If Sa is 1 then we can replace Sa with c
419 // and set dst coeff to 1-Sa.
420 *dstCoeff = kISA_GrBlendCoeff;
421 return kCoverageAsAlpha_BlendOptFlag;
422 }
423 } else if (dstCoeffIsOne) {
424 // the dst coeff is effectively one so blend works out to:
425 // cS + (c)(1)D + (1-c)D = cS + D.
426 *dstCoeff = kOne_GrBlendCoeff;
427 return kCoverageAsAlpha_BlendOptFlag;
428 }
429 }
430 return kNone_BlendOpt;
431}
432
433////////////////////////////////////////////////////////////////////////////////
434
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000435void GrDrawState::AutoViewMatrixRestore::restore() {
436 if (NULL != fDrawState) {
437 fDrawState->setViewMatrix(fViewMatrix);
438 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
439 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000440 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000441 }
442 }
443 }
444 fDrawState = NULL;
445}
446
447void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000448 const SkMatrix& preconcatMatrix) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000449 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000450
451 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000452 if (NULL == drawState) {
453 return;
454 }
455
456 fRestoreMask = 0;
457 fViewMatrix = drawState->getViewMatrix();
458 drawState->preConcatViewMatrix(preconcatMatrix);
459 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000460 if (drawState->isStageEnabled(s)) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000461 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000462 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000463 drawState->fStages[s].localCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000464 }
465 }
466}
467
468////////////////////////////////////////////////////////////////////////////////
469
470void GrDrawState::AutoDeviceCoordDraw::restore() {
471 if (NULL != fDrawState) {
472 fDrawState->setViewMatrix(fViewMatrix);
473 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
474 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000475 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000476 }
477 }
478 }
479 fDrawState = NULL;
480}
481
bsalomon@google.comc7818882013-03-20 19:19:53 +0000482bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000483 GrAssert(NULL != drawState);
484
485 this->restore();
486
487 fDrawState = drawState;
488 if (NULL == fDrawState) {
489 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000490 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000491
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000492 fViewMatrix = drawState->getViewMatrix();
493 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000494 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000495 bool inverted = false;
496
497 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000498 if (drawState->isStageEnabled(s)) {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000499 if (!inverted && !fViewMatrix.invert(&invVM)) {
500 // sad trombone sound
501 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000502 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000503 } else {
504 inverted = true;
505 }
506 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000507 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000508 stage->saveCoordChange(&fSavedCoordChanges[s]);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000509 stage->localCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000510 }
511 }
512 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000513 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000514}