Commits

Alex Szpakowski committed 81f233a

Added SpriteBatch:setBufferSize (issue #655)

  • Participants
  • Parent commits 02760c3

Comments (0)

Files changed (5)

File src/modules/graphics/opengl/SpriteBatch.cpp

  * 3. This notice may not be removed or altered from any source distribution.
  **/
 
+#include "common/config.h"
 #include "SpriteBatch.h"
 
 // OpenGL
 #include "modules/graphics/Geometry.h"
 #include "VertexBuffer.h"
 
+// stdlib
+#include <algorithm>
+
 namespace love
 {
 namespace graphics
 	, array_buf(0)
 	, element_buf(0)
 {
+	if (size <= 0)
+		throw love::Exception("Invalid SpriteBatch size.");
+
 	GLenum gl_usage;
-
 	switch (usage)
 	{
 	default:
 	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;

File src/modules/graphics/opengl/SpriteBatch.h

 	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.
 	 **/
 	int getBufferSize() const;
 	 */
 	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.
 	VertexBuffer *array_buf;
 	VertexIndex *element_buf;
 
+	static StringMap<UsageHint, USAGE_MAX_ENUM>::Entry usageHintEntries[];
+	static StringMap<UsageHint, USAGE_MAX_ENUM> usageHints;
+
 }; // SpriteBatch
 
 } // opengl

File src/modules/graphics/opengl/VertexBuffer.cpp

 	{
 		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);

File src/modules/graphics/opengl/wrap_SpriteBatch.cpp

 	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);
 	{ "setColor", w_SpriteBatch_setColor },
 	{ "getColor", w_SpriteBatch_getColor },
 	{ "getCount", w_SpriteBatch_getCount },
+	{ "setBufferSize", w_SpriteBatch_setBufferSize },
 	{ "getBufferSize", w_SpriteBatch_getBufferSize },
 	{ 0, 0 }
 };

File src/modules/graphics/opengl/wrap_SpriteBatch.h

 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);