X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=effect_chain.h;h=6698c6f70e6b7cf5ee0752fce39840613295810f;hp=989a0199e460689110a709c5d508284bc9e35f4a;hb=9a00101dbb6f98d21c6b8ce4d33200af840ea908;hpb=b8b7f286300668679e61a25beb48f353b5a83f43 diff --git a/effect_chain.h b/effect_chain.h index 989a019..6698c6f 100644 --- a/effect_chain.h +++ b/effect_chain.h @@ -1,15 +1,33 @@ -#ifndef _EFFECT_CHAIN_H -#define _EFFECT_CHAIN_H 1 +#ifndef _MOVIT_EFFECT_CHAIN_H +#define _MOVIT_EFFECT_CHAIN_H 1 +#include +#include +#include #include +#include #include -#include "effect.h" #include "image_format.h" -#include "input.h" -class EffectChain; -class Phase; +class Effect; +class Input; +struct Phase; + +// For internal use within Node. +enum AlphaType { + ALPHA_INVALID = -1, + ALPHA_BLANK, + ALPHA_PREMULTIPLIED, + ALPHA_POSTMULTIPLIED, +}; + +// Whether you want pre- or postmultiplied alpha in the output +// (see effect.h for a discussion of pre- versus postmultiplied alpha). +enum OutputAlphaFormat { + OUTPUT_ALPHA_FORMAT_PREMULTIPLIED, + OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED, +}; // A node in the graph; basically an effect and some associated information. class Node { @@ -40,15 +58,16 @@ private: Phase *phase; // Used during the building of the effect chain. - ColorSpace output_color_space; + Colorspace output_color_space; GammaCurve output_gamma_curve; + AlphaType output_alpha_type; friend class EffectChain; }; // A rendering phase; a single GLSL program rendering a single quad. struct Phase { - GLint glsl_program_num; + GLint glsl_program_num, vertex_shader, fragment_shader; bool input_needs_mipmaps; // Inputs are only inputs from other phases (ie., those that come from RTT); @@ -56,12 +75,13 @@ struct Phase { std::vector inputs; std::vector effects; // In order. - unsigned output_width, output_height; + unsigned output_width, output_height, virtual_output_width, virtual_output_height; }; class EffectChain { public: EffectChain(float aspect_nom, float aspect_denom); // E.g., 16.0f, 9.0f for 16:9. + ~EffectChain(); // User API: // input, effects, output, finalize need to come in that specific order. @@ -88,9 +108,19 @@ public: } Effect *add_effect(Effect *effect, const std::vector &inputs); - void add_output(const ImageFormat &format); + void add_output(const ImageFormat &format, OutputAlphaFormat alpha_format); + + // Set number of output bits, to scale the dither. + // 8 is the right value for most outputs. + // The default, 0, is a special value that means no dither. + void set_dither_bits(unsigned num_bits) + { + this->num_dither_bits = num_bits; + } + void finalize(); + //void render(unsigned char *src, unsigned char *dst); void render_to_screen() { @@ -121,9 +151,10 @@ public: void insert_node_between(Node *sender, Node *middle, Node *receiver); private: - // Fits a rectangle of the given size to the current aspect ratio - // (aspect_nom/aspect_denom) and returns the new width and height. - unsigned fit_rectangle_to_aspect(unsigned width, unsigned height); + // Make sure the output rectangle is at least large enough to hold + // the given input rectangle in both dimensions, and is of the + // current aspect ratio (aspect_nom/aspect_denom). + void size_rectangle_to_fit(unsigned width, unsigned height, unsigned *output_width, unsigned *output_height); // Compute the input sizes for all inputs for all effects in a given phase, // and inform the effects about the results. @@ -148,14 +179,30 @@ private: // 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 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 &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_nodes_topologically(); - void topological_sort_visit_node(Node *node, std::set *visited_nodes, std::vector *sorted_list); + void sort_all_nodes_topologically(); + + // Do the actual topological sort. must be a connected, acyclic subgraph; + // links that go to nodes not in the set will be ignored. + std::vector topological_sort(const std::vector &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 *nodes_left_to_visit, std::vector *sorted_list); // Used during finalize(). + void find_color_spaces_for_inputs(); + void propagate_alpha(); void propagate_gamma_and_color_space(); Node *find_output_node(); @@ -163,24 +210,29 @@ private: 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_dither_if_needed(); float aspect_nom, aspect_denom; ImageFormat output_format; + OutputAlphaFormat output_alpha_format; std::vector nodes; std::map node_map; + Effect *dither_effect; std::vector inputs; // Also contained in nodes. - - GLuint fbo; std::vector phases; - GLenum format, bytes_per_pixel; + unsigned num_dither_bits; bool finalized; }; -#endif // !defined(_EFFECT_CHAIN_H) +#endif // !defined(_MOVIT_EFFECT_CHAIN_H)