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