Browse Source

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.
vrld 13 years ago
parent
commit
3f365857ee

+ 2 - 2
src/modules/graphics/opengl/SpriteBatch.cpp

@@ -69,7 +69,7 @@ namespace opengl
 		// Fill element buffer.
 		// Fill element buffer.
 		{
 		{
 			VertexBuffer::Bind bind(*element_buf);
 			VertexBuffer::Bind bind(*element_buf);
-			VertexBuffer::Mapper mapper(*element_buf, GL_WRITE_ONLY);
+			VertexBuffer::Mapper mapper(*element_buf);
 
 
 			GLushort *indices = static_cast<GLushort*>(mapper.get());
 			GLushort *indices = static_cast<GLushort*>(mapper.get());
 
 
@@ -158,7 +158,7 @@ namespace opengl
 	{
 	{
 		VertexBuffer::Bind bind(*array_buf);
 		VertexBuffer::Bind bind(*array_buf);
 
 
-		return array_buf->map(GL_READ_WRITE);
+		return array_buf->map();
 	}
 	}
 
 
 	void SpriteBatch::unlock()
 	void SpriteBatch::unlock()

+ 8 - 7
src/modules/graphics/opengl/VertexBuffer.cpp

@@ -72,7 +72,7 @@ namespace opengl
 		delete [] buf;
 		delete [] buf;
 	}
 	}
 
 
-	void *VertexArray::map(GLenum/* access*/)
+	void *VertexArray::map()
 	{
 	{
 		return buf;
 		return buf;
 	}
 	}
@@ -122,20 +122,21 @@ namespace opengl
 			unload(false);
 			unload(false);
 	}
 	}
 
 
-	void *VBO::map(GLenum access)
+	void *VBO::map()
 	{
 	{
-		// Don't map twice.
+		// mapping twice could result in memory leaks
 		if (mapped)
 		if (mapped)
-			return mapped;
+			throw love::Exception("VBO is already mapped!");
 
 
-		mapped = glMapBufferARB(getTarget(), access);
+		mapped = malloc(getSize());
 
 
 		return mapped;
 		return mapped;
 	}
 	}
 
 
 	void VBO::unmap()
 	void VBO::unmap()
 	{
 	{
-		glUnmapBufferARB(getTarget());
+		glBufferSubDataARB(getTarget(), 0, getSize(), (void*)mapped);
+		free(mapped);
 		mapped = 0;
 		mapped = 0;
 	}
 	}
 
 
@@ -209,7 +210,7 @@ namespace opengl
 			GLint size;
 			GLint size;
 			glGetBufferParameterivARB(getTarget(), GL_BUFFER_SIZE, &size);
 			glGetBufferParameterivARB(getTarget(), GL_BUFFER_SIZE, &size);
 
 
-			const char *src = static_cast<char *>(map(GL_READ_ONLY));
+			const char *src = static_cast<char *>(map());
 
 
 			if (src)
 			if (src)
 			{
 			{

+ 9 - 6
src/modules/graphics/opengl/VertexBuffer.h

@@ -104,10 +104,9 @@ namespace opengl
 		 *
 		 *
 		 * The VertexBuffer must be bound to use this function.
 		 * 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.
 		 * @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
 		 * Unmap a previously mapped VertexBuffer. The buffer must be unmapped
@@ -182,9 +181,9 @@ namespace opengl
 			/**
 			/**
 			 * Memory-maps a VertexBuffer.
 			 * Memory-maps a VertexBuffer.
 			 */
 			 */
-			Mapper(VertexBuffer& buffer, GLenum access)
+			Mapper(VertexBuffer& buffer)
 				: buf(buffer)
 				: buf(buffer)
-			{ elems = buf.map(access); }
+			{ elems = buf.map(); }
 
 
 			/**
 			/**
 			 * unmaps the buffer
 			 * unmaps the buffer
@@ -236,7 +235,7 @@ namespace opengl
 		virtual ~VertexArray();
 		virtual ~VertexArray();
 
 
 		// Implements VertexBuffer.
 		// Implements VertexBuffer.
-		virtual void *map(GLenum access);
+		virtual void *map();
 		virtual void unmap();
 		virtual void unmap();
 		virtual void bind();
 		virtual void bind();
 		virtual void unbind();
 		virtual void unbind();
@@ -270,7 +269,7 @@ namespace opengl
 		virtual ~VBO();
 		virtual ~VBO();
 
 
 		// Implements VertexBuffer.
 		// Implements VertexBuffer.
-		virtual void *map(GLenum access);
+		virtual void *map();
 		virtual void unmap();
 		virtual void unmap();
 		virtual void bind();
 		virtual void bind();
 		virtual void unbind();
 		virtual void unbind();
@@ -307,6 +306,10 @@ namespace opengl
 		// A pointer to mapped memory. Zero if memory is currently
 		// A pointer to mapped memory. Zero if memory is currently
 		// not mapped.
 		// not mapped.
 		void *mapped;
 		void *mapped;
+
+		// Usage hint for map()/unmap() pair. Same as `access' parameter in
+		// glBufferData or 0 if not mapped.
+		GLenum mapped_access;
 	};
 	};
 
 
 } // opengl
 } // opengl