diff --git a/include/llmr/geometry/vao.hpp b/include/llmr/geometry/vao.hpp index 5e0b54ba6..d99ae6c78 100644 --- a/include/llmr/geometry/vao.hpp +++ b/include/llmr/geometry/vao.hpp @@ -3,38 +3,50 @@ #include -#include +#include namespace llmr { class VertexArrayObject { public: template - inline void setup(Shader& shader, VertexBuffer& vertex_buffer, char *vertex_offset) { - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); + void bind(Shader& shader, VertexBuffer& vertex_buffer, char *vertex_offset) { + if (!vao) { + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); - vertex_buffer.bind(); - shader.bind_vertex(vertex_offset); + vertex_buffer.bind(); + shader.bind_vertex(vertex_offset); + + program = shader.program; + buffer = &vertex_buffer; + offset = vertex_offset; + } else if (program != shader.program) { + throw std::runtime_error("trying to bind VAO to different program"); + } else if (buffer != &vertex_buffer) { + throw std::runtime_error("trying to bind VAO to another buffer"); + } else if (offset != vertex_offset) { + throw std::runtime_error("trying to bind VAO to another offset"); + } else { + // This is the correct program for this VAO. + glBindVertexArray(vao); + } } - inline ~VertexArrayObject() { + ~VertexArrayObject() { if (vao) { glDeleteVertexArrays(1, &vao); } } - inline operator bool() const { - return vao != 0; - } - - inline void bind() { - assert(vao); - glBindVertexArray(vao); - } - private: GLuint vao = 0; + + // For debug reasons, we're storing the bind information so that we can + // detect errors and report + GLuint program = 0; + void *buffer = NULL; + char *offset = 0; }; } diff --git a/include/llmr/renderer/fill_bucket.hpp b/include/llmr/renderer/fill_bucket.hpp index 774b00811..6c54107c3 100644 --- a/include/llmr/renderer/fill_bucket.hpp +++ b/include/llmr/renderer/fill_bucket.hpp @@ -66,11 +66,7 @@ void FillBucket::drawElements(Shader& shader) { char *vertex_index = BUFFER_OFFSET(vertex_start * 2 * sizeof(int16_t)); char *elements_index = BUFFER_OFFSET(elements_start * 3 * sizeof(int16_t)); for (group& group : groups) { - if (!group.array) { - group.array.setup(shader, *buffer, vertex_index); - } else { - group.array.bind(); - } + group.array.bind(shader, *buffer, vertex_index); glDrawElements(GL_TRIANGLES, group.elements_length * 3 - 3, GL_UNSIGNED_SHORT, elements_index); vertex_index += group.vertex_length * 2 * sizeof(uint16_t); elements_index += group.elements_length * 3 * sizeof(uint16_t); @@ -80,12 +76,8 @@ void FillBucket::drawElements(Shader& shader) { template void FillBucket::drawVertices(Shader& shader) { // Draw the entire line - if (!array) { - char *vertex_index = BUFFER_OFFSET(vertex_start * 2 * sizeof(int16_t)); - array.setup(shader, *buffer, vertex_index); - } else { - array.bind(); - } + char *vertex_index = BUFFER_OFFSET(vertex_start * 2 * sizeof(int16_t)); + array.bind(shader, *buffer, vertex_index); glDrawArrays(GL_LINE_STRIP, 0, length); } diff --git a/src/renderer/line_bucket.cpp b/src/renderer/line_bucket.cpp index 5dc0710b8..6e95a7bc6 100644 --- a/src/renderer/line_bucket.cpp +++ b/src/renderer/line_bucket.cpp @@ -270,12 +270,8 @@ size_t LineBucket::size() const { } void LineBucket::bind(LineShader& shader) { - if (!array) { - char *vertex_index = BUFFER_OFFSET(start * 4 * sizeof(int16_t)); - array.setup(shader, *buffer, vertex_index); - } else { - array.bind(); - } + char *vertex_index = BUFFER_OFFSET(start * 4 * sizeof(int16_t)); + array.bind(shader, *buffer, vertex_index); } void LineBucket::drawLines() { diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 4a3a4456f..3187739e8 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -93,11 +93,8 @@ void Painter::drawClippingMask() { glStencilMask(0xC0); glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); - if (!tileStencilArray) { - tileStencilArray.setup(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0)); - } else { - tileStencilArray.bind(); - } + + tileStencilArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0)); // Draw the clipping mask glUniform4f(plainShader->u_color, 1.0f, 0.0f, 1.0f, 1.0f); @@ -281,11 +278,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons glUniform4fv(fillShader->u_color, 1, fill_color.data()); // Draw a rectangle that covers the entire viewport. - if (!tileStencilArray) { - tileStencilArray.setup(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0)); - } else { - tileStencilArray.bind(); - } + tileStencilArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0)); glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.length()); } @@ -373,21 +366,13 @@ void Painter::renderDebug(const Tile::Ptr& tile) { glUniformMatrix4fv(plainShader->u_matrix, 1, GL_FALSE, matrix.data()); // draw tile outline - if (!tileBorderArray) { - tileBorderArray.setup(*plainShader, tileBorderBuffer, BUFFER_OFFSET(0)); - } else { - tileBorderArray.bind(); - } + tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET(0)); glUniform4f(plainShader->u_color, 1.0f, 0.0f, 0.0f, 1.0f); glLineWidth(4.0f); glDrawArrays(GL_LINE_STRIP, 0, tileBorderBuffer.length()); // draw debug info - if (!tile->debugFontArray) { - tile->debugFontArray.setup(*plainShader, tile->debugFontBuffer, BUFFER_OFFSET(0)); - } else { - tile->debugFontArray.bind(); - } + tile->debugFontArray.bind(*plainShader, tile->debugFontBuffer, BUFFER_OFFSET(0)); glUniform4f(plainShader->u_color, 1.0f, 1.0f, 1.0f, 1.0f); glLineWidth(4.0f); glDrawArrays(GL_LINES, 0, tile->debugFontBuffer.length()); @@ -407,13 +392,8 @@ void Painter::renderMatte() { glUseProgram(plainShader->program); glUniformMatrix4fv(plainShader->u_matrix, 1, GL_FALSE, nativeMatrix.data()); - if (!matteArray) { - matteArray.setup(*plainShader, matteBuffer, BUFFER_OFFSET(0)); - } else { - matteArray.bind(); - } - // Draw the clipping mask + matteArray.bind(*plainShader, matteBuffer, BUFFER_OFFSET(0)); glUniform4fv(plainShader->u_color, 1, white.data()); glDrawArrays(GL_TRIANGLES, 0, matteBuffer.length()); @@ -427,11 +407,7 @@ void Painter::renderBackground() { glUniformMatrix4fv(plainShader->u_matrix, 1, GL_FALSE, matrix.data()); // Draw the clipping mask - if (!tileStencilArray) { - tileStencilArray.setup(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0)); - } else { - tileStencilArray.bind(); - } + tileStencilArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0)); glUniform4fv(plainShader->u_color, 1, white.data()); glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.length()); }