X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=effect_chain.cpp;h=c2402daeaef400d9ded80dcbce3378be9f94ac42;hp=bf017166a770f5a2d4d52adf0d68cf303aab30bd;hb=825c90789c229f502520bf0b665596d473f2636d;hpb=5e34f7a8969f4afc169f034d34fb908019b3a389 diff --git a/effect_chain.cpp b/effect_chain.cpp index bf01716..c2402da 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -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,19 +79,22 @@ 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) + 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; assert(ycbcr_format.chroma_subsampling_x == 1); assert(ycbcr_format.chroma_subsampling_y == 1); @@ -178,6 +184,13 @@ GLenum EffectChain::get_input_sampler(Node *node, unsigned input_num) const return GL_TEXTURE0 + node->incoming_links[input_num]->bound_sampler_num; } +GLenum EffectChain::has_input_sampler(Node *node, unsigned input_num) const +{ + assert(input_num < node->incoming_links.size()); + return node->incoming_links[input_num]->bound_sampler_num >= 0 && + node->incoming_links[input_num]->bound_sampler_num < 8; +} + void EffectChain::find_all_nonlinear_inputs(Node *node, vector *nonlinear_inputs) { if (node->output_gamma_curve == GAMMA_LINEAR && @@ -206,7 +219,7 @@ Effect *EffectChain::add_effect(Effect *effect, const vector &inputs) return effect; } -// GLSL pre-1.30 doesn't support token pasting. Replace PREFIX(x) with _x. +// ESSL doesn't support token pasting. Replace PREFIX(x) with _x. string replace_prefix(const string &text, const string &prefix) { string output; @@ -361,7 +374,39 @@ void EffectChain::compile_glsl_program(Phase *phase) frag_shader += "\n"; } frag_shader += string("#define INPUT ") + phase->effect_ids[phase->effects.back()] + "\n"; - frag_shader.append(read_version_dependent_file("footer", "frag")); + + // If we're the last phase, add the right #defines for Y'CbCr multi-output as needed. + vector frag_shader_outputs; // In order. + if (phase->output_node->outgoing_links.empty() && output_color_ycbcr) { + switch (output_ycbcr_splitting) { + case YCBCR_OUTPUT_INTERLEAVED: + // No #defines set. + frag_shader_outputs.push_back("FragColor"); + break; + case YCBCR_OUTPUT_SPLIT_Y_AND_CBCR: + frag_shader += "#define YCBCR_OUTPUT_SPLIT_Y_AND_CBCR 1\n"; + frag_shader_outputs.push_back("Y"); + frag_shader_outputs.push_back("Chroma"); + break; + case YCBCR_OUTPUT_PLANAR: + frag_shader += "#define YCBCR_OUTPUT_PLANAR 1\n"; + frag_shader_outputs.push_back("Y"); + frag_shader_outputs.push_back("Cb"); + frag_shader_outputs.push_back("Cr"); + break; + 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_outputs.push_back("RGBA"); + } + } + 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 @@ -381,7 +426,9 @@ void EffectChain::compile_glsl_program(Phase *phase) extract_uniform_declarations(effect->uniforms_vec2, "vec2", effect_id, &phase->uniforms_vec2, &frag_shader_uniforms); extract_uniform_declarations(effect->uniforms_vec3, "vec3", effect_id, &phase->uniforms_vec3, &frag_shader_uniforms); extract_uniform_declarations(effect->uniforms_vec4, "vec4", effect_id, &phase->uniforms_vec4, &frag_shader_uniforms); + extract_uniform_array_declarations(effect->uniforms_float_array, "float", effect_id, &phase->uniforms_float, &frag_shader_uniforms); extract_uniform_array_declarations(effect->uniforms_vec2_array, "vec2", effect_id, &phase->uniforms_vec2, &frag_shader_uniforms); + extract_uniform_array_declarations(effect->uniforms_vec3_array, "vec3", effect_id, &phase->uniforms_vec3, &frag_shader_uniforms); extract_uniform_array_declarations(effect->uniforms_vec4_array, "vec4", effect_id, &phase->uniforms_vec4, &frag_shader_uniforms); extract_uniform_declarations(effect->uniforms_mat3, "mat3", effect_id, &phase->uniforms_mat3, &frag_shader_uniforms); } @@ -389,7 +436,18 @@ 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"); - phase->glsl_program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader); + + // 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, frag_shader_outputs); // Collect the resulting location numbers for each uniform. collect_uniform_locations(phase->glsl_program_num, &phase->uniforms_sampler2d); @@ -459,7 +517,8 @@ Phase *EffectChain::construct_phase(Node *output, map *complete bool start_new_phase = false; if (node->effect->needs_texture_bounce() && - !deps[i]->effect->is_single_texture()) { + !deps[i]->effect->is_single_texture() && + !deps[i]->effect->override_disable_bounce()) { start_new_phase = true; } @@ -1489,8 +1548,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(); @@ -1605,6 +1664,12 @@ 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. + check_error(); + glDisable(GL_DITHER); + check_error(); + // Save original viewport. GLuint x = 0, y = 0; @@ -1618,6 +1683,7 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height } // Basic state. + check_error(); glDisable(GL_BLEND); check_error(); glDisable(GL_DEPTH_TEST);