Browse Source

Ensure that buffer object is properly created before using it.

pull/68/head
Vladimír Vondruš 12 years ago
parent
commit
8f58d9dd82
  1. 39
      src/Magnum/Buffer.cpp
  2. 18
      src/Magnum/Buffer.h
  3. 11
      src/Magnum/Test/BufferGLTest.cpp

39
src/Magnum/Buffer.cpp

@ -122,10 +122,11 @@ void Buffer::copy(Buffer& read, Buffer& write, const GLintptr readOffset, const
}
#endif
Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint)
Buffer::Buffer(const Target targetHint): _targetHint{targetHint},
#ifdef CORRADE_TARGET_NACL
, _mappedBuffer(nullptr)
_mappedBuffer{nullptr},
#endif
_created{false}
{
glGenBuffers(1, &_id);
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
@ -144,7 +145,20 @@ Buffer::~Buffer() {
glDeleteBuffers(1, &_id);
}
std::string Buffer::label() const {
inline void Buffer::createIfNotAlready() {
if(_created) return;
/* glGen*() does not create the object, just reserves the name. Some
commands (such as glInvalidateBufferData() or glObjectLabel()) operate
with IDs directly and they require the object to be created. Binding the
buffer finally creates it. Also all EXT DSA functions implicitly create
it. */
bindSomewhereInternal(_targetHint);
CORRADE_INTERNAL_ASSERT(_created);
}
std::string Buffer::label() {
createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES
return Context::current()->state().debug->getLabelImplementation(GL_BUFFER, _id);
#else
@ -153,6 +167,7 @@ std::string Buffer::label() const {
}
Buffer& Buffer::setLabelInternal(const Containers::ArrayReference<const char> label) {
createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES
Context::current()->state().debug->labelImplementation(GL_BUFFER, _id, label);
#else
@ -161,14 +176,16 @@ Buffer& Buffer::setLabelInternal(const Containers::ArrayReference<const char> la
return *this;
}
void Buffer::bindInternal(Target target, GLuint id) {
void Buffer::bindInternal(const Target target, Buffer* const buffer) {
const GLuint id = buffer ? buffer->_id : 0;
GLuint& bound = Context::current()->state().buffer->bindings[Implementation::BufferState::indexForTarget(target)];
/* Already bound, nothing to do */
if(bound == id) return;
/* Bind the buffer otherwise */
/* Bind the buffer otherwise, which will also finally create it */
bound = id;
buffer->_created = true;
glBindBuffer(GLenum(target), id);
}
@ -186,6 +203,7 @@ Buffer::Target Buffer::bindSomewhereInternal(Target hint) {
/* Bind the buffer to hint target otherwise */
hintBinding = _id;
_created = true;
glBindBuffer(GLenum(hint), _id);
return hint;
}
@ -274,6 +292,7 @@ void Buffer::copyImplementationDefault(Buffer& read, Buffer& write, GLintptr rea
#ifndef MAGNUM_TARGET_GLES
void Buffer::copyImplementationDSA(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
read._created = write._created = true;
glNamedCopyBufferSubDataEXT(read._id, write._id, readOffset, writeOffset, size);
}
#endif
@ -285,6 +304,7 @@ void Buffer::getParameterImplementationDefault(const GLenum value, GLint* const
#ifndef MAGNUM_TARGET_GLES
void Buffer::getParameterImplementationDSA(const GLenum value, GLint* const data) {
_created = true;
glGetNamedBufferParameterivEXT(_id, value, data);
}
#endif
@ -295,6 +315,7 @@ void Buffer::getSubDataImplementationDefault(const GLintptr offset, const GLsize
}
void Buffer::getSubDataImplementationDSA(const GLintptr offset, const GLsizeiptr size, GLvoid* const data) {
_created = true;
glGetNamedBufferSubDataEXT(_id, offset, size, data);
}
#endif
@ -305,6 +326,7 @@ void Buffer::dataImplementationDefault(GLsizeiptr size, const GLvoid* data, Buff
#ifndef MAGNUM_TARGET_GLES
void Buffer::dataImplementationDSA(GLsizeiptr size, const GLvoid* data, BufferUsage usage) {
_created = true;
glNamedBufferDataEXT(_id, size, data, GLenum(usage));
}
#endif
@ -315,6 +337,7 @@ void Buffer::subDataImplementationDefault(GLintptr offset, GLsizeiptr size, cons
#ifndef MAGNUM_TARGET_GLES
void Buffer::subDataImplementationDSA(GLintptr offset, GLsizeiptr size, const GLvoid* data) {
_created = true;
glNamedBufferSubDataEXT(_id, offset, size, data);
}
#endif
@ -323,6 +346,7 @@ void Buffer::invalidateImplementationNoOp() {}
#ifndef MAGNUM_TARGET_GLES
void Buffer::invalidateImplementationARB() {
createIfNotAlready();
glInvalidateBufferData(_id);
}
#endif
@ -331,6 +355,7 @@ void Buffer::invalidateSubImplementationNoOp(GLintptr, GLsizeiptr) {}
#ifndef MAGNUM_TARGET_GLES
void Buffer::invalidateSubImplementationARB(GLintptr offset, GLsizeiptr length) {
createIfNotAlready();
glInvalidateBufferSubData(_id, offset, length);
}
#endif
@ -348,6 +373,7 @@ void* Buffer::mapImplementationDefault(MapAccess access) {
#ifndef MAGNUM_TARGET_GLES
void* Buffer::mapImplementationDSA(MapAccess access) {
_created = true;
return glMapNamedBufferEXT(_id, GLenum(access));
}
#endif
@ -367,6 +393,7 @@ void* Buffer::mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length,
#ifndef MAGNUM_TARGET_GLES
void* Buffer::mapRangeImplementationDSA(GLintptr offset, GLsizeiptr length, MapFlags access) {
_created = true;
return glMapNamedBufferRangeEXT(_id, offset, length, GLenum(access));
}
#endif
@ -385,6 +412,7 @@ void Buffer::flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr l
#ifndef MAGNUM_TARGET_GLES
void Buffer::flushMappedRangeImplementationDSA(GLintptr offset, GLsizeiptr length) {
_created = true;
glFlushMappedNamedBufferRangeEXT(_id, offset, length);
}
#endif
@ -401,6 +429,7 @@ bool Buffer::unmapImplementationDefault() {
#ifndef MAGNUM_TARGET_GLES
bool Buffer::unmapImplementationDSA() {
_created = true;
return glUnmapNamedBufferEXT(_id);
}
#endif

18
src/Magnum/Buffer.h

@ -569,7 +569,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{BUFFER_OBJECT_EXT}
*/
std::string label() const;
std::string label();
/**
* @brief Set buffer label
@ -852,13 +852,11 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
private:
#endif
/* There should be no need to use these from user code */
static void unbindInternal(Target target) { bindInternal(target, 0); }
void bindInternal(Target target) { bindInternal(target, _id); }
static void unbindInternal(Target target) { bindInternal(target, nullptr); }
void bindInternal(Target target) { bindInternal(target, this); }
private:
Buffer& setLabelInternal(Containers::ArrayReference<const char> label);
static void bindInternal(Target hint, GLuint id);
static void bindInternal(Target hint, Buffer* buffer);
Target MAGNUM_LOCAL bindSomewhereInternal(Target hint);
#ifndef MAGNUM_TARGET_GLES2
@ -868,6 +866,10 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
#endif
#endif
void MAGNUM_LOCAL createIfNotAlready();
Buffer& setLabelInternal(Containers::ArrayReference<const char> label);
#ifndef MAGNUM_TARGET_GLES
void subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data);
#endif
@ -927,6 +929,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
#ifdef CORRADE_TARGET_NACL
void* _mappedBuffer;
#endif
bool _created; /* see createIfNotAlready() for details */
};
CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags)
@ -934,13 +937,14 @@ CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags)
/** @debugoperatorclassenum{Magnum::Buffer,Magnum::Buffer::Target} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Buffer::Target value);
inline Buffer::Buffer(Buffer&& other) noexcept: _id(other._id), _targetHint(other._targetHint) {
inline Buffer::Buffer(Buffer&& other) noexcept: _id{other._id}, _targetHint{other._targetHint}, _created{other._created} {
other._id = 0;
}
inline Buffer& Buffer::operator=(Buffer&& other) noexcept {
std::swap(_id, other._id);
std::swap(_targetHint, other._targetHint);
std::swap(_created, other._created);
return *this;
}

11
src/Magnum/Test/BufferGLTest.cpp

@ -118,20 +118,15 @@ void BufferGLTest::label() {
!Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>())
CORRADE_SKIP("Required extension is not available");
{
/** @todo Is this even legal optimization? */
CORRADE_EXPECT_FAIL("The object must be used at least once before setting/querying label.");
CORRADE_VERIFY(false);
}
Buffer buffer;
buffer.setData({nullptr, 3}, BufferUsage::StaticDraw);
CORRADE_COMPARE(buffer.label(), "");
MAGNUM_VERIFY_NO_ERROR();
buffer.setLabel("MyBuffer");
CORRADE_COMPARE(buffer.label(), "MyBuffer");
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(buffer.label(), "MyBuffer");
}
void BufferGLTest::data() {

Loading…
Cancel
Save