From 3f365857eef5994c1ffcba2cdf537f1ffb3489f6 Mon Sep 17 00:00:00 2001 From: vrld Date: Wed, 7 Mar 2012 23:24:29 +0100 Subject: [PATCH] Replace glMapBufferARB() with temp memory + glBufferSubDataARB(). Instead of letting OpenGL manage the memory mapping, allocate a temporary block of memory upon VBO:map(). Upon VBO::unmap() the block is copied to graphics memory using glBufferSubDataARB() and then released. Hopefully this will fix some weird error with Windows XP + old drivers, where VBOs can be created, but the mapped memory cannot be allocated resulting in the sprite batch drawing nothing at all. According to the interwebs this could actually faster than using OpenGL mapped memory, because there is no unnecessary syncing involved. --- src/modules/graphics/opengl/SpriteBatch.cpp | 4 ++-- src/modules/graphics/opengl/VertexBuffer.cpp | 15 ++++++++------- src/modules/graphics/opengl/VertexBuffer.h | 15 +++++++++------ 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/modules/graphics/opengl/SpriteBatch.cpp b/src/modules/graphics/opengl/SpriteBatch.cpp index d7ce83a7f..c645b916b 100644 --- a/src/modules/graphics/opengl/SpriteBatch.cpp +++ b/src/modules/graphics/opengl/SpriteBatch.cpp @@ -69,7 +69,7 @@ namespace opengl // Fill element buffer. { VertexBuffer::Bind bind(*element_buf); - VertexBuffer::Mapper mapper(*element_buf, GL_WRITE_ONLY); + VertexBuffer::Mapper mapper(*element_buf); GLushort *indices = static_cast(mapper.get()); @@ -158,7 +158,7 @@ namespace opengl { VertexBuffer::Bind bind(*array_buf); - return array_buf->map(GL_READ_WRITE); + return array_buf->map(); } void SpriteBatch::unlock() diff --git a/src/modules/graphics/opengl/VertexBuffer.cpp b/src/modules/graphics/opengl/VertexBuffer.cpp index e1dfed529..d5f969356 100644 --- a/src/modules/graphics/opengl/VertexBuffer.cpp +++ b/src/modules/graphics/opengl/VertexBuffer.cpp @@ -72,7 +72,7 @@ namespace opengl delete [] buf; } - void *VertexArray::map(GLenum/* access*/) + void *VertexArray::map() { return buf; } @@ -122,20 +122,21 @@ namespace opengl unload(false); } - void *VBO::map(GLenum access) + void *VBO::map() { - // Don't map twice. + // mapping twice could result in memory leaks if (mapped) - return mapped; + throw love::Exception("VBO is already mapped!"); - mapped = glMapBufferARB(getTarget(), access); + mapped = malloc(getSize()); return mapped; } void VBO::unmap() { - glUnmapBufferARB(getTarget()); + glBufferSubDataARB(getTarget(), 0, getSize(), (void*)mapped); + free(mapped); mapped = 0; } @@ -209,7 +210,7 @@ namespace opengl GLint size; glGetBufferParameterivARB(getTarget(), GL_BUFFER_SIZE, &size); - const char *src = static_cast(map(GL_READ_ONLY)); + const char *src = static_cast(map()); if (src) { diff --git a/src/modules/graphics/opengl/VertexBuffer.h b/src/modules/graphics/opengl/VertexBuffer.h index a9e13c8c8..1fc1f7c74 100644 --- a/src/modules/graphics/opengl/VertexBuffer.h +++ b/src/modules/graphics/opengl/VertexBuffer.h @@ -104,10 +104,9 @@ namespace opengl * * The VertexBuffer must be bound to use this function. * - * @param access GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE. * @return A pointer to memory which represents the buffer. */ - virtual void *map(GLenum access) = 0; + virtual void *map() = 0; /** * Unmap a previously mapped VertexBuffer. The buffer must be unmapped @@ -182,9 +181,9 @@ namespace opengl /** * Memory-maps a VertexBuffer. */ - Mapper(VertexBuffer& buffer, GLenum access) + Mapper(VertexBuffer& buffer) : buf(buffer) - { elems = buf.map(access); } + { elems = buf.map(); } /** * unmaps the buffer @@ -236,7 +235,7 @@ namespace opengl virtual ~VertexArray(); // Implements VertexBuffer. - virtual void *map(GLenum access); + virtual void *map(); virtual void unmap(); virtual void bind(); virtual void unbind(); @@ -270,7 +269,7 @@ namespace opengl virtual ~VBO(); // Implements VertexBuffer. - virtual void *map(GLenum access); + virtual void *map(); virtual void unmap(); virtual void bind(); virtual void unbind(); @@ -307,6 +306,10 @@ namespace opengl // A pointer to mapped memory. Zero if memory is currently // not mapped. void *mapped; + + // Usage hint for map()/unmap() pair. Same as `access' parameter in + // glBufferData or 0 if not mapped. + GLenum mapped_access; }; } // opengl