summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp')
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp204
1 files changed, 204 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp
new file mode 100755
index 000000000..a5eda6b30
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp
@@ -0,0 +1,204 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferGL.cpp: Implements the class methods for BufferGL.
+
+#include "libANGLE/renderer/gl/BufferGL.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace rx
+{
+
+// Use the GL_COPY_READ_BUFFER binding when two buffers need to be bound simultaneously.
+// GL_ELEMENT_ARRAY_BUFFER is supported on more versions but can modify the state of the currently
+// bound VAO. Two simultaneous buffer bindings are only needed for glCopyBufferSubData which also
+// adds the GL_COPY_READ_BUFFER binding.
+static const GLenum SourceBufferOperationTarget = GL_COPY_READ_BUFFER;
+
+// Use the GL_ELEMENT_ARRAY_BUFFER binding for most operations since it's available on all
+// supported GL versions and doesn't affect any current state when it changes.
+static const GLenum DestBufferOperationTarget = GL_ARRAY_BUFFER;
+
+BufferGL::BufferGL(const gl::BufferState &state,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager)
+ : BufferImpl(state),
+ mIsMapped(false),
+ mMapOffset(0),
+ mMapSize(0),
+ mShadowBufferData(!CanMapBufferForRead(functions)),
+ mShadowCopy(),
+ mBufferSize(0),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mBufferID(0)
+{
+ ASSERT(mFunctions);
+ ASSERT(mStateManager);
+
+ mFunctions->genBuffers(1, &mBufferID);
+}
+
+BufferGL::~BufferGL()
+{
+ mStateManager->deleteBuffer(mBufferID);
+ mBufferID = 0;
+}
+
+gl::Error BufferGL::setData(GLenum /*target*/, const void *data, size_t size, GLenum usage)
+{
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ mFunctions->bufferData(DestBufferOperationTarget, size, data, usage);
+
+ if (mShadowBufferData)
+ {
+ if (!mShadowCopy.resize(size))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize buffer data shadow copy.");
+ }
+
+ if (size > 0 && data != nullptr)
+ {
+ memcpy(mShadowCopy.data(), data, size);
+ }
+ }
+
+ mBufferSize = size;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::setSubData(GLenum /*target*/, const void *data, size_t size, size_t offset)
+{
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ mFunctions->bufferSubData(DestBufferOperationTarget, offset, size, data);
+
+ if (mShadowBufferData && size > 0)
+ {
+ memcpy(mShadowCopy.data() + offset, data, size);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
+{
+ BufferGL *sourceGL = GetAs<BufferGL>(source);
+
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ mStateManager->bindBuffer(SourceBufferOperationTarget, sourceGL->getBufferID());
+
+ mFunctions->copyBufferSubData(SourceBufferOperationTarget, DestBufferOperationTarget, sourceOffset, destOffset, size);
+
+ if (mShadowBufferData && size > 0)
+ {
+ ASSERT(sourceGL->mShadowBufferData);
+ memcpy(mShadowCopy.data() + destOffset, sourceGL->mShadowCopy.data() + sourceOffset, size);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::map(GLenum access, GLvoid **mapPtr)
+{
+ if (mShadowBufferData)
+ {
+ *mapPtr = mShadowCopy.data();
+ }
+ else
+ {
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ *mapPtr = mFunctions->mapBuffer(DestBufferOperationTarget, access);
+ }
+
+ mIsMapped = true;
+ mMapOffset = 0;
+ mMapSize = mBufferSize;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+{
+ if (mShadowBufferData)
+ {
+ *mapPtr = mShadowCopy.data() + offset;
+ }
+ else
+ {
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ *mapPtr = mFunctions->mapBufferRange(DestBufferOperationTarget, offset, length, access);
+ }
+
+ mIsMapped = true;
+ mMapOffset = offset;
+ mMapSize = length;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::unmap(GLboolean *result)
+{
+ ASSERT(result);
+ ASSERT(mIsMapped);
+
+ if (mShadowBufferData)
+ {
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ mFunctions->bufferSubData(DestBufferOperationTarget, mMapOffset, mMapSize,
+ mShadowCopy.data() + mMapOffset);
+ *result = GL_TRUE;
+ }
+ else
+ {
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ *result = mFunctions->unmapBuffer(DestBufferOperationTarget);
+ }
+
+ mIsMapped = false;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange)
+{
+ ASSERT(!mIsMapped);
+
+ if (mShadowBufferData)
+ {
+ *outRange = gl::ComputeIndexRange(type, mShadowCopy.data() + offset, count,
+ primitiveRestartEnabled);
+ }
+ else
+ {
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+
+ const gl::Type &typeInfo = gl::GetTypeInfo(type);
+ const uint8_t *bufferData = MapBufferRangeWithFallback(
+ mFunctions, DestBufferOperationTarget, offset, count * typeInfo.bytes, GL_MAP_READ_BIT);
+ *outRange = gl::ComputeIndexRange(type, bufferData, count, primitiveRestartEnabled);
+ mFunctions->unmapBuffer(DestBufferOperationTarget);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+GLuint BufferGL::getBufferID() const
+{
+ return mBufferID;
+}
+
+}