Home | History | Annotate | Download | only in src
      1 /*
      2     Copyright 2011 Google Inc.
      3 
      4     Licensed under the Apache License, Version 2.0 (the "License");
      5     you may not use this file except in compliance with the License.
      6     You may obtain a copy of the License at
      7 
      8          http://www.apache.org/licenses/LICENSE-2.0
      9 
     10     Unless required by applicable law or agreed to in writing, software
     11     distributed under the License is distributed on an "AS IS" BASIS,
     12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13     See the License for the specific language governing permissions and
     14     limitations under the License.
     15  */
     16 
     17 
     18 #include "GrInOrderDrawBuffer.h"
     19 #include "GrTexture.h"
     20 #include "GrBufferAllocPool.h"
     21 #include "GrIndexBuffer.h"
     22 #include "GrVertexBuffer.h"
     23 #include "GrGpu.h"
     24 
     25 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool,
     26                                          GrIndexBufferAllocPool* indexPool) :
     27         fDraws(&fDrawStorage),
     28         fStates(&fStateStorage),
     29         fClears(&fClearStorage),
     30         fClips(&fClipStorage),
     31         fClipSet(true),
     32 
     33         fLastRectVertexLayout(0),
     34         fQuadIndexBuffer(NULL),
     35         fMaxQuads(0),
     36         fCurrQuad(0),
     37 
     38         fVertexPool(*vertexPool),
     39         fCurrPoolVertexBuffer(NULL),
     40         fCurrPoolStartVertex(0),
     41         fIndexPool(*indexPool),
     42         fCurrPoolIndexBuffer(NULL),
     43         fCurrPoolStartIndex(0),
     44         fReservedVertexBytes(0),
     45         fReservedIndexBytes(0),
     46         fUsedReservedVertexBytes(0),
     47         fUsedReservedIndexBytes(0) {
     48     GrAssert(NULL != vertexPool);
     49     GrAssert(NULL != indexPool);
     50 }
     51 
     52 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
     53     this->reset();
     54     GrSafeUnref(fQuadIndexBuffer);
     55 }
     56 
     57 void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
     58     this->copyDrawState(target);
     59     this->setClip(target.getClip());
     60 }
     61 
     62 void GrInOrderDrawBuffer::setQuadIndexBuffer(const GrIndexBuffer* indexBuffer) {
     63     bool newIdxBuffer = fQuadIndexBuffer != indexBuffer;
     64     if (newIdxBuffer) {
     65         GrSafeUnref(fQuadIndexBuffer);
     66         fQuadIndexBuffer = indexBuffer;
     67         GrSafeRef(fQuadIndexBuffer);
     68         fCurrQuad = 0;
     69         fMaxQuads = (NULL == indexBuffer) ? 0 : indexBuffer->maxQuads();
     70     } else {
     71         GrAssert((NULL == indexBuffer && 0 == fMaxQuads) ||
     72                  (indexBuffer->maxQuads() == fMaxQuads));
     73     }
     74 }
     75 
     76 void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
     77                                    const GrMatrix* matrix,
     78                                    StageBitfield stageEnableBitfield,
     79                                    const GrRect* srcRects[],
     80                                    const GrMatrix* srcMatrices[]) {
     81 
     82     GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad));
     83     GrAssert(!(fDraws.empty() && fCurrQuad));
     84     GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer));
     85 
     86     // if we have a quad IB then either append to the previous run of
     87     // rects or start a new run
     88     if (fMaxQuads) {
     89 
     90         bool appendToPreviousDraw = false;
     91         GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects);
     92         AutoReleaseGeometry geo(this, layout, 4, 0);
     93         AutoViewMatrixRestore avmr(this);
     94         GrMatrix combinedMatrix = this->getViewMatrix();
     95         this->setViewMatrix(GrMatrix::I());
     96         if (NULL != matrix) {
     97             combinedMatrix.preConcat(*matrix);
     98         }
     99 
    100         SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices, layout, geo.vertices());
    101 
    102         // we don't want to miss an opportunity to batch rects together
    103         // simply because the clip has changed if the clip doesn't affect
    104         // the rect.
    105         bool disabledClip = false;
    106         if (this->isClipState() && fClip.isRect()) {
    107 
    108             GrRect clipRect = fClip.getRect(0);
    109             // If the clip rect touches the edge of the viewport, extended it
    110             // out (close) to infinity to avoid bogus intersections.
    111             // We might consider a more exact clip to viewport if this
    112             // conservative test fails.
    113             const GrRenderTarget* target = this->getRenderTarget();
    114             if (0 >= clipRect.fLeft) {
    115                 clipRect.fLeft = GR_ScalarMin;
    116             }
    117             if (target->width() <= clipRect.fRight) {
    118                 clipRect.fRight = GR_ScalarMax;
    119             }
    120             if (0 >= clipRect.top()) {
    121                 clipRect.fTop = GR_ScalarMin;
    122             }
    123             if (target->height() <= clipRect.fBottom) {
    124                 clipRect.fBottom = GR_ScalarMax;
    125             }
    126             int stride = VertexSize(layout);
    127             bool insideClip = true;
    128             for (int v = 0; v < 4; ++v) {
    129                 const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride);
    130                 if (!clipRect.contains(p)) {
    131                     insideClip = false;
    132                     break;
    133                 }
    134             }
    135             if (insideClip) {
    136                 this->disableState(kClip_StateBit);
    137                 disabledClip = true;
    138             }
    139         }
    140         if (!needsNewClip() && !needsNewState() && fCurrQuad > 0 &&
    141             fCurrQuad < fMaxQuads && layout == fLastRectVertexLayout) {
    142 
    143             int vsize = VertexSize(layout);
    144 
    145             Draw& lastDraw = fDraws.back();
    146 
    147             GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer);
    148             GrAssert(kTriangles_PrimitiveType == lastDraw.fPrimitiveType);
    149             GrAssert(0 == lastDraw.fVertexCount % 4);
    150             GrAssert(0 == lastDraw.fIndexCount % 6);
    151             GrAssert(0 == lastDraw.fStartIndex);
    152 
    153             bool clearSinceLastDraw =
    154                             fClears.count() &&
    155                             fClears.back().fBeforeDrawIdx == fDraws.count();
    156 
    157             appendToPreviousDraw =  !clearSinceLastDraw &&
    158                                     lastDraw.fVertexBuffer == fCurrPoolVertexBuffer &&
    159                                    (fCurrQuad * 4 + lastDraw.fStartVertex) == fCurrPoolStartVertex;
    160             if (appendToPreviousDraw) {
    161                 lastDraw.fVertexCount += 4;
    162                 lastDraw.fIndexCount += 6;
    163                 fCurrQuad += 1;
    164                 GrAssert(0 == fUsedReservedVertexBytes);
    165                 fUsedReservedVertexBytes = 4 * vsize;
    166             }
    167         }
    168         if (!appendToPreviousDraw) {
    169             this->setIndexSourceToBuffer(fQuadIndexBuffer);
    170             drawIndexed(kTriangles_PrimitiveType, 0, 0, 4, 6);
    171             fCurrQuad = 1;
    172             fLastRectVertexLayout = layout;
    173         }
    174         if (disabledClip) {
    175             this->enableState(kClip_StateBit);
    176         }
    177     } else {
    178         INHERITED::drawRect(rect, matrix, stageEnableBitfield, srcRects, srcMatrices);
    179     }
    180 }
    181 
    182 void GrInOrderDrawBuffer::drawIndexed(GrPrimitiveType primitiveType,
    183                                       int startVertex,
    184                                       int startIndex,
    185                                       int vertexCount,
    186                                       int indexCount) {
    187 
    188     if (!vertexCount || !indexCount) {
    189         return;
    190     }
    191 
    192     fCurrQuad = 0;
    193 
    194     Draw& draw = fDraws.push_back();
    195     draw.fPrimitiveType = primitiveType;
    196     draw.fStartVertex   = startVertex;
    197     draw.fStartIndex    = startIndex;
    198     draw.fVertexCount   = vertexCount;
    199     draw.fIndexCount    = indexCount;
    200 
    201     draw.fClipChanged = this->needsNewClip();
    202     if (draw.fClipChanged) {
    203        this->pushClip();
    204     }
    205 
    206     draw.fStateChanged = this->needsNewState();
    207     if (draw.fStateChanged) {
    208         this->pushState();
    209     }
    210 
    211     draw.fVertexLayout = fGeometrySrc.fVertexLayout;
    212     switch (fGeometrySrc.fVertexSrc) {
    213     case kBuffer_GeometrySrcType:
    214         draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
    215         break;
    216     case kReserved_GeometrySrcType: {
    217         size_t vertexBytes = (vertexCount + startVertex) *
    218         VertexSize(fGeometrySrc.fVertexLayout);
    219         fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes, vertexBytes);
    220     } // fallthrough
    221     case kArray_GeometrySrcType:
    222         draw.fVertexBuffer = fCurrPoolVertexBuffer;
    223         draw.fStartVertex += fCurrPoolStartVertex;
    224         break;
    225     default:
    226         GrCrash("unknown geom src type");
    227     }
    228     draw.fVertexBuffer->ref();
    229 
    230     switch (fGeometrySrc.fIndexSrc) {
    231     case kBuffer_GeometrySrcType:
    232         draw.fIndexBuffer = fGeometrySrc.fIndexBuffer;
    233         break;
    234     case kReserved_GeometrySrcType: {
    235         size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
    236         fUsedReservedIndexBytes = GrMax(fUsedReservedIndexBytes, indexBytes);
    237     } // fallthrough
    238     case kArray_GeometrySrcType:
    239         draw.fIndexBuffer = fCurrPoolIndexBuffer;
    240         draw.fStartIndex += fCurrPoolStartVertex;
    241         break;
    242     default:
    243         GrCrash("unknown geom src type");
    244     }
    245     draw.fIndexBuffer->ref();
    246 }
    247 
    248 void GrInOrderDrawBuffer::drawNonIndexed(GrPrimitiveType primitiveType,
    249                                          int startVertex,
    250                                          int vertexCount) {
    251     if (!vertexCount) {
    252         return;
    253     }
    254 
    255     fCurrQuad = 0;
    256 
    257     Draw& draw = fDraws.push_back();
    258     draw.fPrimitiveType = primitiveType;
    259     draw.fStartVertex   = startVertex;
    260     draw.fStartIndex    = 0;
    261     draw.fVertexCount   = vertexCount;
    262     draw.fIndexCount    = 0;
    263 
    264     draw.fClipChanged = this->needsNewClip();
    265     if (draw.fClipChanged) {
    266         this->pushClip();
    267     }
    268 
    269     draw.fStateChanged = this->needsNewState();
    270     if (draw.fStateChanged) {
    271         this->pushState();
    272     }
    273 
    274     draw.fVertexLayout = fGeometrySrc.fVertexLayout;
    275     switch (fGeometrySrc.fVertexSrc) {
    276     case kBuffer_GeometrySrcType:
    277         draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
    278         break;
    279     case kReserved_GeometrySrcType: {
    280         size_t vertexBytes = (vertexCount + startVertex) *
    281         VertexSize(fGeometrySrc.fVertexLayout);
    282         fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
    283                                          vertexBytes);
    284     } // fallthrough
    285     case kArray_GeometrySrcType:
    286         draw.fVertexBuffer = fCurrPoolVertexBuffer;
    287         draw.fStartVertex += fCurrPoolStartVertex;
    288         break;
    289     default:
    290         GrCrash("unknown geom src type");
    291     }
    292     draw.fVertexBuffer->ref();
    293     draw.fIndexBuffer = NULL;
    294 }
    295 
    296 void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) {
    297     GrIRect r;
    298     if (NULL == rect) {
    299         // We could do something smart and remove previous draws and clears to
    300         // the current render target. If we get that smart we have to make sure
    301         // those draws aren't read before this clear (render-to-texture).
    302         r.setLTRB(0, 0,
    303                   this->getRenderTarget()->width(),
    304                   this->getRenderTarget()->height());
    305         rect = &r;
    306     }
    307     Clear& clr = fClears.push_back();
    308     clr.fColor = color;
    309     clr.fBeforeDrawIdx = fDraws.count();
    310     clr.fRect = *rect;
    311 }
    312 
    313 void GrInOrderDrawBuffer::reset() {
    314     GrAssert(!fReservedGeometry.fLocked);
    315     uint32_t numStates = fStates.count();
    316     for (uint32_t i = 0; i < numStates; ++i) {
    317         const DrState& dstate = this->accessSavedDrawState(fStates[i]);
    318         for (int s = 0; s < kNumStages; ++s) {
    319             GrSafeUnref(dstate.fTextures[s]);
    320         }
    321         GrSafeUnref(dstate.fRenderTarget);
    322     }
    323     int numDraws = fDraws.count();
    324     for (int d = 0; d < numDraws; ++d) {
    325         // we always have a VB, but not always an IB
    326         GrAssert(NULL != fDraws[d].fVertexBuffer);
    327         fDraws[d].fVertexBuffer->unref();
    328         GrSafeUnref(fDraws[d].fIndexBuffer);
    329     }
    330     fDraws.reset();
    331     fStates.reset();
    332 
    333     fClears.reset();
    334 
    335     fVertexPool.reset();
    336     fIndexPool.reset();
    337 
    338     fClips.reset();
    339 
    340     fCurrQuad = 0;
    341 }
    342 
    343 void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
    344     GrAssert(!fReservedGeometry.fLocked);
    345     GrAssert(NULL != target);
    346     GrAssert(target != this); // not considered and why?
    347 
    348     int numDraws = fDraws.count();
    349     if (!numDraws) {
    350         return;
    351     }
    352 
    353     fVertexPool.unlock();
    354     fIndexPool.unlock();
    355 
    356     GrDrawTarget::AutoStateRestore asr(target);
    357     GrDrawTarget::AutoClipRestore acr(target);
    358     // important to not mess with reserve/lock geometry in the target with this
    359     // on the stack.
    360     GrDrawTarget::AutoGeometrySrcRestore agsr(target);
    361 
    362     int currState = ~0;
    363     int currClip  = ~0;
    364     int currClear = 0;
    365 
    366     for (int i = 0; i < numDraws; ++i) {
    367         while (currClear < fClears.count() &&
    368                i == fClears[currClear].fBeforeDrawIdx) {
    369             target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
    370             ++currClear;
    371         }
    372 
    373         const Draw& draw = fDraws[i];
    374         if (draw.fStateChanged) {
    375             ++currState;
    376             target->restoreDrawState(fStates[currState]);
    377         }
    378         if (draw.fClipChanged) {
    379             ++currClip;
    380             target->setClip(fClips[currClip]);
    381         }
    382 
    383         target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
    384 
    385         if (draw.fIndexCount) {
    386             target->setIndexSourceToBuffer(draw.fIndexBuffer);
    387         }
    388 
    389         if (draw.fIndexCount) {
    390             target->drawIndexed(draw.fPrimitiveType,
    391                                 draw.fStartVertex,
    392                                 draw.fStartIndex,
    393                                 draw.fVertexCount,
    394                                 draw.fIndexCount);
    395         } else {
    396             target->drawNonIndexed(draw.fPrimitiveType,
    397                                    draw.fStartVertex,
    398                                    draw.fVertexCount);
    399         }
    400     }
    401     while (currClear < fClears.count()) {
    402         GrAssert(fDraws.count() == fClears[currClear].fBeforeDrawIdx);
    403         target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
    404         ++currClear;
    405     }
    406 }
    407 
    408 bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
    409                                         int* vertexCount,
    410                                         int* indexCount) const {
    411     // we will recommend a flush if the data could fit in a single
    412     // preallocated buffer but none are left and it can't fit
    413     // in the current buffer (which may not be prealloced).
    414     bool flush = false;
    415     if (NULL != indexCount) {
    416         int32_t currIndices = fIndexPool.currentBufferIndices();
    417         if (*indexCount > currIndices &&
    418             (!fIndexPool.preallocatedBuffersRemaining() &&
    419              *indexCount <= fIndexPool.preallocatedBufferIndices())) {
    420 
    421             flush = true;
    422         }
    423         *indexCount = currIndices;
    424     }
    425     if (NULL != vertexCount) {
    426         int32_t currVertices = fVertexPool.currentBufferVertices(vertexLayout);
    427         if (*vertexCount > currVertices &&
    428             (!fVertexPool.preallocatedBuffersRemaining() &&
    429              *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexLayout))) {
    430 
    431             flush = true;
    432         }
    433         *vertexCount = currVertices;
    434     }
    435     return flush;
    436 }
    437 
    438 bool GrInOrderDrawBuffer::onAcquireGeometry(GrVertexLayout vertexLayout,
    439                                             void**         vertices,
    440                                             void**         indices) {
    441     GrAssert(!fReservedGeometry.fLocked);
    442     if (fReservedGeometry.fVertexCount) {
    443         GrAssert(NULL != vertices);
    444         GrAssert(0 == fReservedVertexBytes);
    445         GrAssert(0 == fUsedReservedVertexBytes);
    446 
    447         fReservedVertexBytes = VertexSize(vertexLayout) *
    448                                fReservedGeometry.fVertexCount;
    449         *vertices = fVertexPool.makeSpace(vertexLayout,
    450                                           fReservedGeometry.fVertexCount,
    451                                           &fCurrPoolVertexBuffer,
    452                                           &fCurrPoolStartVertex);
    453         if (NULL == *vertices) {
    454             return false;
    455         }
    456     }
    457     if (fReservedGeometry.fIndexCount) {
    458         GrAssert(NULL != indices);
    459         GrAssert(0 == fReservedIndexBytes);
    460         GrAssert(0 == fUsedReservedIndexBytes);
    461 
    462         *indices = fIndexPool.makeSpace(fReservedGeometry.fIndexCount,
    463                                         &fCurrPoolIndexBuffer,
    464                                         &fCurrPoolStartIndex);
    465         if (NULL == *indices) {
    466             fVertexPool.putBack(fReservedVertexBytes);
    467             fReservedVertexBytes = 0;
    468             fCurrPoolVertexBuffer = NULL;
    469             return false;
    470         }
    471     }
    472     return true;
    473 }
    474 
    475 void GrInOrderDrawBuffer::onReleaseGeometry() {
    476     GrAssert(fUsedReservedVertexBytes <= fReservedVertexBytes);
    477     GrAssert(fUsedReservedIndexBytes <= fReservedIndexBytes);
    478 
    479     size_t vertexSlack = fReservedVertexBytes - fUsedReservedVertexBytes;
    480     fVertexPool.putBack(vertexSlack);
    481 
    482     size_t indexSlack = fReservedIndexBytes - fUsedReservedIndexBytes;
    483     fIndexPool.putBack(indexSlack);
    484 
    485     fReservedVertexBytes = 0;
    486     fReservedIndexBytes  = 0;
    487     fUsedReservedVertexBytes = 0;
    488     fUsedReservedIndexBytes  = 0;
    489     fCurrPoolVertexBuffer = 0;
    490     fCurrPoolStartVertex = 0;
    491 
    492 }
    493 
    494 void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray,
    495                                                    int vertexCount) {
    496     GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
    497 #if GR_DEBUG
    498     bool success =
    499 #endif
    500     fVertexPool.appendVertices(fGeometrySrc.fVertexLayout,
    501                                vertexCount,
    502                                vertexArray,
    503                                &fCurrPoolVertexBuffer,
    504                                &fCurrPoolStartVertex);
    505     GR_DEBUGASSERT(success);
    506 }
    507 
    508 void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray,
    509                                                   int indexCount) {
    510     GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
    511 #if GR_DEBUG
    512     bool success =
    513 #endif
    514     fIndexPool.appendIndices(indexCount,
    515                              indexArray,
    516                              &fCurrPoolIndexBuffer,
    517                              &fCurrPoolStartIndex);
    518     GR_DEBUGASSERT(success);
    519 }
    520 
    521 bool GrInOrderDrawBuffer::needsNewState() const {
    522      if (fStates.empty()) {
    523         return true;
    524      } else {
    525          const DrState& old = this->accessSavedDrawState(fStates.back());
    526         return old != fCurrDrawState;
    527      }
    528 }
    529 
    530 void GrInOrderDrawBuffer::pushState() {
    531     for (int s = 0; s < kNumStages; ++s) {
    532         GrSafeRef(fCurrDrawState.fTextures[s]);
    533     }
    534     GrSafeRef(fCurrDrawState.fRenderTarget);
    535     this->saveCurrentDrawState(&fStates.push_back());
    536  }
    537 
    538 bool GrInOrderDrawBuffer::needsNewClip() const {
    539    if (fCurrDrawState.fFlagBits & kClip_StateBit) {
    540        if (fClips.empty() || (fClipSet && fClips.back() != fClip)) {
    541            return true;
    542        }
    543     }
    544     return false;
    545 }
    546 
    547 void GrInOrderDrawBuffer::pushClip() {
    548     fClips.push_back() = fClip;
    549     fClipSet = false;
    550 }
    551 
    552 void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip)  {
    553     fClipSet = true;
    554 }
    555