Use VAOs to bind the VBOs.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 8 Mar 2014 20:35:29 +0000 (21:35 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 8 Mar 2014 20:57:27 +0000 (21:57 +0100)
Needed for OpenGL 3.2+ core context support. Also refactor a bit,
since the amount of boilerplate was getting over the top.

effect_chain.cpp
init.cpp
util.cpp
util.h

index c803c62..3376daa 100644 (file)
@@ -1470,6 +1470,7 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height
                }
 
                const GLuint glsl_program_num = phases[phase]->glsl_program_num;
+               check_error();
                glUseProgram(glsl_program_num);
                check_error();
 
@@ -1542,37 +1543,31 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height
                        0.0f, 1.0f
                };
 
-               int position_attrib = glGetAttribLocation(glsl_program_num, "position");
-               assert(position_attrib != -1);
-               glEnableVertexAttribArray(position_attrib);
+               GLuint vao;
+               glGenVertexArrays(1, &vao);
                check_error();
-               glVertexAttribPointer(position_attrib, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+               glBindVertexArray(vao);
                check_error();
 
-               int texcoord_attrib = glGetAttribLocation(glsl_program_num, "texcoord");
-               if (texcoord_attrib != -1) {
-                       glEnableVertexAttribArray(texcoord_attrib);
-                       check_error();
-                       glVertexAttribPointer(texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 0, vertices);  // Same as texcoords.
-                       check_error();
-               }
+               GLuint position_vbo = fill_vertex_attribute(glsl_program_num, "position", 2, GL_FLOAT, sizeof(vertices), vertices);
+               GLuint texcoord_vbo = fill_vertex_attribute(glsl_program_num, "texcoord", 2, GL_FLOAT, sizeof(vertices), vertices);  // Same as vertices.
 
                glDrawArrays(GL_QUADS, 0, 4);
                check_error();
 
+               cleanup_vertex_attribute(glsl_program_num, "position", position_vbo);
+               cleanup_vertex_attribute(glsl_program_num, "texcoord", texcoord_vbo);
+
                glUseProgram(0);
                check_error();
-               glDisableVertexAttribArray(position_attrib);
-               check_error();
-               if (texcoord_attrib != -1) {
-                       glDisableVertexAttribArray(texcoord_attrib);
-                       check_error();
-               }
 
                for (unsigned i = 0; i < phases[phase]->effects.size(); ++i) {
                        Node *node = phases[phase]->effects[i];
                        node->effect->clear_gl_state();
                }
+
+               glDeleteVertexArrays(1, &vao);
+               check_error();
        }
 
        for (map<Phase *, GLuint>::const_iterator texture_it = output_textures.begin();
index 4003163..b7604e4 100644 (file)
--- a/init.cpp
+++ b/init.cpp
@@ -101,28 +101,23 @@ void measure_texel_subpixel_precision()
                0.25f, 0.0f
        };
 
-       int position_attrib = glGetAttribLocation(glsl_program_num, "position");
-       assert(position_attrib != -1);
-       int texcoord_attrib = glGetAttribLocation(glsl_program_num, "texcoord");
-       assert(texcoord_attrib != -1);
-       glEnableVertexAttribArray(position_attrib);
+       GLuint vao;
+       glGenVertexArrays(1, &vao);
        check_error();
-       glVertexAttribPointer(position_attrib, 2, GL_FLOAT, GL_FALSE, 0, vertices);
-       check_error();
-       glEnableVertexAttribArray(texcoord_attrib);
-       check_error();
-       glVertexAttribPointer(texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
+       glBindVertexArray(vao);
        check_error();
 
+       GLuint position_vbo = fill_vertex_attribute(glsl_program_num, "position", 2, GL_FLOAT, sizeof(vertices), vertices);
+       GLuint texcoord_vbo = fill_vertex_attribute(glsl_program_num, "texcoord", 2, GL_FLOAT, sizeof(texcoords), texcoords);
+
        glDrawArrays(GL_QUADS, 0, 4);
        check_error();
 
+       cleanup_vertex_attribute(glsl_program_num, "position", position_vbo);
+       cleanup_vertex_attribute(glsl_program_num, "texcoord", texcoord_vbo);
+
        glUseProgram(0);
        check_error();
-       glDisableVertexAttribArray(position_attrib);
-       check_error();
-       glDisableVertexAttribArray(texcoord_attrib);
-       check_error();
 
        // Now read the data back and see what the card did.
        // (We only look at the red channel; the others will surely be the same.)
@@ -153,6 +148,8 @@ void measure_texel_subpixel_precision()
        check_error();
 
        resource_pool.release_glsl_program(glsl_program_num);
+       glDeleteVertexArrays(1, &vao);
+       check_error();
 }
 
 void measure_roundoff_problems()
@@ -230,25 +227,24 @@ void measure_roundoff_problems()
                0.75f, 0.0f,
                0.25f, 0.0f
        };
-       int position_attrib = glGetAttribLocation(glsl_program_num, "position");
-       assert(position_attrib != -1);
-       int texcoord_attrib = glGetAttribLocation(glsl_program_num, "texcoord");
-       assert(texcoord_attrib != -1);
-       glEnableVertexAttribArray(position_attrib);
-       check_error();
-       glVertexAttribPointer(position_attrib, 2, GL_FLOAT, GL_FALSE, 0, vertices);
-       check_error();
-       glEnableVertexAttribArray(texcoord_attrib);
+
+       GLuint vao;
+       glGenVertexArrays(1, &vao);
        check_error();
-       glVertexAttribPointer(texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
+       glBindVertexArray(vao);
        check_error();
+
+       GLuint position_vbo = fill_vertex_attribute(glsl_program_num, "position", 2, GL_FLOAT, sizeof(vertices), vertices);
+       GLuint texcoord_vbo = fill_vertex_attribute(glsl_program_num, "texcoord", 2, GL_FLOAT, sizeof(texcoords), texcoords);
+
        glDrawArrays(GL_QUADS, 0, 4);
+       check_error();
+
+       cleanup_vertex_attribute(glsl_program_num, "position", position_vbo);
+       cleanup_vertex_attribute(glsl_program_num, "texcoord", texcoord_vbo);
 
        glUseProgram(0);
        check_error();
-       glDisableVertexAttribArray(position_attrib);
-       check_error();
-       glDisableVertexAttribArray(texcoord_attrib);
 
        // Now read the data back and see what the card did. (Ignore the last value.)
        // (We only look at the red channel; the others will surely be the same.)
@@ -281,6 +277,8 @@ void measure_roundoff_problems()
        check_error();
 
        resource_pool.release_glsl_program(glsl_program_num);
+       glDeleteVertexArrays(1, &vao);
+       check_error();
 }
 
 bool check_extensions()
index 9e18e9f..b86e3f7 100644 (file)
--- a/util.cpp
+++ b/util.cpp
@@ -178,4 +178,41 @@ void combine_two_samples(float w1, float w2, float *offset, float *total_weight,
        assert(*offset <= 1.0f);
 }
 
+GLuint fill_vertex_attribute(GLuint glsl_program_num, const string &attribute_name, GLint size, GLenum type, GLsizeiptr data_size, const GLvoid *data)
+{
+       int attrib = glGetAttribLocation(glsl_program_num, attribute_name.c_str());
+       if (attrib == -1) {
+               return -1;
+       }
+
+       GLuint vbo;
+       glGenBuffers(1, &vbo);
+       check_error();
+       glBindBuffer(GL_ARRAY_BUFFER, vbo);
+       check_error();
+       glBufferData(GL_ARRAY_BUFFER, data_size, data, GL_STATIC_DRAW);
+       check_error();
+       glEnableVertexAttribArray(attrib);
+       check_error();
+       glVertexAttribPointer(attrib, size, type, GL_FALSE, 0, BUFFER_OFFSET(0));
+       check_error();
+       glBindBuffer(GL_ARRAY_BUFFER, 0);
+       check_error();
+
+       return vbo;
+}
+
+void cleanup_vertex_attribute(GLuint glsl_program_num, const string &attribute_name, GLuint vbo)
+{
+       int attrib = glGetAttribLocation(glsl_program_num, attribute_name.c_str());
+       if (attrib == -1) {
+               return;
+       }
+
+       glDisableVertexAttribArray(attrib);
+       check_error();
+       glDeleteBuffers(1, &vbo);
+       check_error();
+}
+
 }  // namespace movit
diff --git a/util.h b/util.h
index f62618c..627c629 100644 (file)
--- a/util.h
+++ b/util.h
@@ -43,6 +43,13 @@ std::string output_glsl_mat3(const std::string &name, const Eigen::Matrix3d &m);
 // (estimated) squared errors of the two weights.
 void combine_two_samples(float w1, float w2, float *offset, float *total_weight, float *sum_sq_error);
 
+// Create a VBO with the given data, and bind it to the vertex attribute
+// with name <attribute_name>. Returns the VBO number.
+GLuint fill_vertex_attribute(GLuint glsl_program_num, const std::string &attribute_name, GLint size, GLenum type, GLsizeiptr data_size, const GLvoid *data);
+
+// Clean up after fill_vertex_attribute().
+void cleanup_vertex_attribute(GLuint glsl_program_num, const std::string &attribute_name, GLuint vbo);
+
 }  // namespace movit
 
 #ifdef NDEBUG