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