diff options
author | 2016-03-25 04:55:58 -0700 | |
---|---|---|
committer | 2016-03-25 04:55:59 -0700 | |
commit | f8c3ba40cf4f42b2c2ba1b473c28d7733383223e (patch) | |
tree | 00c671765311aaa35c8a9d6fa0a6b84907c871b9 /src/gpu/gl | |
parent | f299e7105435829c47e94f4cf6e408cad675bc77 (diff) |
Revert of Consolidate GPU buffer implementations (patchset #10 id:180001 of https://codereview.chromium.org/1825393002/ )
Reason for revert:
Lots of Android redness
Original issue's description:
> Consolidate GPU buffer implementations
>
> Consolidates all the different buffer implementations into a single
> GrBuffer class. This will allow us to add new buffer types, use DSA in
> OpenGL, track buffer bindings by unique ID, cache buffers without
> respect to the type of data they have been used for previously, etc.
> This change is strictly a refactor; it introduces no change in
> functionality.
>
> BUG=skia:
> GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1825393002
>
> Committed: https://skia.googlesource.com/skia/+/8b1bff29675afd25843439eade634a57f68fe16f
TBR=bsalomon@google.com,egdaniel@google.com,jvanverth@google.com,cdalton@nvidia.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:
Review URL: https://codereview.chromium.org/1831133004
Diffstat (limited to 'src/gpu/gl')
-rw-r--r-- | src/gpu/gl/GrGLBuffer.cpp | 336 | ||||
-rw-r--r-- | src/gpu/gl/GrGLBuffer.h | 61 | ||||
-rw-r--r-- | src/gpu/gl/GrGLBufferImpl.cpp | 122 | ||||
-rw-r--r-- | src/gpu/gl/GrGLBufferImpl.h | 69 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 6 | ||||
-rw-r--r-- | src/gpu/gl/GrGLDefines.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 241 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 23 | ||||
-rw-r--r-- | src/gpu/gl/GrGLIndexBuffer.cpp | 60 | ||||
-rw-r--r-- | src/gpu/gl/GrGLIndexBuffer.h | 48 | ||||
-rwxr-xr-x | src/gpu/gl/GrGLTransferBuffer.cpp | 51 | ||||
-rwxr-xr-x | src/gpu/gl/GrGLTransferBuffer.h | 48 | ||||
-rw-r--r-- | src/gpu/gl/GrGLVertexArray.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLVertexBuffer.cpp | 60 | ||||
-rw-r--r-- | src/gpu/gl/GrGLVertexBuffer.h | 48 |
15 files changed, 755 insertions, 422 deletions
diff --git a/src/gpu/gl/GrGLBuffer.cpp b/src/gpu/gl/GrGLBuffer.cpp deleted file mode 100644 index ad56ceb729..0000000000 --- a/src/gpu/gl/GrGLBuffer.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "GrGLBuffer.h" -#include "GrGLGpu.h" -#include "SkTraceMemoryDump.h" - -#define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X) -#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), RET, X) - -#if GR_GL_CHECK_ALLOC_WITH_GET_ERROR - #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface) - #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call) - #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface) -#else - #define CLEAR_ERROR_BEFORE_ALLOC(iface) - #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call) - #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR -#endif - -#ifdef SK_DEBUG -#define VALIDATE() this->validate() -#else -#define VALIDATE() do {} while(false) -#endif - -GrGLBuffer* GrGLBuffer::Create(GrGLGpu* gpu, GrBufferType type, size_t size, - GrAccessPattern accessPattern) { - static const int kIsVertexOrIndex = (1 << kVertex_GrBufferType) | (1 << kIndex_GrBufferType); - bool cpuBacked = gpu->glCaps().useNonVBOVertexAndIndexDynamicData() && - kDynamic_GrAccessPattern == accessPattern && - ((kIsVertexOrIndex >> type) & 1); - SkAutoTUnref<GrGLBuffer> buffer(new GrGLBuffer(gpu, type, size, accessPattern, cpuBacked)); - if (!cpuBacked && 0 == buffer->fBufferID) { - return nullptr; - } - return buffer.release(); -} - -// GL_STREAM_DRAW triggers an optimization in Chromium's GPU process where a client's vertex buffer -// objects are implemented as client-side-arrays on tile-deferred architectures. -#define DYNAMIC_DRAW_PARAM GR_GL_STREAM_DRAW - -inline static void get_target_and_usage(GrBufferType type, GrAccessPattern accessPattern, - const GrGLCaps& caps, GrGLenum* target, GrGLenum* usage) { - static const GrGLenum nonXferTargets[] = { - GR_GL_ARRAY_BUFFER, - GR_GL_ELEMENT_ARRAY_BUFFER - }; - GR_STATIC_ASSERT(0 == kVertex_GrBufferType); - GR_STATIC_ASSERT(1 == kIndex_GrBufferType); - - static const GrGLenum drawUsages[] = { - DYNAMIC_DRAW_PARAM, // TODO: Do we really want to use STREAM_DRAW here on non-Chromium? - GR_GL_STATIC_DRAW, - GR_GL_STREAM_DRAW - }; - static const GrGLenum readUsages[] = { - GR_GL_DYNAMIC_READ, - GR_GL_STATIC_READ, - GR_GL_STREAM_READ - }; - GR_STATIC_ASSERT(0 == kDynamic_GrAccessPattern); - GR_STATIC_ASSERT(1 == kStatic_GrAccessPattern); - GR_STATIC_ASSERT(2 == kStream_GrAccessPattern); - GR_STATIC_ASSERT(SK_ARRAY_COUNT(drawUsages) == 1 + kLast_GrAccessPattern); - GR_STATIC_ASSERT(SK_ARRAY_COUNT(readUsages) == 1 + kLast_GrAccessPattern); - - SkASSERT(accessPattern >= 0 && accessPattern <= kLast_GrAccessPattern); - - switch (type) { - case kVertex_GrBufferType: - case kIndex_GrBufferType: - *target = nonXferTargets[type]; - *usage = drawUsages[accessPattern]; - break; - case kXferCpuToGpu_GrBufferType: - if (GrGLCaps::kChromium_TransferBufferType == caps.transferBufferType()) { - *target = GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM; - } else { - SkASSERT(GrGLCaps::kPBO_TransferBufferType == caps.transferBufferType()); - *target = GR_GL_PIXEL_UNPACK_BUFFER; - } - *usage = drawUsages[accessPattern]; - break; - case kXferGpuToCpu_GrBufferType: - if (GrGLCaps::kChromium_TransferBufferType == caps.transferBufferType()) { - *target = GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM; - } else { - SkASSERT(GrGLCaps::kPBO_TransferBufferType == caps.transferBufferType()); - *target = GR_GL_PIXEL_PACK_BUFFER; - } - *usage = readUsages[accessPattern]; - break; - default: - SkFAIL("Unexpected buffer type."); - break; - } -} - -GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, GrBufferType type, size_t size, GrAccessPattern accessPattern, - bool cpuBacked) - : INHERITED(gpu, type, size, accessPattern, cpuBacked), - fCPUData(nullptr), - fTarget(0), - fBufferID(0), - fSizeInBytes(size), - fUsage(0), - fGLSizeInBytes(0) { - if (cpuBacked) { - if (gpu->caps()->mustClearUploadedBufferData()) { - fCPUData = sk_calloc_throw(fSizeInBytes); - } else { - fCPUData = sk_malloc_flags(fSizeInBytes, SK_MALLOC_THROW); - } - } else { - GL_CALL(GenBuffers(1, &fBufferID)); - fSizeInBytes = size; - get_target_and_usage(type, accessPattern, gpu->glCaps(), &fTarget, &fUsage); - if (fBufferID) { - gpu->bindBuffer(fBufferID, fTarget); - CLEAR_ERROR_BEFORE_ALLOC(gpu->glInterface()); - // make sure driver can allocate memory for this buffer - GL_ALLOC_CALL(gpu->glInterface(), BufferData(fTarget, - (GrGLsizeiptr) fSizeInBytes, - nullptr, // data ptr - fUsage)); - if (CHECK_ALLOC_ERROR(gpu->glInterface()) != GR_GL_NO_ERROR) { - gpu->releaseBuffer(fBufferID, fTarget); - fBufferID = 0; - } else { - fGLSizeInBytes = fSizeInBytes; - } - } - } - VALIDATE(); - this->registerWithCache(); -} - -inline GrGLGpu* GrGLBuffer::glGpu() const { - SkASSERT(!this->wasDestroyed()); - return static_cast<GrGLGpu*>(this->getGpu()); -} - -inline const GrGLCaps& GrGLBuffer::glCaps() const { - return this->glGpu()->glCaps(); -} - -void GrGLBuffer::onRelease() { - if (!this->wasDestroyed()) { - VALIDATE(); - // make sure we've not been abandoned or already released - if (fCPUData) { - SkASSERT(!fBufferID); - sk_free(fCPUData); - fCPUData = nullptr; - } else if (fBufferID) { - this->glGpu()->releaseBuffer(fBufferID, fTarget); - fBufferID = 0; - fGLSizeInBytes = 0; - } - fMapPtr = nullptr; - VALIDATE(); - } - - INHERITED::onRelease(); -} - -void GrGLBuffer::onAbandon() { - fBufferID = 0; - fGLSizeInBytes = 0; - fMapPtr = nullptr; - sk_free(fCPUData); - fCPUData = nullptr; - VALIDATE(); - INHERITED::onAbandon(); -} - -void GrGLBuffer::onMap() { - if (this->wasDestroyed()) { - return; - } - - VALIDATE(); - SkASSERT(!this->isMapped()); - - if (0 == fBufferID) { - fMapPtr = fCPUData; - VALIDATE(); - return; - } - - bool readOnly = (kXferGpuToCpu_GrBufferType == this->type()); - - // Handling dirty context is done in the bindBuffer call - switch (this->glCaps().mapBufferType()) { - case GrGLCaps::kNone_MapBufferType: - break; - case GrGLCaps::kMapBuffer_MapBufferType: - this->glGpu()->bindBuffer(fBufferID, fTarget); - // Let driver know it can discard the old data - if (GR_GL_USE_BUFFER_DATA_NULL_HINT || fGLSizeInBytes != fSizeInBytes) { - GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage)); - } - GL_CALL_RET(fMapPtr, MapBuffer(fTarget, readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); - break; - case GrGLCaps::kMapBufferRange_MapBufferType: { - this->glGpu()->bindBuffer(fBufferID, fTarget); - // Make sure the GL buffer size agrees with fDesc before mapping. - if (fGLSizeInBytes != fSizeInBytes) { - GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage)); - } - GrGLbitfield writeAccess = GR_GL_MAP_WRITE_BIT; - // TODO: allow the client to specify invalidation in the transfer buffer case. - if (kXferCpuToGpu_GrBufferType != this->type()) { - writeAccess |= GR_GL_MAP_INVALIDATE_BUFFER_BIT; - } - GL_CALL_RET(fMapPtr, MapBufferRange(fTarget, 0, fSizeInBytes, - readOnly ? GR_GL_MAP_READ_BIT : writeAccess)); - break; - } - case GrGLCaps::kChromium_MapBufferType: - this->glGpu()->bindBuffer(fBufferID, fTarget); - // Make sure the GL buffer size agrees with fDesc before mapping. - if (fGLSizeInBytes != fSizeInBytes) { - GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage)); - } - GL_CALL_RET(fMapPtr, MapBufferSubData(fTarget, 0, fSizeInBytes, - readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); - break; - } - fGLSizeInBytes = fSizeInBytes; - VALIDATE(); -} - -void GrGLBuffer::onUnmap() { - if (this->wasDestroyed()) { - return; - } - - VALIDATE(); - SkASSERT(this->isMapped()); - if (0 == fBufferID) { - fMapPtr = nullptr; - return; - } - // bind buffer handles the dirty context - switch (this->glCaps().mapBufferType()) { - case GrGLCaps::kNone_MapBufferType: - SkDEBUGFAIL("Shouldn't get here."); - return; - case GrGLCaps::kMapBuffer_MapBufferType: // fall through - case GrGLCaps::kMapBufferRange_MapBufferType: - this->glGpu()->bindBuffer(fBufferID, fTarget); - GL_CALL(UnmapBuffer(fTarget)); - break; - case GrGLCaps::kChromium_MapBufferType: - this->glGpu()->bindBuffer(fBufferID, fTarget); - GL_CALL(UnmapBufferSubData(fMapPtr)); - break; - } - fMapPtr = nullptr; -} - -bool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) { - if (this->wasDestroyed()) { - return false; - } - - SkASSERT(!this->isMapped()); - SkASSERT(GR_GL_ARRAY_BUFFER == fTarget || GR_GL_ELEMENT_ARRAY_BUFFER == fTarget); - VALIDATE(); - if (srcSizeInBytes > fSizeInBytes) { - return false; - } - if (0 == fBufferID) { - memcpy(fCPUData, src, srcSizeInBytes); - return true; - } - SkASSERT(srcSizeInBytes <= fSizeInBytes); - // bindbuffer handles dirty context - this->glGpu()->bindBuffer(fBufferID, fTarget); - -#if GR_GL_USE_BUFFER_DATA_NULL_HINT - if (fSizeInBytes == srcSizeInBytes) { - GL_CALL(BufferData(fTarget, (GrGLsizeiptr) srcSizeInBytes, src, fUsage)); - } else { - // Before we call glBufferSubData we give the driver a hint using - // glBufferData with nullptr. 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. - // TODO I think we actually want to try calling bufferData here - GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage)); - GL_CALL(BufferSubData(fTarget, 0, (GrGLsizeiptr) srcSizeInBytes, src)); - } - fGLSizeInBytes = fSizeInBytes; -#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 (map() does a glBufferData(..size, nullptr..)) - GL_CALL(BufferData(fTarget, srcSizeInBytes, src, fUsage)); - fGLSizeInBytes = srcSizeInBytes; -#endif - VALIDATE(); - return true; -} - -void GrGLBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, - const SkString& dumpName) const { - SkString buffer_id; - buffer_id.appendU32(this->bufferID()); - traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer", - buffer_id.c_str()); -} - -#ifdef SK_DEBUG - -void GrGLBuffer::validate() const { - SkASSERT(GR_GL_ARRAY_BUFFER == fTarget || GR_GL_ELEMENT_ARRAY_BUFFER == fTarget || - GR_GL_PIXEL_PACK_BUFFER == fTarget || GR_GL_PIXEL_UNPACK_BUFFER == fTarget || - GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM == fTarget || - GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == fTarget); - // The following assert isn't valid when the buffer has been abandoned: - // SkASSERT((0 == fDesc.fID) == (fCPUData)); - SkASSERT(0 != fBufferID || 0 == fGLSizeInBytes); - SkASSERT(nullptr == fMapPtr || fCPUData || fGLSizeInBytes <= fSizeInBytes); - SkASSERT(nullptr == fCPUData || nullptr == fMapPtr || fCPUData == fMapPtr); -} - -#endif diff --git a/src/gpu/gl/GrGLBuffer.h b/src/gpu/gl/GrGLBuffer.h deleted file mode 100644 index 90d2c43dfa..0000000000 --- a/src/gpu/gl/GrGLBuffer.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrGLBuffer_DEFINED -#define GrGLBuffer_DEFINED - -#include "GrBuffer.h" -#include "gl/GrGLTypes.h" - -class GrGLGpu; -class GrGLCaps; - -class GrGLBuffer : public GrBuffer { -public: - static GrGLBuffer* Create(GrGLGpu*, GrBufferType, size_t size, GrAccessPattern); - - ~GrGLBuffer() { - // either release or abandon should have been called by the owner of this object. - SkASSERT(0 == fBufferID); - } - - GrGLenum target() const { return fTarget; } - GrGLuint bufferID() const { return fBufferID; } - size_t baseOffset() const { return reinterpret_cast<size_t>(fCPUData); } - -protected: - GrGLBuffer(GrGLGpu*, GrBufferType, size_t size, GrAccessPattern, bool cpuBacked); - - void onAbandon() override; - void onRelease() override; - void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, - const SkString& dumpName) const override; - -private: - GrGLGpu* glGpu() const; - const GrGLCaps& glCaps() const; - - void onMap() override; - void onUnmap() override; - bool onUpdateData(const void* src, size_t srcSizeInBytes) override; - -#ifdef SK_DEBUG - void validate() const; -#endif - - void* fCPUData; - GrGLenum fTarget; // GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER, e.g. - GrGLuint fBufferID; - size_t fSizeInBytes; - GrGLenum fUsage; - size_t fGLSizeInBytes; // In certain cases we make the size of the GL buffer object - // smaller or larger than the size in fDesc. - - typedef GrBuffer INHERITED; -}; - -#endif diff --git a/src/gpu/gl/GrGLBufferImpl.cpp b/src/gpu/gl/GrGLBufferImpl.cpp new file mode 100644 index 0000000000..2babce8028 --- /dev/null +++ b/src/gpu/gl/GrGLBufferImpl.cpp @@ -0,0 +1,122 @@ +/* + * 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 "GrGLGpu.h" + +#define GL_CALL(GPU, X) GR_GL_CALL(GPU->glInterface(), X) + +#ifdef SK_DEBUG +#define VALIDATE() this->validate() +#else +#define VALIDATE() do {} while(false) +#endif + +GrGLBufferImpl::GrGLBufferImpl(GrGLGpu* gpu, const Desc& desc, GrGLenum bufferType) + : fDesc(desc) + , fBufferType(bufferType) + , fMapPtr(nullptr) { + if (0 == desc.fID) { + if (gpu->caps()->mustClearUploadedBufferData()) { + fCPUData = sk_calloc_throw(desc.fSizeInBytes); + } else { + fCPUData = sk_malloc_flags(desc.fSizeInBytes, SK_MALLOC_THROW); + } + fGLSizeInBytes = 0; + } else { + fCPUData = nullptr; + // We assume that the GL buffer was created at the desc's size initially. + fGLSizeInBytes = fDesc.fSizeInBytes; + } + VALIDATE(); +} + +void GrGLBufferImpl::release(GrGLGpu* gpu) { + VALIDATE(); + // make sure we've not been abandoned or already released + if (fCPUData) { + sk_free(fCPUData); + fCPUData = nullptr; + } else if (fDesc.fID) { + gpu->releaseBuffer(fDesc.fID, fBufferType); + fDesc.fID = 0; + fGLSizeInBytes = 0; + } + fMapPtr = nullptr; + VALIDATE(); +} + +void GrGLBufferImpl::abandon() { + fDesc.fID = 0; + fGLSizeInBytes = 0; + fMapPtr = nullptr; + sk_free(fCPUData); + fCPUData = nullptr; + VALIDATE(); +} + +void* GrGLBufferImpl::map(GrGLGpu* gpu) { + VALIDATE(); + SkASSERT(!this->isMapped()); + if (0 == fDesc.fID) { + fMapPtr = fCPUData; + } else { + fMapPtr = gpu->mapBuffer(fDesc.fID, fBufferType, fDesc.fUsage, fGLSizeInBytes, + fDesc.fSizeInBytes); + fGLSizeInBytes = fDesc.fSizeInBytes; + } + VALIDATE(); + return fMapPtr; +} + +void GrGLBufferImpl::unmap(GrGLGpu* gpu) { + VALIDATE(); + SkASSERT(this->isMapped()); + if (0 != fDesc.fID) { + gpu->unmapBuffer(fDesc.fID, fBufferType, fMapPtr); + } + fMapPtr = nullptr; +} + +bool GrGLBufferImpl::isMapped() const { + VALIDATE(); + return SkToBool(fMapPtr); +} + +bool GrGLBufferImpl::updateData(GrGLGpu* gpu, const void* src, size_t srcSizeInBytes) { + SkASSERT(!this->isMapped()); + SkASSERT(GR_GL_ARRAY_BUFFER == fBufferType || GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType); + VALIDATE(); + if (srcSizeInBytes > fDesc.fSizeInBytes) { + return false; + } + if (0 == fDesc.fID) { + memcpy(fCPUData, src, srcSizeInBytes); + return true; + } + gpu->bufferData(fDesc.fID, fBufferType, fDesc.fUsage, fDesc.fSizeInBytes, src, + srcSizeInBytes); +#if GR_GL_USE_BUFFER_DATA_NULL_HINT + fGLSizeInBytes = fDesc.fSizeInBytes; +#else + fGLSizeInBytes = srcSizeInBytes; +#endif + VALIDATE(); + return true; +} + +void GrGLBufferImpl::validate() const { + SkASSERT(GR_GL_ARRAY_BUFFER == fBufferType || GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType || + GR_GL_PIXEL_PACK_BUFFER == fBufferType || GR_GL_PIXEL_UNPACK_BUFFER == fBufferType || + GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM == fBufferType || + GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == fBufferType); + // The following assert isn't valid when the buffer has been abandoned: + // SkASSERT((0 == fDesc.fID) == (fCPUData)); + SkASSERT(nullptr == fCPUData || 0 == fGLSizeInBytes); + SkASSERT(nullptr == fMapPtr || fCPUData || fGLSizeInBytes <= fDesc.fSizeInBytes); + SkASSERT(nullptr == fCPUData || nullptr == fMapPtr || fCPUData == fMapPtr); +} diff --git a/src/gpu/gl/GrGLBufferImpl.h b/src/gpu/gl/GrGLBufferImpl.h new file mode 100644 index 0000000000..a8f2cced37 --- /dev/null +++ b/src/gpu/gl/GrGLBufferImpl.h @@ -0,0 +1,69 @@ +/* + * 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 "SkTypes.h" +#include "gl/GrGLTypes.h" + +class GrGLGpu; + +/** + * This class serves as the implementation of GrGL*Buffer classes. It was written to avoid code + * duplication in those classes. + */ +class GrGLBufferImpl : SkNoncopyable { +public: + enum Usage { + kStaticDraw_Usage = 0, + kDynamicDraw_Usage, + kStreamDraw_Usage, + kStreamRead_Usage, + + kLast_Usage = kStreamRead_Usage + }; + static const int kUsageCount = kLast_Usage + 1; + + struct Desc { + GrGLuint fID; // set to 0 to indicate buffer is CPU-backed and not a VBO. + size_t fSizeInBytes; + Usage fUsage; + }; + + GrGLBufferImpl(GrGLGpu*, const Desc&, GrGLenum bufferType); + ~GrGLBufferImpl() { + // either release or abandon should have been called by the owner of this object. + SkASSERT(0 == fDesc.fID); + } + + void abandon(); + void release(GrGLGpu* gpu); + + GrGLuint bufferID() const { return fDesc.fID; } + size_t baseOffset() const { return reinterpret_cast<size_t>(fCPUData); } + GrGLenum bufferType() const { return fBufferType; } + + void* map(GrGLGpu* gpu); + void unmap(GrGLGpu* gpu); + bool isMapped() const; + bool updateData(GrGLGpu* gpu, const void* src, size_t srcSizeInBytes); + +private: + void validate() const; + + Desc fDesc; + GrGLenum fBufferType; // GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER, e.g. + void* fCPUData; + void* fMapPtr; + size_t fGLSizeInBytes; // In certain cases we make the size of the GL buffer object + // smaller or larger than the size in fDesc. + + typedef SkNoncopyable INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 51974d4c02..50a74febe7 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -400,14 +400,14 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, // On many GPUs, map memory is very expensive, so we effectively disable it here by setting the // threshold to the maximum unless the client gives us a hint that map memory is cheap. - if (fBufferMapThreshold < 0) { + if (fGeometryBufferMapThreshold < 0) { // We think mapping on Chromium will be cheaper once we know ahead of time how much space // we will use for all GrBatchs. Right now we might wind up mapping a large buffer and using // a small subset. #if 0 - fBufferMapThreshold = kChromium_GrGLDriver == ctxInfo.driver() ? 0 : SK_MaxS32; + fGeometryBufferMapThreshold = kChromium_GrGLDriver == ctxInfo.driver() ? 0 : SK_MaxS32; #else - fBufferMapThreshold = SK_MaxS32; + fGeometryBufferMapThreshold = SK_MaxS32; #endif } diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h index c97e605ba8..ff4c457250 100644 --- a/src/gpu/gl/GrGLDefines.h +++ b/src/gpu/gl/GrGLDefines.h @@ -122,9 +122,7 @@ #define GR_GL_STREAM_DRAW 0x88E0 #define GR_GL_STREAM_READ 0x88E1 #define GR_GL_STATIC_DRAW 0x88E4 -#define GR_GL_STATIC_READ 0x88E5 #define GR_GL_DYNAMIC_DRAW 0x88E8 -#define GR_GL_DYNAMIC_READ 0x88E9 #define GR_GL_BUFFER_SIZE 0x8764 #define GR_GL_BUFFER_USAGE 0x8765 diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 6b591494b9..3a293610f2 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -6,7 +6,6 @@ */ #include "GrGLGpu.h" -#include "GrGLBuffer.h" #include "GrGLGLSL.h" #include "GrGLStencilAttachment.h" #include "GrGLTextureRenderTarget.h" @@ -844,7 +843,7 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, bool GrGLGpu::onTransferPixels(GrSurface* surface, int left, int top, int width, int height, - GrPixelConfig config, GrBuffer* transferBuffer, + GrPixelConfig config, GrTransferBuffer* buffer, size_t offset, size_t rowBytes) { GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); @@ -860,14 +859,16 @@ bool GrGLGpu::onTransferPixels(GrSurface* surface, this->setScratchTextureUnit(); GL_CALL(BindTexture(glTex->target(), glTex->textureID())); - SkASSERT(kXferCpuToGpu_GrBufferType == transferBuffer->type()); - SkASSERT(!transferBuffer->isMapped()); - const GrGLBuffer* glBuffer = reinterpret_cast<const GrGLBuffer*>(transferBuffer); - this->bindBuffer(glBuffer->bufferID(), glBuffer->target()); + SkASSERT(!buffer->isMapped()); + GrGLTransferBuffer* glBuffer = reinterpret_cast<GrGLTransferBuffer*>(buffer); + // bind the transfer buffer + SkASSERT(GR_GL_PIXEL_UNPACK_BUFFER == glBuffer->bufferType() || + GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == glBuffer->bufferType()); + GL_CALL(BindBuffer(glBuffer->bufferType(), glBuffer->bufferID())); bool success = false; GrMipLevel mipLevel; - mipLevel.fPixels = transferBuffer; + mipLevel.fPixels = buffer; mipLevel.fRowBytes = rowBytes; SkSTArray<1, GrMipLevel> texels; texels.push_back(mipLevel); @@ -1932,8 +1933,111 @@ GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRen // objects are implemented as client-side-arrays on tile-deferred architectures. #define DYNAMIC_USAGE_PARAM GR_GL_STREAM_DRAW -GrBuffer* GrGLGpu::onCreateBuffer(GrBufferType type, size_t size, GrAccessPattern accessPattern) { - return GrGLBuffer::Create(this, type, size, accessPattern); +GrVertexBuffer* GrGLGpu::onCreateVertexBuffer(size_t size, bool dynamic) { + GrGLVertexBuffer::Desc desc; + desc.fUsage = dynamic ? GrGLBufferImpl::kDynamicDraw_Usage : GrGLBufferImpl::kStaticDraw_Usage; + desc.fSizeInBytes = size; + + if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && dynamic) { + desc.fID = 0; + GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, desc); + return vertexBuffer; + } else { + desc.fID = 0; + GL_CALL(GenBuffers(1, &desc.fID)); + if (desc.fID) { + fHWGeometryState.setVertexBufferID(this, 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, + (GrGLsizeiptr) desc.fSizeInBytes, + nullptr, // data ptr + dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW)); + if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { + GL_CALL(DeleteBuffers(1, &desc.fID)); + this->notifyVertexBufferDelete(desc.fID); + return nullptr; + } + GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, desc); + return vertexBuffer; + } + return nullptr; + } +} + +GrIndexBuffer* GrGLGpu::onCreateIndexBuffer(size_t size, bool dynamic) { + GrGLIndexBuffer::Desc desc; + desc.fUsage = dynamic ? GrGLBufferImpl::kDynamicDraw_Usage : GrGLBufferImpl::kStaticDraw_Usage; + desc.fSizeInBytes = size; + + if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && dynamic) { + desc.fID = 0; + GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, desc); + return indexBuffer; + } else { + desc.fID = 0; + GL_CALL(GenBuffers(1, &desc.fID)); + if (desc.fID) { + fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, 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, + (GrGLsizeiptr) desc.fSizeInBytes, + nullptr, // data ptr + dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW)); + if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { + GL_CALL(DeleteBuffers(1, &desc.fID)); + this->notifyIndexBufferDelete(desc.fID); + return nullptr; + } + GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, desc); + return indexBuffer; + } + return nullptr; + } +} + +GrTransferBuffer* GrGLGpu::onCreateTransferBuffer(size_t size, TransferType xferType) { + GrGLCaps::TransferBufferType xferBufferType = this->ctxInfo().caps()->transferBufferType(); + if (GrGLCaps::kNone_TransferBufferType == xferBufferType) { + return nullptr; + } + + GrGLTransferBuffer::Desc desc; + bool toGpu = (kCpuToGpu_TransferType == xferType); + desc.fUsage = toGpu ? GrGLBufferImpl::kStreamDraw_Usage : GrGLBufferImpl::kStreamRead_Usage; + + desc.fSizeInBytes = size; + desc.fID = 0; + GL_CALL(GenBuffers(1, &desc.fID)); + if (desc.fID) { + CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); + // make sure driver can allocate memory for this bmapuffer + GrGLenum target; + if (GrGLCaps::kChromium_TransferBufferType == xferBufferType) { + target = toGpu ? GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM + : GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM; + } else { + SkASSERT(GrGLCaps::kPBO_TransferBufferType == xferBufferType); + target = toGpu ? GR_GL_PIXEL_UNPACK_BUFFER : GR_GL_PIXEL_PACK_BUFFER; + } + GL_CALL(BindBuffer(target, desc.fID)); + GL_ALLOC_CALL(this->glInterface(), + BufferData(target, + (GrGLsizeiptr) desc.fSizeInBytes, + nullptr, // data ptr + (toGpu ? GR_GL_STREAM_DRAW : GR_GL_STREAM_READ))); + if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { + GL_CALL(DeleteBuffers(1, &desc.fID)); + return nullptr; + } + GrTransferBuffer* transferBuffer = new GrGLTransferBuffer(this, desc, target); + return transferBuffer; + } + + return nullptr; } void GrGLGpu::flushScissor(const GrScissorState& scissorState, @@ -2018,18 +2122,18 @@ bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcesso void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc, const GrNonInstancedMesh& mesh, size_t* indexOffsetInBytes) { - const GrGLBuffer* vbuf; - vbuf = static_cast<const GrGLBuffer*>(mesh.vertexBuffer()); + GrGLVertexBuffer* vbuf; + vbuf = (GrGLVertexBuffer*) mesh.vertexBuffer(); SkASSERT(vbuf); SkASSERT(!vbuf->isMapped()); - const GrGLBuffer* ibuf = nullptr; + GrGLIndexBuffer* ibuf = nullptr; if (mesh.isIndexed()) { SkASSERT(indexOffsetInBytes); *indexOffsetInBytes = 0; - ibuf = static_cast<const GrGLBuffer*>(mesh.indexBuffer()); + ibuf = (GrGLIndexBuffer*)mesh.indexBuffer(); SkASSERT(ibuf); SkASSERT(!ibuf->isMapped()); @@ -2119,6 +2223,113 @@ void GrGLGpu::releaseBuffer(GrGLuint id, GrGLenum type) { } } +static GrGLenum get_gl_usage(GrGLBufferImpl::Usage usage) { + static const GrGLenum grToGL[] = { + GR_GL_STATIC_DRAW, // GrGLBufferImpl::kStaticDraw_Usage + DYNAMIC_USAGE_PARAM, // GrGLBufferImpl::kDynamicDraw_Usage + GR_GL_STREAM_DRAW, // GrGLBufferImpl::kStreamDraw_Usage + GR_GL_STREAM_READ, // GrGLBufferImpl::kStreamRead_Usage + }; + static_assert(SK_ARRAY_COUNT(grToGL) == GrGLBufferImpl::kUsageCount, "array_size_mismatch"); + + return grToGL[usage]; +} + +void* GrGLGpu::mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage, + size_t currentSize, size_t requestedSize) { + void* mapPtr = nullptr; + GrGLenum glUsage = get_gl_usage(usage); + bool readOnly = (GrGLBufferImpl::kStreamRead_Usage == usage); + + // Handling dirty context is done in the bindBuffer call + switch (this->glCaps().mapBufferType()) { + case GrGLCaps::kNone_MapBufferType: + break; + case GrGLCaps::kMapBuffer_MapBufferType: + this->bindBuffer(id, type); + // Let driver know it can discard the old data + if (GR_GL_USE_BUFFER_DATA_NULL_HINT || currentSize != requestedSize) { + GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); + } + GL_CALL_RET(mapPtr, MapBuffer(type, readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); + break; + case GrGLCaps::kMapBufferRange_MapBufferType: { + this->bindBuffer(id, type); + // Make sure the GL buffer size agrees with fDesc before mapping. + if (currentSize != requestedSize) { + GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); + } + GrGLbitfield writeAccess = GR_GL_MAP_WRITE_BIT; + // TODO: allow the client to specify invalidation in the stream draw case + if (GrGLBufferImpl::kStreamDraw_Usage != usage) { + writeAccess |= GR_GL_MAP_INVALIDATE_BUFFER_BIT; + } + GL_CALL_RET(mapPtr, MapBufferRange(type, 0, requestedSize, readOnly ? + GR_GL_MAP_READ_BIT : + writeAccess)); + break; + } + case GrGLCaps::kChromium_MapBufferType: + this->bindBuffer(id, type); + // Make sure the GL buffer size agrees with fDesc before mapping. + if (currentSize != requestedSize) { + GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); + } + GL_CALL_RET(mapPtr, MapBufferSubData(type, 0, requestedSize, readOnly ? + GR_GL_READ_ONLY : + GR_GL_WRITE_ONLY)); + break; + } + return mapPtr; +} + +void GrGLGpu::bufferData(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage, + size_t currentSize, const void* src, size_t srcSizeInBytes) { + SkASSERT(srcSizeInBytes <= currentSize); + // bindbuffer handles dirty context + this->bindBuffer(id, type); + GrGLenum glUsage = get_gl_usage(usage); + +#if GR_GL_USE_BUFFER_DATA_NULL_HINT + if (currentSize == srcSizeInBytes) { + GL_CALL(BufferData(type, (GrGLsizeiptr) srcSizeInBytes, src, glUsage)); + } else { + // Before we call glBufferSubData we give the driver a hint using + // glBufferData with nullptr. 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. + // TODO I think we actually want to try calling bufferData here + GL_CALL(BufferData(type, currentSize, nullptr, glUsage)); + GL_CALL(BufferSubData(type, 0, (GrGLsizeiptr) 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 (map() does a glBufferData(..size, nullptr..)) + GL_CALL(BufferData(type, srcSizeInBytes, src, glUsage)); +#endif +} + +void GrGLGpu::unmapBuffer(GrGLuint id, GrGLenum type, void* mapPtr) { + // bind buffer handles the dirty context + switch (this->glCaps().mapBufferType()) { + case GrGLCaps::kNone_MapBufferType: + SkDEBUGFAIL("Shouldn't get here."); + return; + case GrGLCaps::kMapBuffer_MapBufferType: // fall through + case GrGLCaps::kMapBufferRange_MapBufferType: + this->bindBuffer(id, type); + GL_CALL(UnmapBuffer(type)); + break; + case GrGLCaps::kChromium_MapBufferType: + this->bindBuffer(id, type); + GL_CALL(UnmapBufferSubData(mapPtr)); + break; + } +} + void GrGLGpu::disableScissor() { if (kNo_TriState != fHWScissorSettings.fEnabled) { GL_CALL(Disable(GR_GL_SCISSOR_TEST)); @@ -4140,8 +4351,8 @@ void GrGLGpu::resetShaderCacheForTesting() const { /////////////////////////////////////////////////////////////////////////////// GrGLAttribArrayState* GrGLGpu::HWGeometryState::bindArrayAndBuffersToDraw( GrGLGpu* gpu, - const GrGLBuffer* vbuffer, - const GrGLBuffer* ibuffer) { + const GrGLVertexBuffer* vbuffer, + const GrGLIndexBuffer* ibuffer) { SkASSERT(vbuffer); GrGLuint vbufferID = vbuffer->bufferID(); GrGLuint* ibufferIDPtr = nullptr; diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index bc79d2f427..bcb3c193dc 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -10,12 +10,15 @@ #include "GrGLContext.h" #include "GrGLIRect.h" +#include "GrGLIndexBuffer.h" #include "GrGLPathRendering.h" #include "GrGLProgram.h" #include "GrGLRenderTarget.h" #include "GrGLStencilAttachment.h" #include "GrGLTexture.h" +#include "GrGLTransferBuffer.h" #include "GrGLVertexArray.h" +#include "GrGLVertexBuffer.h" #include "GrGpu.h" #include "GrPipelineBuilder.h" #include "GrTypes.h" @@ -23,7 +26,6 @@ #include "SkTArray.h" #include "SkTypes.h" -class GrGLBuffer; class GrPipeline; class GrNonInstancedMesh; class GrSwizzle; @@ -99,6 +101,15 @@ public: void releaseBuffer(GrGLuint id, GrGLenum type); + // sizes are in bytes + void* mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage, size_t currentSize, + size_t requestedSize); + + void unmapBuffer(GrGLuint id, GrGLenum type, void* mapPtr); + + void bufferData(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage, size_t currentSize, + const void* src, size_t srcSizeInBytes); + const GrGLContext* glContextForTesting() const override { return &this->glContext(); } @@ -138,7 +149,9 @@ private: GrGpuResource::LifeCycle lifeCycle, const SkTArray<GrMipLevel>& texels) override; - GrBuffer* onCreateBuffer(GrBufferType, size_t size, GrAccessPattern) override; + GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) override; + GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) override; + GrTransferBuffer* onCreateTransferBuffer(size_t size, TransferType type) override; GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) override; GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&, GrWrapOwnership) override; @@ -195,7 +208,7 @@ private: bool onTransferPixels(GrSurface*, int left, int top, int width, int height, - GrPixelConfig config, GrBuffer* transferBuffer, + GrPixelConfig config, GrTransferBuffer* buffer, size_t offset, size_t rowBytes) override; void onResolveRenderTarget(GrRenderTarget* target) override; @@ -498,8 +511,8 @@ private: * returned GrGLAttribArrayState should be used to set vertex attribute arrays. */ GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGLGpu* gpu, - const GrGLBuffer* vbuffer, - const GrGLBuffer* ibuffer); + const GrGLVertexBuffer* vbuffer, + const GrGLIndexBuffer* ibuffer); /** Variants of the above that takes GL buffer IDs. Note that 0 does not imply that a buffer won't be bound. The "default buffer" will be bound, which is used for client-side diff --git a/src/gpu/gl/GrGLIndexBuffer.cpp b/src/gpu/gl/GrGLIndexBuffer.cpp new file mode 100644 index 0000000000..5a794ad824 --- /dev/null +++ b/src/gpu/gl/GrGLIndexBuffer.cpp @@ -0,0 +1,60 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLIndexBuffer.h" +#include "GrGLGpu.h" +#include "SkTraceMemoryDump.h" + +GrGLIndexBuffer::GrGLIndexBuffer(GrGLGpu* gpu, const Desc& desc) + : INHERITED(gpu, desc.fSizeInBytes, GrGLBufferImpl::kDynamicDraw_Usage == desc.fUsage, + 0 == desc.fID) + , fImpl(gpu, desc, GR_GL_ELEMENT_ARRAY_BUFFER) { + this->registerWithCache(); +} + +void GrGLIndexBuffer::onRelease() { + if (!this->wasDestroyed()) { + fImpl.release(this->getGpuGL()); + } + + INHERITED::onRelease(); +} + +void GrGLIndexBuffer::onAbandon() { + fImpl.abandon(); + INHERITED::onAbandon(); +} + +void* GrGLIndexBuffer::onMap() { + if (!this->wasDestroyed()) { + return fImpl.map(this->getGpuGL()); + } else { + return nullptr; + } +} + +void GrGLIndexBuffer::onUnmap() { + if (!this->wasDestroyed()) { + fImpl.unmap(this->getGpuGL()); + } +} + +bool GrGLIndexBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) { + if (!this->wasDestroyed()) { + return fImpl.updateData(this->getGpuGL(), src, srcSizeInBytes); + } else { + return false; + } +} + +void GrGLIndexBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const { + SkString buffer_id; + buffer_id.appendU32(this->bufferID()); + traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer", + buffer_id.c_str()); +} diff --git a/src/gpu/gl/GrGLIndexBuffer.h b/src/gpu/gl/GrGLIndexBuffer.h new file mode 100644 index 0000000000..628970a0fa --- /dev/null +++ b/src/gpu/gl/GrGLIndexBuffer.h @@ -0,0 +1,48 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLIndexBuffer_DEFINED +#define GrGLIndexBuffer_DEFINED + +#include "GrIndexBuffer.h" +#include "GrGLBufferImpl.h" +#include "gl/GrGLInterface.h" + +class GrGLGpu; + +class GrGLIndexBuffer : public GrIndexBuffer { + +public: + typedef GrGLBufferImpl::Desc Desc; + + GrGLIndexBuffer(GrGLGpu* gpu, const Desc& desc); + + GrGLuint bufferID() const { return fImpl.bufferID(); } + size_t baseOffset() const { return fImpl.baseOffset(); } + +protected: + void onAbandon() override; + void onRelease() override; + void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const override; + +private: + void* onMap() override; + void onUnmap() override; + bool onUpdateData(const void* src, size_t srcSizeInBytes) override; + + GrGLGpu* getGpuGL() const { + SkASSERT(!this->wasDestroyed()); + return (GrGLGpu*)(this->getGpu()); + } + + GrGLBufferImpl fImpl; + + typedef GrIndexBuffer INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLTransferBuffer.cpp b/src/gpu/gl/GrGLTransferBuffer.cpp new file mode 100755 index 0000000000..b7ee766d92 --- /dev/null +++ b/src/gpu/gl/GrGLTransferBuffer.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLTransferBuffer.h" +#include "GrGLGpu.h" +#include "SkTraceMemoryDump.h" + +GrGLTransferBuffer::GrGLTransferBuffer(GrGLGpu* gpu, const Desc& desc, GrGLenum type) + : INHERITED(gpu, desc.fSizeInBytes) + , fImpl(gpu, desc, type) { + this->registerWithCache(); +} + +void GrGLTransferBuffer::onRelease() { + if (!this->wasDestroyed()) { + fImpl.release(this->getGpuGL()); + } + + INHERITED::onRelease(); +} + +void GrGLTransferBuffer::onAbandon() { + fImpl.abandon(); + INHERITED::onAbandon(); +} + +void* GrGLTransferBuffer::onMap() { + if (!this->wasDestroyed()) { + return fImpl.map(this->getGpuGL()); + } else { + return nullptr; + } +} + +void GrGLTransferBuffer::onUnmap() { + if (!this->wasDestroyed()) { + fImpl.unmap(this->getGpuGL()); + } +} + +void GrGLTransferBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const { + SkString buffer_id; + buffer_id.appendU32(this->bufferID()); + traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer", + buffer_id.c_str()); +} diff --git a/src/gpu/gl/GrGLTransferBuffer.h b/src/gpu/gl/GrGLTransferBuffer.h new file mode 100755 index 0000000000..e01d4447df --- /dev/null +++ b/src/gpu/gl/GrGLTransferBuffer.h @@ -0,0 +1,48 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLTransferBuffer_DEFINED +#define GrGLTransferBuffer_DEFINED + +#include "GrTransferBuffer.h" +#include "GrGLBufferImpl.h" +#include "gl/GrGLInterface.h" + +class GrGLGpu; + +class GrGLTransferBuffer : public GrTransferBuffer { + +public: + typedef GrGLBufferImpl::Desc Desc; + + GrGLTransferBuffer(GrGLGpu* gpu, const Desc& desc, GrGLenum type); + + GrGLuint bufferID() const { return fImpl.bufferID(); } + size_t baseOffset() const { return fImpl.baseOffset(); } + GrGLenum bufferType() const { return fImpl.bufferType(); } + +protected: + void onAbandon() override; + void onRelease() override; + void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const override; + +private: + void* onMap() override; + void onUnmap() override; + + GrGLGpu* getGpuGL() const { + SkASSERT(!this->wasDestroyed()); + return (GrGLGpu*)(this->getGpu()); + } + + GrGLBufferImpl fImpl; + + typedef GrTransferBuffer INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLVertexArray.h b/src/gpu/gl/GrGLVertexArray.h index 4a99d59058..f5a97672f3 100644 --- a/src/gpu/gl/GrGLVertexArray.h +++ b/src/gpu/gl/GrGLVertexArray.h @@ -13,6 +13,8 @@ #include "gl/GrGLTypes.h" #include "SkTArray.h" +class GrGLVertexBuffer; +class GrGLIndexBuffer; class GrGLGpu; /** diff --git a/src/gpu/gl/GrGLVertexBuffer.cpp b/src/gpu/gl/GrGLVertexBuffer.cpp new file mode 100644 index 0000000000..2294844fc4 --- /dev/null +++ b/src/gpu/gl/GrGLVertexBuffer.cpp @@ -0,0 +1,60 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLVertexBuffer.h" +#include "GrGLGpu.h" +#include "SkTraceMemoryDump.h" + +GrGLVertexBuffer::GrGLVertexBuffer(GrGLGpu* gpu, const Desc& desc) + : INHERITED(gpu, desc.fSizeInBytes, GrGLBufferImpl::kDynamicDraw_Usage == desc.fUsage, + 0 == desc.fID) + , fImpl(gpu, desc, GR_GL_ARRAY_BUFFER) { + this->registerWithCache(); +} + +void GrGLVertexBuffer::onRelease() { + if (!this->wasDestroyed()) { + fImpl.release(this->getGpuGL()); + } + + INHERITED::onRelease(); +} + +void GrGLVertexBuffer::onAbandon() { + fImpl.abandon(); + INHERITED::onAbandon(); +} + +void* GrGLVertexBuffer::onMap() { + if (!this->wasDestroyed()) { + return fImpl.map(this->getGpuGL()); + } else { + return nullptr; + } +} + +void GrGLVertexBuffer::onUnmap() { + if (!this->wasDestroyed()) { + fImpl.unmap(this->getGpuGL()); + } +} + +bool GrGLVertexBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) { + if (!this->wasDestroyed()) { + return fImpl.updateData(this->getGpuGL(), src, srcSizeInBytes); + } else { + return false; + } +} + +void GrGLVertexBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const { + SkString buffer_id; + buffer_id.appendU32(this->bufferID()); + traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer", + buffer_id.c_str()); +} diff --git a/src/gpu/gl/GrGLVertexBuffer.h b/src/gpu/gl/GrGLVertexBuffer.h new file mode 100644 index 0000000000..93c6b2badd --- /dev/null +++ b/src/gpu/gl/GrGLVertexBuffer.h @@ -0,0 +1,48 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLVertexBuffer_DEFINED +#define GrGLVertexBuffer_DEFINED + +#include "GrVertexBuffer.h" +#include "GrGLBufferImpl.h" +#include "gl/GrGLInterface.h" + +class GrGLGpu; + +class GrGLVertexBuffer : public GrVertexBuffer { + +public: + typedef GrGLBufferImpl::Desc Desc; + + GrGLVertexBuffer(GrGLGpu* gpu, const Desc& desc); + + GrGLuint bufferID() const { return fImpl.bufferID(); } + size_t baseOffset() const { return fImpl.baseOffset(); } + +protected: + void onAbandon() override; + void onRelease() override; + void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const override; + +private: + void* onMap() override; + void onUnmap() override; + bool onUpdateData(const void* src, size_t srcSizeInBytes) override; + + GrGLGpu* getGpuGL() const { + SkASSERT(!this->wasDestroyed()); + return (GrGLGpu*)(this->getGpu()); + } + + GrGLBufferImpl fImpl; + + typedef GrVertexBuffer INHERITED; +}; + +#endif |