• 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 "GrContext.h"
13 #include "GrDrawTargetCaps.h"
14 #include "GrPath.h"
15 #include "GrRenderTarget.h"
16 #include "GrTexture.h"
17 #include "GrVertexBuffer.h"
18 
19 #include "SkStrokeRec.h"
20 
21 ////////////////////////////////////////////////////////////////////////////////
22 
operator =(const DrawInfo & di)23 GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
24     fPrimitiveType  = di.fPrimitiveType;
25     fStartVertex    = di.fStartVertex;
26     fStartIndex     = di.fStartIndex;
27     fVertexCount    = di.fVertexCount;
28     fIndexCount     = di.fIndexCount;
29 
30     fInstanceCount          = di.fInstanceCount;
31     fVerticesPerInstance    = di.fVerticesPerInstance;
32     fIndicesPerInstance     = di.fIndicesPerInstance;
33 
34     if (NULL != di.fDevBounds) {
35         SkASSERT(di.fDevBounds == &di.fDevBoundsStorage);
36         fDevBoundsStorage = di.fDevBoundsStorage;
37         fDevBounds = &fDevBoundsStorage;
38     } else {
39         fDevBounds = NULL;
40     }
41 
42     fDstCopy = di.fDstCopy;
43 
44     return *this;
45 }
46 
47 #ifdef SK_DEBUG
isInstanced() const48 bool GrDrawTarget::DrawInfo::isInstanced() const {
49     if (fInstanceCount > 0) {
50         SkASSERT(0 == fIndexCount % fIndicesPerInstance);
51         SkASSERT(0 == fVertexCount % fVerticesPerInstance);
52         SkASSERT(fIndexCount / fIndicesPerInstance == fInstanceCount);
53         SkASSERT(fVertexCount / fVerticesPerInstance == fInstanceCount);
54         // there is no way to specify a non-zero start index to drawIndexedInstances().
55         SkASSERT(0 == fStartIndex);
56         return true;
57     } else {
58         SkASSERT(!fVerticesPerInstance);
59         SkASSERT(!fIndicesPerInstance);
60         return false;
61     }
62 }
63 #endif
64 
adjustInstanceCount(int instanceOffset)65 void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
66     SkASSERT(this->isInstanced());
67     SkASSERT(instanceOffset + fInstanceCount >= 0);
68     fInstanceCount += instanceOffset;
69     fVertexCount = fVerticesPerInstance * fInstanceCount;
70     fIndexCount = fIndicesPerInstance * fInstanceCount;
71 }
72 
adjustStartVertex(int vertexOffset)73 void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
74     fStartVertex += vertexOffset;
75     SkASSERT(fStartVertex >= 0);
76 }
77 
adjustStartIndex(int indexOffset)78 void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
79     SkASSERT(this->isIndexed());
80     fStartIndex += indexOffset;
81     SkASSERT(fStartIndex >= 0);
82 }
83 
84 ////////////////////////////////////////////////////////////////////////////////
85 
86 #define DEBUG_INVAL_BUFFER 0xdeadcafe
87 #define DEBUG_INVAL_START_IDX -1
88 
GrDrawTarget(GrContext * context)89 GrDrawTarget::GrDrawTarget(GrContext* context)
90     : fClip(NULL)
91     , fContext(context) {
92     SkASSERT(NULL != context);
93 
94     fDrawState = &fDefaultDrawState;
95     // We assume that fDrawState always owns a ref to the object it points at.
96     fDefaultDrawState.ref();
97     GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
98 #ifdef SK_DEBUG
99     geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
100     geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
101     geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
102     geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
103 #endif
104     geoSrc.fVertexSrc = kNone_GeometrySrcType;
105     geoSrc.fIndexSrc  = kNone_GeometrySrcType;
106 }
107 
~GrDrawTarget()108 GrDrawTarget::~GrDrawTarget() {
109     SkASSERT(1 == fGeoSrcStateStack.count());
110     SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
111     SkASSERT(kNone_GeometrySrcType == geoSrc.fIndexSrc);
112     SkASSERT(kNone_GeometrySrcType == geoSrc.fVertexSrc);
113     fDrawState->unref();
114 }
115 
releaseGeometry()116 void GrDrawTarget::releaseGeometry() {
117     int popCnt = fGeoSrcStateStack.count() - 1;
118     while (popCnt) {
119         this->popGeometrySource();
120         --popCnt;
121     }
122     this->resetVertexSource();
123     this->resetIndexSource();
124 }
125 
setClip(const GrClipData * clip)126 void GrDrawTarget::setClip(const GrClipData* clip) {
127     clipWillBeSet(clip);
128     fClip = clip;
129 }
130 
getClip() const131 const GrClipData* GrDrawTarget::getClip() const {
132     return fClip;
133 }
134 
setDrawState(GrDrawState * drawState)135 void GrDrawTarget::setDrawState(GrDrawState*  drawState) {
136     SkASSERT(NULL != fDrawState);
137     if (NULL == drawState) {
138         drawState = &fDefaultDrawState;
139     }
140     if (fDrawState != drawState) {
141         fDrawState->unref();
142         drawState->ref();
143         fDrawState = drawState;
144     }
145 }
146 
reserveVertexSpace(size_t vertexSize,int vertexCount,void ** vertices)147 bool GrDrawTarget::reserveVertexSpace(size_t vertexSize,
148                                       int vertexCount,
149                                       void** vertices) {
150     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
151     bool acquired = false;
152     if (vertexCount > 0) {
153         SkASSERT(NULL != vertices);
154         this->releasePreviousVertexSource();
155         geoSrc.fVertexSrc = kNone_GeometrySrcType;
156 
157         acquired = this->onReserveVertexSpace(vertexSize,
158                                               vertexCount,
159                                               vertices);
160     }
161     if (acquired) {
162         geoSrc.fVertexSrc = kReserved_GeometrySrcType;
163         geoSrc.fVertexCount = vertexCount;
164         geoSrc.fVertexSize = vertexSize;
165     } else if (NULL != vertices) {
166         *vertices = NULL;
167     }
168     return acquired;
169 }
170 
reserveIndexSpace(int indexCount,void ** indices)171 bool GrDrawTarget::reserveIndexSpace(int indexCount,
172                                      void** indices) {
173     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
174     bool acquired = false;
175     if (indexCount > 0) {
176         SkASSERT(NULL != indices);
177         this->releasePreviousIndexSource();
178         geoSrc.fIndexSrc = kNone_GeometrySrcType;
179 
180         acquired = this->onReserveIndexSpace(indexCount, indices);
181     }
182     if (acquired) {
183         geoSrc.fIndexSrc = kReserved_GeometrySrcType;
184         geoSrc.fIndexCount = indexCount;
185     } else if (NULL != indices) {
186         *indices = NULL;
187     }
188     return acquired;
189 
190 }
191 
reserveVertexAndIndexSpace(int vertexCount,int indexCount,void ** vertices,void ** indices)192 bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount,
193                                               int indexCount,
194                                               void** vertices,
195                                               void** indices) {
196     size_t vertexSize = this->drawState()->getVertexSize();
197     this->willReserveVertexAndIndexSpace(vertexCount, indexCount);
198     if (vertexCount) {
199         if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) {
200             if (indexCount) {
201                 this->resetIndexSource();
202             }
203             return false;
204         }
205     }
206     if (indexCount) {
207         if (!this->reserveIndexSpace(indexCount, indices)) {
208             if (vertexCount) {
209                 this->resetVertexSource();
210             }
211             return false;
212         }
213     }
214     return true;
215 }
216 
geometryHints(int32_t * vertexCount,int32_t * indexCount) const217 bool GrDrawTarget::geometryHints(int32_t* vertexCount,
218                                  int32_t* indexCount) const {
219     if (NULL != vertexCount) {
220         *vertexCount = -1;
221     }
222     if (NULL != indexCount) {
223         *indexCount = -1;
224     }
225     return false;
226 }
227 
releasePreviousVertexSource()228 void GrDrawTarget::releasePreviousVertexSource() {
229     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
230     switch (geoSrc.fVertexSrc) {
231         case kNone_GeometrySrcType:
232             break;
233         case kArray_GeometrySrcType:
234             this->releaseVertexArray();
235             break;
236         case kReserved_GeometrySrcType:
237             this->releaseReservedVertexSpace();
238             break;
239         case kBuffer_GeometrySrcType:
240             geoSrc.fVertexBuffer->unref();
241 #ifdef SK_DEBUG
242             geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
243 #endif
244             break;
245         default:
246             GrCrash("Unknown Vertex Source Type.");
247             break;
248     }
249 }
250 
releasePreviousIndexSource()251 void GrDrawTarget::releasePreviousIndexSource() {
252     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
253     switch (geoSrc.fIndexSrc) {
254         case kNone_GeometrySrcType:   // these two don't require
255             break;
256         case kArray_GeometrySrcType:
257             this->releaseIndexArray();
258             break;
259         case kReserved_GeometrySrcType:
260             this->releaseReservedIndexSpace();
261             break;
262         case kBuffer_GeometrySrcType:
263             geoSrc.fIndexBuffer->unref();
264 #ifdef SK_DEBUG
265             geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
266 #endif
267             break;
268         default:
269             GrCrash("Unknown Index Source Type.");
270             break;
271     }
272 }
273 
setVertexSourceToArray(const void * vertexArray,int vertexCount)274 void GrDrawTarget::setVertexSourceToArray(const void* vertexArray,
275                                           int vertexCount) {
276     this->releasePreviousVertexSource();
277     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
278     geoSrc.fVertexSrc = kArray_GeometrySrcType;
279     geoSrc.fVertexSize = this->drawState()->getVertexSize();
280     geoSrc.fVertexCount = vertexCount;
281     this->onSetVertexSourceToArray(vertexArray, vertexCount);
282 }
283 
setIndexSourceToArray(const void * indexArray,int indexCount)284 void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
285                                          int indexCount) {
286     this->releasePreviousIndexSource();
287     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
288     geoSrc.fIndexSrc = kArray_GeometrySrcType;
289     geoSrc.fIndexCount = indexCount;
290     this->onSetIndexSourceToArray(indexArray, indexCount);
291 }
292 
setVertexSourceToBuffer(const GrVertexBuffer * buffer)293 void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) {
294     this->releasePreviousVertexSource();
295     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
296     geoSrc.fVertexSrc    = kBuffer_GeometrySrcType;
297     geoSrc.fVertexBuffer = buffer;
298     buffer->ref();
299     geoSrc.fVertexSize = this->drawState()->getVertexSize();
300 }
301 
setIndexSourceToBuffer(const GrIndexBuffer * buffer)302 void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
303     this->releasePreviousIndexSource();
304     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
305     geoSrc.fIndexSrc     = kBuffer_GeometrySrcType;
306     geoSrc.fIndexBuffer  = buffer;
307     buffer->ref();
308 }
309 
resetVertexSource()310 void GrDrawTarget::resetVertexSource() {
311     this->releasePreviousVertexSource();
312     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
313     geoSrc.fVertexSrc = kNone_GeometrySrcType;
314 }
315 
resetIndexSource()316 void GrDrawTarget::resetIndexSource() {
317     this->releasePreviousIndexSource();
318     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
319     geoSrc.fIndexSrc = kNone_GeometrySrcType;
320 }
321 
pushGeometrySource()322 void GrDrawTarget::pushGeometrySource() {
323     this->geometrySourceWillPush();
324     GeometrySrcState& newState = fGeoSrcStateStack.push_back();
325     newState.fIndexSrc = kNone_GeometrySrcType;
326     newState.fVertexSrc = kNone_GeometrySrcType;
327 #ifdef SK_DEBUG
328     newState.fVertexCount  = ~0;
329     newState.fVertexBuffer = (GrVertexBuffer*)~0;
330     newState.fIndexCount   = ~0;
331     newState.fIndexBuffer = (GrIndexBuffer*)~0;
332 #endif
333 }
334 
popGeometrySource()335 void GrDrawTarget::popGeometrySource() {
336     // if popping last element then pops are unbalanced with pushes
337     SkASSERT(fGeoSrcStateStack.count() > 1);
338 
339     this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
340     this->releasePreviousVertexSource();
341     this->releasePreviousIndexSource();
342     fGeoSrcStateStack.pop_back();
343 }
344 
345 ////////////////////////////////////////////////////////////////////////////////
346 
checkDraw(GrPrimitiveType type,int startVertex,int startIndex,int vertexCount,int indexCount) const347 bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
348                              int startIndex, int vertexCount,
349                              int indexCount) const {
350     const GrDrawState& drawState = this->getDrawState();
351 #ifdef SK_DEBUG
352     const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
353     int maxVertex = startVertex + vertexCount;
354     int maxValidVertex;
355     switch (geoSrc.fVertexSrc) {
356         case kNone_GeometrySrcType:
357             GrCrash("Attempting to draw without vertex src.");
358         case kReserved_GeometrySrcType: // fallthrough
359         case kArray_GeometrySrcType:
360             maxValidVertex = geoSrc.fVertexCount;
361             break;
362         case kBuffer_GeometrySrcType:
363             maxValidVertex = static_cast<int>(geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize);
364             break;
365     }
366     if (maxVertex > maxValidVertex) {
367         GrCrash("Drawing outside valid vertex range.");
368     }
369     if (indexCount > 0) {
370         int maxIndex = startIndex + indexCount;
371         int maxValidIndex;
372         switch (geoSrc.fIndexSrc) {
373             case kNone_GeometrySrcType:
374                 GrCrash("Attempting to draw indexed geom without index src.");
375             case kReserved_GeometrySrcType: // fallthrough
376             case kArray_GeometrySrcType:
377                 maxValidIndex = geoSrc.fIndexCount;
378                 break;
379             case kBuffer_GeometrySrcType:
380                 maxValidIndex = static_cast<int>(geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t));
381                 break;
382         }
383         if (maxIndex > maxValidIndex) {
384             GrCrash("Index reads outside valid index range.");
385         }
386     }
387 
388     SkASSERT(NULL != drawState.getRenderTarget());
389 
390     for (int s = 0; s < drawState.numColorStages(); ++s) {
391         const GrEffectRef& effect = *drawState.getColorStage(s).getEffect();
392         int numTextures = effect->numTextures();
393         for (int t = 0; t < numTextures; ++t) {
394             GrTexture* texture = effect->texture(t);
395             SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
396         }
397     }
398     for (int s = 0; s < drawState.numCoverageStages(); ++s) {
399         const GrEffectRef& effect = *drawState.getCoverageStage(s).getEffect();
400         int numTextures = effect->numTextures();
401         for (int t = 0; t < numTextures; ++t) {
402             GrTexture* texture = effect->texture(t);
403             SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
404         }
405     }
406 
407     SkASSERT(drawState.validateVertexAttribs());
408 #endif
409     if (NULL == drawState.getRenderTarget()) {
410         return false;
411     }
412     return true;
413 }
414 
setupDstReadIfNecessary(GrDeviceCoordTexture * dstCopy,const SkRect * drawBounds)415 bool GrDrawTarget::setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds) {
416     if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) {
417         return true;
418     }
419     GrRenderTarget* rt = this->drawState()->getRenderTarget();
420     SkIRect copyRect;
421     const GrClipData* clip = this->getClip();
422     clip->getConservativeBounds(rt, &copyRect);
423 
424     if (NULL != drawBounds) {
425         SkIRect drawIBounds;
426         drawBounds->roundOut(&drawIBounds);
427         if (!copyRect.intersect(drawIBounds)) {
428 #ifdef SK_DEBUG
429             GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n");
430 #endif
431             return false;
432         }
433     } else {
434 #ifdef SK_DEBUG
435         //GrPrintf("No dev bounds when dst copy is made.\n");
436 #endif
437     }
438 
439     // MSAA consideration: When there is support for reading MSAA samples in the shader we could
440     // have per-sample dst values by making the copy multisampled.
441     GrTextureDesc desc;
442     this->initCopySurfaceDstDesc(rt, &desc);
443     desc.fWidth = copyRect.width();
444     desc.fHeight = copyRect.height();
445 
446     GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch);
447 
448     if (NULL == ast.texture()) {
449         GrPrintf("Failed to create temporary copy of destination texture.\n");
450         return false;
451     }
452     SkIPoint dstPoint = {0, 0};
453     if (this->copySurface(ast.texture(), rt, copyRect, dstPoint)) {
454         dstCopy->setTexture(ast.texture());
455         dstCopy->setOffset(copyRect.fLeft, copyRect.fTop);
456         return true;
457     } else {
458         return false;
459     }
460 }
461 
drawIndexed(GrPrimitiveType type,int startVertex,int startIndex,int vertexCount,int indexCount,const SkRect * devBounds)462 void GrDrawTarget::drawIndexed(GrPrimitiveType type,
463                                int startVertex,
464                                int startIndex,
465                                int vertexCount,
466                                int indexCount,
467                                const SkRect* devBounds) {
468     if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
469         DrawInfo info;
470         info.fPrimitiveType = type;
471         info.fStartVertex   = startVertex;
472         info.fStartIndex    = startIndex;
473         info.fVertexCount   = vertexCount;
474         info.fIndexCount    = indexCount;
475 
476         info.fInstanceCount         = 0;
477         info.fVerticesPerInstance   = 0;
478         info.fIndicesPerInstance    = 0;
479 
480         if (NULL != devBounds) {
481             info.setDevBounds(*devBounds);
482         }
483         // TODO: We should continue with incorrect blending.
484         if (!this->setupDstReadIfNecessary(&info)) {
485             return;
486         }
487         this->onDraw(info);
488     }
489 }
490 
drawNonIndexed(GrPrimitiveType type,int startVertex,int vertexCount,const SkRect * devBounds)491 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
492                                   int startVertex,
493                                   int vertexCount,
494                                   const SkRect* devBounds) {
495     if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
496         DrawInfo info;
497         info.fPrimitiveType = type;
498         info.fStartVertex   = startVertex;
499         info.fStartIndex    = 0;
500         info.fVertexCount   = vertexCount;
501         info.fIndexCount    = 0;
502 
503         info.fInstanceCount         = 0;
504         info.fVerticesPerInstance   = 0;
505         info.fIndicesPerInstance    = 0;
506 
507         if (NULL != devBounds) {
508             info.setDevBounds(*devBounds);
509         }
510         // TODO: We should continue with incorrect blending.
511         if (!this->setupDstReadIfNecessary(&info)) {
512             return;
513         }
514         this->onDraw(info);
515     }
516 }
517 
stencilPath(const GrPath * path,SkPath::FillType fill)518 void GrDrawTarget::stencilPath(const GrPath* path, SkPath::FillType fill) {
519     // TODO: extract portions of checkDraw that are relevant to path stenciling.
520     SkASSERT(NULL != path);
521     SkASSERT(this->caps()->pathRenderingSupport());
522     SkASSERT(!SkPath::IsInverseFillType(fill));
523     this->onStencilPath(path, fill);
524 }
525 
drawPath(const GrPath * path,SkPath::FillType fill)526 void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) {
527     // TODO: extract portions of checkDraw that are relevant to path rendering.
528     SkASSERT(NULL != path);
529     SkASSERT(this->caps()->pathRenderingSupport());
530     const GrDrawState* drawState = &getDrawState();
531 
532     SkRect devBounds;
533     if (SkPath::IsInverseFillType(fill)) {
534         devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()),
535                                    SkIntToScalar(drawState->getRenderTarget()->height()));
536     } else {
537         devBounds = path->getBounds();
538     }
539     SkMatrix viewM = drawState->getViewMatrix();
540     viewM.mapRect(&devBounds);
541 
542     GrDeviceCoordTexture dstCopy;
543     if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) {
544         return;
545     }
546 
547     this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL);
548 }
549 
550 ////////////////////////////////////////////////////////////////////////////////
551 
willUseHWAALines() const552 bool GrDrawTarget::willUseHWAALines() const {
553     // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
554     // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
555     // our alpha is 0xff and tweaking the color for partial coverage is OK
556     if (!this->caps()->hwAALineSupport() ||
557         !this->getDrawState().isHWAntialiasState()) {
558         return false;
559     }
560     GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts();
561     return (GrDrawState::kDisableBlend_BlendOptFlag & opts) &&
562            (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts);
563 }
564 
canApplyCoverage() const565 bool GrDrawTarget::canApplyCoverage() const {
566     // we can correctly apply coverage if a) we have dual source blending
567     // or b) one of our blend optimizations applies.
568     return this->caps()->dualSourceBlendingSupport() ||
569            GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
570 }
571 
572 ////////////////////////////////////////////////////////////////////////////////
573 
drawIndexedInstances(GrPrimitiveType type,int instanceCount,int verticesPerInstance,int indicesPerInstance,const SkRect * devBounds)574 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
575                                         int instanceCount,
576                                         int verticesPerInstance,
577                                         int indicesPerInstance,
578                                         const SkRect* devBounds) {
579     if (!verticesPerInstance || !indicesPerInstance) {
580         return;
581     }
582 
583     int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
584     if (!maxInstancesPerDraw) {
585         return;
586     }
587 
588     DrawInfo info;
589     info.fPrimitiveType = type;
590     info.fStartIndex = 0;
591     info.fStartVertex = 0;
592     info.fIndicesPerInstance = indicesPerInstance;
593     info.fVerticesPerInstance = verticesPerInstance;
594 
595     // Set the same bounds for all the draws.
596     if (NULL != devBounds) {
597         info.setDevBounds(*devBounds);
598     }
599     // TODO: We should continue with incorrect blending.
600     if (!this->setupDstReadIfNecessary(&info)) {
601         return;
602     }
603 
604     while (instanceCount) {
605         info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
606         info.fVertexCount = info.fInstanceCount * verticesPerInstance;
607         info.fIndexCount = info.fInstanceCount * indicesPerInstance;
608 
609         if (this->checkDraw(type,
610                             info.fStartVertex,
611                             info.fStartIndex,
612                             info.fVertexCount,
613                             info.fIndexCount)) {
614             this->onDraw(info);
615         }
616         info.fStartVertex += info.fVertexCount;
617         instanceCount -= info.fInstanceCount;
618     }
619 }
620 
621 ////////////////////////////////////////////////////////////////////////////////
622 
623 namespace {
624 
625 // position + (optional) texture coord
626 extern const GrVertexAttrib gBWRectPosUVAttribs[] = {
627     {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
628     {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
629 };
630 
set_vertex_attributes(GrDrawState * drawState,bool hasUVs)631 void set_vertex_attributes(GrDrawState* drawState, bool hasUVs) {
632     if (hasUVs) {
633         drawState->setVertexAttribs<gBWRectPosUVAttribs>(2);
634     } else {
635         drawState->setVertexAttribs<gBWRectPosUVAttribs>(1);
636     }
637 }
638 
639 };
640 
onDrawRect(const SkRect & rect,const SkMatrix * matrix,const SkRect * localRect,const SkMatrix * localMatrix)641 void GrDrawTarget::onDrawRect(const SkRect& rect,
642                               const SkMatrix* matrix,
643                               const SkRect* localRect,
644                               const SkMatrix* localMatrix) {
645 
646     GrDrawState::AutoViewMatrixRestore avmr;
647     if (NULL != matrix) {
648         avmr.set(this->drawState(), *matrix);
649     }
650 
651     set_vertex_attributes(this->drawState(), NULL != localRect);
652 
653     AutoReleaseGeometry geo(this, 4, 0);
654     if (!geo.succeeded()) {
655         GrPrintf("Failed to get space for vertices!\n");
656         return;
657     }
658 
659     size_t vsize = this->drawState()->getVertexSize();
660     geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
661     if (NULL != localRect) {
662         GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
663                                             sizeof(GrPoint));
664         coords->setRectFan(localRect->fLeft, localRect->fTop,
665                            localRect->fRight, localRect->fBottom,
666                            vsize);
667         if (NULL != localMatrix) {
668             localMatrix->mapPointsWithStride(coords, vsize, 4);
669         }
670     }
671     SkTLazy<SkRect> bounds;
672     if (this->getDrawState().willEffectReadDstColor()) {
673         bounds.init();
674         this->getDrawState().getViewMatrix().mapRect(bounds.get(), rect);
675     }
676 
677     this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, bounds.getMaybeNull());
678 }
679 
clipWillBeSet(const GrClipData * clipData)680 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
681 }
682 
683 ////////////////////////////////////////////////////////////////////////////////
684 
AutoStateRestore()685 GrDrawTarget::AutoStateRestore::AutoStateRestore() {
686     fDrawTarget = NULL;
687 }
688 
AutoStateRestore(GrDrawTarget * target,ASRInit init,const SkMatrix * vm)689 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
690                                                  ASRInit init,
691                                                  const SkMatrix* vm) {
692     fDrawTarget = NULL;
693     this->set(target, init, vm);
694 }
695 
~AutoStateRestore()696 GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
697     if (NULL != fDrawTarget) {
698         fDrawTarget->setDrawState(fSavedState);
699         fSavedState->unref();
700     }
701 }
702 
set(GrDrawTarget * target,ASRInit init,const SkMatrix * vm)703 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) {
704     SkASSERT(NULL == fDrawTarget);
705     fDrawTarget = target;
706     fSavedState = target->drawState();
707     SkASSERT(fSavedState);
708     fSavedState->ref();
709     if (kReset_ASRInit == init) {
710         if (NULL == vm) {
711             // calls the default cons
712             fTempState.init();
713         } else {
714             SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm));
715         }
716     } else {
717         SkASSERT(kPreserve_ASRInit == init);
718         if (NULL == vm) {
719             fTempState.set(*fSavedState);
720         } else {
721             SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm));
722         }
723     }
724     target->setDrawState(fTempState.get());
725 }
726 
setIdentity(GrDrawTarget * target,ASRInit init)727 bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) {
728     SkASSERT(NULL == fDrawTarget);
729     fDrawTarget = target;
730     fSavedState = target->drawState();
731     SkASSERT(fSavedState);
732     fSavedState->ref();
733     if (kReset_ASRInit == init) {
734         // calls the default cons
735         fTempState.init();
736     } else {
737         SkASSERT(kPreserve_ASRInit == init);
738         // calls the copy cons
739         fTempState.set(*fSavedState);
740         if (!fTempState.get()->setIdentityViewMatrix()) {
741             // let go of any resources held by the temp
742             fTempState.get()->reset();
743             fDrawTarget = NULL;
744             fSavedState->unref();
745             fSavedState = NULL;
746             return false;
747         }
748     }
749     target->setDrawState(fTempState.get());
750     return true;
751 }
752 
753 ////////////////////////////////////////////////////////////////////////////////
754 
AutoReleaseGeometry(GrDrawTarget * target,int vertexCount,int indexCount)755 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
756                                          GrDrawTarget*  target,
757                                          int vertexCount,
758                                          int indexCount) {
759     fTarget = NULL;
760     this->set(target, vertexCount, indexCount);
761 }
762 
AutoReleaseGeometry()763 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
764     fTarget = NULL;
765 }
766 
~AutoReleaseGeometry()767 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
768     this->reset();
769 }
770 
set(GrDrawTarget * target,int vertexCount,int indexCount)771 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
772                                             int vertexCount,
773                                             int indexCount) {
774     this->reset();
775     fTarget = target;
776     bool success = true;
777     if (NULL != fTarget) {
778         fTarget = target;
779         success = target->reserveVertexAndIndexSpace(vertexCount,
780                                                      indexCount,
781                                                      &fVertices,
782                                                      &fIndices);
783         if (!success) {
784             fTarget = NULL;
785             this->reset();
786         }
787     }
788     SkASSERT(success == (NULL != fTarget));
789     return success;
790 }
791 
reset()792 void GrDrawTarget::AutoReleaseGeometry::reset() {
793     if (NULL != fTarget) {
794         if (NULL != fVertices) {
795             fTarget->resetVertexSource();
796         }
797         if (NULL != fIndices) {
798             fTarget->resetIndexSource();
799         }
800         fTarget = NULL;
801     }
802     fVertices = NULL;
803     fIndices = NULL;
804 }
805 
AutoClipRestore(GrDrawTarget * target,const SkIRect & newClip)806 GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
807     fTarget = target;
808     fClip = fTarget->getClip();
809     fStack.init();
810     fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
811     fReplacementClip.fClipStack = fStack.get();
812     target->setClip(&fReplacementClip);
813 }
814 
815 namespace {
816 // returns true if the read/written rect intersects the src/dst and false if not.
clip_srcrect_and_dstpoint(const GrSurface * dst,const GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint,SkIRect * clippedSrcRect,SkIPoint * clippedDstPoint)817 bool clip_srcrect_and_dstpoint(const GrSurface* dst,
818                                const GrSurface* src,
819                                const SkIRect& srcRect,
820                                const SkIPoint& dstPoint,
821                                SkIRect* clippedSrcRect,
822                                SkIPoint* clippedDstPoint) {
823     *clippedSrcRect = srcRect;
824     *clippedDstPoint = dstPoint;
825 
826     // clip the left edge to src and dst bounds, adjusting dstPoint if necessary
827     if (clippedSrcRect->fLeft < 0) {
828         clippedDstPoint->fX -= clippedSrcRect->fLeft;
829         clippedSrcRect->fLeft = 0;
830     }
831     if (clippedDstPoint->fX < 0) {
832         clippedSrcRect->fLeft -= clippedDstPoint->fX;
833         clippedDstPoint->fX = 0;
834     }
835 
836     // clip the top edge to src and dst bounds, adjusting dstPoint if necessary
837     if (clippedSrcRect->fTop < 0) {
838         clippedDstPoint->fY -= clippedSrcRect->fTop;
839         clippedSrcRect->fTop = 0;
840     }
841     if (clippedDstPoint->fY < 0) {
842         clippedSrcRect->fTop -= clippedDstPoint->fY;
843         clippedDstPoint->fY = 0;
844     }
845 
846     // clip the right edge to the src and dst bounds.
847     if (clippedSrcRect->fRight > src->width()) {
848         clippedSrcRect->fRight = src->width();
849     }
850     if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
851         clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
852     }
853 
854     // clip the bottom edge to the src and dst bounds.
855     if (clippedSrcRect->fBottom > src->height()) {
856         clippedSrcRect->fBottom = src->height();
857     }
858     if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
859         clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
860     }
861 
862     // The above clipping steps may have inverted the rect if it didn't intersect either the src or
863     // dst bounds.
864     return !clippedSrcRect->isEmpty();
865 }
866 }
867 
copySurface(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)868 bool GrDrawTarget::copySurface(GrSurface* dst,
869                                GrSurface* src,
870                                const SkIRect& srcRect,
871                                const SkIPoint& dstPoint) {
872     SkASSERT(NULL != dst);
873     SkASSERT(NULL != src);
874 
875     SkIRect clippedSrcRect;
876     SkIPoint clippedDstPoint;
877     // If the rect is outside the src or dst then we've already succeeded.
878     if (!clip_srcrect_and_dstpoint(dst,
879                                    src,
880                                    srcRect,
881                                    dstPoint,
882                                    &clippedSrcRect,
883                                    &clippedDstPoint)) {
884         SkASSERT(this->canCopySurface(dst, src, srcRect, dstPoint));
885         return true;
886     }
887 
888     bool result = this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
889     SkASSERT(result == this->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint));
890     return result;
891 }
892 
canCopySurface(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)893 bool GrDrawTarget::canCopySurface(GrSurface* dst,
894                                   GrSurface* src,
895                                   const SkIRect& srcRect,
896                                   const SkIPoint& dstPoint) {
897     SkASSERT(NULL != dst);
898     SkASSERT(NULL != src);
899 
900     SkIRect clippedSrcRect;
901     SkIPoint clippedDstPoint;
902     // If the rect is outside the src or dst then we're guaranteed success
903     if (!clip_srcrect_and_dstpoint(dst,
904                                    src,
905                                    srcRect,
906                                    dstPoint,
907                                    &clippedSrcRect,
908                                    &clippedDstPoint)) {
909         return true;
910     }
911     return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
912 }
913 
onCanCopySurface(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)914 bool GrDrawTarget::onCanCopySurface(GrSurface* dst,
915                                     GrSurface* src,
916                                     const SkIRect& srcRect,
917                                     const SkIPoint& dstPoint) {
918     // Check that the read/write rects are contained within the src/dst bounds.
919     SkASSERT(!srcRect.isEmpty());
920     SkASSERT(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect));
921     SkASSERT(dstPoint.fX >= 0 && dstPoint.fY >= 0);
922     SkASSERT(dstPoint.fX + srcRect.width() <= dst->width() &&
923              dstPoint.fY + srcRect.height() <= dst->height());
924 
925     return !dst->isSameAs(src) && NULL != dst->asRenderTarget() && NULL != src->asTexture();
926 }
927 
onCopySurface(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)928 bool GrDrawTarget::onCopySurface(GrSurface* dst,
929                                  GrSurface* src,
930                                  const SkIRect& srcRect,
931                                  const SkIPoint& dstPoint) {
932     if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) {
933         return false;
934     }
935 
936     GrRenderTarget* rt = dst->asRenderTarget();
937     GrTexture* tex = src->asTexture();
938 
939     GrDrawTarget::AutoStateRestore asr(this, kReset_ASRInit);
940     this->drawState()->setRenderTarget(rt);
941     SkMatrix matrix;
942     matrix.setTranslate(SkIntToScalar(srcRect.fLeft - dstPoint.fX),
943                         SkIntToScalar(srcRect.fTop - dstPoint.fY));
944     matrix.postIDiv(tex->width(), tex->height());
945     this->drawState()->addColorTextureEffect(tex, matrix);
946     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX,
947                                         dstPoint.fY,
948                                         srcRect.width(),
949                                         srcRect.height());
950     this->drawSimpleRect(dstRect);
951     return true;
952 }
953 
initCopySurfaceDstDesc(const GrSurface * src,GrTextureDesc * desc)954 void GrDrawTarget::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) {
955     // Make the dst of the copy be a render target because the default copySurface draws to the dst.
956     desc->fOrigin = kDefault_GrSurfaceOrigin;
957     desc->fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
958     desc->fConfig = src->config();
959 }
960 
961 ///////////////////////////////////////////////////////////////////////////////
962 
reset()963 void GrDrawTargetCaps::reset() {
964     f8BitPaletteSupport = false;
965     fNPOTTextureTileSupport = false;
966     fTwoSidedStencilSupport = false;
967     fStencilWrapOpsSupport = false;
968     fHWAALineSupport = false;
969     fShaderDerivativeSupport = false;
970     fGeometryShaderSupport = false;
971     fDualSourceBlendingSupport = false;
972     fBufferLockSupport = false;
973     fPathRenderingSupport = false;
974     fDstReadInShaderSupport = false;
975     fReuseScratchTextures = true;
976 
977     fMaxRenderTargetSize = 0;
978     fMaxTextureSize = 0;
979     fMaxSampleCount = 0;
980 
981     memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
982 }
983 
operator =(const GrDrawTargetCaps & other)984 GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
985     f8BitPaletteSupport = other.f8BitPaletteSupport;
986     fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
987     fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
988     fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
989     fHWAALineSupport = other.fHWAALineSupport;
990     fShaderDerivativeSupport = other.fShaderDerivativeSupport;
991     fGeometryShaderSupport = other.fGeometryShaderSupport;
992     fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
993     fBufferLockSupport = other.fBufferLockSupport;
994     fPathRenderingSupport = other.fPathRenderingSupport;
995     fDstReadInShaderSupport = other.fDstReadInShaderSupport;
996     fReuseScratchTextures = other.fReuseScratchTextures;
997 
998     fMaxRenderTargetSize = other.fMaxRenderTargetSize;
999     fMaxTextureSize = other.fMaxTextureSize;
1000     fMaxSampleCount = other.fMaxSampleCount;
1001 
1002     memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport));
1003 
1004     return *this;
1005 }
1006 
dump() const1007 SkString GrDrawTargetCaps::dump() const {
1008     SkString r;
1009     static const char* gNY[] = {"NO", "YES"};
1010     r.appendf("8 Bit Palette Support       : %s\n", gNY[f8BitPaletteSupport]);
1011     r.appendf("NPOT Texture Tile Support   : %s\n", gNY[fNPOTTextureTileSupport]);
1012     r.appendf("Two Sided Stencil Support   : %s\n", gNY[fTwoSidedStencilSupport]);
1013     r.appendf("Stencil Wrap Ops  Support   : %s\n", gNY[fStencilWrapOpsSupport]);
1014     r.appendf("HW AA Lines Support         : %s\n", gNY[fHWAALineSupport]);
1015     r.appendf("Shader Derivative Support   : %s\n", gNY[fShaderDerivativeSupport]);
1016     r.appendf("Geometry Shader Support     : %s\n", gNY[fGeometryShaderSupport]);
1017     r.appendf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1018     r.appendf("Buffer Lock Support         : %s\n", gNY[fBufferLockSupport]);
1019     r.appendf("Path Rendering Support      : %s\n", gNY[fPathRenderingSupport]);
1020     r.appendf("Dst Read In Shader Support  : %s\n", gNY[fDstReadInShaderSupport]);
1021     r.appendf("Reuse Scratch Textures      : %s\n", gNY[fReuseScratchTextures]);
1022     r.appendf("Max Texture Size            : %d\n", fMaxTextureSize);
1023     r.appendf("Max Render Target Size      : %d\n", fMaxRenderTargetSize);
1024     r.appendf("Max Sample Count            : %d\n", fMaxSampleCount);
1025 
1026     static const char* kConfigNames[] = {
1027         "Unknown",  // kUnknown_GrPixelConfig
1028         "Alpha8",   // kAlpha_8_GrPixelConfig,
1029         "Index8",   // kIndex_8_GrPixelConfig,
1030         "RGB565",   // kRGB_565_GrPixelConfig,
1031         "RGBA444",  // kRGBA_4444_GrPixelConfig,
1032         "RGBA8888", // kRGBA_8888_GrPixelConfig,
1033         "BGRA8888", // kBGRA_8888_GrPixelConfig,
1034     };
1035     GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
1036     GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
1037     GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig);
1038     GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig);
1039     GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig);
1040     GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
1041     GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
1042     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
1043 
1044     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
1045     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]);
1046     for (size_t i = 0; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
1047         if (i != kUnknown_GrPixelConfig) {
1048             r.appendf("%s is renderable: %s, with MSAA: %s\n",
1049                      kConfigNames[i],
1050                      gNY[fConfigRenderSupport[i][0]],
1051                      gNY[fConfigRenderSupport[i][1]]);
1052         }
1053     }
1054     return r;
1055 }
1056