]> git.sesse.net Git - movit/blobdiff - effect_chain.cpp
Add a temporary variable to reduce the amount of tedious typing.
[movit] / effect_chain.cpp
index 8d3c61d27f4293eed70e9b5dfd4b02e6af9e9bbf..b6f2a5b50b9441649bd9658e77aacfa9efb7e0e3 100644 (file)
@@ -53,6 +53,15 @@ EffectChain::~EffectChain()
                delete nodes[i];
        }
        for (unsigned i = 0; i < phases.size(); ++i) {
+               glBindVertexArray(phases[i]->vao);
+               check_error();
+
+               cleanup_vertex_attribute(phases[i]->glsl_program_num, "position", phases[i]->position_vbo);
+               cleanup_vertex_attribute(phases[i]->glsl_program_num, "texcoord", phases[i]->texcoord_vbo);
+
+               glBindVertexArray(0);
+               check_error();
+
                resource_pool->release_glsl_program(phases[i]->glsl_program_num);
                delete phases[i];
        }
@@ -287,6 +296,27 @@ void EffectChain::compile_glsl_program(Phase *phase)
        frag_shader.append(read_file("footer.frag"));
 
        phase->glsl_program_num = resource_pool->compile_glsl_program(read_file("vs.vert"), frag_shader);
+
+       // Prepare the geometry for the fullscreen quad used in this phase.
+       // (We have separate VAOs per shader, since the bindings can in theory
+       // be different.)
+       float vertices[] = {
+               0.0f, 1.0f,
+               0.0f, 0.0f,
+               1.0f, 1.0f,
+               1.0f, 0.0f
+       };
+
+       glGenVertexArrays(1, &phase->vao);
+       check_error();
+       glBindVertexArray(phase->vao);
+       check_error();
+
+       phase->position_vbo = fill_vertex_attribute(phase->glsl_program_num, "position", 2, GL_FLOAT, sizeof(vertices), vertices);
+       phase->texcoord_vbo = fill_vertex_attribute(phase->glsl_program_num, "texcoord", 2, GL_FLOAT, sizeof(vertices), vertices);  // Same as vertices.
+
+       glBindVertexArray(0);
+       check_error();
 }
 
 // Construct GLSL programs, starting at the given effect and following
@@ -1447,29 +1477,31 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height
        // since otherwise this turns into an (albeit simple) register allocation problem.
        map<Phase *, GLuint> output_textures;
 
-       for (unsigned phase = 0; phase < phases.size(); ++phase) {
+       for (unsigned phase_num = 0; phase_num < phases.size(); ++phase_num) {
+               Phase *phase = phases[phase_num];
+
                // Find a texture for this phase.
-               inform_input_sizes(phases[phase]);
-               if (phase != phases.size() - 1) {
-                       find_output_size(phases[phase]);
+               inform_input_sizes(phase);
+               if (phase_num != phases.size() - 1) {
+                       find_output_size(phase);
 
-                       GLuint tex_num = resource_pool->create_2d_texture(GL_RGBA16F_ARB, phases[phase]->output_width, phases[phase]->output_height);
-                       output_textures.insert(make_pair(phases[phase], tex_num));
+                       GLuint tex_num = resource_pool->create_2d_texture(GL_RGBA16F_ARB, phase->output_width, phase->output_height);
+                       output_textures.insert(make_pair(phase, tex_num));
                }
 
-               const GLuint glsl_program_num = phases[phase]->glsl_program_num;
+               const GLuint glsl_program_num = phase->glsl_program_num;
                check_error();
                glUseProgram(glsl_program_num);
                check_error();
 
                // Set up RTT inputs for this phase.
-               for (unsigned sampler = 0; sampler < phases[phase]->inputs.size(); ++sampler) {
+               for (unsigned sampler = 0; sampler < phase->inputs.size(); ++sampler) {
                        glActiveTexture(GL_TEXTURE0 + sampler);
-                       Phase *input = phases[phase]->inputs[sampler];
+                       Phase *input = phase->inputs[sampler];
                        input->output_node->bound_sampler_num = sampler;
                        glBindTexture(GL_TEXTURE_2D, output_textures[input]);
                        check_error();
-                       if (phases[phase]->input_needs_mipmaps) {
+                       if (phase->input_needs_mipmaps) {
                                if (generated_mipmaps.count(input) == 0) {
                                        glGenerateMipmap(GL_TEXTURE_2D);
                                        check_error();
@@ -1486,13 +1518,13 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
                        check_error();
 
-                       string texture_name = string("tex_") + phases[phase]->effect_ids[input->output_node];
+                       string texture_name = string("tex_") + phase->effect_ids[input->output_node];
                        glUniform1i(glGetUniformLocation(glsl_program_num, texture_name.c_str()), sampler);
                        check_error();
                }
 
                // And now the output.
-               if (phase == phases.size() - 1) {
+               if (phase_num == phases.size() - 1) {
                        // Last phase goes to the output the user specified.
                        glBindFramebuffer(GL_FRAMEBUFFER, dest_fbo);
                        check_error();
@@ -1508,20 +1540,20 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height
                                GL_FRAMEBUFFER,
                                GL_COLOR_ATTACHMENT0,
                                GL_TEXTURE_2D,
-                               output_textures[phases[phase]],
+                               output_textures[phase],
                                0);
                        check_error();
                        GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
                        assert(status == GL_FRAMEBUFFER_COMPLETE);
-                       glViewport(0, 0, phases[phase]->output_width, phases[phase]->output_height);
+                       glViewport(0, 0, phase->output_width, phase->output_height);
                }
 
                // Give the required parameters to all the effects.
-               unsigned sampler_num = phases[phase]->inputs.size();
-               for (unsigned i = 0; i < phases[phase]->effects.size(); ++i) {
-                       Node *node = phases[phase]->effects[i];
+               unsigned sampler_num = phase->inputs.size();
+               for (unsigned i = 0; i < phase->effects.size(); ++i) {
+                       Node *node = phase->effects[i];
                        unsigned old_sampler_num = sampler_num;
-                       node->effect->set_gl_state(glsl_program_num, phases[phase]->effect_ids[node], &sampler_num);
+                       node->effect->set_gl_state(glsl_program_num, phase->effect_ids[node], &sampler_num);
                        check_error();
 
                        if (node->effect->is_single_texture()) {
@@ -1532,39 +1564,15 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height
                        }
                }
 
-               // Now draw!
-               float vertices[] = {
-                       0.0f, 1.0f,
-                       0.0f, 0.0f,
-                       1.0f, 1.0f,
-                       1.0f, 0.0f
-               };
-
-               GLuint vao;
-               glGenVertexArrays(1, &vao);
-               check_error();
-               glBindVertexArray(vao);
+               glBindVertexArray(phase->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(vertices), vertices);  // Same as vertices.
-
                glDrawArrays(GL_TRIANGLE_STRIP, 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();
-
-               for (unsigned i = 0; i < phases[phase]->effects.size(); ++i) {
-                       Node *node = phases[phase]->effects[i];
+               for (unsigned i = 0; i < phase->effects.size(); ++i) {
+                       Node *node = phase->effects[i];
                        node->effect->clear_gl_state();
                }
-
-               glDeleteVertexArrays(1, &vao);
-               check_error();
        }
 
        for (map<Phase *, GLuint>::const_iterator texture_it = output_textures.begin();
@@ -1575,6 +1583,10 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height
 
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        check_error();
+       glBindVertexArray(0);
+       check_error();
+       glUseProgram(0);
+       check_error();
 }
 
 }  // namespace movit