Browse Source

Added SpriteBatch:setBufferSize (issue #655)

Alex Szpakowski 12 years ago
parent
commit
3fb78d5458

+ 49 - 1
src/modules/graphics/opengl/SpriteBatch.cpp

@@ -18,6 +18,7 @@
  * 3. This notice may not be removed or altered from any source distribution.
  **/
 
+#include "common/config.h"
 #include "SpriteBatch.h"
 
 // OpenGL
@@ -28,6 +29,9 @@
 #include "modules/graphics/Geometry.h"
 #include "VertexBuffer.h"
 
+// stdlib
+#include <algorithm>
+
 namespace love
 {
 namespace graphics
@@ -43,8 +47,10 @@ SpriteBatch::SpriteBatch(Image *image, int size, int usage)
 	, array_buf(0)
 	, element_buf(0)
 {
-	GLenum gl_usage;
+	if (size <= 0)
+		throw love::Exception("Invalid SpriteBatch size.");
 
+	GLenum gl_usage;
 	switch (usage)
 	{
 	default:
@@ -211,6 +217,48 @@ int SpriteBatch::getCount() const
 	return next;
 }
 
+void SpriteBatch::setBufferSize(int newsize)
+{
+	if (newsize <= 0)
+		throw love::Exception("Invalid SpriteBatch size.");
+
+	if (newsize == size)
+		return;
+
+	size_t vertex_size = sizeof(vertex) * 4 * newsize;
+	VertexBuffer *new_array_buf = VertexBuffer::Create(vertex_size, GL_ARRAY_BUFFER, array_buf->getUsage());
+
+	void *new_data = 0;
+	try
+	{
+		// VBO::map can throw an exception. Also we want to scope the bind.
+		VertexBuffer::Bind bind(*new_array_buf);
+		new_data = new_array_buf->map();
+	}
+	catch (love::Exception &)
+	{
+		delete new_array_buf;
+		throw;
+	}
+
+	// Map (lock) the old VertexBuffer to get a pointer to its data.
+	void *old_data = lock();
+
+	// Copy as much of the old data into the new VertexBuffer as can fit.
+	memcpy(new_data, old_data, sizeof(vertex) * 4 * std::min(newsize, size));
+
+	// We don't need to unmap the old VertexBuffer since we're deleting it.
+	delete array_buf;
+
+	array_buf = new_array_buf;
+	size = newsize;
+
+	next = std::min(next, newsize);
+
+	// But we should unmap (unlock) the new one!
+	unlock();
+}
+
 int SpriteBatch::getBufferSize() const
 {
 	return size;

+ 9 - 3
src/modules/graphics/opengl/SpriteBatch.h

@@ -97,6 +97,12 @@ public:
 	 **/
 	int getCount() const;
 
+	/**
+	 * Sets the total number of sprites this SpriteBatch can hold.
+	 * Leaves existing sprite data intact when possible.
+	 **/
+	void setBufferSize(int newsize);
+
 	/**
 	 * Get the total number of sprites this SpriteBatch can hold.
 	 **/
@@ -121,9 +127,6 @@ private:
 	 */
 	void setColorv(vertex *v, const Color &color);
 
-	static StringMap<UsageHint, USAGE_MAX_ENUM>::Entry usageHintEntries[];
-	static StringMap<UsageHint, USAGE_MAX_ENUM> usageHints;
-
 	Image *image;
 
 	// Max number of sprites in the batch.
@@ -141,6 +144,9 @@ private:
 	VertexBuffer *array_buf;
 	VertexIndex *element_buf;
 
+	static StringMap<UsageHint, USAGE_MAX_ENUM>::Entry usageHintEntries[];
+	static StringMap<UsageHint, USAGE_MAX_ENUM> usageHints;
+
 }; // SpriteBatch
 
 } // opengl

+ 2 - 3
src/modules/graphics/opengl/VertexBuffer.cpp

@@ -246,11 +246,10 @@ void VBO::unload(bool save)
 	{
 		VertexBuffer::Bind bind(*this);
 
-		GLint size;
-		glGetBufferParameterivARB(getTarget(), GL_BUFFER_SIZE, &size);
+		bool mapped = is_mapped;
 
 		map(); // saves buffer content to memory_map.
-		unmap();
+		is_mapped = mapped;
 	}
 
 	glDeleteBuffersARB(1, &vbo);

+ 16 - 0
src/modules/graphics/opengl/wrap_SpriteBatch.cpp

@@ -221,6 +221,21 @@ int w_SpriteBatch_getCount(lua_State *L)
 	return 1;
 }
 
+int w_SpriteBatch_setBufferSize(lua_State *L)
+{
+	SpriteBatch *t = luax_checkspritebatch(L, 1);
+	int size = luaL_checkint(L, 2);
+	try
+	{
+		t->setBufferSize(size);
+	}
+	catch (love::Exception &e)
+	{
+		return luaL_error(L, "%s", e.what());
+	}
+	return 0;
+}
+
 int w_SpriteBatch_getBufferSize(lua_State *L)
 {
 	SpriteBatch *t = luax_checkspritebatch(L, 1);
@@ -242,6 +257,7 @@ static const luaL_Reg functions[] =
 	{ "setColor", w_SpriteBatch_setColor },
 	{ "getColor", w_SpriteBatch_getColor },
 	{ "getCount", w_SpriteBatch_getCount },
+	{ "setBufferSize", w_SpriteBatch_setBufferSize },
 	{ "getBufferSize", w_SpriteBatch_getBufferSize },
 	{ 0, 0 }
 };

+ 1 - 0
src/modules/graphics/opengl/wrap_SpriteBatch.h

@@ -44,6 +44,7 @@ int w_SpriteBatch_getImage(lua_State *L);
 int w_SpriteBatch_setColor(lua_State *L);
 int w_SpriteBatch_getColor(lua_State *L);
 int w_SpriteBatch_getCount(lua_State *L);
+int w_SpriteBatch_setBufferSize(lua_State *L);
 int w_SpriteBatch_getBufferSize(lua_State *L);
 
 extern "C" int luaopen_spritebatch(lua_State *L);