• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GrGLIndexBuffer(GrGpuGL * gpu,bool isWrapped,GrGLuint id,size_t sizeInBytes,bool dynamic)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 
onRelease()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 
onAbandon()39 void GrGLIndexBuffer::onAbandon() {
40     fBufferID = 0;
41     fLockPtr = NULL;
42 
43     INHERITED::onAbandon();
44 }
45 
bind() const46 void GrGLIndexBuffer::bind() const {
47     GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, fBufferID));
48     GPUGL->notifyIndexBufferBind(this);
49 }
50 
bufferID() const51 GrGLuint GrGLIndexBuffer::bufferID() const {
52     return fBufferID;
53 }
54 
lock()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 
lockPtr() const76 void* GrGLIndexBuffer::lockPtr() const {
77     return fLockPtr;
78 }
79 
unlock()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 
isLocked() const90 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 
updateData(const void * src,size_t srcSizeInBytes)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