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