]> git.sesse.net Git - movit/blob - effect_chain.h
Add edge information about odd things, such as bounces, resizes and non-standard...
[movit] / effect_chain.h
1 #ifndef _EFFECT_CHAIN_H
2 #define _EFFECT_CHAIN_H 1
3
4 #include <set>
5 #include <vector>
6
7 #include "effect.h"
8 #include "image_format.h"
9 #include "input.h"
10
11 class EffectChain;
12 class Phase;
13
14 // A node in the graph; basically an effect and some associated information.
15 class Node {
16 public:
17         Effect *effect;
18
19         // Edges in the graph (forward and backward).
20         std::vector<Node *> outgoing_links;
21         std::vector<Node *> incoming_links;
22
23 private:
24         // Identifier used to create unique variables in GLSL.
25         std::string effect_id;
26
27         // If output goes to RTT (otherwise, none of these are set).
28         // The Phsae pointer is a but ugly; we should probably fix so
29         // that Phase takes other phases as inputs, instead of Node.
30         GLuint output_texture;
31         unsigned output_texture_width, output_texture_height;
32         Phase *phase;
33
34         // Used during the building of the effect chain.
35         ColorSpace output_color_space;
36         GammaCurve output_gamma_curve;
37
38         friend class EffectChain;
39 };
40
41 // A rendering phase; a single GLSL program rendering a single quad.
42 struct Phase {
43         GLint glsl_program_num;
44         bool input_needs_mipmaps;
45
46         // Inputs are only inputs from other phases (ie., those that come from RTT);
47         // input textures are not counted here.
48         std::vector<Node *> inputs;
49
50         std::vector<Node *> effects;  // In order.
51         unsigned output_width, output_height;
52 };
53
54 class EffectChain {
55 public:
56         EffectChain(unsigned width, unsigned height);
57
58         // User API:
59         // input, effects, output, finalize need to come in that specific order.
60
61         // EffectChain takes ownership of the given input.
62         // input is returned back for convenience.
63         Input *add_input(Input *input);
64
65         // EffectChain takes ownership of the given effect.
66         // effect is returned back for convenience.
67         Effect *add_effect(Effect *effect) {
68                 return add_effect(effect, last_added_effect());
69         }
70         Effect *add_effect(Effect *effect, Effect *input) {
71                 std::vector<Effect *> inputs;
72                 inputs.push_back(input);
73                 return add_effect(effect, inputs);
74         }
75         Effect *add_effect(Effect *effect, Effect *input1, Effect *input2) {
76                 std::vector<Effect *> inputs;
77                 inputs.push_back(input1);
78                 inputs.push_back(input2);
79                 return add_effect(effect, inputs);
80         }
81         Effect *add_effect(Effect *effect, const std::vector<Effect *> &inputs);
82
83         // Similar to add_effect, but:
84         //
85         //  * Does not insert any normalizing effects.
86         //  * Does not ask the effect to insert itself, so it won't work
87         //    with meta-effects.
88         //
89         // We should really separate out these two “sides” of Effect in the
90         // type system soon.
91         void add_effect_raw(Effect *effect, const std::vector<Effect *> &inputs);
92
93         void add_output(const ImageFormat &format);
94         void finalize();
95
96         //void render(unsigned char *src, unsigned char *dst);
97         void render_to_screen();
98
99         Effect *last_added_effect() {
100                 if (nodes.empty()) {
101                         return NULL;
102                 } else {
103                         return nodes.back()->effect;
104                 }       
105         }
106
107 private:
108         // Determine the preferred output size of a given phase.
109         // Requires that all input phases (if any) already have output sizes set.
110         void find_output_size(Phase *phase);
111
112         void find_all_nonlinear_inputs(Node *effect,
113                                        std::vector<Node *> *nonlinear_inputs,
114                                        std::vector<Node *> *intermediates);
115         Node *normalize_to_linear_gamma(Node *input);
116         Node *normalize_to_srgb(Node *input);
117
118         // Create a GLSL program computing the given effects in order.
119         Phase *compile_glsl_program(const std::vector<Node *> &inputs,
120                                     const std::vector<Node *> &effects);
121
122         // Create all GLSL programs needed to compute the given effect, and all outputs
123         // that depends on it (whenever possible).
124         void construct_glsl_programs(Node *output);
125
126         // Output the current graph to the given file in a Graphviz-compatible format;
127         // only useful for debugging.
128         void output_dot(const char *filename);
129
130         unsigned width, height;
131         ImageFormat output_format;
132
133         std::vector<Node *> nodes;
134         std::map<Effect *, Node *> node_map;
135
136         std::vector<Input *> inputs;  // Also contained in nodes.
137
138         GLuint fbo;
139         std::vector<Phase *> phases;
140
141         GLenum format, bytes_per_pixel;
142         bool finalized;
143 };
144
145 #endif // !defined(_EFFECT_CHAIN_H)