• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2010 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 
11 #include "GrDrawTarget.h"
12 #include "GrRenderTarget.h"
13 #include "GrTexture.h"
14 #include "GrVertexBuffer.h"
15 
16 #include "SkStrokeRec.h"
17 
SK_DEFINE_INST_COUNT(GrDrawTarget)18 SK_DEFINE_INST_COUNT(GrDrawTarget)
19 
20 ////////////////////////////////////////////////////////////////////////////////
21 
22 GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
23     fPrimitiveType  = di.fPrimitiveType;
24     fStartVertex    = di.fStartVertex;
25     fStartIndex     = di.fStartIndex;
26     fVertexCount    = di.fVertexCount;
27     fIndexCount     = di.fIndexCount;
28 
29     fInstanceCount          = di.fInstanceCount;
30     fVerticesPerInstance    = di.fVerticesPerInstance;
31     fIndicesPerInstance     = di.fIndicesPerInstance;
32 
33     if (NULL != di.fDevBounds) {
34         GrAssert(di.fDevBounds == &di.fDevBoundsStorage);
35         fDevBoundsStorage = di.fDevBoundsStorage;
36         fDevBounds = &fDevBoundsStorage;
37     } else {
38         fDevBounds = NULL;
39     }
40     return *this;
41 }
42 
43 #if GR_DEBUG
isInstanced() const44 bool GrDrawTarget::DrawInfo::isInstanced() const {
45     if (fInstanceCount > 0) {
46         GrAssert(0 == fIndexCount % fIndicesPerInstance);
47         GrAssert(0 == fVertexCount % fVerticesPerInstance);
48         GrAssert(fIndexCount / fIndicesPerInstance == fInstanceCount);
49         GrAssert(fVertexCount / fVerticesPerInstance == fInstanceCount);
50         // there is no way to specify a non-zero start index to drawIndexedInstances().
51         GrAssert(0 == fStartIndex);
52         return true;
53     } else {
54         GrAssert(!fVerticesPerInstance);
55         GrAssert(!fIndicesPerInstance);
56         return false;
57     }
58 }
59 #endif
60 
adjustInstanceCount(int instanceOffset)61 void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
62     GrAssert(this->isInstanced());
63     GrAssert(instanceOffset + fInstanceCount >= 0);
64     fInstanceCount += instanceOffset;
65     fVertexCount = fVerticesPerInstance * fInstanceCount;
66     fIndexCount = fIndicesPerInstance * fInstanceCount;
67 }
68 
adjustStartVertex(int vertexOffset)69 void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
70     fStartVertex += vertexOffset;
71     GrAssert(fStartVertex >= 0);
72 }
73 
adjustStartIndex(int indexOffset)74 void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
75     GrAssert(this->isIndexed());
76     fStartIndex += indexOffset;
77     GrAssert(fStartIndex >= 0);
78 }
79 
80 ////////////////////////////////////////////////////////////////////////////////
81 
82 #define DEBUG_INVAL_BUFFER 0xdeadcafe
83 #define DEBUG_INVAL_START_IDX -1
84 
GrDrawTarget()85 GrDrawTarget::GrDrawTarget() : fClip(NULL) {
86     fDrawState = &fDefaultDrawState;
87     // We assume that fDrawState always owns a ref to the object it points at.
88     fDefaultDrawState.ref();
89     GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
90 #if GR_DEBUG
91     geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
92     geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
93     geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
94     geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
95 #endif
96     geoSrc.fVertexSrc = kNone_GeometrySrcType;
97     geoSrc.fIndexSrc  = kNone_GeometrySrcType;
98 }
99 
~GrDrawTarget()100 GrDrawTarget::~GrDrawTarget() {
101     GrAssert(1 == fGeoSrcStateStack.count());
102     SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
103     GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
104     GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
105     fDrawState->unref();
106 }
107 
releaseGeometry()108 void GrDrawTarget::releaseGeometry() {
109     int popCnt = fGeoSrcStateStack.count() - 1;
110     while (popCnt) {
111         this->popGeometrySource();
112         --popCnt;
113     }
114     this->resetVertexSource();
115     this->resetIndexSource();
116 }
117 
setClip(const GrClipData * clip)118 void GrDrawTarget::setClip(const GrClipData* clip) {
119     clipWillBeSet(clip);
120     fClip = clip;
121 }
122 
getClip() const123 const GrClipData* GrDrawTarget::getClip() const {
124     return fClip;
125 }
126 
setDrawState(GrDrawState * drawState)127 void GrDrawTarget::setDrawState(GrDrawState*  drawState) {
128     GrAssert(NULL != fDrawState);
129     if (NULL == drawState) {
130         drawState = &fDefaultDrawState;
131     }
132     if (fDrawState != drawState) {
133         fDrawState->unref();
134         drawState->ref();
135         fDrawState = drawState;
136     }
137 }
138 
reserveVertexSpace(GrVertexLayout vertexLayout,int vertexCount,void ** vertices)139 bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
140                                       int vertexCount,
141                                       void** vertices) {
142     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
143     bool acquired = false;
144     if (vertexCount > 0) {
145         GrAssert(NULL != vertices);
146         this->releasePreviousVertexSource();
147         geoSrc.fVertexSrc = kNone_GeometrySrcType;
148 
149         acquired = this->onReserveVertexSpace(GrDrawState::VertexSize(vertexLayout),
150                                               vertexCount,
151                                               vertices);
152     }
153     if (acquired) {
154         geoSrc.fVertexSrc = kReserved_GeometrySrcType;
155         geoSrc.fVertexCount = vertexCount;
156         geoSrc.fVertexLayout = vertexLayout;
157     } else if (NULL != vertices) {
158         *vertices = NULL;
159     }
160     return acquired;
161 }
162 
reserveIndexSpace(int indexCount,void ** indices)163 bool GrDrawTarget::reserveIndexSpace(int indexCount,
164                                      void** indices) {
165     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
166     bool acquired = false;
167     if (indexCount > 0) {
168         GrAssert(NULL != indices);
169         this->releasePreviousIndexSource();
170         geoSrc.fIndexSrc = kNone_GeometrySrcType;
171 
172         acquired = this->onReserveIndexSpace(indexCount, indices);
173     }
174     if (acquired) {
175         geoSrc.fIndexSrc = kReserved_GeometrySrcType;
176         geoSrc.fIndexCount = indexCount;
177     } else if (NULL != indices) {
178         *indices = NULL;
179     }
180     return acquired;
181 
182 }
183 
reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,int vertexCount,int indexCount,void ** vertices,void ** indices)184 bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
185                                               int vertexCount,
186                                               int indexCount,
187                                               void** vertices,
188                                               void** indices) {
189     this->willReserveVertexAndIndexSpace(GrDrawState::VertexSize(vertexLayout), vertexCount, indexCount);
190     if (vertexCount) {
191         if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
192             if (indexCount) {
193                 this->resetIndexSource();
194             }
195             return false;
196         }
197     }
198     if (indexCount) {
199         if (!this->reserveIndexSpace(indexCount, indices)) {
200             if (vertexCount) {
201                 this->resetVertexSource();
202             }
203             return false;
204         }
205     }
206     return true;
207 }
208 
geometryHints(size_t vertexSize,int32_t * vertexCount,int32_t * indexCount) const209 bool GrDrawTarget::geometryHints(size_t vertexSize,
210                                  int32_t* vertexCount,
211                                  int32_t* indexCount) const {
212     if (NULL != vertexCount) {
213         *vertexCount = -1;
214     }
215     if (NULL != indexCount) {
216         *indexCount = -1;
217     }
218     return false;
219 }
220 
releasePreviousVertexSource()221 void GrDrawTarget::releasePreviousVertexSource() {
222     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
223     switch (geoSrc.fVertexSrc) {
224         case kNone_GeometrySrcType:
225             break;
226         case kArray_GeometrySrcType:
227             this->releaseVertexArray();
228             break;
229         case kReserved_GeometrySrcType:
230             this->releaseReservedVertexSpace();
231             break;
232         case kBuffer_GeometrySrcType:
233             geoSrc.fVertexBuffer->unref();
234 #if GR_DEBUG
235             geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
236 #endif
237             break;
238         default:
239             GrCrash("Unknown Vertex Source Type.");
240             break;
241     }
242 }
243 
releasePreviousIndexSource()244 void GrDrawTarget::releasePreviousIndexSource() {
245     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
246     switch (geoSrc.fIndexSrc) {
247         case kNone_GeometrySrcType:   // these two don't require
248             break;
249         case kArray_GeometrySrcType:
250             this->releaseIndexArray();
251             break;
252         case kReserved_GeometrySrcType:
253             this->releaseReservedIndexSpace();
254             break;
255         case kBuffer_GeometrySrcType:
256             geoSrc.fIndexBuffer->unref();
257 #if GR_DEBUG
258             geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
259 #endif
260             break;
261         default:
262             GrCrash("Unknown Index Source Type.");
263             break;
264     }
265 }
266 
setVertexSourceToArray(GrVertexLayout vertexLayout,const void * vertexArray,int vertexCount)267 void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
268                                           const void* vertexArray,
269                                           int vertexCount) {
270     this->releasePreviousVertexSource();
271     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
272     geoSrc.fVertexSrc = kArray_GeometrySrcType;
273     geoSrc.fVertexLayout = vertexLayout;
274     geoSrc.fVertexCount = vertexCount;
275     this->onSetVertexSourceToArray(vertexArray, vertexCount);
276 }
277 
setIndexSourceToArray(const void * indexArray,int indexCount)278 void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
279                                          int indexCount) {
280     this->releasePreviousIndexSource();
281     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
282     geoSrc.fIndexSrc = kArray_GeometrySrcType;
283     geoSrc.fIndexCount = indexCount;
284     this->onSetIndexSourceToArray(indexArray, indexCount);
285 }
286 
setVertexSourceToBuffer(GrVertexLayout vertexLayout,const GrVertexBuffer * buffer)287 void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
288                                            const GrVertexBuffer* buffer) {
289     this->releasePreviousVertexSource();
290     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
291     geoSrc.fVertexSrc    = kBuffer_GeometrySrcType;
292     geoSrc.fVertexBuffer = buffer;
293     buffer->ref();
294     geoSrc.fVertexLayout = vertexLayout;
295 }
296 
setIndexSourceToBuffer(const GrIndexBuffer * buffer)297 void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
298     this->releasePreviousIndexSource();
299     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
300     geoSrc.fIndexSrc     = kBuffer_GeometrySrcType;
301     geoSrc.fIndexBuffer  = buffer;
302     buffer->ref();
303 }
304 
resetVertexSource()305 void GrDrawTarget::resetVertexSource() {
306     this->releasePreviousVertexSource();
307     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
308     geoSrc.fVertexSrc = kNone_GeometrySrcType;
309 }
310 
resetIndexSource()311 void GrDrawTarget::resetIndexSource() {
312     this->releasePreviousIndexSource();
313     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
314     geoSrc.fIndexSrc = kNone_GeometrySrcType;
315 }
316 
pushGeometrySource()317 void GrDrawTarget::pushGeometrySource() {
318     this->geometrySourceWillPush();
319     GeometrySrcState& newState = fGeoSrcStateStack.push_back();
320     newState.fIndexSrc = kNone_GeometrySrcType;
321     newState.fVertexSrc = kNone_GeometrySrcType;
322 #if GR_DEBUG
323     newState.fVertexCount  = ~0;
324     newState.fVertexBuffer = (GrVertexBuffer*)~0;
325     newState.fIndexCount   = ~0;
326     newState.fIndexBuffer = (GrIndexBuffer*)~0;
327 #endif
328 }
329 
popGeometrySource()330 void GrDrawTarget::popGeometrySource() {
331     // if popping last element then pops are unbalanced with pushes
332     GrAssert(fGeoSrcStateStack.count() > 1);
333 
334     this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
335     this->releasePreviousVertexSource();
336     this->releasePreviousIndexSource();
337     fGeoSrcStateStack.pop_back();
338 }
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 
checkDraw(GrPrimitiveType type,int startVertex,int startIndex,int vertexCount,int indexCount) const342 bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
343                              int startIndex, int vertexCount,
344                              int indexCount) const {
345     const GrDrawState& drawState = this->getDrawState();
346 #if GR_DEBUG
347     const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
348     int maxVertex = startVertex + vertexCount;
349     int maxValidVertex;
350     switch (geoSrc.fVertexSrc) {
351         case kNone_GeometrySrcType:
352             GrCrash("Attempting to draw without vertex src.");
353         case kReserved_GeometrySrcType: // fallthrough
354         case kArray_GeometrySrcType:
355             maxValidVertex = geoSrc.fVertexCount;
356             break;
357         case kBuffer_GeometrySrcType:
358             maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / GrDrawState::VertexSize(geoSrc.fVertexLayout);
359             break;
360     }
361     if (maxVertex > maxValidVertex) {
362         GrCrash("Drawing outside valid vertex range.");
363     }
364     if (indexCount > 0) {
365         int maxIndex = startIndex + indexCount;
366         int maxValidIndex;
367         switch (geoSrc.fIndexSrc) {
368             case kNone_GeometrySrcType:
369                 GrCrash("Attempting to draw indexed geom without index src.");
370             case kReserved_GeometrySrcType: // fallthrough
371             case kArray_GeometrySrcType:
372                 maxValidIndex = geoSrc.fIndexCount;
373                 break;
374             case kBuffer_GeometrySrcType:
375                 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
376                 break;
377         }
378         if (maxIndex > maxValidIndex) {
379             GrCrash("Index reads outside valid index range.");
380         }
381     }
382 
383     GrAssert(NULL != drawState.getRenderTarget());
384     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
385         if (drawState.isStageEnabled(s)) {
386             const GrEffectRef& effect = *drawState.getStage(s).getEffect();
387             int numTextures = effect->numTextures();
388             for (int t = 0; t < numTextures; ++t) {
389                 GrTexture* texture = effect->texture(t);
390                 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
391             }
392         }
393     }
394 #endif
395     if (NULL == drawState.getRenderTarget()) {
396         return false;
397     }
398     return true;
399 }
400 
drawIndexed(GrPrimitiveType type,int startVertex,int startIndex,int vertexCount,int indexCount,const SkRect * devBounds)401 void GrDrawTarget::drawIndexed(GrPrimitiveType type,
402                                int startVertex,
403                                int startIndex,
404                                int vertexCount,
405                                int indexCount,
406                                const SkRect* devBounds) {
407     if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
408         DrawInfo info;
409         info.fPrimitiveType = type;
410         info.fStartVertex   = startVertex;
411         info.fStartIndex    = startIndex;
412         info.fVertexCount   = vertexCount;
413         info.fIndexCount    = indexCount;
414 
415         info.fInstanceCount         = 0;
416         info.fVerticesPerInstance   = 0;
417         info.fIndicesPerInstance    = 0;
418 
419         if (NULL != devBounds) {
420             info.setDevBounds(*devBounds);
421         }
422         this->onDraw(info);
423     }
424 }
425 
drawNonIndexed(GrPrimitiveType type,int startVertex,int vertexCount,const SkRect * devBounds)426 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
427                                   int startVertex,
428                                   int vertexCount,
429                                   const SkRect* devBounds) {
430     if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
431         DrawInfo info;
432         info.fPrimitiveType = type;
433         info.fStartVertex   = startVertex;
434         info.fStartIndex    = 0;
435         info.fVertexCount   = vertexCount;
436         info.fIndexCount    = 0;
437 
438         info.fInstanceCount         = 0;
439         info.fVerticesPerInstance   = 0;
440         info.fIndicesPerInstance    = 0;
441 
442         if (NULL != devBounds) {
443             info.setDevBounds(*devBounds);
444         }
445         this->onDraw(info);
446     }
447 }
448 
stencilPath(const GrPath * path,const SkStrokeRec & stroke,SkPath::FillType fill)449 void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
450     // TODO: extract portions of checkDraw that are relevant to path stenciling.
451     GrAssert(NULL != path);
452     GrAssert(fCaps.pathStencilingSupport());
453     GrAssert(!stroke.isHairlineStyle());
454     GrAssert(!SkPath::IsInverseFillType(fill));
455     this->onStencilPath(path, stroke, fill);
456 }
457 
458 ////////////////////////////////////////////////////////////////////////////////
459 
460 // Some blend modes allow folding a partial coverage value into the color's
461 // alpha channel, while others will blend incorrectly.
canTweakAlphaForCoverage() const462 bool GrDrawTarget::canTweakAlphaForCoverage() const {
463     /**
464      * The fractional coverage is f
465      * The src and dst coeffs are Cs and Cd
466      * The dst and src colors are S and D
467      * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
468      * By tweaking the source color's alpha we're replacing S with S'=fS. It's
469      * obvious that that first term will always be ok. The second term can be
470      * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
471      * for Cd we find that only 1, ISA, and ISC produce the correct depth
472      * coefficient in terms of S' and D.
473      */
474     GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
475     return kOne_GrBlendCoeff == dstCoeff ||
476            kISA_GrBlendCoeff == dstCoeff ||
477            kISC_GrBlendCoeff == dstCoeff ||
478            this->getDrawState().isCoverageDrawing();
479 }
480 
481 namespace {
default_blend_opts_vertex_layout()482 GrVertexLayout default_blend_opts_vertex_layout() {
483     GrVertexLayout layout = 0;
484     return layout;
485 }
486 }
487 
488 GrDrawTarget::BlendOptFlags
getBlendOpts(bool forceCoverage,GrBlendCoeff * srcCoeff,GrBlendCoeff * dstCoeff) const489 GrDrawTarget::getBlendOpts(bool forceCoverage,
490                            GrBlendCoeff* srcCoeff,
491                            GrBlendCoeff* dstCoeff) const {
492 
493     GrVertexLayout layout;
494     if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
495         layout = default_blend_opts_vertex_layout();
496     } else {
497         layout = this->getVertexLayout();
498     }
499 
500     const GrDrawState& drawState = this->getDrawState();
501 
502     GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
503     if (NULL == srcCoeff) {
504         srcCoeff = &bogusSrcCoeff;
505     }
506     *srcCoeff = drawState.getSrcBlendCoeff();
507 
508     if (NULL == dstCoeff) {
509         dstCoeff = &bogusDstCoeff;
510     }
511     *dstCoeff = drawState.getDstBlendCoeff();
512 
513     if (drawState.isColorWriteDisabled()) {
514         *srcCoeff = kZero_GrBlendCoeff;
515         *dstCoeff = kOne_GrBlendCoeff;
516     }
517 
518     bool srcAIsOne = drawState.srcAlphaWillBeOne(layout);
519     bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
520                          (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
521     bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
522                          (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
523 
524     bool covIsZero = !drawState.isCoverageDrawing() &&
525                      !(layout & GrDrawState::kCoverage_VertexLayoutBit) &&
526                      0 == drawState.getCoverage();
527     // When coeffs are (0,1) there is no reason to draw at all, unless
528     // stenciling is enabled. Having color writes disabled is effectively
529     // (0,1). The same applies when coverage is known to be 0.
530     if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
531         if (drawState.getStencil().doesWrite()) {
532             return kDisableBlend_BlendOptFlag |
533                    kEmitTransBlack_BlendOptFlag;
534         } else {
535             return kSkipDraw_BlendOptFlag;
536         }
537     }
538 
539     // check for coverage due to constant coverage, per-vertex coverage,
540     // edge aa or coverage stage
541     bool hasCoverage = forceCoverage ||
542                        0xffffffff != drawState.getCoverage() ||
543                        (layout & GrDrawState::kCoverage_VertexLayoutBit) ||
544                        (layout & GrDrawState::kEdge_VertexLayoutBit);
545     for (int s = drawState.getFirstCoverageStage();
546          !hasCoverage && s < GrDrawState::kNumStages;
547          ++s) {
548         if (drawState.isStageEnabled(s)) {
549             hasCoverage = true;
550         }
551     }
552 
553     // if we don't have coverage we can check whether the dst
554     // has to read at all. If not, we'll disable blending.
555     if (!hasCoverage) {
556         if (dstCoeffIsZero) {
557             if (kOne_GrBlendCoeff == *srcCoeff) {
558                 // if there is no coverage and coeffs are (1,0) then we
559                 // won't need to read the dst at all, it gets replaced by src
560                 return kDisableBlend_BlendOptFlag;
561             } else if (kZero_GrBlendCoeff == *srcCoeff) {
562                 // if the op is "clear" then we don't need to emit a color
563                 // or blend, just write transparent black into the dst.
564                 *srcCoeff = kOne_GrBlendCoeff;
565                 *dstCoeff = kZero_GrBlendCoeff;
566                 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
567             }
568         }
569     } else if (drawState.isCoverageDrawing()) {
570         // we have coverage but we aren't distinguishing it from alpha by request.
571         return kCoverageAsAlpha_BlendOptFlag;
572     } else {
573         // check whether coverage can be safely rolled into alpha
574         // of if we can skip color computation and just emit coverage
575         if (this->canTweakAlphaForCoverage()) {
576             return kCoverageAsAlpha_BlendOptFlag;
577         }
578         if (dstCoeffIsZero) {
579             if (kZero_GrBlendCoeff == *srcCoeff) {
580                 // the source color is not included in the blend
581                 // the dst coeff is effectively zero so blend works out to:
582                 // (c)(0)D + (1-c)D = (1-c)D.
583                 *dstCoeff = kISA_GrBlendCoeff;
584                 return  kEmitCoverage_BlendOptFlag;
585             } else if (srcAIsOne) {
586                 // the dst coeff is effectively zero so blend works out to:
587                 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
588                 // If Sa is 1 then we can replace Sa with c
589                 // and set dst coeff to 1-Sa.
590                 *dstCoeff = kISA_GrBlendCoeff;
591                 return  kCoverageAsAlpha_BlendOptFlag;
592             }
593         } else if (dstCoeffIsOne) {
594             // the dst coeff is effectively one so blend works out to:
595             // cS + (c)(1)D + (1-c)D = cS + D.
596             *dstCoeff = kOne_GrBlendCoeff;
597             return  kCoverageAsAlpha_BlendOptFlag;
598         }
599     }
600     return kNone_BlendOpt;
601 }
602 
willUseHWAALines() const603 bool GrDrawTarget::willUseHWAALines() const {
604     // there is a conflict between using smooth lines and our use of
605     // premultiplied alpha. Smooth lines tweak the incoming alpha value
606     // but not in a premul-alpha way. So we only use them when our alpha
607     // is 0xff and tweaking the color for partial coverage is OK
608     if (!fCaps.hwAALineSupport() ||
609         !this->getDrawState().isHWAntialiasState()) {
610         return false;
611     }
612     BlendOptFlags opts = this->getBlendOpts();
613     return (kDisableBlend_BlendOptFlag & opts) &&
614            (kCoverageAsAlpha_BlendOptFlag & opts);
615 }
616 
canApplyCoverage() const617 bool GrDrawTarget::canApplyCoverage() const {
618     // we can correctly apply coverage if a) we have dual source blending
619     // or b) one of our blend optimizations applies.
620     return this->getCaps().dualSourceBlendingSupport() ||
621            kNone_BlendOpt != this->getBlendOpts(true);
622 }
623 
624 ////////////////////////////////////////////////////////////////////////////////
625 
drawIndexedInstances(GrPrimitiveType type,int instanceCount,int verticesPerInstance,int indicesPerInstance,const SkRect * devBounds)626 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
627                                         int instanceCount,
628                                         int verticesPerInstance,
629                                         int indicesPerInstance,
630                                         const SkRect* devBounds) {
631     if (!verticesPerInstance || !indicesPerInstance) {
632         return;
633     }
634 
635     int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
636     if (!maxInstancesPerDraw) {
637         return;
638     }
639 
640     DrawInfo info;
641     info.fPrimitiveType = type;
642     info.fStartIndex = 0;
643     info.fStartVertex = 0;
644     info.fIndicesPerInstance = indicesPerInstance;
645     info.fVerticesPerInstance = verticesPerInstance;
646 
647     // Set the same bounds for all the draws.
648     if (NULL != devBounds) {
649         info.setDevBounds(*devBounds);
650     }
651 
652     while (instanceCount) {
653         info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
654         info.fVertexCount = info.fInstanceCount * verticesPerInstance;
655         info.fIndexCount = info.fInstanceCount * indicesPerInstance;
656 
657         if (this->checkDraw(type,
658                             info.fStartVertex,
659                             info.fStartIndex,
660                             info.fVertexCount,
661                             info.fIndexCount)) {
662             this->onDraw(info);
663         }
664         info.fStartVertex += info.fVertexCount;
665         instanceCount -= info.fInstanceCount;
666     }
667 }
668 
669 ////////////////////////////////////////////////////////////////////////////////
670 
drawRect(const GrRect & rect,const SkMatrix * matrix,const GrRect * srcRects[],const SkMatrix * srcMatrices[])671 void GrDrawTarget::drawRect(const GrRect& rect,
672                             const SkMatrix* matrix,
673                             const GrRect* srcRects[],
674                             const SkMatrix* srcMatrices[]) {
675     GrVertexLayout layout = 0;
676     uint32_t explicitCoordMask = 0;
677 
678     if (NULL != srcRects) {
679         for (int s = 0; s < GrDrawState::kNumStages; ++s) {
680             int numTC = 0;
681             if (NULL != srcRects[s]) {
682                 layout |= GrDrawState::StageTexCoordVertexLayoutBit(s, numTC);
683                 explicitCoordMask |= (1 << s);
684                 ++numTC;
685             }
686         }
687     }
688 
689     GrDrawState::AutoViewMatrixRestore avmr;
690     if (NULL != matrix) {
691         avmr.set(this->drawState(), *matrix, explicitCoordMask);
692     }
693 
694     AutoReleaseGeometry geo(this, layout, 4, 0);
695     if (!geo.succeeded()) {
696         GrPrintf("Failed to get space for vertices!\n");
697         return;
698     }
699 
700     int stageOffsets[GrDrawState::kNumStages];
701     int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets,  NULL, NULL, NULL);
702     geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
703 
704     for (int i = 0; i < GrDrawState::kNumStages; ++i) {
705         if (explicitCoordMask & (1 << i)) {
706             GrAssert(0 != stageOffsets[i]);
707             GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
708                                                 stageOffsets[i]);
709             coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
710                                srcRects[i]->fRight, srcRects[i]->fBottom,
711                                vsize);
712             if (NULL != srcMatrices && NULL != srcMatrices[i]) {
713                 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
714             }
715         } else {
716             GrAssert(0 == stageOffsets[i]);
717         }
718     }
719 
720     this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
721 }
722 
clipWillBeSet(const GrClipData * clipData)723 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
724 }
725 
726 ////////////////////////////////////////////////////////////////////////////////
727 
AutoStateRestore()728 GrDrawTarget::AutoStateRestore::AutoStateRestore() {
729     fDrawTarget = NULL;
730 }
731 
AutoStateRestore(GrDrawTarget * target,ASRInit init)732 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
733                                                  ASRInit init) {
734     fDrawTarget = NULL;
735     this->set(target, init);
736 }
737 
~AutoStateRestore()738 GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
739     if (NULL != fDrawTarget) {
740         fDrawTarget->setDrawState(fSavedState);
741         fSavedState->unref();
742     }
743 }
744 
set(GrDrawTarget * target,ASRInit init)745 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
746     GrAssert(NULL == fDrawTarget);
747     fDrawTarget = target;
748     fSavedState = target->drawState();
749     GrAssert(fSavedState);
750     fSavedState->ref();
751     if (kReset_ASRInit == init) {
752         // calls the default cons
753         fTempState.init();
754     } else {
755         GrAssert(kPreserve_ASRInit == init);
756         // calls the copy cons
757         fTempState.set(*fSavedState);
758     }
759     target->setDrawState(fTempState.get());
760 }
761 
762 ////////////////////////////////////////////////////////////////////////////////
763 
AutoReleaseGeometry(GrDrawTarget * target,GrVertexLayout vertexLayout,int vertexCount,int indexCount)764 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
765                                          GrDrawTarget*  target,
766                                          GrVertexLayout vertexLayout,
767                                          int vertexCount,
768                                          int indexCount) {
769     fTarget = NULL;
770     this->set(target, vertexLayout, vertexCount, indexCount);
771 }
772 
AutoReleaseGeometry()773 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
774     fTarget = NULL;
775 }
776 
~AutoReleaseGeometry()777 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
778     this->reset();
779 }
780 
set(GrDrawTarget * target,GrVertexLayout vertexLayout,int vertexCount,int indexCount)781 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
782                                             GrVertexLayout vertexLayout,
783                                             int vertexCount,
784                                             int indexCount) {
785     this->reset();
786     fTarget = target;
787     bool success = true;
788     if (NULL != fTarget) {
789         fTarget = target;
790         success = target->reserveVertexAndIndexSpace(vertexLayout,
791                                                      vertexCount,
792                                                      indexCount,
793                                                      &fVertices,
794                                                      &fIndices);
795         if (!success) {
796             fTarget = NULL;
797             this->reset();
798         }
799     }
800     GrAssert(success == (NULL != fTarget));
801     return success;
802 }
803 
reset()804 void GrDrawTarget::AutoReleaseGeometry::reset() {
805     if (NULL != fTarget) {
806         if (NULL != fVertices) {
807             fTarget->resetVertexSource();
808         }
809         if (NULL != fIndices) {
810             fTarget->resetIndexSource();
811         }
812         fTarget = NULL;
813     }
814     fVertices = NULL;
815     fIndices = NULL;
816 }
817 
AutoClipRestore(GrDrawTarget * target,const SkIRect & newClip)818 GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
819     fTarget = target;
820     fClip = fTarget->getClip();
821     fStack.init();
822     fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
823     fReplacementClip.fClipStack = fStack.get();
824     target->setClip(&fReplacementClip);
825 }
826 
print() const827 void GrDrawTarget::Caps::print() const {
828     static const char* gNY[] = {"NO", "YES"};
829     GrPrintf("8 Bit Palette Support       : %s\n", gNY[fInternals.f8BitPaletteSupport]);
830     GrPrintf("NPOT Texture Tile Support   : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
831     GrPrintf("Two Sided Stencil Support   : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
832     GrPrintf("Stencil Wrap Ops  Support   : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
833     GrPrintf("HW AA Lines Support         : %s\n", gNY[fInternals.fHWAALineSupport]);
834     GrPrintf("Shader Derivative Support   : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
835     GrPrintf("Geometry Shader Support     : %s\n", gNY[fInternals.fGeometryShaderSupport]);
836     GrPrintf("FSAA Support                : %s\n", gNY[fInternals.fFSAASupport]);
837     GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
838     GrPrintf("Buffer Lock Support         : %s\n", gNY[fInternals.fBufferLockSupport]);
839     GrPrintf("Path Stenciling Support     : %s\n", gNY[fInternals.fPathStencilingSupport]);
840     GrPrintf("Max Texture Size            : %d\n", fInternals.fMaxTextureSize);
841     GrPrintf("Max Render Target Size      : %d\n", fInternals.fMaxRenderTargetSize);
842 }
843