From e49ad45404adf43c585bdf625ce05e2d61c28e9f Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Wed, 20 Feb 2013 19:33:20 +0000 Subject: Add GrGLBufferImpl to unify implementation of GrGLVertexBuffer and GrGLIndexBuffer. Review URL: https://codereview.appspot.com/7346055 git-svn-id: http://skia.googlecode.com/svn/trunk@7798 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gyp/gpu.gypi | 2 + src/gpu/gl/GrGLBufferImpl.cpp | 131 ++++++++++++++++++++++++++++++++++++++++ src/gpu/gl/GrGLBufferImpl.h | 57 +++++++++++++++++ src/gpu/gl/GrGLIndexBuffer.cpp | 112 ++++++---------------------------- src/gpu/gl/GrGLIndexBuffer.h | 29 ++++----- src/gpu/gl/GrGLVertexBuffer.cpp | 125 ++++++-------------------------------- src/gpu/gl/GrGLVertexBuffer.h | 28 +++++---- src/gpu/gl/GrGpuGL.cpp | 68 ++++++++++----------- src/gpu/gl/GrGpuGL.h | 14 ++--- 9 files changed, 298 insertions(+), 268 deletions(-) create mode 100644 src/gpu/gl/GrGLBufferImpl.cpp create mode 100644 src/gpu/gl/GrGLBufferImpl.h diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 62137a0e81..93ccd422f0 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -134,6 +134,8 @@ '<(skia_src_path)/gpu/effects/GrTextureDomainEffect.cpp', '<(skia_src_path)/gpu/effects/GrTextureDomainEffect.h', + '<(skia_src_path)/gpu/gl/GrGLBufferImpl.cpp', + '<(skia_src_path)/gpu/gl/GrGLBufferImpl.h', '<(skia_src_path)/gpu/gl/GrGLCaps.cpp', '<(skia_src_path)/gpu/gl/GrGLCaps.h', '<(skia_src_path)/gpu/gl/GrGLContextInfo.cpp', diff --git a/src/gpu/gl/GrGLBufferImpl.cpp b/src/gpu/gl/GrGLBufferImpl.cpp new file mode 100644 index 0000000000..0ab83fb77a --- /dev/null +++ b/src/gpu/gl/GrGLBufferImpl.cpp @@ -0,0 +1,131 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLBufferImpl.h" +#include "GrGpuGL.h" + +#define GL_CALL(GPU, X) GR_GL_CALL(GPU->glInterface(), X) + +GrGLBufferImpl::GrGLBufferImpl(GrGpuGL* gpu, const Desc& desc, GrGLenum bufferType) + : fDesc(desc) + , fBufferType(bufferType) + , fLockPtr(NULL) { + GrAssert(GR_GL_ARRAY_BUFFER == bufferType || GR_GL_ELEMENT_ARRAY_BUFFER == bufferType); +} + +void GrGLBufferImpl::release(GrGpuGL* gpu) { + // make sure we've not been abandoned + if (fDesc.fID && !fDesc.fIsWrapped) { + GL_CALL(gpu, DeleteBuffers(1, &fDesc.fID)); + if (GR_GL_ARRAY_BUFFER == fBufferType) { + gpu->notifyVertexBufferDelete(fDesc.fID); + } else { + GrAssert(GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType); + gpu->notifyIndexBufferDelete(fDesc.fID); + } + fDesc.fID = 0; + } +} + +void GrGLBufferImpl::abandon() { + fDesc.fID = 0; + fLockPtr = NULL; +} + +void GrGLBufferImpl::bind(GrGpuGL* gpu) const { + GL_CALL(gpu, BindBuffer(fBufferType, fDesc.fID)); + if (GR_GL_ARRAY_BUFFER == fBufferType) { + gpu->notifyVertexBufferBind(fDesc.fID); + } else { + GrAssert(GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType); + gpu->notifyIndexBufferBind(fDesc.fID); + } +} + +void* GrGLBufferImpl::lock(GrGpuGL* gpu) { + GrAssert(0 != fDesc.fID); + GrAssert(!this->isLocked()); + if (gpu->getCaps().bufferLockSupport()) { + this->bind(gpu); + // Let driver know it can discard the old data + GL_CALL(gpu, BufferData(fBufferType, + fDesc.fSizeInBytes, + NULL, + fDesc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW)); + GR_GL_CALL_RET(gpu->glInterface(), + fLockPtr, + MapBuffer(fBufferType, GR_GL_WRITE_ONLY)); + return fLockPtr; + } + return NULL; +} + +void GrGLBufferImpl::unlock(GrGpuGL* gpu) { + + GrAssert(0 != fDesc.fID); + GrAssert(this->isLocked()); + GrAssert(gpu->getCaps().bufferLockSupport()); + + this->bind(gpu); + GL_CALL(gpu, UnmapBuffer(fBufferType)); + fLockPtr = NULL; +} + +bool GrGLBufferImpl::isLocked() const { + GrAssert(0 != fDesc.fID); + return NULL != fLockPtr; +} + +bool GrGLBufferImpl::updateData(GrGpuGL* gpu, const void* src, size_t srcSizeInBytes) { + GrAssert(!this->isLocked()); + if (srcSizeInBytes > fDesc.fSizeInBytes) { + return false; + } + if (0 == fDesc.fID) { + return false; + } + this->bind(gpu); + GrGLenum usage = fDesc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW; + +#if GR_GL_USE_BUFFER_DATA_NULL_HINT + if (fDesc.fSizeInBytes == srcSizeInBytes) { + GL_CALL(gpu, BufferData(fBufferType, srcSizeInBytes, src, usage)); + } else { + // Before we call glBufferSubData we give the driver a hint using + // glBufferData with NULL. This makes the old buffer contents + // inaccessible to future draws. The GPU may still be processing + // draws that reference the old contents. With this hint it can + // assign a different allocation for the new contents to avoid + // flushing the gpu past draws consuming the old contents. + GL_CALL(gpu, BufferData(fBufferType, fDesc.fSizeInBytes, NULL, usage)); + GL_CALL(gpu, BufferSubData(fBufferType, 0, srcSizeInBytes, src)); + } +#else + // Note that we're cheating on the size here. Currently no methods + // allow a partial update that preserves contents of non-updated + // portions of the buffer (lock() does a glBufferData(..size, NULL..)) + bool doSubData = false; +#if GR_GL_MAC_BUFFER_OBJECT_PERFOMANCE_WORKAROUND + static int N = 0; + // 128 was chosen experimentally. At 256 a slight hitchiness was noticed + // when dragging a Chromium window around with a canvas tab backgrounded. + doSubData = 0 == (N % 128); + ++N; +#endif + if (doSubData) { + // The workaround is to do a glBufferData followed by glBufferSubData. + // Chromium's command buffer may turn a glBufferSubData where the size + // exactly matches the buffer size into a glBufferData. So we tack 1 + // extra byte onto the glBufferData. + GL_CALL(gpu, BufferData(fBufferType, srcSizeInBytes + 1, NULL, usage)); + GL_CALL(gpu, BufferSubData(fBufferType, 0, srcSizeInBytes, src)); + } else { + GL_CALL(gpu, BufferData(fBufferType, srcSizeInBytes, src, usage)); + } +#endif + return true; +} diff --git a/src/gpu/gl/GrGLBufferImpl.h b/src/gpu/gl/GrGLBufferImpl.h new file mode 100644 index 0000000000..7b44f14dc1 --- /dev/null +++ b/src/gpu/gl/GrGLBufferImpl.h @@ -0,0 +1,57 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLBufferImpl_DEFINED +#define GrGLBufferImpl_DEFINED + +#include "GrNoncopyable.h" +#include "gl/GrGLFunctions.h" + +class GrGpuGL; + +/** + * This class serves as the implementation of GrGL*Buffer classes. It was written to avoid code + * duplication in those classes. + */ +class GrGLBufferImpl : public GrNoncopyable { +public: + struct Desc { + bool fIsWrapped; + GrGLuint fID; + size_t fSizeInBytes; + bool fDynamic; + }; + + GrGLBufferImpl(GrGpuGL*, const Desc&, GrGLenum bufferType); + ~GrGLBufferImpl() { + // either release or abandon should have been called by the owner of this object. + GrAssert(0 == fDesc.fID); + } + + void abandon(); + void release(GrGpuGL* gpu); + + GrGLuint bufferID() const { return fDesc.fID; } + size_t baseOffset() const { return 0; } + + void bind(GrGpuGL* gpu) const; + + void* lock(GrGpuGL* gpu); + void* lockPtr() const { return fLockPtr; } + void unlock(GrGpuGL* gpu); + bool isLocked() const; + bool updateData(GrGpuGL* gpu, const void* src, size_t srcSizeInBytes); + +private: + Desc fDesc; + GrGLenum fBufferType; // GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER + void* fLockPtr; + + typedef GrNoncopyable INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLIndexBuffer.cpp b/src/gpu/gl/GrGLIndexBuffer.cpp index 035bfaccce..ff167347f9 100644 --- a/src/gpu/gl/GrGLIndexBuffer.cpp +++ b/src/gpu/gl/GrGLIndexBuffer.cpp @@ -5,129 +5,53 @@ * found in the LICENSE file. */ - - #include "GrGLIndexBuffer.h" #include "GrGpuGL.h" -#define GPUGL static_cast(getGpu()) - -#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X) - -GrGLIndexBuffer::GrGLIndexBuffer(GrGpuGL* gpu, - bool isWrapped, - GrGLuint id, - size_t sizeInBytes, - bool dynamic) - : INHERITED(gpu, isWrapped, sizeInBytes, dynamic) - , fBufferID(id) - , fLockPtr(NULL) { - +GrGLIndexBuffer::GrGLIndexBuffer(GrGpuGL* gpu, const Desc& desc) + : INHERITED(gpu, desc.fIsWrapped, desc.fSizeInBytes, desc.fDynamic) + , fImpl(gpu, desc, GR_GL_ELEMENT_ARRAY_BUFFER) { } void GrGLIndexBuffer::onRelease() { - // make sure we've not been abandoned - if (fBufferID && !this->isWrapped()) { - GPUGL->notifyIndexBufferDelete(this); - GL_CALL(DeleteBuffers(1, &fBufferID)); - fBufferID = 0; + if (this->isValid()) { + fImpl.release(this->getGpuGL()); } INHERITED::onRelease(); } void GrGLIndexBuffer::onAbandon() { - fBufferID = 0; - fLockPtr = NULL; - + fImpl.abandon(); INHERITED::onAbandon(); } -void GrGLIndexBuffer::bind() const { - GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, fBufferID)); - GPUGL->notifyIndexBufferBind(this); -} - void* GrGLIndexBuffer::lock() { - GrAssert(fBufferID); - GrAssert(!isLocked()); - if (this->getGpu()->getCaps().bufferLockSupport()) { - this->bind(); - // Let driver know it can discard the old data - GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, - this->sizeInBytes(), - NULL, - this->dynamic() ? GR_GL_DYNAMIC_DRAW : - GR_GL_STATIC_DRAW)); - GR_GL_CALL_RET(GPUGL->glInterface(), - fLockPtr, - MapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, - GR_GL_WRITE_ONLY)); - - return fLockPtr; + if (this->isValid()) { + return fImpl.lock(this->getGpuGL()); + } else { + return NULL; } - return NULL; } void* GrGLIndexBuffer::lockPtr() const { - return fLockPtr; + return fImpl.lockPtr(); } void GrGLIndexBuffer::unlock() { - GrAssert(fBufferID); - GrAssert(isLocked()); - GrAssert(this->getGpu()->getCaps().bufferLockSupport()); - - this->bind(); - GL_CALL(UnmapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER)); - fLockPtr = NULL; + if (this->isValid()) { + fImpl.unlock(this->getGpuGL()); + } } bool GrGLIndexBuffer::isLocked() const { - // this check causes a lot of noise in the gl log -#if 0 - if (this->isValid() && this->getGpu()->getCaps().fBufferLockSupport) { - this->bind(); - GrGLint mapped; - GL_CALL(GetBufferParameteriv(GR_GL_ELEMENT_ARRAY_BUFFER, - GR_GL_BUFFER_MAPPED, &mapped)); - GrAssert(!!mapped == !!fLockPtr); - } -#endif - return NULL != fLockPtr; + return fImpl.isLocked(); } bool GrGLIndexBuffer::updateData(const void* src, size_t srcSizeInBytes) { - GrAssert(fBufferID); - GrAssert(!isLocked()); - if (srcSizeInBytes > this->sizeInBytes()) { - return false; - } - this->bind(); - GrGLenum usage = dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW; - -#if GR_GL_USE_BUFFER_DATA_NULL_HINT - if (this->sizeInBytes() == srcSizeInBytes) { - GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, - srcSizeInBytes, src, usage)); + if (this->isValid()) { + return fImpl.updateData(this->getGpuGL(), src, srcSizeInBytes); } else { - // Before we call glBufferSubData we give the driver a hint using - // glBufferData with NULL. This makes the old buffer contents - // inaccessible to future draws. The GPU may still be processing - // draws that reference the old contents. With this hint it can - // assign a different allocation for the new contents to avoid - // flushing the gpu past draws consuming the old contents. - GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, - this->sizeInBytes(), NULL, usage)); - GL_CALL(BufferSubData(GR_GL_ELEMENT_ARRAY_BUFFER, - 0, srcSizeInBytes, src)); + return false; } -#else - // Note that we're cheating on the size here. Currently no methods - // allow a partial update that preserves contents of non-updated - // portions of the buffer (lock() does a glBufferData(..size, NULL..)) - GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, - srcSizeInBytes, src, usage)); -#endif - return true; } diff --git a/src/gpu/gl/GrGLIndexBuffer.h b/src/gpu/gl/GrGLIndexBuffer.h index 5182573abf..5c8588b211 100644 --- a/src/gpu/gl/GrGLIndexBuffer.h +++ b/src/gpu/gl/GrGLIndexBuffer.h @@ -5,12 +5,11 @@ * found in the LICENSE file. */ - - #ifndef GrGLIndexBuffer_DEFINED #define GrGLIndexBuffer_DEFINED #include "GrIndexBuffer.h" +#include "GrGLBufferImpl.h" #include "gl/GrGLInterface.h" class GrGpuGL; @@ -18,19 +17,19 @@ class GrGpuGL; class GrGLIndexBuffer : public GrIndexBuffer { public: + typedef GrGLBufferImpl::Desc Desc; - GrGLIndexBuffer(GrGpuGL* gpu, - bool isWrapped, - GrGLuint id, - size_t sizeInBytes, - bool dynamic); - + GrGLIndexBuffer(GrGpuGL* gpu, const Desc& desc); virtual ~GrGLIndexBuffer() { this->release(); } - GrGLuint bufferID() const { return fBufferID; } - size_t baseOffset() const { return 0; } + GrGLuint bufferID() const { return fImpl.bufferID(); } + size_t baseOffset() const { return fImpl.baseOffset(); } - void bind() const; + void bind() const { + if (this->isValid()) { + fImpl.bind(this->getGpuGL()); + } + } // overrides of GrIndexBuffer virtual void* lock(); @@ -40,15 +39,17 @@ public: virtual bool updateData(const void* src, size_t srcSizeInBytes); protected: - // overrides of GrResource virtual void onAbandon() SK_OVERRIDE; virtual void onRelease() SK_OVERRIDE; private: + GrGpuGL* getGpuGL() const { + GrAssert(this->isValid()); + return (GrGpuGL*)(this->getGpu()); + } - GrGLuint fBufferID; - void* fLockPtr; + GrGLBufferImpl fImpl; typedef GrIndexBuffer INHERITED; }; diff --git a/src/gpu/gl/GrGLVertexBuffer.cpp b/src/gpu/gl/GrGLVertexBuffer.cpp index 42b76ea4a8..4152251433 100644 --- a/src/gpu/gl/GrGLVertexBuffer.cpp +++ b/src/gpu/gl/GrGLVertexBuffer.cpp @@ -5,141 +5,54 @@ * found in the LICENSE file. */ - - #include "GrGLVertexBuffer.h" #include "GrGpuGL.h" -#define GPUGL static_cast(getGpu()) - -#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X) - -GrGLVertexBuffer::GrGLVertexBuffer(GrGpuGL* gpu, - bool isWrapped, - GrGLuint id, - size_t sizeInBytes, - bool dynamic) - : INHERITED(gpu, isWrapped, sizeInBytes, dynamic) - , fBufferID(id) - , fLockPtr(NULL) { +GrGLVertexBuffer::GrGLVertexBuffer(GrGpuGL* gpu, const Desc& desc) + : INHERITED(gpu, desc.fIsWrapped, desc.fSizeInBytes, desc.fDynamic) + , fImpl(gpu, desc, GR_GL_ARRAY_BUFFER) { } void GrGLVertexBuffer::onRelease() { - // make sure we've not been abandoned - if (fBufferID && !this->isWrapped()) { - GPUGL->notifyVertexBufferDelete(this); - GL_CALL(DeleteBuffers(1, &fBufferID)); - fBufferID = 0; + if (this->isValid()) { + fImpl.release(this->getGpuGL()); } INHERITED::onRelease(); } -void GrGLVertexBuffer::onAbandon() { - fBufferID = 0; - fLockPtr = NULL; +void GrGLVertexBuffer::onAbandon() { + fImpl.abandon(); INHERITED::onAbandon(); } -void GrGLVertexBuffer::bind() const { - GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, fBufferID)); - GPUGL->notifyVertexBufferBind(this); -} - void* GrGLVertexBuffer::lock() { - GrAssert(fBufferID); - GrAssert(!isLocked()); - if (this->getGpu()->getCaps().bufferLockSupport()) { - this->bind(); - // Let driver know it can discard the old data - GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, this->sizeInBytes(), NULL, - this->dynamic() ? GR_GL_DYNAMIC_DRAW : - GR_GL_STATIC_DRAW)); - GR_GL_CALL_RET(GPUGL->glInterface(), - fLockPtr, - MapBuffer(GR_GL_ARRAY_BUFFER, GR_GL_WRITE_ONLY)); - return fLockPtr; + if (this->isValid()) { + return fImpl.lock(this->getGpuGL()); + } else { + return NULL; } - return NULL; } void* GrGLVertexBuffer::lockPtr() const { - return fLockPtr; + return fImpl.lockPtr(); } void GrGLVertexBuffer::unlock() { - - GrAssert(fBufferID); - GrAssert(isLocked()); - GrAssert(this->getGpu()->getCaps().bufferLockSupport()); - - this->bind(); - GL_CALL(UnmapBuffer(GR_GL_ARRAY_BUFFER)); - fLockPtr = NULL; + if (this->isValid()) { + fImpl.unlock(this->getGpuGL()); + } } bool GrGLVertexBuffer::isLocked() const { - GrAssert(!this->isValid() || fBufferID); - // this check causes a lot of noise in the gl log -#if 0 - if (this->isValid() && this->getGpu()->getCaps().fBufferLockSupport) { - GrGLint mapped; - this->bind(); - GL_CALL(GetBufferParameteriv(GR_GL_ARRAY_BUFFER, - GR_GL_BUFFER_MAPPED, &mapped)); - GrAssert(!!mapped == !!fLockPtr); - } -#endif - return NULL != fLockPtr; + return fImpl.isLocked(); } bool GrGLVertexBuffer::updateData(const void* src, size_t srcSizeInBytes) { - GrAssert(fBufferID); - GrAssert(!isLocked()); - if (srcSizeInBytes > this->sizeInBytes()) { - return false; - } - this->bind(); - GrGLenum usage = dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW; - -#if GR_GL_USE_BUFFER_DATA_NULL_HINT - if (this->sizeInBytes() == srcSizeInBytes) { - GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, srcSizeInBytes, src, usage)); - } else { - // Before we call glBufferSubData we give the driver a hint using - // glBufferData with NULL. This makes the old buffer contents - // inaccessible to future draws. The GPU may still be processing - // draws that reference the old contents. With this hint it can - // assign a different allocation for the new contents to avoid - // flushing the gpu past draws consuming the old contents. - GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, - this->sizeInBytes(), NULL, usage)); - GL_CALL(BufferSubData(GR_GL_ARRAY_BUFFER, 0, srcSizeInBytes, src)); - } -#else - // Note that we're cheating on the size here. Currently no methods - // allow a partial update that preserves contents of non-updated - // portions of the buffer (lock() does a glBufferData(..size, NULL..)) - bool doSubData = false; -#if GR_GL_MAC_BUFFER_OBJECT_PERFOMANCE_WORKAROUND - static int N = 0; - // 128 was chosen experimentally. At 256 a slight hitchiness was noticed - // when dragging a Chromium window around with a canvas tab backgrounded. - doSubData = 0 == (N % 128); - ++N; -#endif - if (doSubData) { - // The workaround is to do a glBufferData followed by glBufferSubData. - // Chromium's command buffer may turn a glBufferSubData where the size - // exactly matches the buffer size into a glBufferData. So we tack 1 - // extra byte onto the glBufferData. - GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, srcSizeInBytes + 1, - NULL, usage)); - GL_CALL(BufferSubData(GR_GL_ARRAY_BUFFER, 0, srcSizeInBytes, src)); + if (this->isValid()) { + return fImpl.updateData(this->getGpuGL(), src, srcSizeInBytes); } else { - GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, srcSizeInBytes, src, usage)); + return false; } -#endif - return true; } diff --git a/src/gpu/gl/GrGLVertexBuffer.h b/src/gpu/gl/GrGLVertexBuffer.h index 61b5020404..f15a5dab63 100644 --- a/src/gpu/gl/GrGLVertexBuffer.h +++ b/src/gpu/gl/GrGLVertexBuffer.h @@ -5,12 +5,11 @@ * found in the LICENSE file. */ - - #ifndef GrGLVertexBuffer_DEFINED #define GrGLVertexBuffer_DEFINED #include "GrVertexBuffer.h" +#include "GrGLBufferImpl.h" #include "gl/GrGLInterface.h" class GrGpuGL; @@ -18,17 +17,19 @@ class GrGpuGL; class GrGLVertexBuffer : public GrVertexBuffer { public: - GrGLVertexBuffer(GrGpuGL* gpu, - bool isWrapped, - GrGLuint id, - size_t sizeInBytes, - bool dynamic); + typedef GrGLBufferImpl::Desc Desc; + + GrGLVertexBuffer(GrGpuGL* gpu, const Desc& desc); virtual ~GrGLVertexBuffer() { this->release(); } - GrGLuint bufferID() const { return fBufferID; } - size_t baseOffset() const { return 0; } + GrGLuint bufferID() const { return fImpl.bufferID(); } + size_t baseOffset() const { return fImpl.baseOffset(); } - void bind() const; + void bind() const { + if (this->isValid()) { + fImpl.bind(this->getGpuGL()); + } + } // overrides of GrVertexBuffer virtual void* lock(); @@ -43,9 +44,12 @@ protected: virtual void onRelease() SK_OVERRIDE; private: + GrGpuGL* getGpuGL() const { + GrAssert(this->isValid()); + return (GrGpuGL*)(this->getGpu()); + } - GrGLuint fBufferID; - void* fLockPtr; + GrGLBufferImpl fImpl; typedef GrVertexBuffer INHERITED; }; diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index abf5ac937b..785b500899 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -1226,58 +1226,58 @@ bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, //////////////////////////////////////////////////////////////////////////////// GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) { - GrGLuint id; - GL_CALL(GenBuffers(1, &id)); - if (id) { - GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, id)); + GrGLVertexBuffer::Desc desc; + desc.fDynamic = dynamic; + desc.fSizeInBytes = size; + desc.fIsWrapped = false; + + GL_CALL(GenBuffers(1, &desc.fID)); + if (desc.fID) { + GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, desc.fID)); CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); // make sure driver can allocate memory for this buffer GL_ALLOC_CALL(this->glInterface(), BufferData(GR_GL_ARRAY_BUFFER, - size, + desc.fSizeInBytes, NULL, // data ptr - dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW)); + desc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW)); if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { - GL_CALL(DeleteBuffers(1, &id)); + GL_CALL(DeleteBuffers(1, &desc.fID)); // deleting bound buffer does implicit bind to 0 fHWGeometryState.setVertexBufferID(0); return NULL; } - static const bool kIsWrapped = false; - GrGLVertexBuffer* vertexBuffer = SkNEW_ARGS(GrGLVertexBuffer, (this, - kIsWrapped, - id, - size, - dynamic)); - fHWGeometryState.setVertexBufferID(id); + GrGLVertexBuffer* vertexBuffer = SkNEW_ARGS(GrGLVertexBuffer, (this, desc)); + fHWGeometryState.setVertexBufferID(desc.fID); return vertexBuffer; } return NULL; } GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) { - GrGLuint id; - GL_CALL(GenBuffers(1, &id)); - if (id) { - GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id)); + GrGLIndexBuffer::Desc desc; + desc.fDynamic = dynamic; + desc.fSizeInBytes = size; + desc.fIsWrapped = false; + + GL_CALL(GenBuffers(1, &desc.fID)); + if (desc.fID) { + GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, desc.fID)); CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); // make sure driver can allocate memory for this buffer GL_ALLOC_CALL(this->glInterface(), BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, - size, + desc.fSizeInBytes, NULL, // data ptr - dynamic ? GR_GL_DYNAMIC_DRAW : - GR_GL_STATIC_DRAW)); + desc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW)); if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { - GL_CALL(DeleteBuffers(1, &id)); + GL_CALL(DeleteBuffers(1, &desc.fID)); // deleting bound buffer does implicit bind to 0 fHWGeometryState.setIndexBufferID(0); return NULL; } - static const bool kIsWrapped = false; - GrIndexBuffer* indexBuffer = SkNEW_ARGS(GrGLIndexBuffer, - (this, kIsWrapped, id, size, dynamic)); - fHWGeometryState.setIndexBufferID(id); + GrIndexBuffer* indexBuffer = SkNEW_ARGS(GrGLIndexBuffer, (this, desc)); + fHWGeometryState.setIndexBufferID(desc.fID); return indexBuffer; } return NULL; @@ -2145,20 +2145,20 @@ void GrGpuGL::flushMiscFixedFunctionState() { } } -void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) { - fHWGeometryState.setVertexBufferID(buffer->bufferID()); +void GrGpuGL::notifyVertexBufferBind(GrGLuint id) { + fHWGeometryState.setVertexBufferID(id); } -void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) { - fHWGeometryState.notifyVertexBufferDelete(buffer); +void GrGpuGL::notifyVertexBufferDelete(GrGLuint id) { + fHWGeometryState.notifyVertexBufferDelete(id); } -void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) { - fHWGeometryState.setIndexBufferID(buffer->bufferID()); +void GrGpuGL::notifyIndexBufferBind(GrGLuint id) { + fHWGeometryState.setIndexBufferID(id); } -void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) { - fHWGeometryState.notifyIndexBufferDelete(buffer); +void GrGpuGL::notifyIndexBufferDelete(GrGLuint id) { + fHWGeometryState.notifyIndexBufferDelete(id); } void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) { diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index fae4a93c6c..8d1e7dda45 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -58,10 +58,10 @@ public: const GrGLCaps& glCaps() const { return fGLContextInfo.caps(); } // Callbacks to update state tracking when related GL objects are bound or deleted - void notifyVertexBufferBind(const GrGLVertexBuffer* buffer); - void notifyVertexBufferDelete(const GrGLVertexBuffer* buffer); - void notifyIndexBufferBind(const GrGLIndexBuffer* buffer); - void notifyIndexBufferDelete(const GrGLIndexBuffer* buffer); + void notifyVertexBufferBind(GrGLuint id); + void notifyVertexBufferDelete(GrGLuint id); + void notifyIndexBufferBind(GrGLuint id); + void notifyIndexBufferDelete(GrGLuint id); void notifyTextureDelete(GrGLTexture* texture); void notifyRenderTargetDelete(GrRenderTarget* renderTarget); @@ -291,8 +291,7 @@ private: } } - void notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) { - GrGLuint id = buffer->bufferID(); + void notifyVertexBufferDelete(GrGLuint id) { if (0 != id) { if (this->isVertexBufferIDBound(id)) { // deleting bound buffer does implied bind to 0 @@ -306,8 +305,7 @@ private: } } - void notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) { - GrGLuint id = buffer->bufferID(); + void notifyIndexBufferDelete(GrGLuint id) { if (0 != id) { if (this->isIndexBufferIDBound(id)) { // deleting bound buffer does implied bind to 0 -- cgit v1.2.3