180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc. 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrGLIndexBuffer.h" 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrGpuGL.h" 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GPUGL static_cast<GrGpuGL*>(getGpu()) 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X) 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrGLIndexBuffer::GrGLIndexBuffer(GrGpuGL* gpu, 18d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger bool isWrapped, 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrGLuint id, 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t sizeInBytes, 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool dynamic) 22d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger : INHERITED(gpu, isWrapped, sizeInBytes, dynamic) 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fBufferID(id) 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fLockPtr(NULL) { 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGLIndexBuffer::onRelease() { 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // make sure we've not been abandoned 30d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger if (fBufferID && !this->isWrapped()) { 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GPUGL->notifyIndexBufferDelete(this); 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GL_CALL(DeleteBuffers(1, &fBufferID)); 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fBufferID = 0; 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru INHERITED::onRelease(); 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGLIndexBuffer::onAbandon() { 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fBufferID = 0; 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fLockPtr = NULL; 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru INHERITED::onAbandon(); 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGLIndexBuffer::bind() const { 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, fBufferID)); 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GPUGL->notifyIndexBufferBind(this); 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrGLuint GrGLIndexBuffer::bufferID() const { 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return fBufferID; 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid* GrGLIndexBuffer::lock() { 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(fBufferID); 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(!isLocked()); 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (this->getGpu()->getCaps().bufferLockSupport()) { 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->bind(); 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Let driver know it can discard the old data 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->sizeInBytes(), 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru NULL, 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->dynamic() ? GR_GL_DYNAMIC_DRAW : 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GR_GL_STATIC_DRAW)); 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GR_GL_CALL_RET(GPUGL->glInterface(), 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fLockPtr, 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru MapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GR_GL_WRITE_ONLY)); 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return fLockPtr; 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid* GrGLIndexBuffer::lockPtr() const { 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return fLockPtr; 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGLIndexBuffer::unlock() { 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(fBufferID); 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(isLocked()); 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(this->getGpu()->getCaps().bufferLockSupport()); 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->bind(); 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GL_CALL(UnmapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER)); 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fLockPtr = NULL; 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrGLIndexBuffer::isLocked() const { 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // this check causes a lot of noise in the gl log 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (this->isValid() && this->getGpu()->getCaps().fBufferLockSupport) { 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->bind(); 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrGLint mapped; 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GL_CALL(GetBufferParameteriv(GR_GL_ELEMENT_ARRAY_BUFFER, 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GR_GL_BUFFER_MAPPED, &mapped)); 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(!!mapped == !!fLockPtr); 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL != fLockPtr; 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrGLIndexBuffer::updateData(const void* src, size_t srcSizeInBytes) { 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(fBufferID); 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrAssert(!isLocked()); 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (srcSizeInBytes > this->sizeInBytes()) { 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->bind(); 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrGLenum usage = dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW; 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_GL_USE_BUFFER_DATA_NULL_HINT 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (this->sizeInBytes() == srcSizeInBytes) { 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru srcSizeInBytes, src, usage)); 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Before we call glBufferSubData we give the driver a hint using 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // glBufferData with NULL. This makes the old buffer contents 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // inaccessible to future draws. The GPU may still be processing 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // draws that reference the old contents. With this hint it can 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // assign a different allocation for the new contents to avoid 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // flushing the gpu past draws consuming the old contents. 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->sizeInBytes(), NULL, usage)); 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GL_CALL(BufferSubData(GR_GL_ELEMENT_ARRAY_BUFFER, 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0, srcSizeInBytes, src)); 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Note that we're cheating on the size here. Currently no methods 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // allow a partial update that preserves contents of non-updated 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // portions of the buffer (lock() does a glBufferData(..size, NULL..)) 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru srcSizeInBytes, src, usage)); 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 138