From 3fb78d54584ce80f4a579175247ad26a08cc5251 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 29 Jun 2013 00:04:56 -0300 Subject: [PATCH] Added SpriteBatch:setBufferSize (issue #655) --- src/modules/graphics/opengl/SpriteBatch.cpp | 50 ++++++++++++++++++- src/modules/graphics/opengl/SpriteBatch.h | 12 +++-- src/modules/graphics/opengl/VertexBuffer.cpp | 5 +- .../graphics/opengl/wrap_SpriteBatch.cpp | 16 ++++++ .../graphics/opengl/wrap_SpriteBatch.h | 1 + 5 files changed, 77 insertions(+), 7 deletions(-) diff --git a/src/modules/graphics/opengl/SpriteBatch.cpp b/src/modules/graphics/opengl/SpriteBatch.cpp index a4f8ffac7..bb298430b 100644 --- a/src/modules/graphics/opengl/SpriteBatch.cpp +++ b/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 + 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; diff --git a/src/modules/graphics/opengl/SpriteBatch.h b/src/modules/graphics/opengl/SpriteBatch.h index 6ef526fe4..07d354cf7 100644 --- a/src/modules/graphics/opengl/SpriteBatch.h +++ b/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::Entry usageHintEntries[]; - static StringMap usageHints; - Image *image; // Max number of sprites in the batch. @@ -141,6 +144,9 @@ private: VertexBuffer *array_buf; VertexIndex *element_buf; + static StringMap::Entry usageHintEntries[]; + static StringMap usageHints; + }; // SpriteBatch } // opengl diff --git a/src/modules/graphics/opengl/VertexBuffer.cpp b/src/modules/graphics/opengl/VertexBuffer.cpp index ae70742be..a8bc11d08 100644 --- a/src/modules/graphics/opengl/VertexBuffer.cpp +++ b/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); diff --git a/src/modules/graphics/opengl/wrap_SpriteBatch.cpp b/src/modules/graphics/opengl/wrap_SpriteBatch.cpp index 39db51fba..ad0d21b5e 100644 --- a/src/modules/graphics/opengl/wrap_SpriteBatch.cpp +++ b/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 } }; diff --git a/src/modules/graphics/opengl/wrap_SpriteBatch.h b/src/modules/graphics/opengl/wrap_SpriteBatch.h index 87c8e467e..10e4384f3 100644 --- a/src/modules/graphics/opengl/wrap_SpriteBatch.h +++ b/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);