]> git.sesse.net Git - movit/blobdiff - effect_chain.cpp
Disable dither explicitly per frame; fixes some weird artifacts I found.
[movit] / effect_chain.cpp
index 4c2df4c2de6dbce9563c4f34700891b113acdc7e..b6b5f59925df18b83ea75100e276e6d153076310 100644 (file)
@@ -37,8 +37,11 @@ namespace movit {
 EffectChain::EffectChain(float aspect_nom, float aspect_denom, ResourcePool *resource_pool)
        : aspect_nom(aspect_nom),
          aspect_denom(aspect_denom),
+         output_color_rgba(false),
+         output_color_ycbcr(false),
          dither_effect(NULL),
          num_dither_bits(0),
+         output_origin(OUTPUT_ORIGIN_BOTTOM_LEFT),
          finalized(false),
          resource_pool(resource_pool),
          do_phase_timing(false) {
@@ -76,18 +79,20 @@ Input *EffectChain::add_input(Input *input)
 void EffectChain::add_output(const ImageFormat &format, OutputAlphaFormat alpha_format)
 {
        assert(!finalized);
+       assert(!output_color_rgba);
        output_format = format;
        output_alpha_format = alpha_format;
-       output_color_type = OUTPUT_COLOR_RGB;
+       output_color_rgba = true;
 }
 
 void EffectChain::add_ycbcr_output(const ImageFormat &format, OutputAlphaFormat alpha_format,
                                    const YCbCrFormat &ycbcr_format, YCbCrOutputSplitting output_splitting)
 {
        assert(!finalized);
+       assert(!output_color_ycbcr);
        output_format = format;
        output_alpha_format = alpha_format;
-       output_color_type = OUTPUT_COLOR_YCBCR;
+       output_color_ycbcr = true;
        output_ycbcr_format = ycbcr_format;
        output_ycbcr_splitting = output_splitting;
 
@@ -207,7 +212,7 @@ Effect *EffectChain::add_effect(Effect *effect, const vector<Effect *> &inputs)
        return effect;
 }
 
-// GLSL pre-1.30 doesn't support token pasting. Replace PREFIX(x) with <effect_id>_x.
+// ESSL doesn't support token pasting. Replace PREFIX(x) with <effect_id>_x.
 string replace_prefix(const string &text, const string &prefix)
 {
        string output;
@@ -364,7 +369,7 @@ void EffectChain::compile_glsl_program(Phase *phase)
        frag_shader += string("#define INPUT ") + phase->effect_ids[phase->effects.back()] + "\n";
 
        // If we're the last phase, add the right #defines for Y'CbCr multi-output as needed.
-       if (phase->output_node->outgoing_links.empty() && output_color_type == OUTPUT_COLOR_YCBCR) {
+       if (phase->output_node->outgoing_links.empty() && output_color_ycbcr) {
                switch (output_ycbcr_splitting) {
                case YCBCR_OUTPUT_INTERLEAVED:
                        // No #defines set.
@@ -378,8 +383,15 @@ void EffectChain::compile_glsl_program(Phase *phase)
                default:
                        assert(false);
                }
+
+               if (output_color_rgba) {
+                       // Note: Needs to come in the header, because not only the
+                       // output needs to see it (YCbCrConversionEffect and DitherEffect
+                       // do, too).
+                       frag_shader_header += "#define YCBCR_ALSO_OUTPUT_RGBA 1\n";
+               }
        }
-       frag_shader.append(read_version_dependent_file("footer", "frag"));
+       frag_shader.append(read_file("footer.frag"));
 
        // Collect uniforms from all effects and output them. Note that this needs
        // to happen after output_fragment_shader(), even though the uniforms come
@@ -407,6 +419,17 @@ void EffectChain::compile_glsl_program(Phase *phase)
        frag_shader = frag_shader_header + frag_shader_uniforms + frag_shader;
 
        string vert_shader = read_version_dependent_file("vs", "vert");
+
+       // If we're the last phase and need to flip the picture to compensate for
+       // the origin, tell the vertex shader so.
+       if (phase->output_node->outgoing_links.empty() && output_origin == OUTPUT_ORIGIN_TOP_LEFT) {
+               const string needle = "#define FLIP_ORIGIN 0";
+               size_t pos = vert_shader.find(needle);
+               assert(pos != string::npos);
+
+               vert_shader[pos + needle.size() - 1] = '1';
+       }
+
        phase->glsl_program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader);
 
        // Collect the resulting location numbers for each uniform.
@@ -1507,8 +1530,8 @@ void EffectChain::fix_output_gamma()
 // gamma-encoded data.
 void EffectChain::add_ycbcr_conversion_if_needed()
 {
-       assert(output_color_type == OUTPUT_COLOR_RGB || output_color_type == OUTPUT_COLOR_YCBCR);
-       if (output_color_type != OUTPUT_COLOR_YCBCR) {
+       assert(output_color_rgba || output_color_ycbcr);
+       if (!output_color_ycbcr) {
                return;
        }
        Node *output = find_output_node();
@@ -1623,6 +1646,10 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height
 {
        assert(finalized);
 
+       // This needs to be set anew, in case we are coming from a different context
+       // from when we initialized.
+       glDisable(GL_DITHER);
+
        // Save original viewport.
        GLuint x = 0, y = 0;