6 #include "effect_util.h"
9 #include "resource_pool.h"
16 FFTInput::FFTInput(unsigned width, unsigned height)
20 convolve_width(width),
21 convolve_height(height),
24 register_int("fft_width", &fft_width);
25 register_int("fft_height", &fft_height);
26 register_uniform_sampler2d("tex", &uniform_tex);
31 if (texture_num != 0) {
32 resource_pool->release_2d_texture(texture_num);
36 void FFTInput::set_gl_state(GLuint glsl_program_num, const string& prefix, unsigned *sampler_num)
38 glActiveTexture(GL_TEXTURE0 + *sampler_num);
41 if (texture_num == 0) {
42 assert(pixel_data != NULL);
44 // Do the FFT. Our FFTs should typically be small enough and
45 // the data changed often enough that FFTW_ESTIMATE should be
46 // quite OK. Otherwise, we'd need to worry about caching these
47 // plans (possibly including FFTW wisdom).
48 fftw_complex *in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * fft_width * fft_height);
49 fftw_complex *out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * fft_width * fft_height);
50 fftw_plan p = fftw_plan_dft_2d(fft_height, fft_width, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
53 for (int i = 0; i < fft_height * fft_width; ++i) {
57 for (unsigned y = 0; y < convolve_height; ++y) {
58 for (unsigned x = 0; x < convolve_width; ++x) {
59 int i = y * fft_width + x;
60 in[i][0] = pixel_data[y * convolve_width + x];
68 fp16_int_t *kernel = new fp16_int_t[fft_width * fft_height * 2];
69 for (int i = 0; i < fft_width * fft_height; ++i) {
70 kernel[i * 2 + 0] = fp32_to_fp16(out[i][0]);
71 kernel[i * 2 + 1] = fp32_to_fp16(out[i][1]);
74 // (Re-)upload the texture.
75 texture_num = resource_pool->create_2d_texture(GL_RG16F, fft_width, fft_height);
76 glBindTexture(GL_TEXTURE_2D, texture_num);
78 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
80 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
82 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
84 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fft_width, fft_height, GL_RG, GL_HALF_FLOAT, kernel);
86 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
88 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
90 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
97 glBindTexture(GL_TEXTURE_2D, texture_num);
101 // Bind it to a sampler.
102 uniform_tex = *sampler_num;
106 string FFTInput::output_fragment_shader()
108 return string("#define FIXUP_SWAP_RB 0\n#define FIXUP_RED_TO_GRAYSCALE 0\n") +
109 read_file("flat_input.frag");
112 void FFTInput::invalidate_pixel_data()
114 if (texture_num != 0) {
115 resource_pool->release_2d_texture(texture_num);
120 bool FFTInput::set_int(const std::string& key, int value)
122 if (key == "needs_mipmaps") {
123 // We cannot supply mipmaps; it would not make any sense for FFT data.
126 if (key == "fft_width") {
127 if (value < int(convolve_width)) {
130 invalidate_pixel_data();
132 if (key == "fft_height") {
133 if (value < int(convolve_height)) {
136 invalidate_pixel_data();
138 return Effect::set_int(key, value);