]> git.sesse.net Git - nageru/blobdiff - flow.cpp
Remove some debugging code.
[nageru] / flow.cpp
index 873bdf294b1143aaf6eec681419419d5c513e844..68392dc535b5a13c2efe5234a037347431df53af 100644 (file)
--- a/flow.cpp
+++ b/flow.cpp
@@ -778,16 +778,16 @@ Splat::Splat(const OperatingPoint &op)
 
        uniform_splat_size = glGetUniformLocation(splat_program, "splat_size");
        uniform_alpha = glGetUniformLocation(splat_program, "alpha");
-       uniform_image_tex = glGetUniformLocation(splat_program, "image_tex");
+       uniform_gray_tex = glGetUniformLocation(splat_program, "gray_tex");
        uniform_flow_tex = glGetUniformLocation(splat_program, "flow_tex");
        uniform_inv_flow_size = glGetUniformLocation(splat_program, "inv_flow_size");
 }
 
-void Splat::exec(GLuint image_tex, GLuint bidirectional_flow_tex, GLuint flow_tex, GLuint depth_rb, int width, int height, float alpha)
+void Splat::exec(GLuint gray_tex, GLuint bidirectional_flow_tex, GLuint flow_tex, GLuint depth_rb, int width, int height, float alpha)
 {
        glUseProgram(splat_program);
 
-       bind_sampler(splat_program, uniform_image_tex, 0, image_tex, linear_sampler);
+       bind_sampler(splat_program, uniform_gray_tex, 0, gray_tex, linear_sampler);
        bind_sampler(splat_program, uniform_flow_tex, 1, bidirectional_flow_tex, nearest_sampler);
 
        glProgramUniform2f(splat_program, uniform_splat_size, op.splat_size / width, op.splat_size / height);
@@ -915,10 +915,19 @@ void HoleBlend::exec(GLuint flow_tex, GLuint depth_rb, GLuint temp_tex[3], int w
        glDisable(GL_DEPTH_TEST);
 }
 
-Blend::Blend()
+Blend::Blend(bool split_ycbcr_output)
+       : split_ycbcr_output(split_ycbcr_output)
 {
+       string frag_shader = read_file("blend.frag");
+       if (split_ycbcr_output) {
+               // Insert after the first #version line.
+               size_t offset = frag_shader.find('\n');
+               assert(offset != string::npos);
+               frag_shader = frag_shader.substr(0, offset + 1) + "#define SPLIT_YCBCR_OUTPUT 1\n" + frag_shader.substr(offset + 1);
+       }
+
        blend_vs_obj = compile_shader(read_file("vs.vert"), GL_VERTEX_SHADER);
-       blend_fs_obj = compile_shader(read_file("blend.frag"), GL_FRAGMENT_SHADER);
+       blend_fs_obj = compile_shader(frag_shader, GL_FRAGMENT_SHADER);
        blend_program = link_program(blend_vs_obj, blend_fs_obj);
 
        uniform_image_tex = glGetUniformLocation(blend_program, "image_tex");
@@ -927,7 +936,7 @@ Blend::Blend()
        uniform_flow_consistency_tolerance = glGetUniformLocation(blend_program, "flow_consistency_tolerance");
 }
 
-void Blend::exec(GLuint image_tex, GLuint flow_tex, GLuint output_tex, int level_width, int level_height, float alpha)
+void Blend::exec(GLuint image_tex, GLuint flow_tex, GLuint output_tex, GLuint output2_tex, int level_width, int level_height, float alpha)
 {
        glUseProgram(blend_program);
        bind_sampler(blend_program, uniform_image_tex, 0, image_tex, linear_sampler);
@@ -935,13 +944,20 @@ void Blend::exec(GLuint image_tex, GLuint flow_tex, GLuint output_tex, int level
        glProgramUniform1f(blend_program, uniform_alpha, alpha);
 
        glViewport(0, 0, level_width, level_height);
-       fbos.render_to(output_tex);
+       if (split_ycbcr_output) {
+               fbos_split.render_to(output_tex, output2_tex);
+       } else {
+               fbos.render_to(output_tex);
+       }
        glDisable(GL_BLEND);  // A bit ironic, perhaps.
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 }
 
-Interpolate::Interpolate(int width, int height, const OperatingPoint &op)
-       : width(width), height(height), flow_level(op.finest_level), op(op), splat(op) {
+Interpolate::Interpolate(const OperatingPoint &op, bool split_ycbcr_output)
+       : flow_level(op.finest_level),
+         split_ycbcr_output(split_ycbcr_output),
+         splat(op),
+         blend(split_ycbcr_output) {
        // Set up the vertex data that will be shared between all passes.
        float vertices[] = {
                0.0f, 1.0f,
@@ -961,7 +977,7 @@ Interpolate::Interpolate(int width, int height, const OperatingPoint &op)
        glVertexAttribPointer(position_attrib, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
 }
 
-GLuint Interpolate::exec(GLuint image_tex, GLuint bidirectional_flow_tex, GLuint width, GLuint height, float alpha)
+pair<GLuint, GLuint> Interpolate::exec(GLuint image_tex, GLuint gray_tex, GLuint bidirectional_flow_tex, GLuint width, GLuint height, float alpha)
 {
        GPUTimers timers;
 
@@ -973,7 +989,7 @@ GLuint Interpolate::exec(GLuint image_tex, GLuint bidirectional_flow_tex, GLuint
        // Pick out the right level to test splatting results on.
        GLuint tex_view;
        glGenTextures(1, &tex_view);
-       glTextureView(tex_view, GL_TEXTURE_2D_ARRAY, image_tex, GL_RGBA8, flow_level, 1, 0, 2);
+       glTextureView(tex_view, GL_TEXTURE_2D_ARRAY, gray_tex, GL_R8, flow_level, 1, 0, 2);
 
        int flow_width = width >> flow_level;
        int flow_height = height >> flow_level;
@@ -1003,10 +1019,20 @@ GLuint Interpolate::exec(GLuint image_tex, GLuint bidirectional_flow_tex, GLuint
        pool.release_texture(temp_tex[2]);
        pool.release_renderbuffer(depth_rb);
 
-       GLuint output_tex = pool.get_texture(GL_RGBA8, width, height);
-       {
-               ScopedTimer timer("Blend", &total_timer);
-               blend.exec(image_tex, flow_tex, output_tex, width, height, alpha);
+       GLuint output_tex, output2_tex = 0;
+       if (split_ycbcr_output) {
+               output_tex = pool.get_texture(GL_R8, width, height);
+               output2_tex = pool.get_texture(GL_RG8, width, height);
+               {
+                       ScopedTimer timer("Blend", &total_timer);
+                       blend.exec(image_tex, flow_tex, output_tex, output2_tex, width, height, alpha);
+               }
+       } else {
+               output_tex = pool.get_texture(GL_RGBA8, width, height);
+               {
+                       ScopedTimer timer("Blend", &total_timer);
+                       blend.exec(image_tex, flow_tex, output_tex, 0, width, height, alpha);
+               }
        }
        pool.release_texture(flow_tex);
        total_timer.end();
@@ -1014,16 +1040,19 @@ GLuint Interpolate::exec(GLuint image_tex, GLuint bidirectional_flow_tex, GLuint
                timers.print();
        }
 
-       return output_tex;
+       return make_pair(output_tex, output2_tex);
 }
 
 GLuint TexturePool::get_texture(GLenum format, GLuint width, GLuint height, GLuint num_layers)
 {
-       for (Texture &tex : textures) {
-               if (!tex.in_use && !tex.is_renderbuffer && tex.format == format &&
-                   tex.width == width && tex.height == height && tex.num_layers == num_layers) {
-                       tex.in_use = true;
-                       return tex.tex_num;
+       {
+               lock_guard<mutex> lock(mu);
+               for (Texture &tex : textures) {
+                       if (!tex.in_use && !tex.is_renderbuffer && tex.format == format &&
+                           tex.width == width && tex.height == height && tex.num_layers == num_layers) {
+                               tex.in_use = true;
+                               return tex.tex_num;
+                       }
                }
        }
 
@@ -1041,17 +1070,23 @@ GLuint TexturePool::get_texture(GLenum format, GLuint width, GLuint height, GLui
        tex.num_layers = num_layers;
        tex.in_use = true;
        tex.is_renderbuffer = false;
-       textures.push_back(tex);
+       {
+               lock_guard<mutex> lock(mu);
+               textures.push_back(tex);
+       }
        return tex.tex_num;
 }
 
 GLuint TexturePool::get_renderbuffer(GLenum format, GLuint width, GLuint height)
 {
-       for (Texture &tex : textures) {
-               if (!tex.in_use && tex.is_renderbuffer && tex.format == format &&
-                   tex.width == width && tex.height == height) {
-                       tex.in_use = true;
-                       return tex.tex_num;
+       {
+               lock_guard<mutex> lock(mu);
+               for (Texture &tex : textures) {
+                       if (!tex.in_use && tex.is_renderbuffer && tex.format == format &&
+                           tex.width == width && tex.height == height) {
+                               tex.in_use = true;
+                               return tex.tex_num;
+                       }
                }
        }
 
@@ -1064,12 +1099,16 @@ GLuint TexturePool::get_renderbuffer(GLenum format, GLuint width, GLuint height)
        tex.height = height;
        tex.in_use = true;
        tex.is_renderbuffer = true;
-       textures.push_back(tex);
+       {
+               lock_guard<mutex> lock(mu);
+               textures.push_back(tex);
+       }
        return tex.tex_num;
 }
 
 void TexturePool::release_texture(GLuint tex_num)
 {
+       lock_guard<mutex> lock(mu);
        for (Texture &tex : textures) {
                if (!tex.is_renderbuffer && tex.tex_num == tex_num) {
                        assert(tex.in_use);
@@ -1082,6 +1121,7 @@ void TexturePool::release_texture(GLuint tex_num)
 
 void TexturePool::release_renderbuffer(GLuint tex_num)
 {
+       lock_guard<mutex> lock(mu);
        for (Texture &tex : textures) {
                if (tex.is_renderbuffer && tex.tex_num == tex_num) {
                        assert(tex.in_use);