frag_shader += "\n";
}
- for (unsigned i = 0; i < effects.size(); ++i) {
- Node *node = effects[i];
+ std::vector<Node *> sorted_effects = topological_sort(effects);
+
+ for (unsigned i = 0; i < sorted_effects.size(); ++i) {
+ Node *node = sorted_effects[i];
if (node->incoming_links.size() == 1) {
frag_shader += std::string("#define INPUT ") + node->incoming_links[0]->effect_id + "\n";
input_needs_mipmaps |= node->effect->needs_mipmaps();
}
- for (unsigned i = 0; i < effects.size(); ++i) {
- Node *node = effects[i];
+ for (unsigned i = 0; i < sorted_effects.size(); ++i) {
+ Node *node = sorted_effects[i];
if (node->effect->num_inputs() == 0) {
CHECK(node->effect->set_int("needs_mipmaps", input_needs_mipmaps));
}
}
- frag_shader += std::string("#define INPUT ") + effects.back()->effect_id + "\n";
+ frag_shader += std::string("#define INPUT ") + sorted_effects.back()->effect_id + "\n";
frag_shader.append(read_file("footer.frag"));
if (movit_debug_level == MOVIT_DEBUG_ON) {
phase->fragment_shader = fs_obj;
phase->input_needs_mipmaps = input_needs_mipmaps;
phase->inputs = true_inputs;
- phase->effects = effects;
+ phase->effects = sorted_effects;
return phase;
}
Node *node = effects_todo_this_phase.top();
effects_todo_this_phase.pop();
- // This should currently only happen for effects that are phase outputs,
- // and we throw those out separately below.
+ // 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;
+ }
assert(completed_effects.count(node) == 0);
this_phase_effects.push_back(node);
phase->output_height = best_width * aspect_denom / aspect_nom;
}
-void EffectChain::sort_nodes_topologically()
+void EffectChain::sort_all_nodes_topologically()
{
- std::set<Node *> visited_nodes;
+ nodes = topological_sort(nodes);
+}
+
+std::vector<Node *> EffectChain::topological_sort(const std::vector<Node *> &nodes)
+{
+ std::set<Node *> nodes_left_to_visit(nodes.begin(), nodes.end());
std::vector<Node *> sorted_list;
for (unsigned i = 0; i < nodes.size(); ++i) {
- if (nodes[i]->incoming_links.size() == 0) {
- topological_sort_visit_node(nodes[i], &visited_nodes, &sorted_list);
- }
+ topological_sort_visit_node(nodes[i], &nodes_left_to_visit, &sorted_list);
}
reverse(sorted_list.begin(), sorted_list.end());
- nodes = sorted_list;
+ return sorted_list;
}
-void EffectChain::topological_sort_visit_node(Node *node, std::set<Node *> *visited_nodes, std::vector<Node *> *sorted_list)
+void EffectChain::topological_sort_visit_node(Node *node, std::set<Node *> *nodes_left_to_visit, std::vector<Node *> *sorted_list)
{
- if (visited_nodes->count(node) != 0) {
+ if (nodes_left_to_visit->count(node) == 0) {
return;
}
- visited_nodes->insert(node);
+ nodes_left_to_visit->erase(node);
for (unsigned i = 0; i < node->outgoing_links.size(); ++i) {
- topological_sort_visit_node(node->outgoing_links[i], visited_nodes, sorted_list);
+ topological_sort_visit_node(node->outgoing_links[i], nodes_left_to_visit, sorted_list);
}
sorted_list->push_back(node);
}
void EffectChain::propagate_gamma_and_color_space()
{
// We depend on going through the nodes in order.
- sort_nodes_topologically();
+ sort_all_nodes_topologically();
for (unsigned i = 0; i < nodes.size(); ++i) {
Node *node = nodes[i];
void EffectChain::propagate_alpha()
{
// We depend on going through the nodes in order.
- sort_nodes_topologically();
+ sort_all_nodes_topologically();
for (unsigned i = 0; i < nodes.size(); ++i) {
Node *node = nodes[i];