]> git.sesse.net Git - movit/blob - effect_chain.h
f521e9c40c083667d58e1aa795a615dc841c4700
[movit] / effect_chain.h
1 #ifndef _EFFECT_CHAIN_H
2 #define _EFFECT_CHAIN_H 1
3
4 #include <vector>
5
6 #include "effect.h"
7 #include "effect_id.h"
8
9 enum PixelFormat { FORMAT_RGB, FORMAT_RGBA, FORMAT_BGR, FORMAT_BGRA };
10
11 enum ColorSpace {
12         COLORSPACE_sRGB = 0,
13         COLORSPACE_REC_709 = 0,  // Same as sRGB.
14         COLORSPACE_REC_601_525 = 1,
15         COLORSPACE_REC_601_625 = 2,
16 };
17
18 enum GammaCurve {
19         GAMMA_LINEAR = 0,
20         GAMMA_sRGB = 1,
21         GAMMA_REC_601 = 2,
22         GAMMA_REC_709 = 2,  // Same as Rec. 601.
23 };
24
25 struct ImageFormat {
26         PixelFormat pixel_format;
27         ColorSpace color_space;
28         GammaCurve gamma_curve;
29 };
30
31 class EffectChain {
32 public:
33         EffectChain(unsigned width, unsigned height);
34
35         // User API:
36         // input, effects, output, finalize need to come in that specific order.
37
38         void add_input(const ImageFormat &format);
39
40         // The returned pointer is owned by EffectChain.
41         Effect *add_effect(EffectId effect) {
42                 return add_effect(effect, get_last_added_effect());
43         }
44         Effect *add_effect(EffectId effect, Effect *input) {
45                 std::vector<Effect *> inputs;
46                 inputs.push_back(input);
47                 return add_effect(effect, inputs);
48         }
49         Effect *add_effect(EffectId effect, Effect *input1, Effect *input2) {
50                 std::vector<Effect *> inputs;
51                 inputs.push_back(input1);
52                 inputs.push_back(input2);
53                 return add_effect(effect, inputs);
54         }
55         Effect *add_effect(EffectId effect, const std::vector<Effect *> &inputs);
56
57         // Similar to add_effect, but:
58         //
59         //  * Does not insert any normalizing effects.
60         //  * Does not ask the effect to insert itself, so it won't work
61         //    with meta-effects.
62         //
63         // We should really separate out these two “sides” of Effect in the
64         // type system soon.
65         void add_effect_raw(Effect *effect, const std::vector<Effect *> &inputs);
66
67         void add_output(const ImageFormat &format);
68         void finalize();
69
70         //void render(unsigned char *src, unsigned char *dst);
71         void render_to_screen(unsigned char *src);
72
73         Effect *get_last_added_effect() { 
74                 return last_added_effect;
75         }
76
77 private:
78         struct Phase {
79                 GLint glsl_program_num;
80                 bool input_needs_mipmaps;
81                 unsigned start, end;
82         };
83
84         Effect *normalize_to_linear_gamma(Effect *input);
85         Effect *normalize_to_srgb(Effect *input);
86
87         // Create a GLSL program computing effects [start, end>.
88         Phase compile_glsl_program(unsigned start_index, unsigned end_index);
89
90         unsigned width, height;
91         ImageFormat input_format, output_format;
92         std::vector<Effect *> effects;
93         std::multimap<Effect *, Effect *> outgoing_links;
94         std::multimap<Effect *, Effect *> incoming_links;
95         Effect *last_added_effect;
96
97         GLuint source_image_num;
98         bool use_srgb_texture_format;
99
100         GLuint fbo;
101         GLuint temp_textures[2];
102
103         std::vector<Phase> phases;
104
105         GLenum format, bytes_per_pixel;
106         bool finalized;
107
108         // Used during the building of the effect chain.
109         std::map<Effect *, ColorSpace> output_color_space;
110         std::map<Effect *, GammaCurve> output_gamma_curve;      
111 };
112
113
114 #endif // !defined(_EFFECT_CHAIN_H)