+ // Create all GLSL programs needed to compute the given effect, and all outputs
+ // that depend on it (whenever possible). Returns the phase that has <output>
+ // as the last effect. Also pushes all phases in order onto <phases>.
+ Phase *construct_phase(Node *output, std::map<Node *, Phase *> *completed_effects);
+
+ // Do the actual rendering of the chain. If <dest_fbo> is not (GLuint)-1,
+ // renders to that FBO. If <destinations> is non-empty, render to that set
+ // of textures (last phase, save for the dummy phase, must be a compute shader),
+ // with x/y ignored. Having both set is an error.
+ void render(GLuint dest_fbo, const std::vector<DestinationTexture> &destinations,
+ unsigned x, unsigned y, unsigned width, unsigned height);
+
+ // Execute one phase, ie. set up all inputs, effects and outputs, and render the quad.
+ // If <destinations> is empty, uses whatever output is current (and the phase must not be
+ // a compute shader).
+ void execute_phase(Phase *phase,
+ const std::map<Phase *, GLuint> &output_textures,
+ const std::vector<DestinationTexture> &destinations,
+ std::set<Phase *> *generated_mipmaps);
+
+ // Set up uniforms for one phase. The program must already be bound.
+ void setup_uniforms(Phase *phase);
+
+ // Set up the given sampler number for sampling from an RTT texture.
+ void setup_rtt_sampler(int sampler_num, bool use_mipmaps);
+
+ // Output the current graph to the given file in a Graphviz-compatible format;
+ // only useful for debugging.
+ void output_dot(const char *filename);
+ std::vector<std::string> get_labels_for_edge(const Node *from, const Node *to);
+ void output_dot_edge(FILE *fp,
+ const std::string &from_node_id,
+ const std::string &to_node_id,
+ const std::vector<std::string> &labels);
+
+ // Some of the graph algorithms assume that the nodes array is sorted
+ // topologically (inputs are always before outputs), but some operations
+ // (like graph rewriting) can change that. This function restores that order.
+ void sort_all_nodes_topologically();
+
+ // Do the actual topological sort. <nodes> must be a connected, acyclic subgraph;
+ // links that go to nodes not in the set will be ignored.
+ std::vector<Node *> topological_sort(const std::vector<Node *> &nodes);
+
+ // Utility function used by topological_sort() to do a depth-first search.
+ // The reason why we store nodes left to visit instead of a more conventional
+ // list of nodes to visit is that we want to be able to limit ourselves to
+ // a subgraph instead of all nodes. The set thus serves a dual purpose.
+ void topological_sort_visit_node(Node *node, std::set<Node *> *nodes_left_to_visit, std::vector<Node *> *sorted_list);
+
+ // Used during finalize().
+ void find_color_spaces_for_inputs();
+ void propagate_alpha();
+ void propagate_gamma_and_color_space();
+ Node *find_output_node();
+
+ bool node_needs_colorspace_fix(Node *node);
+ void fix_internal_color_spaces();
+ void fix_output_color_space();
+
+ bool node_needs_alpha_fix(Node *node);
+ void fix_internal_alpha(unsigned step);
+ void fix_output_alpha();
+
+ bool node_needs_gamma_fix(Node *node);
+ void fix_internal_gamma_by_asking_inputs(unsigned step);
+ void fix_internal_gamma_by_inserting_nodes(unsigned step);
+ void fix_output_gamma();
+ void add_ycbcr_conversion_if_needed();
+ void add_dither_if_needed();
+ void add_dummy_effect_if_needed();
+
+ float aspect_nom, aspect_denom;
+ ImageFormat output_format;
+ OutputAlphaFormat output_alpha_format;
+
+ bool output_color_rgba;
+ int num_output_color_ycbcr; // Max 2.
+ YCbCrFormat output_ycbcr_format; // If num_output_color_ycbcr is > 0.
+ GLenum output_ycbcr_type; // If num_output_color_ycbcr is > 0.
+ YCbCrOutputSplitting output_ycbcr_splitting[2]; // If num_output_color_ycbcr is > N.
+
+ std::vector<Node *> nodes;
+ std::map<Effect *, Node *> node_map;
+ Effect *dither_effect;
+ Node *ycbcr_conversion_effect_node;
+
+ std::vector<Input *> inputs; // Also contained in nodes.
+ std::vector<Phase *> phases;
+
+ GLenum intermediate_format;
+ FramebufferTransformation intermediate_transformation;
+ unsigned num_dither_bits;
+ OutputOrigin output_origin;