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