| // | |
| // Copyright (c) 2002-2010 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. | |
| // | |
| // Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or | |
| // index data. Implements GL buffer objects and related functionality. | |
| // [OpenGL ES 2.0.24] section 2.9 page 21. | |
| #include "libGLESv2/Buffer.h" | |
| #include <cstdlib> | |
| #include <limits> | |
| #include <utility> | |
| #include "common/debug.h" | |
| #include "libGLESv2/geometry/backend.h" | |
| namespace gl | |
| { | |
| Buffer::Buffer(BufferBackEnd *backEnd) | |
| : mBackEnd(backEnd), mIdentityTranslation(NULL) | |
| { | |
| } | |
| Buffer::~Buffer() | |
| { | |
| delete mIdentityTranslation; | |
| } | |
| GLenum Buffer::bufferData(const void* data, GLsizeiptr size, GLenum usage) | |
| { | |
| if (size < 0) return GL_INVALID_VALUE; | |
| const GLubyte* newdata = static_cast<const GLubyte*>(data); | |
| if (size == 0) | |
| { | |
| mContents.clear(); | |
| delete mIdentityTranslation; | |
| mIdentityTranslation = NULL; | |
| } | |
| else if (size != mContents.size()) | |
| { | |
| // vector::resize only provides the basic exception guarantee, so use temporaries & swap to get the strong exception guarantee. | |
| // We don't want to risk having mContents and mIdentityTranslation that have different contents or even different sizes. | |
| std::vector<GLubyte> newContents; | |
| if (newdata != NULL) | |
| { | |
| newContents.assign(newdata, newdata + size); | |
| } | |
| else | |
| { | |
| newContents.assign(size, 0); | |
| } | |
| TranslatedVertexBuffer *newIdentityTranslation = mBackEnd->createVertexBuffer(size); | |
| // No exceptions allowed after this point. | |
| mContents.swap(newContents); | |
| delete mIdentityTranslation; | |
| mIdentityTranslation = newIdentityTranslation; | |
| } | |
| else if (newdata != NULL) | |
| { | |
| mContents.assign(newdata, newdata + size); | |
| } | |
| mUsage = usage; | |
| return copyToIdentityBuffer(0, size); | |
| } | |
| GLenum Buffer::bufferSubData(const void* data, GLsizeiptr size, GLintptr offset) | |
| { | |
| if (size < 0 || offset < 0) return GL_INVALID_VALUE; | |
| if (std::numeric_limits<GLsizeiptr>::max() - offset < size) return GL_INVALID_VALUE; | |
| if (size + offset > static_cast<GLsizeiptr>(mContents.size())) return GL_INVALID_VALUE; | |
| const GLubyte *newdata = static_cast<const GLubyte*>(data); | |
| copy(newdata, newdata + size, mContents.begin() + offset); | |
| return copyToIdentityBuffer(offset, size); | |
| } | |
| GLenum Buffer::copyToIdentityBuffer(GLintptr offset, GLsizeiptr length) | |
| { | |
| ASSERT(offset >= 0 && length >= 0); | |
| if (length > 0) // If length == 0 mIdentityTranslation might be NULL. | |
| { | |
| // This is a stalling map. Not great for performance. | |
| GLubyte *p = static_cast<GLubyte*>(mIdentityTranslation->map()); | |
| memcpy(p + offset, &mContents[0] + offset, length); | |
| mIdentityTranslation->unmap(); | |
| } | |
| return GL_NO_ERROR; | |
| } | |
| } |