X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=effect_chain.cpp;h=a8c2e52c564679872ad92d31c48f391a45e699be;hb=faf8ad966f79932fe890b564d39f96342ae1e844;hp=a9b892725358039173725feea5306692f3432988;hpb=7221906173f1cf1ce6913cbe9d62d5ca11e9ee0d;p=movit diff --git a/effect_chain.cpp b/effect_chain.cpp index a9b8927..a8c2e52 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -317,7 +318,7 @@ Phase *EffectChain::compile_glsl_program( // without any explicit recursion. void EffectChain::construct_glsl_programs(Node *output) { - // Which effects have already been completed in this phase? + // Which effects have already been completed? // We need to keep track of it, as an effect with multiple outputs // could otherwise be calculated multiple times. std::set completed_effects; @@ -348,10 +349,13 @@ void EffectChain::construct_glsl_programs(Node *output) // This should currently only happen for effects that are inputs // (either true inputs or phase outputs). We special-case inputs, // and then deduplicate phase outputs in compile_glsl_program(). - if (node->effect->num_inputs() == 0 && completed_effects.count(node)) { - continue; + if (node->effect->num_inputs() == 0) { + if (find(this_phase_effects.begin(), this_phase_effects.end(), node) != this_phase_effects.end()) { + continue; + } + } else { + assert(completed_effects.count(node) == 0); } - assert(completed_effects.count(node) == 0); this_phase_effects.push_back(node); completed_effects.insert(node); @@ -451,21 +455,26 @@ void EffectChain::output_dot(const char *filename) fprintf(fp, " output [shape=box label=\"(output)\"];\n"); for (unsigned i = 0; i < nodes.size(); ++i) { // Find out which phase this event belongs to. - int in_phase = -1; + std::vector in_phases; for (unsigned j = 0; j < phases.size(); ++j) { const Phase* p = phases[j]; if (std::find(p->effects.begin(), p->effects.end(), nodes[i]) != p->effects.end()) { - assert(in_phase == -1); - in_phase = j; + in_phases.push_back(j); } } - if (in_phase == -1) { + if (in_phases.empty()) { fprintf(fp, " n%ld [label=\"%s\"];\n", (long)nodes[i], nodes[i]->effect->effect_type_id().c_str()); - } else { + } else if (in_phases.size() == 1) { fprintf(fp, " n%ld [label=\"%s\" style=\"filled\" fillcolor=\"/accent8/%d\"];\n", (long)nodes[i], nodes[i]->effect->effect_type_id().c_str(), - (in_phase % 8) + 1); + (in_phases[0] % 8) + 1); + } else { + // If we had new enough Graphviz, style="wedged" would probably be ideal here. + // But alas. + fprintf(fp, " n%ld [label=\"%s [in multiple phases]\" style=\"filled\" fillcolor=\"/accent8/%d\"];\n", + (long)nodes[i], nodes[i]->effect->effect_type_id().c_str(), + (in_phases[0] % 8) + 1); } char from_node_id[256]; @@ -938,7 +947,7 @@ void EffectChain::fix_internal_color_spaces() } // Go through each input that is not sRGB, and insert - // a colorspace conversion before it. + // a colorspace conversion after it. for (unsigned j = 0; j < node->incoming_links.size(); ++j) { Node *input = node->incoming_links[j]; assert(input->output_color_space != COLORSPACE_INVALID); @@ -949,7 +958,8 @@ void EffectChain::fix_internal_color_spaces() CHECK(conversion->effect->set_int("source_space", input->output_color_space)); CHECK(conversion->effect->set_int("destination_space", COLORSPACE_sRGB)); conversion->output_color_space = COLORSPACE_sRGB; - insert_node_between(input, conversion, node); + replace_sender(input, conversion); + connect_nodes(input, conversion); } // Re-sort topologically, and propagate the new information. @@ -1029,7 +1039,8 @@ void EffectChain::fix_internal_alpha(unsigned step) conversion = add_node(new AlphaDivisionEffect()); } conversion->output_alpha_type = desired_type; - insert_node_between(input, conversion, node); + replace_sender(input, conversion); + connect_nodes(input, conversion); } // Re-sort topologically, and propagate the new information. @@ -1212,7 +1223,7 @@ void EffectChain::fix_internal_gamma_by_inserting_nodes(unsigned step) } // If not, go through each input that is not linear gamma, - // and insert a gamma conversion before it. + // and insert a gamma conversion after it. for (unsigned j = 0; j < node->incoming_links.size(); ++j) { Node *input = node->incoming_links[j]; assert(input->output_gamma_curve != GAMMA_INVALID); @@ -1222,7 +1233,8 @@ void EffectChain::fix_internal_gamma_by_inserting_nodes(unsigned step) Node *conversion = add_node(new GammaExpansionEffect()); CHECK(conversion->effect->set_int("source_curve", input->output_gamma_curve)); conversion->output_gamma_curve = GAMMA_LINEAR; - insert_node_between(input, conversion, node); + replace_sender(input, conversion); + connect_nodes(input, conversion); } // Re-sort topologically, and propagate the new information. @@ -1299,6 +1311,10 @@ Node *EffectChain::find_output_node() void EffectChain::finalize() { + // Save the current locale, and set it to C, so that we can output decimal + // numbers with printf and be sure to get them in the format mandated by GLSL. + char *saved_locale = setlocale(LC_NUMERIC, "C"); + // Output the graph as it is before we do any conversions on it. output_dot("step0-start.dot"); @@ -1391,6 +1407,7 @@ void EffectChain::finalize() assert(phases[0]->inputs.empty()); finalized = true; + setlocale(LC_NUMERIC, saved_locale); } void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height)