• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
setIdentityViewMatrix()11 bool GrDrawState::setIdentityViewMatrix()  {
12     if (fColorStages.count() || fCoverageStages.count()) {
13         SkMatrix invVM;
14         if (!fCommon.fViewMatrix.invert(&invVM)) {
15             // sad trombone sound
16             return false;
17         }
18         for (int s = 0; s < fColorStages.count(); ++s) {
19             fColorStages[s].localCoordChange(invVM);
20         }
21         for (int s = 0; s < fCoverageStages.count(); ++s) {
22             fCoverageStages[s].localCoordChange(invVM);
23         }
24     }
25     fCommon.fViewMatrix.reset();
26     return true;
27 }
28 
setFromPaint(const GrPaint & paint,const SkMatrix & vm,GrRenderTarget * rt)29 void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
30     SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
31 
32     fColorStages.reset();
33     fCoverageStages.reset();
34 
35     for (int i = 0; i < paint.numColorStages(); ++i) {
36         fColorStages.push_back(paint.getColorStage(i));
37     }
38 
39     for (int i = 0; i < paint.numCoverageStages(); ++i) {
40         fCoverageStages.push_back(paint.getCoverageStage(i));
41     }
42 
43     this->setRenderTarget(rt);
44 
45     fCommon.fViewMatrix = vm;
46 
47     // These have no equivalent in GrPaint, set them to defaults
48     fCommon.fBlendConstant = 0x0;
49     fCommon.fDrawFace = kBoth_DrawFace;
50     fCommon.fStencilSettings.setDisabled();
51     this->resetStateFlags();
52 
53     // Enable the clip bit
54     this->enableState(GrDrawState::kClip_StateBit);
55 
56     this->setColor(paint.getColor());
57     this->setState(GrDrawState::kDither_StateBit, paint.isDither());
58     this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
59 
60     this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
61     this->setCoverage(paint.getCoverage());
62 }
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 
vertex_size(const GrVertexAttrib * attribs,int count)66 static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
67     // this works as long as we're 4 byte-aligned
68 #ifdef SK_DEBUG
69     uint32_t overlapCheck = 0;
70 #endif
71     SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
72     size_t size = 0;
73     for (int index = 0; index < count; ++index) {
74         size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
75         size += attribSize;
76 #ifdef SK_DEBUG
77         size_t dwordCount = attribSize >> 2;
78         uint32_t mask = (1 << dwordCount)-1;
79         size_t offsetShift = attribs[index].fOffset >> 2;
80         SkASSERT(!(overlapCheck & (mask << offsetShift)));
81         overlapCheck |= (mask << offsetShift);
82 #endif
83     }
84     return size;
85 }
86 
getVertexSize() const87 size_t GrDrawState::getVertexSize() const {
88     return vertex_size(fCommon.fVAPtr, fCommon.fVACount);
89 }
90 
91 ////////////////////////////////////////////////////////////////////////////////
92 
setVertexAttribs(const GrVertexAttrib * attribs,int count)93 void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
94     SkASSERT(count <= kMaxVertexAttribCnt);
95 
96     fCommon.fVAPtr = attribs;
97     fCommon.fVACount = count;
98 
99     // Set all the indices to -1
100     memset(fCommon.fFixedFunctionVertexAttribIndices,
101            0xff,
102            sizeof(fCommon.fFixedFunctionVertexAttribIndices));
103 #ifdef SK_DEBUG
104     uint32_t overlapCheck = 0;
105 #endif
106     for (int i = 0; i < count; ++i) {
107         if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
108             // The fixed function attribs can only be specified once
109             SkASSERT(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
110             SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
111                      GrVertexAttribTypeVectorCount(attribs[i].fType));
112             fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
113         }
114 #ifdef SK_DEBUG
115         size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
116         uint32_t mask = (1 << dwordCount)-1;
117         size_t offsetShift = attribs[i].fOffset >> 2;
118         SkASSERT(!(overlapCheck & (mask << offsetShift)));
119         overlapCheck |= (mask << offsetShift);
120 #endif
121     }
122     // Positions must be specified.
123     SkASSERT(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 
setDefaultVertexAttribs()128 void GrDrawState::setDefaultVertexAttribs() {
129     static const GrVertexAttrib kPositionAttrib =
130         {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
131 
132     fCommon.fVAPtr = &kPositionAttrib;
133     fCommon.fVACount = 1;
134 
135     // set all the fixed function indices to -1 except position.
136     memset(fCommon.fFixedFunctionVertexAttribIndices,
137            0xff,
138            sizeof(fCommon.fFixedFunctionVertexAttribIndices));
139     fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
140 }
141 
142 ////////////////////////////////////////////////////////////////////////////////
143 
validateVertexAttribs() const144 bool GrDrawState::validateVertexAttribs() const {
145     // check consistency of effects and attributes
146     GrSLType slTypes[kMaxVertexAttribCnt];
147     for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
148         slTypes[i] = static_cast<GrSLType>(-1);
149     }
150     int totalStages = fColorStages.count() + fCoverageStages.count();
151     for (int s = 0; s < totalStages; ++s) {
152         int covIdx = s - fColorStages.count();
153         const GrEffectStage& stage = covIdx < 0 ? fColorStages[s] : fCoverageStages[covIdx];
154         const GrEffectRef* effect = stage.getEffect();
155         SkASSERT(NULL != effect);
156         // make sure that any attribute indices have the correct binding type, that the attrib
157         // type and effect's shader lang type are compatible, and that attributes shared by
158         // multiple effects use the same shader lang type.
159         const int* attributeIndices = stage.getVertexAttribIndices();
160         int numAttributes = stage.getVertexAttribIndexCount();
161         for (int i = 0; i < numAttributes; ++i) {
162             int attribIndex = attributeIndices[i];
163             if (attribIndex >= fCommon.fVACount ||
164                 kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
165                 return false;
166             }
167 
168             GrSLType effectSLType = (*effect)->vertexAttribType(i);
169             GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
170             int slVecCount = GrSLTypeVectorCount(effectSLType);
171             int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
172             if (slVecCount != attribVecCount ||
173                 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
174                     slTypes[attribIndex] != effectSLType)) {
175                 return false;
176             }
177             slTypes[attribIndex] = effectSLType;
178         }
179     }
180 
181     return true;
182 }
183 
willEffectReadDstColor() const184 bool GrDrawState::willEffectReadDstColor() const {
185     if (!this->isColorWriteDisabled()) {
186         for (int s = 0; s < fColorStages.count(); ++s) {
187             if ((*fColorStages[s].getEffect())->willReadDstColor()) {
188                 return true;
189             }
190         }
191     }
192     for (int s = 0; s < fCoverageStages.count(); ++s) {
193         if ((*fCoverageStages[s].getEffect())->willReadDstColor()) {
194             return true;
195         }
196     }
197     return false;
198 }
199 
200 ////////////////////////////////////////////////////////////////////////////////
201 
srcAlphaWillBeOne() const202 bool GrDrawState::srcAlphaWillBeOne() const {
203     uint32_t validComponentFlags;
204     GrColor color;
205     // Check if per-vertex or constant color may have partial alpha
206     if (this->hasColorVertexAttribute()) {
207         validComponentFlags = 0;
208         color = 0; // not strictly necessary but we get false alarms from tools about uninit.
209     } else {
210         validComponentFlags = kRGBA_GrColorComponentFlags;
211         color = this->getColor();
212     }
213 
214     // Run through the color stages
215     for (int s = 0; s < fColorStages.count(); ++s) {
216         const GrEffectRef* effect = fColorStages[s].getEffect();
217         (*effect)->getConstantColorComponents(&color, &validComponentFlags);
218     }
219 
220     // Check whether coverage is treated as color. If so we run through the coverage computation.
221     if (this->isCoverageDrawing()) {
222         GrColor coverageColor = this->getCoverageColor();
223         GrColor oldColor = color;
224         color = 0;
225         for (int c = 0; c < 4; ++c) {
226             if (validComponentFlags & (1 << c)) {
227                 U8CPU a = (oldColor >> (c * 8)) & 0xff;
228                 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
229                 color |= (SkMulDiv255Round(a, b) << (c * 8));
230             }
231         }
232         for (int s = 0; s < fCoverageStages.count(); ++s) {
233             const GrEffectRef* effect = fCoverageStages[s].getEffect();
234             (*effect)->getConstantColorComponents(&color, &validComponentFlags);
235         }
236     }
237     return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
238 }
239 
hasSolidCoverage() const240 bool GrDrawState::hasSolidCoverage() const {
241     // If we're drawing coverage directly then coverage is effectively treated as color.
242     if (this->isCoverageDrawing()) {
243         return true;
244     }
245 
246     GrColor coverage;
247     uint32_t validComponentFlags;
248     // Initialize to an unknown starting coverage if per-vertex coverage is specified.
249     if (this->hasCoverageVertexAttribute()) {
250         validComponentFlags = 0;
251     } else {
252         coverage = fCommon.fCoverage;
253         validComponentFlags = kRGBA_GrColorComponentFlags;
254     }
255 
256     // Run through the coverage stages and see if the coverage will be all ones at the end.
257     for (int s = 0; s < fCoverageStages.count(); ++s) {
258         const GrEffectRef* effect = fCoverageStages[s].getEffect();
259         (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
260     }
261     return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
262 }
263 
264 ////////////////////////////////////////////////////////////////////////////////
265 
266 // Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
267 // others will blend incorrectly.
canTweakAlphaForCoverage() const268 bool GrDrawState::canTweakAlphaForCoverage() const {
269     /*
270      The fractional coverage is f.
271      The src and dst coeffs are Cs and Cd.
272      The dst and src colors are S and D.
273      We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
274      we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
275      term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
276      find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
277      Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
278      color by definition.
279      */
280     return kOne_GrBlendCoeff == fCommon.fDstBlend ||
281            kISA_GrBlendCoeff == fCommon.fDstBlend ||
282            kISC_GrBlendCoeff == fCommon.fDstBlend ||
283            this->isCoverageDrawing();
284 }
285 
getBlendOpts(bool forceCoverage,GrBlendCoeff * srcCoeff,GrBlendCoeff * dstCoeff) const286 GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
287                                                      GrBlendCoeff* srcCoeff,
288                                                      GrBlendCoeff* dstCoeff) const {
289 
290     GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
291     if (NULL == srcCoeff) {
292         srcCoeff = &bogusSrcCoeff;
293     }
294     *srcCoeff = this->getSrcBlendCoeff();
295 
296     if (NULL == dstCoeff) {
297         dstCoeff = &bogusDstCoeff;
298     }
299     *dstCoeff = this->getDstBlendCoeff();
300 
301     if (this->isColorWriteDisabled()) {
302         *srcCoeff = kZero_GrBlendCoeff;
303         *dstCoeff = kOne_GrBlendCoeff;
304     }
305 
306     bool srcAIsOne = this->srcAlphaWillBeOne();
307     bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
308                          (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
309     bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
310                          (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
311 
312     bool covIsZero = !this->isCoverageDrawing() &&
313                      !this->hasCoverageVertexAttribute() &&
314                      0 == this->getCoverageColor();
315     // When coeffs are (0,1) there is no reason to draw at all, unless
316     // stenciling is enabled. Having color writes disabled is effectively
317     // (0,1). The same applies when coverage is known to be 0.
318     if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
319         if (this->getStencil().doesWrite()) {
320             return kDisableBlend_BlendOptFlag |
321                    kEmitCoverage_BlendOptFlag;
322         } else {
323             return kSkipDraw_BlendOptFlag;
324         }
325     }
326 
327     // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
328     bool hasCoverage = forceCoverage ||
329                        0xffffffff != this->getCoverageColor() ||
330                        this->hasCoverageVertexAttribute() ||
331                        fCoverageStages.count() > 0;
332 
333     // if we don't have coverage we can check whether the dst
334     // has to read at all. If not, we'll disable blending.
335     if (!hasCoverage) {
336         if (dstCoeffIsZero) {
337             if (kOne_GrBlendCoeff == *srcCoeff) {
338                 // if there is no coverage and coeffs are (1,0) then we
339                 // won't need to read the dst at all, it gets replaced by src
340                 return kDisableBlend_BlendOptFlag;
341             } else if (kZero_GrBlendCoeff == *srcCoeff) {
342                 // if the op is "clear" then we don't need to emit a color
343                 // or blend, just write transparent black into the dst.
344                 *srcCoeff = kOne_GrBlendCoeff;
345                 *dstCoeff = kZero_GrBlendCoeff;
346                 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
347             }
348         }
349     } else if (this->isCoverageDrawing()) {
350         // we have coverage but we aren't distinguishing it from alpha by request.
351         return kCoverageAsAlpha_BlendOptFlag;
352     } else {
353         // check whether coverage can be safely rolled into alpha
354         // of if we can skip color computation and just emit coverage
355         if (this->canTweakAlphaForCoverage()) {
356             return kCoverageAsAlpha_BlendOptFlag;
357         }
358         if (dstCoeffIsZero) {
359             if (kZero_GrBlendCoeff == *srcCoeff) {
360                 // the source color is not included in the blend
361                 // the dst coeff is effectively zero so blend works out to:
362                 // (c)(0)D + (1-c)D = (1-c)D.
363                 *dstCoeff = kISA_GrBlendCoeff;
364                 return  kEmitCoverage_BlendOptFlag;
365             } else if (srcAIsOne) {
366                 // the dst coeff is effectively zero so blend works out to:
367                 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
368                 // If Sa is 1 then we can replace Sa with c
369                 // and set dst coeff to 1-Sa.
370                 *dstCoeff = kISA_GrBlendCoeff;
371                 return  kCoverageAsAlpha_BlendOptFlag;
372             }
373         } else if (dstCoeffIsOne) {
374             // the dst coeff is effectively one so blend works out to:
375             // cS + (c)(1)D + (1-c)D = cS + D.
376             *dstCoeff = kOne_GrBlendCoeff;
377             return  kCoverageAsAlpha_BlendOptFlag;
378         }
379     }
380     if (kOne_GrBlendCoeff == *srcCoeff &&
381         kZero_GrBlendCoeff == *dstCoeff &&
382         this->willEffectReadDstColor()) {
383         // In this case the shader will fully resolve the color, coverage, and dst and we don't
384         // need blending.
385         return kDisableBlend_BlendOptFlag;
386     }
387     return kNone_BlendOpt;
388 }
389 
390 ////////////////////////////////////////////////////////////////////////////////
391 
restore()392 void GrDrawState::AutoViewMatrixRestore::restore() {
393     if (NULL != fDrawState) {
394         SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
395         fDrawState->fCommon.fViewMatrix = fViewMatrix;
396         SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
397         int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
398         SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
399 
400         int i = 0;
401         for (int s = 0; s < fNumColorStages; ++s, ++i) {
402             fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
403         }
404         for (int s = 0; s < numCoverageStages; ++s, ++i) {
405             fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
406         }
407         fDrawState = NULL;
408     }
409 }
410 
set(GrDrawState * drawState,const SkMatrix & preconcatMatrix)411 void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
412                                              const SkMatrix& preconcatMatrix) {
413     this->restore();
414 
415     SkASSERT(NULL == fDrawState);
416     if (NULL == drawState || preconcatMatrix.isIdentity()) {
417         return;
418     }
419     fDrawState = drawState;
420 
421     fViewMatrix = drawState->getViewMatrix();
422     drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix);
423 
424     this->doEffectCoordChanges(preconcatMatrix);
425     SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
426 }
427 
setIdentity(GrDrawState * drawState)428 bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
429     this->restore();
430 
431     if (NULL == drawState) {
432         return false;
433     }
434 
435     if (drawState->getViewMatrix().isIdentity()) {
436         return true;
437     }
438 
439     fViewMatrix = drawState->getViewMatrix();
440     if (0 == drawState->numTotalStages()) {
441         drawState->fCommon.fViewMatrix.reset();
442         fDrawState = drawState;
443         fNumColorStages = 0;
444         fSavedCoordChanges.reset(0);
445         SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
446         return true;
447     } else {
448         SkMatrix inv;
449         if (!fViewMatrix.invert(&inv)) {
450             return false;
451         }
452         drawState->fCommon.fViewMatrix.reset();
453         fDrawState = drawState;
454         this->doEffectCoordChanges(inv);
455         SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
456         return true;
457     }
458 }
459 
doEffectCoordChanges(const SkMatrix & coordChangeMatrix)460 void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
461     fSavedCoordChanges.reset(fDrawState->numTotalStages());
462     int i = 0;
463 
464     fNumColorStages = fDrawState->numColorStages();
465     for (int s = 0; s < fNumColorStages; ++s, ++i) {
466         fDrawState->fColorStages[s].saveCoordChange(&fSavedCoordChanges[i]);
467         fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
468     }
469 
470     int numCoverageStages = fDrawState->numCoverageStages();
471     for (int s = 0; s < numCoverageStages; ++s, ++i) {
472         fDrawState->fCoverageStages[s].saveCoordChange(&fSavedCoordChanges[i]);
473         fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
474     }
475 }
476