blob: e7975461184cbf1d9cb533264f03ffd099dc9b82 [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
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000136bool GrDrawState::AttributesBindExplicitTexCoords(GrAttribBindings attribBindings) {
137 return SkToBool(kTexCoord_AttribBindingsMask & attribBindings);
138}
139
140////////////////////////////////////////////////////////////////////////////////
141
142void GrDrawState::VertexAttributesUnitTest() {
jvanverth@google.com39768252013-02-14 15:25:44 +0000143 // Ensure that our tex coord mask is correct
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000144 GrAttribBindings texCoordMask;
jvanverth@google.com39768252013-02-14 15:25:44 +0000145 gen_tex_coord_mask(&texCoordMask);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000146 GrAssert(texCoordMask == kTexCoord_AttribBindingsMask);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000147
148 // not necessarily exhaustive
149 static bool run;
150 if (!run) {
151 run = true;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000152
153 GrVertexAttribArray<6> attribs;
154 GrAssert(0 == vertex_size(attribs.begin(), attribs.count()));
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000155
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000156 GrVertexAttrib currAttrib = {kFloat_GrVertexAttribType, 0};
157 attribs.push_back(currAttrib);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000158 GrAssert(sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
159 attribs[0].fType = kVec2f_GrVertexAttribType;
160 GrAssert(2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
161 attribs[0].fType = kVec3f_GrVertexAttribType;
162 GrAssert(3*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
163 attribs[0].fType = kVec4f_GrVertexAttribType;
164 GrAssert(4*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
165 attribs[0].fType = kVec4ub_GrVertexAttribType;
166 GrAssert(4*sizeof(char) == vertex_size(attribs.begin(), attribs.count()));
167
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000168 currAttrib.set(kVec2f_GrVertexAttribType, attribs[0].fOffset + 4*sizeof(char));
169 attribs.push_back(currAttrib);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000170 GrAssert(4*sizeof(char) + 2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000171 currAttrib.set(kVec3f_GrVertexAttribType, attribs[1].fOffset + 2*sizeof(float));
172 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000173 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000174 vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000175 currAttrib.set(kFloat_GrVertexAttribType, attribs[2].fOffset + 3*sizeof(float));
176 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000177 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000178 vertex_size(attribs.begin(), attribs.count()));
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000179 currAttrib.set(kVec4f_GrVertexAttribType, attribs[3].fOffset + sizeof(float));
180 attribs.push_back(currAttrib);
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000181 GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) + 4*sizeof(float) ==
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000182 vertex_size(attribs.begin(), attribs.count()));
183
184 GrAttribBindings tcMask = 0;
185 GrAssert(!AttributesBindExplicitTexCoords(0));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000186 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000187 tcMask |= ExplicitTexCoordAttribBindingsBit(s);
188 GrAssert(AttributesBindExplicitTexCoords(tcMask));
189 GrAssert(StageBindsExplicitTexCoords(tcMask, s));
jvanverth@google.com39768252013-02-14 15:25:44 +0000190 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000191 GrAssert(!StageBindsExplicitTexCoords(tcMask, s2));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000192 }
jvanverth@google.comcc782382013-01-28 20:39:48 +0000193 }
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000194 GrAssert(kTexCoord_AttribBindingsMask == tcMask);
jvanverth@google.comcc782382013-01-28 20:39:48 +0000195 }
196}
197
198////////////////////////////////////////////////////////////////////////////////
199
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000200bool GrDrawState::StageBindsExplicitTexCoords(GrAttribBindings bindings, int stageIdx) {
201 return SkToBool(bindings & ExplicitTexCoordAttribBindingsBit(stageIdx));
jvanverth@google.comcc782382013-01-28 20:39:48 +0000202}
203
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000204bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000205
206 uint32_t validComponentFlags;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000207 GrColor color;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000208 // Check if per-vertex or constant color may have partial alpha
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000209 if (bindings & kColor_AttribBindingsBit) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000210 validComponentFlags = 0;
bsalomon@google.com89e6f5b2013-02-27 18:43:47 +0000211 color = 0; // not strictly necessary but we get false alarms from tools about uninit.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000212 } else {
213 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
214 color = this->getColor();
215 }
216
217 // Run through the color stages
218 int stageCnt = getFirstCoverageStage();
219 for (int s = 0; s < stageCnt; ++s) {
220 const GrEffectRef* effect = this->getStage(s).getEffect();
221 if (NULL != effect) {
222 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
223 }
224 }
225
226 // Check if the color filter could introduce an alpha.
227 // We could skip the above work when this is true, but it is rare and the right fix is to make
228 // the color filter a GrEffect and implement getConstantColorComponents() for it.
229 if (SkXfermode::kDst_Mode != this->getColorFilterMode()) {
230 validComponentFlags = 0;
231 }
232
233 // Check whether coverage is treated as color. If so we run through the coverage computation.
234 if (this->isCoverageDrawing()) {
235 GrColor coverageColor = this->getCoverage();
236 GrColor oldColor = color;
237 color = 0;
238 for (int c = 0; c < 4; ++c) {
239 if (validComponentFlags & (1 << c)) {
240 U8CPU a = (oldColor >> (c * 8)) & 0xff;
241 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
242 color |= (SkMulDiv255Round(a, b) << (c * 8));
243 }
244 }
245 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
246 const GrEffectRef* effect = this->getStage(s).getEffect();
247 if (NULL != effect) {
248 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
249 }
250 }
251 }
252 return (GrEffect::kA_ValidComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
253}
254
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000255bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000256 // If we're drawing coverage directly then coverage is effectively treated as color.
257 if (this->isCoverageDrawing()) {
258 return true;
259 }
260
261 GrColor coverage;
262 uint32_t validComponentFlags;
263 // Initialize to an unknown starting coverage if per-vertex coverage is specified.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000264 if (bindings & kCoverage_AttribBindingsBit) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000265 validComponentFlags = 0;
266 } else {
267 coverage = fCommon.fCoverage;
268 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
269 }
270
271 // Run through the coverage stages and see if the coverage will be all ones at the end.
272 for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
273 const GrEffectRef* effect = this->getStage(s).getEffect();
274 if (NULL != effect) {
275 (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
276 }
277 }
278 return (GrEffect::kAll_ValidComponentFlags == validComponentFlags) && (0xffffffff == coverage);
279}
280
jvanverth@google.comcc782382013-01-28 20:39:48 +0000281////////////////////////////////////////////////////////////////////////////////
282
bsalomon@google.com2b446732013-02-12 16:47:41 +0000283// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
284// others will blend incorrectly.
285bool GrDrawState::canTweakAlphaForCoverage() const {
286 /*
287 The fractional coverage is f.
288 The src and dst coeffs are Cs and Cd.
289 The dst and src colors are S and D.
290 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
291 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
292 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
293 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
294 Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
295 color by definition.
296 */
297 return kOne_GrBlendCoeff == fCommon.fDstBlend ||
298 kISA_GrBlendCoeff == fCommon.fDstBlend ||
299 kISC_GrBlendCoeff == fCommon.fDstBlend ||
300 this->isCoverageDrawing();
301}
302
303GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
304 GrBlendCoeff* srcCoeff,
305 GrBlendCoeff* dstCoeff) const {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000306 GrAttribBindings bindings = this->getAttribBindings();
bsalomon@google.com2b446732013-02-12 16:47:41 +0000307
308 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
309 if (NULL == srcCoeff) {
310 srcCoeff = &bogusSrcCoeff;
311 }
312 *srcCoeff = this->getSrcBlendCoeff();
313
314 if (NULL == dstCoeff) {
315 dstCoeff = &bogusDstCoeff;
316 }
317 *dstCoeff = this->getDstBlendCoeff();
318
319 if (this->isColorWriteDisabled()) {
320 *srcCoeff = kZero_GrBlendCoeff;
321 *dstCoeff = kOne_GrBlendCoeff;
322 }
323
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000324 bool srcAIsOne = this->srcAlphaWillBeOne(bindings);
bsalomon@google.com2b446732013-02-12 16:47:41 +0000325 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
326 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
327 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
328 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
329
330 bool covIsZero = !this->isCoverageDrawing() &&
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000331 !(bindings & GrDrawState::kCoverage_AttribBindingsBit) &&
bsalomon@google.com2b446732013-02-12 16:47:41 +0000332 0 == this->getCoverage();
333 // When coeffs are (0,1) there is no reason to draw at all, unless
334 // stenciling is enabled. Having color writes disabled is effectively
335 // (0,1). The same applies when coverage is known to be 0.
336 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
337 if (this->getStencil().doesWrite()) {
338 return kDisableBlend_BlendOptFlag |
339 kEmitTransBlack_BlendOptFlag;
340 } else {
341 return kSkipDraw_BlendOptFlag;
342 }
343 }
344
345 // check for coverage due to constant coverage, per-vertex coverage,
346 // edge aa or coverage stage
347 bool hasCoverage = forceCoverage ||
348 0xffffffff != this->getCoverage() ||
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000349 (bindings & GrDrawState::kCoverage_AttribBindingsBit) ||
350 (bindings & GrDrawState::kEdge_AttribBindingsBit);
bsalomon@google.com2b446732013-02-12 16:47:41 +0000351 for (int s = this->getFirstCoverageStage();
352 !hasCoverage && s < GrDrawState::kNumStages;
353 ++s) {
354 if (this->isStageEnabled(s)) {
355 hasCoverage = true;
356 }
357 }
358
359 // if we don't have coverage we can check whether the dst
360 // has to read at all. If not, we'll disable blending.
361 if (!hasCoverage) {
362 if (dstCoeffIsZero) {
363 if (kOne_GrBlendCoeff == *srcCoeff) {
364 // if there is no coverage and coeffs are (1,0) then we
365 // won't need to read the dst at all, it gets replaced by src
366 return kDisableBlend_BlendOptFlag;
367 } else if (kZero_GrBlendCoeff == *srcCoeff) {
368 // if the op is "clear" then we don't need to emit a color
369 // or blend, just write transparent black into the dst.
370 *srcCoeff = kOne_GrBlendCoeff;
371 *dstCoeff = kZero_GrBlendCoeff;
372 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
373 }
374 }
375 } else if (this->isCoverageDrawing()) {
376 // we have coverage but we aren't distinguishing it from alpha by request.
377 return kCoverageAsAlpha_BlendOptFlag;
378 } else {
379 // check whether coverage can be safely rolled into alpha
380 // of if we can skip color computation and just emit coverage
381 if (this->canTweakAlphaForCoverage()) {
382 return kCoverageAsAlpha_BlendOptFlag;
383 }
384 if (dstCoeffIsZero) {
385 if (kZero_GrBlendCoeff == *srcCoeff) {
386 // the source color is not included in the blend
387 // the dst coeff is effectively zero so blend works out to:
388 // (c)(0)D + (1-c)D = (1-c)D.
389 *dstCoeff = kISA_GrBlendCoeff;
390 return kEmitCoverage_BlendOptFlag;
391 } else if (srcAIsOne) {
392 // the dst coeff is effectively zero so blend works out to:
393 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
394 // If Sa is 1 then we can replace Sa with c
395 // and set dst coeff to 1-Sa.
396 *dstCoeff = kISA_GrBlendCoeff;
397 return kCoverageAsAlpha_BlendOptFlag;
398 }
399 } else if (dstCoeffIsOne) {
400 // the dst coeff is effectively one so blend works out to:
401 // cS + (c)(1)D + (1-c)D = cS + D.
402 *dstCoeff = kOne_GrBlendCoeff;
403 return kCoverageAsAlpha_BlendOptFlag;
404 }
405 }
406 return kNone_BlendOpt;
407}
408
409////////////////////////////////////////////////////////////////////////////////
410
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000411void GrDrawState::AutoViewMatrixRestore::restore() {
412 if (NULL != fDrawState) {
413 fDrawState->setViewMatrix(fViewMatrix);
414 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
415 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000416 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000417 }
418 }
419 }
420 fDrawState = NULL;
421}
422
423void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000424 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000425 uint32_t explicitCoordStageMask) {
426 this->restore();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000427
428 fDrawState = drawState;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000429 if (NULL == drawState) {
430 return;
431 }
432
433 fRestoreMask = 0;
434 fViewMatrix = drawState->getViewMatrix();
435 drawState->preConcatViewMatrix(preconcatMatrix);
436 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
437 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
438 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000439 fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
440 drawState->fStages[s].preConcatCoordChange(preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000441 }
442 }
443}
444
445////////////////////////////////////////////////////////////////////////////////
446
447void GrDrawState::AutoDeviceCoordDraw::restore() {
448 if (NULL != fDrawState) {
449 fDrawState->setViewMatrix(fViewMatrix);
450 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
451 if (fRestoreMask & (1 << s)) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000452 fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000453 }
454 }
455 }
456 fDrawState = NULL;
457}
458
459bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState,
460 uint32_t explicitCoordStageMask) {
461 GrAssert(NULL != drawState);
462
463 this->restore();
464
465 fDrawState = drawState;
466 if (NULL == fDrawState) {
467 return false;
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000468 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000469
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000470 fViewMatrix = drawState->getViewMatrix();
471 fRestoreMask = 0;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000472 SkMatrix invVM;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000473 bool inverted = false;
474
475 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
476 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
477 if (!inverted && !fViewMatrix.invert(&invVM)) {
478 // sad trombone sound
479 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000480 return false;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000481 } else {
482 inverted = true;
483 }
484 fRestoreMask |= (1 << s);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000485 GrEffectStage* stage = drawState->fStages + s;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000486 stage->saveCoordChange(&fSavedCoordChanges[s]);
487 stage->preConcatCoordChange(invVM);
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000488 }
489 }
490 drawState->viewMatrix()->reset();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000491 return true;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000492}