diff --git a/platform/msvc2010/love.vcxproj b/platform/msvc2010/love.vcxproj
index 159f5335c..4abc36f8c 100644
--- a/platform/msvc2010/love.vcxproj
+++ b/platform/msvc2010/love.vcxproj
@@ -104,6 +104,7 @@
+
@@ -270,6 +271,7 @@
+
diff --git a/platform/msvc2010/love.vcxproj.filters b/platform/msvc2010/love.vcxproj.filters
index f90f350c5..aeb7c8138 100644
--- a/platform/msvc2010/love.vcxproj.filters
+++ b/platform/msvc2010/love.vcxproj.filters
@@ -595,6 +595,9 @@
modules\graphics\opengl
+
+ modules\graphics\opengl
+
@@ -966,6 +969,9 @@
modules\graphics\opengl
+
+ modules\graphics\opengl
+
diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp
index 644f3e513..540a7c693 100644
--- a/src/modules/graphics/Graphics.cpp
+++ b/src/modules/graphics/Graphics.cpp
@@ -153,7 +153,6 @@ namespace graphics
{
{ "framebuffers", Graphics::SUPPORT_FRAMEBUFFERS },
{ "pixeleffects", Graphics::SUPPORT_PIXELEFFECTS },
- { "spritebatches", Graphics::SUPPORT_SPRITEBATCHES }
};
StringMap Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries));
diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h
index 29837489c..e48edaca1 100644
--- a/src/modules/graphics/Graphics.h
+++ b/src/modules/graphics/Graphics.h
@@ -82,7 +82,6 @@ namespace graphics
{
SUPPORT_FRAMEBUFFERS = 1,
SUPPORT_PIXELEFFECTS,
- SUPPORT_SPRITEBATCHES,
SUPPORT_MAX_ENUM
};
diff --git a/src/modules/graphics/opengl/SpriteBatch.cpp b/src/modules/graphics/opengl/SpriteBatch.cpp
index 041aa7b0e..3bbe050d1 100644
--- a/src/modules/graphics/opengl/SpriteBatch.cpp
+++ b/src/modules/graphics/opengl/SpriteBatch.cpp
@@ -26,6 +26,7 @@
// LOVE
#include "Image.h"
#include "Quad.h"
+#include "VertexBuffer.h"
namespace love
{
@@ -34,80 +35,68 @@ namespace graphics
namespace opengl
{
SpriteBatch::SpriteBatch(Image * image, int size, int usage)
- : image(image), size(size), next(0), usage(usage), lockp(0), color(0)
+ : image(image)
+ , size(size)
+ , next(0)
+ , color(0)
+ , array_buf(0)
+ , element_buf(0)
{
- if (!(GLEE_ARB_vertex_buffer_object || GLEE_VERSION_1_5))
- throw love::Exception("Your OpenGL version does not support SpriteBatches. Go upgrade!");
-
image->retain();
- vertices = new vertex[size*4];
- indices = new GLushort[size*6];
+ GLenum gl_usage;
- for(int i = 0; i(element_buf->map(GL_WRITE_ONLY));
+
+ if (indices)
+ {
+ for (int i = 0; i < size; ++i)
+ {
+ indices[i*6+0] = 0+(i*4);
+ indices[i*6+1] = 1+(i*4);
+ indices[i*6+2] = 2+(i*4);
+
+ indices[i*6+3] = 0+(i*4);
+ indices[i*6+4] = 2+(i*4);
+ indices[i*6+5] = 3+(i*4);
+ }
+ }
+
+ element_buf->unmap();
+ }
}
SpriteBatch::~SpriteBatch()
{
image->release();
- if(vbo[0] != 0 && vbo[1] != 0)
- glDeleteBuffers(2, vbo);
-
- delete [] vertices;
- delete [] indices;
delete color;
- }
-
- bool SpriteBatch::isSupported()
- {
- return (GLEE_ARB_vertex_buffer_object || GLEE_VERSION_1_5);
- }
-
- bool SpriteBatch::loadVolatile()
- {
- // Find out which OpenGL VBO usage hint to use.
- gl_usage = GL_STREAM_DRAW_ARB;
- gl_usage = (usage == USAGE_DYNAMIC) ? GL_DYNAMIC_DRAW_ARB : gl_usage;
- gl_usage = (usage == USAGE_STATIC) ? GL_STATIC_DRAW_ARB : gl_usage;
- gl_usage = (usage == USAGE_STREAM) ? GL_STREAM_DRAW_ARB : gl_usage;
-
- glGenBuffersARB(2, vbo);
-
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertex)*size*4, vertices, gl_usage);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
-
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo[1]);
- glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLushort)*size*6, indices, GL_STATIC_DRAW_ARB);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
-
- return true;
- }
-
- void SpriteBatch::unloadVolatile()
- {
- vertex * v = (vertex *)lock();
-
- // Copy to system memory.
- memcpy(vertices, v, sizeof(vertex)*size*4);
-
- unlock();
-
- // Delete the buffers.
- if(vbo[0] != 0 && vbo[1] != 0)
- glDeleteBuffersARB(2, vbo);
+ delete array_buf;
+ delete element_buf;
}
void SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky)
@@ -115,21 +104,18 @@ namespace opengl
// Only do this if there's a free slot.
if(next < size)
{
- // Get a pointer to the correct insertion position.
- vertex * v = vertices + next*4;
-
// Needed for texture coordinates.
- memcpy(v, image->getVertices(), sizeof(vertex)*4);
+ memcpy(sprite, image->getVertices(), sizeof(vertex)*4);
// Transform.
Matrix t;
t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
- t.transform(v, v, 4);
+ t.transform(sprite, sprite, 4);
if (color)
- setColorv(v, *color);
+ setColorv(sprite, *color);
- addv(v);
+ addv(sprite);
// Increment counter.
next++;
@@ -141,21 +127,18 @@ namespace opengl
// Only do this if there's a free slot.
if(next < size)
{
- // Get a pointer to the correct insertion position.
- vertex * v = vertices + next*4;
-
// Needed for colors.
- memcpy(v, quad->getVertices(), sizeof(vertex)*4);
+ memcpy(sprite, quad->getVertices(), sizeof(vertex)*4);
// Transform.
Matrix t;
t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
- t.transform(v, v, 4);
+ t.transform(sprite, sprite, 4);
if (color)
- setColorv(v, *color);
+ setColorv(sprite, *color);
- addv(v);
+ addv(sprite);
// Increment counter.
next++;
@@ -170,22 +153,16 @@ namespace opengl
void * SpriteBatch::lock()
{
- // If already locked, prevent from locking again.
- if(lockp != 0)
- return lockp;
+ VertexArray::Bind bind(*array_buf);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]);
- lockp = (vertex *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- return lockp;
+ return array_buf->map(GL_READ_WRITE);
}
void SpriteBatch::unlock()
{
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]);
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
- lockp = 0;
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ VertexArray::Bind bind(*array_buf);
+
+ array_buf->unmap();
}
void SpriteBatch::setImage(Image * newimage)
@@ -211,6 +188,10 @@ namespace opengl
void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
{
+ const int color_offset = 0;
+ const int vertex_offset = sizeof(unsigned char) * 4;
+ const int texel_offset = sizeof(unsigned char) * 4 + sizeof(float) * 2;
+
static Matrix t;
glPushMatrix();
@@ -220,51 +201,38 @@ namespace opengl
image->bind();
- // Enable vertex arrays.
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- // Bind the VBO buffer.
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo[1]);
+ VertexBuffer::Bind array_bind(*array_buf);
+ VertexBuffer::Bind element_bind(*element_buf);
// Apply per-sprite color, if a color is set.
if (color)
{
glEnableClientState(GL_COLOR_ARRAY);
- glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), 0);
+ glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), array_buf->getPointer(color_offset));
}
- glVertexPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)(sizeof(unsigned char)*4));
- glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)(sizeof(unsigned char)*4+sizeof(float)*2));
-
- glDrawElements(GL_TRIANGLES, next*6, GL_UNSIGNED_SHORT, 0);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, sizeof(vertex), array_buf->getPointer(vertex_offset));
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), array_buf->getPointer(texel_offset));
+
+ glDrawElements(GL_TRIANGLES, next*6, GL_UNSIGNED_SHORT, element_buf->getPointer(0));
- // Disable vertex arrays.
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
-
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
glPopMatrix();
}
void SpriteBatch::addv(const vertex * v)
{
- if(lockp != 0)
- {
- // Copy into mapped memory if buffer is locked.
- memcpy(lockp + (next*4), v, sizeof(vertex)*4);
- }
- else
- {
- // ... use glBufferSubData otherwise.
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]);
- glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, (next*4)*sizeof(vertex), sizeof(vertex)*4, v);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- }
+ int sprite_size = sizeof(vertex) * 4;
+
+ VertexArray::Bind bind(*array_buf);
+
+ array_buf->fill(next * sprite_size, sprite_size, v);
}
void SpriteBatch::setColorv(vertex * v, const Color & color)
diff --git a/src/modules/graphics/opengl/SpriteBatch.h b/src/modules/graphics/opengl/SpriteBatch.h
index 58599ea1a..0c5fd55c0 100644
--- a/src/modules/graphics/opengl/SpriteBatch.h
+++ b/src/modules/graphics/opengl/SpriteBatch.h
@@ -46,8 +46,9 @@ namespace opengl
// Forward declarations.
class Image;
class Quad;
+ class VertexBuffer;
- class SpriteBatch : public Drawable, public Volatile
+ class SpriteBatch : public Drawable
{
private:
@@ -59,25 +60,15 @@ namespace opengl
// The next free element.
int next;
- GLuint vbo[2];
-
- // Vertex Buffer.
- vertex * vertices;
-
- // Index buffer.
- GLushort * indices;
-
- // The uage hint for the vertex buffer.
- int usage;
- int gl_usage;
-
- // If the buffer is locked, this pointer is nonzero.
- vertex * lockp;
+ vertex sprite[4];
// Current color. This color, if present, will be applied to the next
// added quad.
Color * color;
+ VertexBuffer *array_buf;
+ VertexBuffer *element_buf;
+
public:
enum UsageHint
@@ -90,12 +81,6 @@ namespace opengl
SpriteBatch(Image * image, int size, int usage);
virtual ~SpriteBatch();
- static bool isSupported();
-
- // Implements Volatile.
- bool loadVolatile();
- void unloadVolatile();
-
void add(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky);
void addq(Quad * quad, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky);
void clear();
diff --git a/src/modules/graphics/opengl/VertexBuffer.cpp b/src/modules/graphics/opengl/VertexBuffer.cpp
new file mode 100644
index 000000000..0bcb622b8
--- /dev/null
+++ b/src/modules/graphics/opengl/VertexBuffer.cpp
@@ -0,0 +1,237 @@
+/**
+* Copyright (c) 2006-2011 LOVE Development Team
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#include "VertexBuffer.h"
+
+#include "common/Exception.h"
+
+#include
+
+namespace love
+{
+namespace graphics
+{
+namespace opengl
+{
+ // VertexBuffer
+
+ VertexBuffer *VertexBuffer::Create(int size, GLenum target, GLenum usage)
+ {
+ try
+ {
+ // Try to create a VBO.
+ return new VBO(size, target, usage);
+
+ } catch (const love::Exception &e)
+ {
+ (void)e;
+
+ // VBO not supported ... create regular array.
+ return new VertexArray(size, target, usage);
+ }
+ }
+
+ VertexBuffer::VertexBuffer(int size, GLenum target, GLenum usage)
+ : size(size)
+ , target(target)
+ , usage(usage)
+ {
+ }
+
+ VertexBuffer::~VertexBuffer()
+ {
+ }
+
+ // VertexBuffer::Bind
+
+ VertexBuffer::Bind::Bind(VertexBuffer &buf)
+ : buf(buf)
+ {
+ buf.bind();
+ }
+
+ VertexBuffer::Bind::~Bind()
+ {
+ buf.unbind();
+ }
+
+ // VertexArray
+
+ VertexArray::VertexArray(int size, GLenum target, GLenum usage)
+ : VertexBuffer(size, target, usage)
+ , buf(new char[size])
+ {
+ }
+
+ VertexArray::~VertexArray()
+ {
+ delete [] buf;
+ }
+
+ void *VertexArray::map(GLenum access)
+ {
+ return buf;
+ }
+
+ void VertexArray::unmap()
+ {
+ }
+
+ void VertexArray::bind()
+ {
+ }
+
+ void VertexArray::unbind()
+ {
+ }
+
+ void VertexArray::fill(int offset, int size, const void *data)
+ {
+ memcpy(buf + offset, data, size);
+ }
+
+ const void *VertexArray::getPointer(int offset) const
+ {
+ return buf + offset;
+ }
+
+ // VBO
+
+ VBO::VBO(int size, GLenum target, GLenum usage)
+ : VertexBuffer(size, target, usage)
+ , vbo(0)
+ , buffer_copy(0)
+ , mapped(0)
+ {
+ if (!(GLEE_ARB_vertex_buffer_object || GLEE_VERSION_1_5))
+ throw love::Exception("Not supported");
+
+ bool ok = load(false);
+
+ if (!ok)
+ throw love::Exception("Could not load VBO.");
+ }
+
+ VBO::~VBO()
+ {
+ if (vbo != 0)
+ unload(false);
+ }
+
+ void *VBO::map(GLenum access)
+ {
+ // Don't map twice.
+ if (mapped)
+ return mapped;
+
+ mapped = glMapBufferARB(getTarget(), access);
+
+ return mapped;
+ }
+
+ void VBO::unmap()
+ {
+ glUnmapBufferARB(getTarget());
+ mapped = 0;
+ }
+
+ void VBO::bind()
+ {
+ glBindBufferARB(getTarget(), vbo);
+ }
+
+ void VBO::unbind()
+ {
+ glBindBufferARB(getTarget(), 0);
+ }
+
+ void VBO::fill(int offset, int size, const void *data)
+ {
+ if (mapped)
+ memcpy(static_cast(mapped) + offset, data, size);
+ else
+ glBufferSubDataARB(getTarget(), offset, size, data);
+ }
+
+ const void *VBO::getPointer(int offset) const
+ {
+ return reinterpret_cast(offset);
+ }
+
+ bool VBO::loadVolatile()
+ {
+ return load(true);
+ }
+
+ void VBO::unloadVolatile()
+ {
+ unload(true);
+ }
+
+ bool VBO::load(bool restore)
+ {
+ glGenBuffersARB(1, &vbo);
+
+ VertexBuffer::Bind bind(*this);
+
+ // Copy the old buffer only if 'restore' was requested.
+ const GLvoid *src = restore ? buffer_copy : 0;
+
+ // Note that if 'src' is '0', no data will be copied.
+ glBufferDataARB(getTarget(), getSize(), src, getUsage());
+
+ // Clean up buffer_copy, if it exists.
+ delete[] buffer_copy;
+ buffer_copy = 0;
+
+ return true;
+ }
+
+ void VBO::unload(bool save)
+ {
+ // Clean up buffer_copy, if it exists.
+ delete[] buffer_copy;
+ buffer_copy = 0;
+
+ // Save data before unloading.
+ if (save)
+ {
+ VertexBuffer::Bind bind(*this);
+
+ GLint size;
+ glGetBufferParameterivARB(getTarget(), GL_BUFFER_SIZE, &size);
+
+ const char *src = static_cast(map(GL_READ_ONLY));
+
+ if (src)
+ {
+ buffer_copy = new char[size];
+ memcpy(buffer_copy, src, size);
+ unmap();
+ }
+ }
+
+ glDeleteBuffers(1, &vbo);
+ vbo = 0;
+ }
+
+} // opengl
+} // graphics
+} // love
diff --git a/src/modules/graphics/opengl/VertexBuffer.h b/src/modules/graphics/opengl/VertexBuffer.h
new file mode 100644
index 000000000..efe58339a
--- /dev/null
+++ b/src/modules/graphics/opengl/VertexBuffer.h
@@ -0,0 +1,287 @@
+/**
+* Copyright (c) 2006-2011 LOVE Development Team
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+
+#ifndef LOVE_GRAPHICS_OPENGL_VERTEX_BUFFER_H
+#define LOVE_GRAPHICS_OPENGL_VERTEX_BUFFER_H
+
+// LOVE
+#include
+
+// OpenGL
+#include "GLee.h"
+#include
+
+namespace love
+{
+namespace graphics
+{
+namespace opengl
+{
+ /**
+ * VertexBuffer is an abstraction over VBOs (Vertex Buffer Objecys), which
+ * falls back to regular vertex arrays if VBOs are not supported.
+ *
+ * This allows code to take advantage of VBOs where available, but still
+ * work on older systems where it's *not* available. Everyone's happy.
+ *
+ * The class is (for now) meant for internal use.
+ */
+ class VertexBuffer
+ {
+ public:
+
+ /**
+ * Create a new VertexBuffer (either a plain vertex array, or a VBO),
+ * based on what's supported on the system.
+ *
+ * If VBOs are not supported, a plain vertex array will automatically
+ * be created and returned instead.
+ *
+ * @param size The size of the VertexBuffer (in bytes).
+ * @param target GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER.
+ * @param usage GL_DYNAMIC_DRAW, etc.
+ * @return A new VertexBuffer.
+ */
+ static VertexBuffer *Create(int size, GLenum target, GLenum usage);
+
+ /**
+ * Constructor.
+ *
+ * @param size The size of the VertexBuffer in bytes.
+ * @param target The target VertexBuffer object, e.g. GL_ARRAY_BUFFER.
+ * @param usage Usage hint, e.g. GL_DYNAMIC_DRAW.
+ */
+ VertexBuffer(int size, GLenum target, GLenum usage);
+
+ /**
+ * Destructor. Does nothing, but must be declared virtual.
+ */
+ virtual ~VertexBuffer();
+
+ /**
+ * Get the size of the VertexBuffer, in bytes.
+ *
+ * @return The size of the VertexBuffer.
+ */
+ int getSize() const { return size; }
+
+ /**
+ * Get the target buffer object.
+ *
+ * @return The target buffer object, e.g. GL_ARRAY_BUFFER.
+ */
+ GLenum getTarget() const { return target; }
+
+ /**
+ * Get the usage hint for this VertexBuffer.
+ *
+ * @return The usage hint, e.g. GL_DYNAMIC_DRAW.
+ */
+ GLenum getUsage() const { return usage; }
+
+ /**
+ * Map the VertexBuffer to client memory.
+ *
+ * This can be faster for large changes to the buffer. For smaller
+ * changes, see fill().
+ *
+ * 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;
+
+ /**
+ * Unmap a previously mapped VertexBuffer. The buffer must be unmapped
+ * when used to draw elements.
+ *
+ * The VertexBuffer must be bound to use this function.
+ */
+ virtual void unmap() = 0;
+
+ /**
+ * Bind the VertexBuffer to the specified target.
+ * (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER).
+ *
+ * @param target GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER.
+ */
+ virtual void bind() = 0;
+
+ /**
+ * Unbind a prevously bound VertexBuffer.
+ */
+ virtual void unbind() = 0;
+
+ /**
+ * Fill a portion of the buffer with data.
+ *
+ * The VertexBuffer must be bound to use this function.
+ *
+ * @param offset The offset in the VertexBuffer to store the data.
+ * @param size The size of the incoming data.
+ * @param data Pointer to memory to copy data from.
+ */
+ virtual void fill(int offset, int size, const void *data) = 0;
+
+ /**
+ * Get a pointer which represents the specified byte offset.
+ *
+ * @param offset The byte offset. (0 is first byte).
+ * @return A pointer which represents the offset.
+ */
+ virtual const void *getPointer(int offset) const = 0;
+
+ /**
+ * This helper class can bind a VertexArray temporarily, and
+ * automatically un-bind when it's destroyed.
+ */
+ class Bind
+ {
+ public:
+
+ /**
+ * Bind a VertexBuffer.
+ */
+ Bind(VertexBuffer &buf);
+
+ /**
+ * Unbinds a VertexBuffer.
+ */
+ ~Bind();
+
+ private:
+
+ // VertexBuffer to work on.
+ VertexBuffer &buf;
+ };
+
+ private:
+
+ // The size of the buffer, in bytes.
+ int size;
+
+ // The target buffer object. (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER).
+ GLenum target;
+
+ // Usage hint. GL_[DYNAMIC, STATIC, STREAM]_DRAW.
+ GLenum usage;
+ };
+
+ /**
+ * Implementation of VertexBuffer which uses plain arrays to store the data.
+ *
+ * This implementation should be supported everywhere, and acts as a fallback
+ * on systems which do not support VBOs.
+ */
+ class VertexArray : public VertexBuffer
+ {
+ public:
+
+ /**
+ * @copydoc VertexBuffer(int, GLenum, GLenum)
+ */
+ VertexArray(int size, GLenum target, GLenum usage);
+
+ /**
+ * Frees the data we've allocated.
+ */
+ virtual ~VertexArray();
+
+ // Implements VertexBuffer.
+ virtual void *map(GLenum access);
+ virtual void unmap();
+ virtual void bind();
+ virtual void unbind();
+ virtual void fill(int offset, int size, const void *data);
+ virtual const void *getPointer(int offset) const ;
+
+ private:
+ // Holds the data.
+ char *buf;
+ };
+
+ /**
+ * Vertex Buffer Object (VBO) implementation of VertexBuffer.
+ *
+ * This will be used on all systems that support it. It's in general
+ * faster than vertex arrays, but especially in use-cases where there
+ * is no need to update the data every frame.
+ */
+ class VBO : public VertexBuffer, public Volatile
+ {
+ public:
+
+ /**
+ * @copydoc VertexBuffer(int, GLenum, GLenum)
+ */
+ VBO(int size, GLenum target, GLenum usage);
+
+ /**
+ * Deletes the VBOs from OpenGL.
+ */
+ virtual ~VBO();
+
+ // Implements VertexBuffer.
+ virtual void *map(GLenum access);
+ virtual void unmap();
+ virtual void bind();
+ virtual void unbind();
+ virtual void fill(int offset, int size, const void *data);
+ virtual const void *getPointer(int offset) const ;
+
+ // Implements Volatile.
+ bool loadVolatile();
+ void unloadVolatile();
+
+ private:
+
+ /**
+ * Creates the VBO, and optionally restores data we saved earlier.
+ *
+ * @param restore True to restore data previously saved with 'unload'.
+ * @return True on success, false otherwise.
+ */
+ bool load(bool restore);
+
+ /**
+ * Optionally save the data in the VBO, then delete it.
+ *
+ * @param save True to save the data before deleting.
+ */
+ void unload(bool save);
+
+ // The VBO identifier. Assigned by OpenGL.
+ GLuint vbo;
+
+ // *May* contain data saved by 'unload'.
+ char *buffer_copy;
+
+ // A pointer to mapped memory. Zero if memory is currently
+ // not mapped.
+ void *mapped;
+ };
+
+} // opengl
+} // graphics
+} // love
+
+#endif // LOVE_GRAPHICS_OPENGL_SPRITE_BATCH_H
diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp
index 2c89f96d9..c9ea82e26 100644
--- a/src/modules/graphics/opengl/wrap_Graphics.cpp
+++ b/src/modules/graphics/opengl/wrap_Graphics.cpp
@@ -774,10 +774,6 @@ namespace opengl
if (!PixelEffect::isSupported())
supported = false;
break;
- case Graphics::SUPPORT_SPRITEBATCHES:
- if (!SpriteBatch::isSupported())
- supported = false;
- break;
default:
supported = false;
}