Add an FFT convolution effect.
[movit] / fft_input.h
1 #ifndef _MOVIT_FFT_INPUT_H
2 #define _MOVIT_FFT_INPUT_H 1
3
4 // FFTInput is used by FFTConvolutionEffect to send in the FFTed version of a
5 // mostly static, one-channel data set, typically the convolution kernel
6 // with some zero padding.
7 //
8 // Since the kernel is typically small and unlikely to change often,
9 // it will be faster to FFT it once on the CPU (using the excellent FFTW3
10 // library) and keep it in a texture, rather than FFT-ing it over and over on
11 // the GPU. (We do not currently support caching Movit intermediates between
12 // frames.) As an extra bonus, we can then do it in double precision and round
13 // precisely to fp16 afterwards.
14 //
15 // This class is tested as part of by FFTConvolutionEffectTest.
16
17 #include <GL/glew.h>
18 #include <assert.h>
19 #include <string>
20
21 #include "effect.h"
22 #include "effect_chain.h"
23 #include "image_format.h"
24 #include "input.h"
25
26 namespace movit {
27
28 class ResourcePool;
29
30 class FFTInput : public Input {
31 public:
32         FFTInput(unsigned width, unsigned height);
33         ~FFTInput();
34
35         virtual std::string effect_type_id() const { return "FFTInput"; }
36         std::string output_fragment_shader();
37
38         // FFTs the data and uploads the texture if it has changed since last time.
39         void set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num);
40
41         unsigned get_width() const { return fft_width; }
42         unsigned get_height() const { return fft_height; }
43
44         // Strictly speaking, FFT data doesn't have any colorspace or gamma;
45         // these values are the Movit standards for “do nothing”.
46         Colorspace get_color_space() const { return COLORSPACE_sRGB; }
47         GammaCurve get_gamma_curve() const { return GAMMA_LINEAR; }
48         virtual AlphaHandling alpha_handling() const { return INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA; }
49         virtual bool is_single_texture() const { return true; }
50         virtual bool can_output_linear_gamma() const { return true; }
51
52         // Tells the input where to fetch the actual pixel data. Note that if you change
53         // this data, you must either call set_pixel_data() again (using the same pointer
54         // is fine), or invalidate_pixel_data(). Otherwise, the FFT won't be recalculated,
55         // and the texture won't be re-uploaded on subsequent frames.
56         void set_pixel_data(const float *pixel_data)
57         {
58                 this->pixel_data = pixel_data;
59                 invalidate_pixel_data();
60         }
61
62         void invalidate_pixel_data();
63
64         virtual void inform_added(EffectChain *chain)
65         {
66                 resource_pool = chain->get_resource_pool();
67         }
68
69         virtual bool set_int(const std::string& key, int value);
70
71 private:
72         GLuint texture_num;
73         int fft_width, fft_height;
74         unsigned convolve_width, convolve_height;
75         const float *pixel_data;
76         ResourcePool *resource_pool;
77 };
78
79 }  // namespace movit
80
81 #endif // !defined(_MOVIT_FFT_INPUT_H)