Home | History | Annotate | Download | only in gpu
      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 
     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
     49 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 
     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 
     74 void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
     75     fStartVertex += vertexOffset;
     76     SkASSERT(fStartVertex >= 0);
     77 }
     78 
     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 
     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 
    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 
    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 
    128 void GrDrawTarget::setClip(const GrClipData* clip) {
    129     clipWillBeSet(clip);
    130     fClip = clip;
    131 }
    132 
    133 const GrClipData* GrDrawTarget::getClip() const {
    134     return fClip;
    135 }
    136 
    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 
    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 
    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 
    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 
    219 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 
    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 
    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 
    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 
    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 
    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 
    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 
    312 void GrDrawTarget::resetVertexSource() {
    313     this->releasePreviousVertexSource();
    314     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    315     geoSrc.fVertexSrc = kNone_GeometrySrcType;
    316 }
    317 
    318 void GrDrawTarget::resetIndexSource() {
    319     this->releasePreviousIndexSource();
    320     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    321     geoSrc.fIndexSrc = kNone_GeometrySrcType;
    322 }
    323 
    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 
    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 
    349 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 
    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 
    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 
    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 
    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 
    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 
    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;
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    723 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
    724 }
    725 
    726 ////////////////////////////////////////////////////////////////////////////////
    727 
    728 GrDrawTarget::AutoStateRestore::AutoStateRestore() {
    729     fDrawTarget = NULL;
    730 }
    731 
    732 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
    733                                                  ASRInit init,
    734                                                  const SkMatrix* vm) {
    735     fDrawTarget = NULL;
    736     this->set(target, init, vm);
    737 }
    738 
    739 GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
    740     if (fDrawTarget) {
    741         fDrawTarget->setDrawState(fSavedState);
    742         fSavedState->unref();
    743     }
    744 }
    745 
    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 
    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 
    798 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
    799                                          GrDrawTarget*  target,
    800                                          int vertexCount,
    801                                          int indexCount) {
    802     fTarget = NULL;
    803     this->set(target, vertexCount, indexCount);
    804 }
    805 
    806 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
    807     fTarget = NULL;
    808 }
    809 
    810 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
    811     this->reset();
    812 }
    813 
    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 
    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 
    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.
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   1079 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 
   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