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