#include "buffer.h" #include #include #include #include #include static size_t get_buffer_size_bytes( BufferType type, const BufferDataDesc* desc) { return desc->count * gfx_get_buffer_type_size_bytes(type); } static GLenum get_buffer_usage(BufferUsage usage) { switch (usage) { case BufferStatic: return GL_STATIC_DRAW; case BufferDynamic: return GL_DYNAMIC_DRAW; } FAIL("Unhandled buffer usage"); return GL_STATIC_DRAW; } size_t gfx_get_buffer_type_size_bytes(BufferType type) { switch (type) { case BufferUntyped: return 1; case Buffer2d: return sizeof(vec2); case Buffer3d: return sizeof(vec3); case Buffer4d: return sizeof(vec4); case BufferFloat: return sizeof(float); case BufferU8: return sizeof(uint8_t); case BufferU16: return sizeof(uint16_t); } FAIL("Unhandled buffer type"); return 0; } bool gfx_init_buffer(Buffer* buffer, const BufferDesc* desc) { assert(buffer); buffer->type = desc->type; buffer->usage = desc->usage; buffer->size_bytes = get_buffer_size_bytes(desc->type, &desc->data); const GLenum usage = get_buffer_usage(desc->usage); glGenBuffers(1, &buffer->vbo); glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo); glBufferData(GL_ARRAY_BUFFER, buffer->size_bytes, desc->data.data, usage); glBindBuffer(GL_ARRAY_BUFFER, 0); ASSERT_GL; return true; } void gfx_del_buffer(Buffer* buffer) { assert(buffer); if (buffer->vbo) { glDeleteBuffers(1, &buffer->vbo); buffer->vbo = 0; } } void gfx_update_buffer(Buffer* buffer, const BufferDataDesc* desc) { assert(buffer); assert(desc); // OpenGL allows updating static buffers, but it is not optimal for // performance, so we enforce data in static buffers remain static. assert(buffer->usage == BufferDynamic); const size_t update_size_bytes = get_buffer_size_bytes(buffer->type, desc); assert(update_size_bytes <= buffer->size_bytes); glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo); glBufferSubData(GL_ARRAY_BUFFER, 0, update_size_bytes, desc->data); glBindBuffer(GL_ARRAY_BUFFER, 0); }