Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 
      9 
     10 #include "GrGLIndexBuffer.h"
     11 #include "GrGpuGL.h"
     12 
     13 #define GPUGL static_cast<GrGpuGL*>(getGpu())
     14 
     15 #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
     16 
     17 GrGLIndexBuffer::GrGLIndexBuffer(GrGpuGL* gpu,
     18                                  bool isWrapped,
     19                                  GrGLuint id,
     20                                  size_t sizeInBytes,
     21                                  bool dynamic)
     22     : INHERITED(gpu, isWrapped, sizeInBytes, dynamic)
     23     , fBufferID(id)
     24     , fLockPtr(NULL) {
     25 
     26 }
     27 
     28 void GrGLIndexBuffer::onRelease() {
     29     // make sure we've not been abandoned
     30     if (fBufferID && !this->isWrapped()) {
     31         GPUGL->notifyIndexBufferDelete(this);
     32         GL_CALL(DeleteBuffers(1, &fBufferID));
     33         fBufferID = 0;
     34     }
     35 
     36     INHERITED::onRelease();
     37 }
     38 
     39 void GrGLIndexBuffer::onAbandon() {
     40     fBufferID = 0;
     41     fLockPtr = NULL;
     42 
     43     INHERITED::onAbandon();
     44 }
     45 
     46 void GrGLIndexBuffer::bind() const {
     47     GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, fBufferID));
     48     GPUGL->notifyIndexBufferBind(this);
     49 }
     50 
     51 GrGLuint GrGLIndexBuffer::bufferID() const {
     52     return fBufferID;
     53 }
     54 
     55 void* GrGLIndexBuffer::lock() {
     56     GrAssert(fBufferID);
     57     GrAssert(!isLocked());
     58     if (this->getGpu()->getCaps().bufferLockSupport()) {
     59         this->bind();
     60         // Let driver know it can discard the old data
     61         GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
     62                            this->sizeInBytes(),
     63                            NULL,
     64                            this->dynamic() ? GR_GL_DYNAMIC_DRAW :
     65                                              GR_GL_STATIC_DRAW));
     66         GR_GL_CALL_RET(GPUGL->glInterface(),
     67                        fLockPtr,
     68                        MapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
     69                                  GR_GL_WRITE_ONLY));
     70 
     71         return fLockPtr;
     72     }
     73     return NULL;
     74 }
     75 
     76 void* GrGLIndexBuffer::lockPtr() const {
     77     return fLockPtr;
     78 }
     79 
     80 void GrGLIndexBuffer::unlock() {
     81     GrAssert(fBufferID);
     82     GrAssert(isLocked());
     83     GrAssert(this->getGpu()->getCaps().bufferLockSupport());
     84 
     85     this->bind();
     86     GL_CALL(UnmapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER));
     87     fLockPtr = NULL;
     88 }
     89 
     90 bool GrGLIndexBuffer::isLocked() const {
     91     // this check causes a lot of noise in the gl log
     92 #if 0
     93     if (this->isValid() && this->getGpu()->getCaps().fBufferLockSupport) {
     94         this->bind();
     95         GrGLint mapped;
     96         GL_CALL(GetBufferParameteriv(GR_GL_ELEMENT_ARRAY_BUFFER,
     97                                      GR_GL_BUFFER_MAPPED, &mapped));
     98         GrAssert(!!mapped == !!fLockPtr);
     99     }
    100 #endif
    101     return NULL != fLockPtr;
    102 }
    103 
    104 bool GrGLIndexBuffer::updateData(const void* src, size_t srcSizeInBytes) {
    105     GrAssert(fBufferID);
    106     GrAssert(!isLocked());
    107     if (srcSizeInBytes > this->sizeInBytes()) {
    108         return false;
    109     }
    110     this->bind();
    111     GrGLenum usage = dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW;
    112 
    113 #if GR_GL_USE_BUFFER_DATA_NULL_HINT
    114     if (this->sizeInBytes() == srcSizeInBytes) {
    115         GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
    116                             srcSizeInBytes, src, usage));
    117     } else {
    118         // Before we call glBufferSubData we give the driver a hint using
    119         // glBufferData with NULL. This makes the old buffer contents
    120         // inaccessible to future draws. The GPU may still be processing
    121         // draws that reference the old contents. With this hint it can
    122         // assign a different allocation for the new contents to avoid
    123         // flushing the gpu past draws consuming the old contents.
    124         GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
    125                            this->sizeInBytes(), NULL, usage));
    126         GL_CALL(BufferSubData(GR_GL_ELEMENT_ARRAY_BUFFER,
    127                               0, srcSizeInBytes, src));
    128     }
    129 #else
    130     // Note that we're cheating on the size here. Currently no methods
    131     // allow a partial update that preserves contents of non-updated
    132     // portions of the buffer (lock() does a glBufferData(..size, NULL..))
    133     GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
    134                        srcSizeInBytes, src, usage));
    135 #endif
    136     return true;
    137 }
    138