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