Meshes will now use the smallest integer data type possible for index buffer (vertex map) values, instead of always using 32-bit integer numbers.

This commit is contained in:
Alex Szpakowski
2014-02-12 02:22:57 -04:00
parent c17cada9e0
commit 6259e38d84
5 changed files with 122 additions and 31 deletions
+7
View File
@@ -53,6 +53,7 @@ Graphics::Graphics()
, width(0)
, height(0)
, created(false)
, activeStencil(false)
, savedState()
{
currentWindow = love::window::sdl::Window::createSingleton();
@@ -383,6 +384,8 @@ void Graphics::defineStencil()
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
activeStencil = true;
}
void Graphics::useStencil(bool invert)
@@ -394,8 +397,12 @@ void Graphics::useStencil(bool invert)
void Graphics::discardStencil()
{
if (!activeStencil)
return;
setColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
glDisable(GL_STENCIL_TEST);
activeStencil = false;
}
Image *Graphics::newImage(love::image::ImageData *data, Texture::Format format)
+2
View File
@@ -482,6 +482,8 @@ private:
int height;
bool created;
bool activeStencil;
DisplayState savedState;
}; // Graphics
+102 -22
View File
@@ -38,6 +38,7 @@ Mesh::Mesh(const std::vector<Vertex> &verts, Mesh::DrawMode mode)
, vertex_count(0)
, ibo(nullptr)
, element_count(0)
, element_data_type(getGLDataTypeFromMax(verts.size()))
, instance_count(1)
, draw_mode(mode)
, range_min(-1)
@@ -53,6 +54,7 @@ Mesh::Mesh(int vertexcount, Mesh::DrawMode mode)
, vertex_count(0)
, ibo(nullptr)
, element_count(0)
, element_data_type(getGLDataTypeFromMax(vertexcount))
, draw_mode(mode)
, range_min(-1)
, range_max(-1)
@@ -151,15 +153,42 @@ size_t Mesh::getVertexCount() const
return vertex_count;
}
/**
* Copies index data from a vector to a mapped index buffer.
**/
template <typename T>
static void copyToIndexBuffer(const std::vector<uint32> &indices, VertexBuffer::Mapper &buffermap, size_t maxval)
{
T *elems = (T *) buffermap.get();
for (size_t i = 0; i < indices.size(); i++)
{
if (indices[i] >= maxval)
throw love::Exception("Invalid vertex map value: %d", indices[i] + 1);
elems[i] = (T) indices[i];
}
}
void Mesh::setVertexMap(const std::vector<uint32> &map)
{
for (size_t i = 0; i < map.size(); i++)
{
if (map[i] >= vertex_count)
throw love::Exception("Invalid vertex map value: %d", map[i] + 1);
}
GLenum datatype = getGLDataTypeFromMax(vertex_count);
size_t size = sizeof(uint32) * map.size();
// Calculate the size in bytes of the index buffer data.
size_t size = map.size();
switch (datatype)
{
case GL_UNSIGNED_BYTE:
size *= sizeof(uint8);
break;
case GL_UNSIGNED_SHORT:
size *= sizeof(uint16);
break;
case GL_UNSIGNED_INT:
default:
size *= sizeof(uint32);
break;
}
if (ibo && size > ibo->getSize())
{
@@ -175,27 +204,68 @@ void Mesh::setVertexMap(const std::vector<uint32> &map)
element_count = map.size();
if (ibo && element_count > 0)
{
VertexBuffer::Bind ibo_bind(*ibo);
VertexBuffer::Mapper ibo_map(*ibo);
if (!ibo || element_count == 0)
return;
// Fill the buffer.
memcpy(ibo_map.get(), &map[0], size);
VertexBuffer::Bind ibo_bind(*ibo);
VertexBuffer::Mapper ibo_map(*ibo);
// Fill the buffer with the index values from the vector.
switch (datatype)
{
case GL_UNSIGNED_BYTE:
copyToIndexBuffer<uint8>(map, ibo_map, vertex_count);
break;
case GL_UNSIGNED_SHORT:
copyToIndexBuffer<uint16>(map, ibo_map, vertex_count);
break;
case GL_UNSIGNED_INT:
default:
copyToIndexBuffer<uint32>(map, ibo_map, vertex_count);
break;
}
element_data_type = datatype;
}
const uint32 *Mesh::getVertexMap() const
/**
* Copies index data from a mapped buffer to a vector.
**/
template <typename T>
static void copyFromIndexBuffer(void *buffer, std::vector<uint32> &indices, size_t maxval)
{
if (ibo && element_count > 0)
T *elems = (T *) buffer;
for (size_t i = 0; i < maxval; i++)
indices.push_back((uint32) elems[i]);
}
void Mesh::getVertexMap(std::vector<uint32> &map) const
{
if (!ibo || element_count == 0)
return;
map.clear();
map.reserve(element_count);
VertexBuffer::Bind ibo_bind(*ibo);
// We unmap the buffer in Mesh::draw and Mesh::setVertexMap.
void *buffer = ibo->map();
// Fill the vector from the buffer.
switch (element_data_type)
{
VertexBuffer::Bind ibo_bind(*ibo);
// We unmap the buffer in Mesh::draw and Mesh::setVertexMap.
return (uint32 *) ibo->map();
case GL_UNSIGNED_BYTE:
copyFromIndexBuffer<uint8>(buffer, map, vertex_count);
break;
case GL_UNSIGNED_SHORT:
copyFromIndexBuffer<uint16>(buffer, map, vertex_count);
break;
case GL_UNSIGNED_INT:
default:
copyFromIndexBuffer<uint32>(buffer, map, vertex_count);
break;
}
return nullptr;
}
size_t Mesh::getVertexMapCount() const
@@ -335,7 +405,7 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo
min = std::min(std::max(range_min, 0), max);
const void *indices = ibo->getPointer(min * sizeof(uint32));
GLenum type = GL_UNSIGNED_INT;
GLenum type = element_data_type;
if (instance_count > 1)
gl.drawElementsInstanced(mode, max - min + 1, type, indices, instance_count);
@@ -375,7 +445,7 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo
texture->postdraw();
}
GLenum Mesh::getGLDrawMode(Mesh::DrawMode mode) const
GLenum Mesh::getGLDrawMode(DrawMode mode) const
{
switch (mode)
{
@@ -394,6 +464,16 @@ GLenum Mesh::getGLDrawMode(Mesh::DrawMode mode) const
return GL_TRIANGLES;
}
GLenum Mesh::getGLDataTypeFromMax(size_t maxvalue) const
{
if (maxvalue > LOVE_UINT16_MAX)
return GL_UNSIGNED_INT;
else if (maxvalue > LOVE_UINT8_MAX)
return GL_UNSIGNED_SHORT;
else
return GL_UNSIGNED_BYTE;
}
bool Mesh::getConstant(const char *in, Mesh::DrawMode &out)
{
return drawModes.find(in, out);
+5 -4
View File
@@ -109,11 +109,10 @@ public:
void setVertexMap(const std::vector<uint32> &map);
/**
* Gets a pointer to the vertex map array. The pointer is only valid until
* the next function call in the graphics module.
* May return null if the vertex map is empty.
* Fills the uint32 vector passed into the method with the previously set
* vertex map (index buffer) values.
**/
const uint32 *getVertexMap() const;
void getVertexMap(std::vector<uint32> &map) const;
/**
* Gets the total number of elements in the vertex map array.
@@ -171,6 +170,7 @@ public:
private:
GLenum getGLDrawMode(DrawMode mode) const;
GLenum getGLDataTypeFromMax(size_t maxvalue) const;
// Vertex buffer.
VertexBuffer *vbo;
@@ -179,6 +179,7 @@ private:
// Element (vertex index) buffer, for the vertex map.
VertexBuffer *ibo;
size_t element_count;
GLenum element_data_type;
int instance_count;
+6 -5
View File
@@ -220,14 +220,15 @@ int w_Mesh_setVertexMap(lua_State *L)
int w_Mesh_getVertexMap(lua_State *L)
{
Mesh *t = luax_checkmesh(L, 1);
const uint32 *vertex_map = 0;
EXCEPT_GUARD(vertex_map = t->getVertexMap();)
size_t elements = t->getVertexMapCount();
std::vector<uint32> vertex_map;
EXCEPT_GUARD(t->getVertexMap(vertex_map);)
lua_createtable(L, elements, 0);
size_t element_count = vertex_map.size();
for (size_t i = 0; i < elements; i++)
lua_createtable(L, element_count, 0);
for (size_t i = 0; i < element_count; i++)
{
lua_pushinteger(L, lua_Integer(vertex_map[i]) + 1);
lua_rawseti(L, -2, i + 1);