aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2016-03-25 04:55:58 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-03-25 04:55:59 -0700
commitf8c3ba40cf4f42b2c2ba1b473c28d7733383223e (patch)
tree00c671765311aaa35c8a9d6fa0a6b84907c871b9 /src/gpu/gl
parentf299e7105435829c47e94f4cf6e408cad675bc77 (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.cpp336
-rw-r--r--src/gpu/gl/GrGLBuffer.h61
-rw-r--r--src/gpu/gl/GrGLBufferImpl.cpp122
-rw-r--r--src/gpu/gl/GrGLBufferImpl.h69
-rw-r--r--src/gpu/gl/GrGLCaps.cpp6
-rw-r--r--src/gpu/gl/GrGLDefines.h2
-rw-r--r--src/gpu/gl/GrGLGpu.cpp241
-rw-r--r--src/gpu/gl/GrGLGpu.h23
-rw-r--r--src/gpu/gl/GrGLIndexBuffer.cpp60
-rw-r--r--src/gpu/gl/GrGLIndexBuffer.h48
-rwxr-xr-xsrc/gpu/gl/GrGLTransferBuffer.cpp51
-rwxr-xr-xsrc/gpu/gl/GrGLTransferBuffer.h48
-rw-r--r--src/gpu/gl/GrGLVertexArray.h2
-rw-r--r--src/gpu/gl/GrGLVertexBuffer.cpp60
-rw-r--r--src/gpu/gl/GrGLVertexBuffer.h48
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