Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrDrawState.cpp
1 /*
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"
9 #include "GrPaint.h"
10 #include "GrDrawTargetCaps.h"
11
12 //////////////////////////////////////////////////////////////////////////////s
13
14 bool GrDrawState::State::HaveCompatibleState(const State& a, const State& b,
15                                              bool explicitLocalCoords) {
16     if (a.fColorStages.count() != b.fColorStages.count() ||
17         a.fCoverageStages.count() != b.fCoverageStages.count() ||
18         a.fSrcBlend != b.fSrcBlend ||
19         a.fDstBlend != b.fDstBlend) {
20         return false;
21     }
22     for (int i = 0; i < a.fColorStages.count(); i++) {
23         if (!GrEffectStage::AreCompatible(a.fColorStages[i], b.fColorStages[i],
24                                           explicitLocalCoords)) {
25             return false;
26         }
27     }
28     for (int i = 0; i < a.fCoverageStages.count(); i++) {
29         if (!GrEffectStage::AreCompatible(a.fCoverageStages[i], b.fCoverageStages[i],
30                                           explicitLocalCoords)) {
31             return false;
32         }
33     }
34     return true;
35 }
36 //////////////////////////////////////////////////////////////////////////////s
37 GrDrawState::CombinedState GrDrawState::CombineIfPossible(
38     const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
39
40     bool usingVertexColors = a.hasColorVertexAttribute();
41     if (!usingVertexColors && a.fColor != b.fColor) {
42         return kIncompatible_CombinedState;
43     }
44
45     if (a.fRenderTarget.get() != b.fRenderTarget.get() ||
46         !a.fViewMatrix.cheapEqualTo(b.fViewMatrix) ||
47         a.fBlendConstant != b.fBlendConstant ||
48         a.fFlagBits != b.fFlagBits ||
49         a.fVACount != b.fVACount ||
50         memcmp(a.fVAPtr, b.fVAPtr, a.fVACount * sizeof(GrVertexAttrib)) ||
51         a.fStencilSettings != b.fStencilSettings ||
52         a.fDrawFace != b.fDrawFace) {
53         return kIncompatible_CombinedState;
54     }
55
56     bool usingVertexCoverage = a.hasCoverageVertexAttribute();
57     if (!usingVertexCoverage && a.fCoverage != b.fCoverage) {
58         return kIncompatible_CombinedState;
59     }
60
61     bool explicitLocalCoords = a.hasLocalCoordAttribute();
62
63     SkASSERT(0 == memcmp(a.fFixedFunctionVertexAttribIndices,
64                             b.fFixedFunctionVertexAttribIndices,
65                             sizeof(a.fFixedFunctionVertexAttribIndices)));
66     if (!State::HaveCompatibleState(a.fState, b.fState, explicitLocalCoords)) {
67         return kIncompatible_CombinedState;
68     }
69
70     if (usingVertexColors) {
71         // If one is opaque and the other is not then the combined state is not opaque. Moreover,
72         // if the opaqueness affects the ability to get color/coverage blending correct then we
73         // don't combine the draw states.
74         bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
75         bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
76         if (aIsOpaque != bIsOpaque) {
77             const GrDrawState* opaque;
78             const GrDrawState* nonOpaque;
79             if (aIsOpaque) {
80                 opaque = &a;
81                 nonOpaque = &b;
82             } else {
83                 opaque = &b;
84                 nonOpaque = &a;
85             }
86             if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
87                 SkASSERT(!nonOpaque->hasSolidCoverage());
88                 if (!nonOpaque->couldApplyCoverage(caps)) {
89                     return kIncompatible_CombinedState;
90                 }
91             }
92             return aIsOpaque ? kB_CombinedState : kA_CombinedState;
93         }
94     }
95     return kAOrB_CombinedState;
96 }
97
98 //////////////////////////////////////////////////////////////////////////////s
99
100 GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
101     SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
102     *this = state;
103     if (!preConcatMatrix.isIdentity()) {
104         for (int i = 0; i < this->numColorStages(); ++i) {
105             fState.fColorStages[i].localCoordChange(preConcatMatrix);
106         }
107         for (int i = 0; i < this->numCoverageStages(); ++i) {
108             fState.fCoverageStages[i].localCoordChange(preConcatMatrix);
109         }
110         this->invalidateBlendOptFlags();
111     }
112 }
113
114 GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
115     SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
116     this->setRenderTarget(that.fRenderTarget.get());
117     fColor = that.fColor;
118     fViewMatrix = that.fViewMatrix;
119     fBlendConstant = that.fBlendConstant;
120     fFlagBits = that.fFlagBits;
121     fVACount = that.fVACount;
122     fVAPtr = that.fVAPtr;
123     fStencilSettings = that.fStencilSettings;
124     fCoverage = that.fCoverage;
125     fDrawFace = that.fDrawFace;
126     fOptSrcBlend = that.fOptSrcBlend;
127     fOptDstBlend = that.fOptDstBlend;
128     fBlendOptFlags = that.fBlendOptFlags;
129
130     fState = that.fState;
131     fHints = that.fHints;
132
133     memcpy(fFixedFunctionVertexAttribIndices,
134             that.fFixedFunctionVertexAttribIndices,
135             sizeof(fFixedFunctionVertexAttribIndices));
136     return *this;
137 }
138
139 void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
140     SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
141     fState.reset();
142
143     fRenderTarget.reset(NULL);
144
145     this->setDefaultVertexAttribs();
146
147     fColor = 0xffffffff;
148     if (NULL == initialViewMatrix) {
149         fViewMatrix.reset();
150     } else {
151         fViewMatrix = *initialViewMatrix;
152     }
153     fBlendConstant = 0x0;
154     fFlagBits = 0x0;
155     fStencilSettings.setDisabled();
156     fCoverage = 0xffffffff;
157     fDrawFace = kBoth_DrawFace;
158
159     fHints = 0;
160
161     this->invalidateBlendOptFlags();
162 }
163
164 bool GrDrawState::setIdentityViewMatrix()  {
165     if (this->numTotalStages()) {
166         SkMatrix invVM;
167         if (!fViewMatrix.invert(&invVM)) {
168             // sad trombone sound
169             return false;
170         }
171         for (int s = 0; s < this->numColorStages(); ++s) {
172             fState.fColorStages[s].localCoordChange(invVM);
173         }
174         for (int s = 0; s < this->numCoverageStages(); ++s) {
175             fState.fCoverageStages[s].localCoordChange(invVM);
176         }
177     }
178     fViewMatrix.reset();
179     return true;
180 }
181
182 void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
183     SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
184
185     fState.reset();
186
187     for (int i = 0; i < paint.numColorStages(); ++i) {
188         fState.fColorStages.push_back(paint.getColorStage(i));
189     }
190
191     for (int i = 0; i < paint.numCoverageStages(); ++i) {
192         fState.fCoverageStages.push_back(paint.getCoverageStage(i));
193     }
194
195     this->setRenderTarget(rt);
196
197     fViewMatrix = vm;
198
199     // These have no equivalent in GrPaint, set them to defaults
200     fBlendConstant = 0x0;
201     fDrawFace = kBoth_DrawFace;
202     fStencilSettings.setDisabled();
203     this->resetStateFlags();
204     fHints = 0;
205
206     // Enable the clip bit
207     this->enableState(GrDrawState::kClip_StateBit);
208
209     this->setColor(paint.getColor());
210     this->setState(GrDrawState::kDither_StateBit, paint.isDither());
211     this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
212
213     this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
214     this->setCoverage(paint.getCoverage());
215     this->invalidateBlendOptFlags();
216 }
217
218 ////////////////////////////////////////////////////////////////////////////////
219
220 static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
221     // this works as long as we're 4 byte-aligned
222 #ifdef SK_DEBUG
223     uint32_t overlapCheck = 0;
224 #endif
225     SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
226     size_t size = 0;
227     for (int index = 0; index < count; ++index) {
228         size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
229         size += attribSize;
230 #ifdef SK_DEBUG
231         size_t dwordCount = attribSize >> 2;
232         uint32_t mask = (1 << dwordCount)-1;
233         size_t offsetShift = attribs[index].fOffset >> 2;
234         SkASSERT(!(overlapCheck & (mask << offsetShift)));
235         overlapCheck |= (mask << offsetShift);
236 #endif
237     }
238     return size;
239 }
240
241 size_t GrDrawState::getVertexSize() const {
242     return vertex_size(fVAPtr, fVACount);
243 }
244
245 ////////////////////////////////////////////////////////////////////////////////
246
247 void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
248     SkASSERT(count <= kMaxVertexAttribCnt);
249
250     fVAPtr = attribs;
251     fVACount = count;
252
253     // Set all the indices to -1
254     memset(fFixedFunctionVertexAttribIndices,
255            0xff,
256            sizeof(fFixedFunctionVertexAttribIndices));
257 #ifdef SK_DEBUG
258     uint32_t overlapCheck = 0;
259 #endif
260     for (int i = 0; i < count; ++i) {
261         if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
262             // The fixed function attribs can only be specified once
263             SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
264             SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
265                      GrVertexAttribTypeVectorCount(attribs[i].fType));
266             fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
267         }
268 #ifdef SK_DEBUG
269         size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
270         uint32_t mask = (1 << dwordCount)-1;
271         size_t offsetShift = attribs[i].fOffset >> 2;
272         SkASSERT(!(overlapCheck & (mask << offsetShift)));
273         overlapCheck |= (mask << offsetShift);
274 #endif
275     }
276     this->invalidateBlendOptFlags();
277     // Positions must be specified.
278     SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
279 }
280
281 ////////////////////////////////////////////////////////////////////////////////
282
283 void GrDrawState::setDefaultVertexAttribs() {
284     static const GrVertexAttrib kPositionAttrib =
285         {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
286
287     fVAPtr = &kPositionAttrib;
288     fVACount = 1;
289
290     // set all the fixed function indices to -1 except position.
291     memset(fFixedFunctionVertexAttribIndices,
292            0xff,
293            sizeof(fFixedFunctionVertexAttribIndices));
294     fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
295     this->invalidateBlendOptFlags();
296 }
297
298 ////////////////////////////////////////////////////////////////////////////////
299
300 bool GrDrawState::validateVertexAttribs() const {
301     // check consistency of effects and attributes
302     GrSLType slTypes[kMaxVertexAttribCnt];
303     for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
304         slTypes[i] = static_cast<GrSLType>(-1);
305     }
306     int totalStages = this->numTotalStages();
307     for (int s = 0; s < totalStages; ++s) {
308         int covIdx = s - this->numColorStages();
309         const GrEffectStage& stage = covIdx < 0 ? this->getColorStage(s) :
310                                                   this->getCoverageStage(covIdx);
311         const GrEffect* effect = stage.getEffect();
312         SkASSERT(NULL != effect);
313         // make sure that any attribute indices have the correct binding type, that the attrib
314         // type and effect's shader lang type are compatible, and that attributes shared by
315         // multiple effects use the same shader lang type.
316         const int* attributeIndices = stage.getVertexAttribIndices();
317         int numAttributes = stage.getVertexAttribIndexCount();
318         for (int i = 0; i < numAttributes; ++i) {
319             int attribIndex = attributeIndices[i];
320             if (attribIndex >= fVACount ||
321                 kEffect_GrVertexAttribBinding != fVAPtr[attribIndex].fBinding) {
322                 return false;
323             }
324
325             GrSLType effectSLType = effect->vertexAttribType(i);
326             GrVertexAttribType attribType = fVAPtr[attribIndex].fType;
327             int slVecCount = GrSLTypeVectorCount(effectSLType);
328             int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
329             if (slVecCount != attribVecCount ||
330                 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
331                     slTypes[attribIndex] != effectSLType)) {
332                 return false;
333             }
334             slTypes[attribIndex] = effectSLType;
335         }
336     }
337
338     return true;
339 }
340
341 bool GrDrawState::willEffectReadDstColor() const {
342     if (!this->isColorWriteDisabled()) {
343         for (int s = 0; s < this->numColorStages(); ++s) {
344             if (this->getColorStage(s).getEffect()->willReadDstColor()) {
345                 return true;
346             }
347         }
348     }
349     for (int s = 0; s < this->numCoverageStages(); ++s) {
350         if (this->getCoverageStage(s).getEffect()->willReadDstColor()) {
351             return true;
352         }
353     }
354     return false;
355 }
356
357 ////////////////////////////////////////////////////////////////////////////////
358
359 bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
360     if (caps.dualSourceBlendingSupport()) {
361         return true;
362     }
363     // we can correctly apply coverage if a) we have dual source blending
364     // or b) one of our blend optimizations applies
365     // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
366     GrBlendCoeff srcCoeff;
367     GrBlendCoeff dstCoeff;
368     GrDrawState::BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
369     return GrDrawState::kNone_BlendOpt != flag ||
370            (this->willEffectReadDstColor() &&
371             kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
372 }
373
374 bool GrDrawState::srcAlphaWillBeOne() const {
375     uint32_t validComponentFlags;
376     GrColor color;
377     // Check if per-vertex or constant color may have partial alpha
378     if (this->hasColorVertexAttribute()) {
379         if (fHints & kVertexColorsAreOpaque_Hint) {
380             validComponentFlags = kA_GrColorComponentFlag;
381             color = 0xFF << GrColor_SHIFT_A;            
382         } else {
383             validComponentFlags = 0;
384             color = 0; // not strictly necessary but we get false alarms from tools about uninit.
385         }
386     } else {
387         validComponentFlags = kRGBA_GrColorComponentFlags;
388         color = this->getColor();
389     }
390
391     // Run through the color stages
392     for (int s = 0; s < this->numColorStages(); ++s) {
393         const GrEffect* effect = this->getColorStage(s).getEffect();
394         effect->getConstantColorComponents(&color, &validComponentFlags);
395     }
396
397     // Check whether coverage is treated as color. If so we run through the coverage computation.
398     if (this->isCoverageDrawing()) {
399         GrColor coverageColor = this->getCoverageColor();
400         GrColor oldColor = color;
401         color = 0;
402         for (int c = 0; c < 4; ++c) {
403             if (validComponentFlags & (1 << c)) {
404                 U8CPU a = (oldColor >> (c * 8)) & 0xff;
405                 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
406                 color |= (SkMulDiv255Round(a, b) << (c * 8));
407             }
408         }
409         for (int s = 0; s < this->numCoverageStages(); ++s) {
410             const GrEffect* effect = this->getCoverageStage(s).getEffect();
411             effect->getConstantColorComponents(&color, &validComponentFlags);
412         }
413     }
414     return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
415 }
416
417 bool GrDrawState::hasSolidCoverage() const {
418     // If we're drawing coverage directly then coverage is effectively treated as color.
419     if (this->isCoverageDrawing()) {
420         return true;
421     }
422
423     GrColor coverage;
424     uint32_t validComponentFlags;
425     // Initialize to an unknown starting coverage if per-vertex coverage is specified.
426     if (this->hasCoverageVertexAttribute()) {
427         validComponentFlags = 0;
428     } else {
429         coverage = fCoverage;
430         validComponentFlags = kRGBA_GrColorComponentFlags;
431     }
432
433     // Run through the coverage stages and see if the coverage will be all ones at the end.
434     for (int s = 0; s < this->numCoverageStages(); ++s) {
435         const GrEffect* effect = this->getCoverageStage(s).getEffect();
436         effect->getConstantColorComponents(&coverage, &validComponentFlags);
437     }
438     return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
439 }
440
441 ////////////////////////////////////////////////////////////////////////////////
442
443 // Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
444 // others will blend incorrectly.
445 bool GrDrawState::canTweakAlphaForCoverage() const {
446     /*
447      The fractional coverage is f.
448      The src and dst coeffs are Cs and Cd.
449      The dst and src colors are S and D.
450      We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
451      we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
452      term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
453      find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
454      Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
455      color by definition.
456      */
457     return kOne_GrBlendCoeff == fState.fDstBlend ||
458            kISA_GrBlendCoeff == fState.fDstBlend ||
459            kISC_GrBlendCoeff == fState.fDstBlend ||
460            this->isCoverageDrawing();
461 }
462
463 GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
464                                                      GrBlendCoeff* srcCoeff,
465                                                      GrBlendCoeff* dstCoeff) const {
466     GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
467     if (NULL == srcCoeff) {
468         srcCoeff = &bogusSrcCoeff;
469     }
470     if (NULL == dstCoeff) {
471         dstCoeff = &bogusDstCoeff;
472     }
473
474     if (forceCoverage) {
475         return this->calcBlendOpts(true, srcCoeff, dstCoeff);
476     }
477
478     if (0 == (fBlendOptFlags & kInvalid_BlendOptFlag)) {
479         *srcCoeff = fOptSrcBlend;
480         *dstCoeff = fOptDstBlend;
481         return fBlendOptFlags;
482     }
483
484     fBlendOptFlags = this->calcBlendOpts(forceCoverage, srcCoeff, dstCoeff);
485     fOptSrcBlend = *srcCoeff;
486     fOptDstBlend = *dstCoeff;
487
488     return fBlendOptFlags;
489 }
490
491 GrDrawState::BlendOptFlags GrDrawState::calcBlendOpts(bool forceCoverage,
492                                                       GrBlendCoeff* srcCoeff,
493                                                       GrBlendCoeff* dstCoeff) const {
494     *srcCoeff = this->getSrcBlendCoeff();
495     *dstCoeff = this->getDstBlendCoeff();
496
497     if (this->isColorWriteDisabled()) {
498         *srcCoeff = kZero_GrBlendCoeff;
499         *dstCoeff = kOne_GrBlendCoeff;
500     }
501
502     bool srcAIsOne = this->srcAlphaWillBeOne();
503     bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
504                          (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
505     bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
506                          (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
507
508     // When coeffs are (0,1) there is no reason to draw at all, unless
509     // stenciling is enabled. Having color writes disabled is effectively
510     // (0,1).
511     if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
512         if (this->getStencil().doesWrite()) {
513             return kEmitCoverage_BlendOptFlag;
514         } else {
515             return kSkipDraw_BlendOptFlag;
516         }
517     }
518
519     bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
520
521     // if we don't have coverage we can check whether the dst
522     // has to read at all. If not, we'll disable blending.
523     if (!hasCoverage) {
524         if (dstCoeffIsZero) {
525             if (kOne_GrBlendCoeff == *srcCoeff) {
526                 // if there is no coverage and coeffs are (1,0) then we
527                 // won't need to read the dst at all, it gets replaced by src
528                 *dstCoeff = kZero_GrBlendCoeff;
529                 return kNone_BlendOpt;
530             } else if (kZero_GrBlendCoeff == *srcCoeff) {
531                 // if the op is "clear" then we don't need to emit a color
532                 // or blend, just write transparent black into the dst.
533                 *srcCoeff = kOne_GrBlendCoeff;
534                 *dstCoeff = kZero_GrBlendCoeff;
535                 return kEmitTransBlack_BlendOptFlag;
536             }
537         }
538     } else if (this->isCoverageDrawing()) {
539         // we have coverage but we aren't distinguishing it from alpha by request.
540         return kCoverageAsAlpha_BlendOptFlag;
541     } else {
542         // check whether coverage can be safely rolled into alpha
543         // of if we can skip color computation and just emit coverage
544         if (this->canTweakAlphaForCoverage()) {
545             return kCoverageAsAlpha_BlendOptFlag;
546         }
547         if (dstCoeffIsZero) {
548             if (kZero_GrBlendCoeff == *srcCoeff) {
549                 // the source color is not included in the blend
550                 // the dst coeff is effectively zero so blend works out to:
551                 // (c)(0)D + (1-c)D = (1-c)D.
552                 *dstCoeff = kISA_GrBlendCoeff;
553                 return  kEmitCoverage_BlendOptFlag;
554             } else if (srcAIsOne) {
555                 // the dst coeff is effectively zero so blend works out to:
556                 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
557                 // If Sa is 1 then we can replace Sa with c
558                 // and set dst coeff to 1-Sa.
559                 *dstCoeff = kISA_GrBlendCoeff;
560                 return  kCoverageAsAlpha_BlendOptFlag;
561             }
562         } else if (dstCoeffIsOne) {
563             // the dst coeff is effectively one so blend works out to:
564             // cS + (c)(1)D + (1-c)D = cS + D.
565             *dstCoeff = kOne_GrBlendCoeff;
566             return  kCoverageAsAlpha_BlendOptFlag;
567         }
568     }
569
570     return kNone_BlendOpt;
571 }
572
573 bool GrDrawState::canIgnoreColorAttribute() const {
574     if (fBlendOptFlags & kInvalid_BlendOptFlag) {
575         this->getBlendOpts();
576     }
577     return SkToBool(fBlendOptFlags & (GrDrawState::kEmitTransBlack_BlendOptFlag |
578                                       GrDrawState::kEmitCoverage_BlendOptFlag));
579 }
580
581 //////////////////////////////////////////////////////////////////////////////
582
583 GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(
584     GrDrawState* drawState) {
585     SkASSERT(NULL != drawState);
586     fDrawState = drawState;
587     fVAPtr = drawState->fVAPtr;
588     fVACount = drawState->fVACount;
589     fDrawState->setDefaultVertexAttribs();
590 }
591
592 //////////////////////////////////////////////////////////////////////////////s
593
594 void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
595     if (NULL != fDrawState) {
596         int m = fDrawState->numColorStages() - fColorEffectCnt;
597         SkASSERT(m >= 0);
598         fDrawState->fState.fColorStages.pop_back_n(m);
599
600         int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
601         SkASSERT(n >= 0);
602         fDrawState->fState.fCoverageStages.pop_back_n(n);
603         if (m + n > 0) {
604             fDrawState->invalidateBlendOptFlags();
605         }
606         SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
607     }
608     fDrawState = ds;
609     if (NULL != ds) {
610         fColorEffectCnt = ds->numColorStages();
611         fCoverageEffectCnt = ds->numCoverageStages();
612         SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
613     }
614 }
615
616 ////////////////////////////////////////////////////////////////////////////////
617
618 void GrDrawState::AutoViewMatrixRestore::restore() {
619     if (NULL != fDrawState) {
620         SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
621         fDrawState->fViewMatrix = fViewMatrix;
622         SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
623         int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
624         SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
625
626         int i = 0;
627         for (int s = 0; s < fNumColorStages; ++s, ++i) {
628             fDrawState->fState.fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
629         }
630         for (int s = 0; s < numCoverageStages; ++s, ++i) {
631             fDrawState->fState.fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
632         }
633         fDrawState = NULL;
634     }
635 }
636
637 void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
638                                              const SkMatrix& preconcatMatrix) {
639     this->restore();
640
641     SkASSERT(NULL == fDrawState);
642     if (NULL == drawState || preconcatMatrix.isIdentity()) {
643         return;
644     }
645     fDrawState = drawState;
646
647     fViewMatrix = drawState->getViewMatrix();
648     drawState->fViewMatrix.preConcat(preconcatMatrix);
649
650     this->doEffectCoordChanges(preconcatMatrix);
651     SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
652 }
653
654 bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
655     this->restore();
656
657     if (NULL == drawState) {
658         return false;
659     }
660
661     if (drawState->getViewMatrix().isIdentity()) {
662         return true;
663     }
664
665     fViewMatrix = drawState->getViewMatrix();
666     if (0 == drawState->numTotalStages()) {
667         drawState->fViewMatrix.reset();
668         fDrawState = drawState;
669         fNumColorStages = 0;
670         fSavedCoordChanges.reset(0);
671         SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
672         return true;
673     } else {
674         SkMatrix inv;
675         if (!fViewMatrix.invert(&inv)) {
676             return false;
677         }
678         drawState->fViewMatrix.reset();
679         fDrawState = drawState;
680         this->doEffectCoordChanges(inv);
681         SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
682         return true;
683     }
684 }
685
686 void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
687     fSavedCoordChanges.reset(fDrawState->numTotalStages());
688     int i = 0;
689
690     fNumColorStages = fDrawState->numColorStages();
691     for (int s = 0; s < fNumColorStages; ++s, ++i) {
692         fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
693         fDrawState->fState.fColorStages[s].localCoordChange(coordChangeMatrix);
694     }
695
696     int numCoverageStages = fDrawState->numCoverageStages();
697     for (int s = 0; s < numCoverageStages; ++s, ++i) {
698         fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
699         fDrawState->fState.fCoverageStages[s].localCoordChange(coordChangeMatrix);
700     }
701 }