]> git.sesse.net Git - movit/commitdiff
Rework uniform setting.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 13 Sep 2015 15:44:58 +0000 (17:44 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 13 Sep 2015 15:52:47 +0000 (17:52 +0200)
One would think something as mundane as setting a few uniforms wouldn't
really mean much for performance, but seemingly this is not always so --
I had a real-world shader that counted no less than 55 uniforms.
Of course, not all of these were actually used, but we still have to go
through looking up the name etc. for every single one, every single frame.

Thus, we introduce a new way of dealing with uniforms: Register them before
finalization time, and then EffectChain can store their numbers once and
for all, instead of this repeated lookup. The system is also set up such
that we can go to uniform buffer objects (UBOs) in the very near future.

It's a bit unfortunate that uniform declaration now is removed from the
.frag files, where it sat very nicely, but the alternative would be to
try to parse GLSL, which I'm a bit wary at right now. All effects are
converted, leaving the set_uniform_* functions without any users, but
they are kept around for now in case external effects want them.

This seems to bring 1–2% speedup for my use case; hopefully UBOs will
bring a tiny bit more.

59 files changed:
blur_effect.cpp
blur_effect.frag
blur_effect.h
complex_modulate_effect.cpp
complex_modulate_effect.frag
complex_modulate_effect.h
deconvolution_sharpen_effect.cpp
deconvolution_sharpen_effect.frag
deconvolution_sharpen_effect.h
dither_effect.cpp
dither_effect.frag
dither_effect.h
effect.cpp
effect.h
effect_chain.cpp
effect_chain.h
effect_util.h
fft_input.cpp
fft_input.h
fft_pass_effect.cpp
fft_pass_effect.frag
fft_pass_effect.h
flat_input.cpp
flat_input.frag
flat_input.h
gamma_compression_effect.cpp
gamma_compression_effect.frag
gamma_compression_effect.h
gamma_expansion_effect.cpp
gamma_expansion_effect.frag
gamma_expansion_effect.h
lift_gamma_gain_effect.cpp
lift_gamma_gain_effect.frag
lift_gamma_gain_effect.h
luma_mix_effect.cpp
luma_mix_effect.frag
luma_mix_effect.h
padding_effect.cpp
padding_effect.frag
padding_effect.h
resample_effect.cpp
resample_effect.frag
resample_effect.h
slice_effect.cpp
slice_effect.frag
slice_effect.h
version.h
vignette_effect.cpp
vignette_effect.frag
vignette_effect.h
white_balance_effect.cpp
white_balance_effect.frag
white_balance_effect.h
ycbcr_422interleaved_input.cpp
ycbcr_422interleaved_input.frag
ycbcr_422interleaved_input.h
ycbcr_input.cpp
ycbcr_input.frag
ycbcr_input.h

index 29e46b0583890f1e1f2c4b65ec130ec086f38bb9..2084768bc54393985bbfccdf48f0be1f10741f08 100644 (file)
@@ -108,8 +108,9 @@ SingleBlurPassEffect::SingleBlurPassEffect(BlurEffect *parent)
          num_taps(16),
          radius(3.0f),
          direction(HORIZONTAL),
          num_taps(16),
          radius(3.0f),
          direction(HORIZONTAL),
-         width(1280),
-         height(720)
+         width(1280),
+         height(720),
+         uniform_samples(NULL)
 {
        register_float("radius", &radius);
        register_int("direction", (int *)&direction);
 {
        register_float("radius", &radius);
        register_int("direction", (int *)&direction);
@@ -120,11 +121,18 @@ SingleBlurPassEffect::SingleBlurPassEffect(BlurEffect *parent)
        register_int("num_taps", &num_taps);
 }
 
        register_int("num_taps", &num_taps);
 }
 
+SingleBlurPassEffect::~SingleBlurPassEffect()
+{
+       delete[] uniform_samples;
+}
+
 string SingleBlurPassEffect::output_fragment_shader()
 {
        char buf[256];
        sprintf(buf, "#define DIRECTION_VERTICAL %d\n#define NUM_TAPS %d\n",
                (direction == VERTICAL), num_taps);
 string SingleBlurPassEffect::output_fragment_shader()
 {
        char buf[256];
        sprintf(buf, "#define DIRECTION_VERTICAL %d\n#define NUM_TAPS %d\n",
                (direction == VERTICAL), num_taps);
+       uniform_samples = new float[2 * (num_taps / 2 + 1)];
+       register_uniform_vec2_array("samples", uniform_samples, num_taps / 2 + 1);
        return buf + read_file("blur_effect.frag");
 }
 
        return buf + read_file("blur_effect.frag");
 }
 
@@ -176,11 +184,10 @@ void SingleBlurPassEffect::set_gl_state(GLuint glsl_program_num, const string &p
        //
        // We pack the parameters into a float4: The relative sample coordinates
        // in (x,y), and the weight in z. w is unused.
        //
        // We pack the parameters into a float4: The relative sample coordinates
        // in (x,y), and the weight in z. w is unused.
-       float* samples = new float[2 * (num_taps / 2 + 1)];
 
        // Center sample.
 
        // Center sample.
-       samples[2 * 0 + 0] = 0.0f;
-       samples[2 * 0 + 1] = weight[0];
+       uniform_samples[2 * 0 + 0] = 0.0f;
+       uniform_samples[2 * 0 + 1] = weight[0];
 
        // All other samples.
        for (int i = 1; i < num_taps / 2 + 1; ++i) {
 
        // All other samples.
        for (int i = 1; i < num_taps / 2 + 1; ++i) {
@@ -201,14 +208,11 @@ void SingleBlurPassEffect::set_gl_state(GLuint glsl_program_num, const string &p
                float pos, total_weight;
                combine_two_samples(w1, w2, pos1, pos2, size, &pos, &total_weight, NULL);
 
                float pos, total_weight;
                combine_two_samples(w1, w2, pos1, pos2, size, &pos, &total_weight, NULL);
 
-               samples[2 * i + 0] = pos;
-               samples[2 * i + 1] = total_weight;
+               uniform_samples[2 * i + 0] = pos;
+               uniform_samples[2 * i + 1] = total_weight;
        }
 
        }
 
-       set_uniform_vec2_array(glsl_program_num, prefix, "samples", samples, num_taps / 2 + 1);
-
        delete[] weight;
        delete[] weight;
-       delete[] samples;
 }
 
 void SingleBlurPassEffect::clear_gl_state()
 }
 
 void SingleBlurPassEffect::clear_gl_state()
index 8a7a4a6f81af70430508bd665439296bc7d3435d..f8497b3fb19d45ca439af30177f3272b910b7841 100644 (file)
@@ -2,7 +2,8 @@
 // DIRECTION_VERTICAL will be #defined to 1 if we are doing a vertical blur,
 // 0 otherwise.
 
 // DIRECTION_VERTICAL will be #defined to 1 if we are doing a vertical blur,
 // 0 otherwise.
 
-uniform vec2 PREFIX(samples)[NUM_TAPS / 2 + 1];
+// Implicit uniforms:
+// uniform vec2 PREFIX(samples)[NUM_TAPS / 2 + 1];
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 sum = vec4(PREFIX(samples)[0].y) * INPUT(tc);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 sum = vec4(PREFIX(samples)[0].y) * INPUT(tc);
index eb35790573c0bac7b6f37030a68c73b39276f06e..8ad3da92dc27bb0f164184b04c042de569714038 100644 (file)
@@ -66,6 +66,7 @@ public:
        // If parent is non-NULL, calls to inform_input_size will be forwarded
        // so that it can make reasonable decisions for both blur passes.
        SingleBlurPassEffect(BlurEffect *parent);
        // If parent is non-NULL, calls to inform_input_size will be forwarded
        // so that it can make reasonable decisions for both blur passes.
        SingleBlurPassEffect(BlurEffect *parent);
+       virtual ~SingleBlurPassEffect();
        virtual std::string effect_type_id() const { return "SingleBlurPassEffect"; }
 
        std::string output_fragment_shader();
        virtual std::string effect_type_id() const { return "SingleBlurPassEffect"; }
 
        std::string output_fragment_shader();
@@ -102,6 +103,7 @@ private:
        float radius;
        Direction direction;
        int width, height, virtual_width, virtual_height;
        float radius;
        Direction direction;
        int width, height, virtual_width, virtual_height;
+       float *uniform_samples;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index 9483f6b1f0f09202b54d6c8d8e54cf48f67e274c..6b508231c11aa6e0e6921b3e2fa514f7f230aaab 100644 (file)
@@ -14,6 +14,7 @@ ComplexModulateEffect::ComplexModulateEffect()
 {
        register_int("num_repeats_x", &num_repeats_x);
        register_int("num_repeats_y", &num_repeats_y);
 {
        register_int("num_repeats_x", &num_repeats_x);
        register_int("num_repeats_y", &num_repeats_y);
+       register_vec2("num_repeats", uniform_num_repeats);
 }
 
 string ComplexModulateEffect::output_fragment_shader()
 }
 
 string ComplexModulateEffect::output_fragment_shader()
@@ -25,8 +26,8 @@ void ComplexModulateEffect::set_gl_state(GLuint glsl_program_num, const string &
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
 
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
 
-       float num_repeats[] = { float(num_repeats_x), float(num_repeats_y) };
-       set_uniform_vec2(glsl_program_num, prefix, "num_repeats", num_repeats);
+       uniform_num_repeats[0] = float(num_repeats_x);
+       uniform_num_repeats[1] = float(num_repeats_y);
 
        // Set the secondary input to repeat (and nearest while we're at it).
        Node *self = chain->find_node_for_effect(this);
 
        // Set the secondary input to repeat (and nearest while we're at it).
        Node *self = chain->find_node_for_effect(this);
index 46de5da8ca96ef7c62146dd4b11bff2e6d5710d2..d07a7291c27a02547a42141006911b5f9bb0aa66 100644 (file)
@@ -1,4 +1,5 @@
-uniform vec2 PREFIX(num_repeats);
+// Implicit uniforms:
+// uniform vec2 PREFIX(num_repeats);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 pixel = INPUT1(tc);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 pixel = INPUT1(tc);
index e2bf50d5851fb0b64f5c71a8f13bfc9fe3e8df79..335c90010754cbe197b5bf9fe58c33a2e2b1f553 100644 (file)
@@ -55,6 +55,7 @@ private:
        EffectChain *chain;
        int primary_input_width, primary_input_height;
        int num_repeats_x, num_repeats_y;
        EffectChain *chain;
        int primary_input_width, primary_input_height;
        int num_repeats_x, num_repeats_y;
+       float uniform_num_repeats[2];
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index c4ad5cd2cd699b65c223d505dc0fd88932b4e3e1..2db15dc1bc98af9b3e340551028b99b29574321e 100644 (file)
@@ -31,7 +31,8 @@ DeconvolutionSharpenEffect::DeconvolutionSharpenEffect()
          last_circle_radius(-1.0f),
          last_gaussian_radius(-1.0f),
          last_correlation(-1.0f),
          last_circle_radius(-1.0f),
          last_gaussian_radius(-1.0f),
          last_correlation(-1.0f),
-         last_noise(-1.0f)
+         last_noise(-1.0f),
+         uniform_samples(NULL)
 {
        register_int("matrix_size", &R);
        register_float("circle_radius", &circle_radius);
 {
        register_int("matrix_size", &R);
        register_float("circle_radius", &circle_radius);
@@ -40,6 +41,11 @@ DeconvolutionSharpenEffect::DeconvolutionSharpenEffect()
        register_float("noise", &noise);
 }
 
        register_float("noise", &noise);
 }
 
+DeconvolutionSharpenEffect::~DeconvolutionSharpenEffect()
+{
+       delete[] uniform_samples;
+}
+
 string DeconvolutionSharpenEffect::output_fragment_shader()
 {
        char buf[256];
 string DeconvolutionSharpenEffect::output_fragment_shader()
 {
        char buf[256];
@@ -48,6 +54,9 @@ string DeconvolutionSharpenEffect::output_fragment_shader()
        assert(R >= 1);
        assert(R <= 25);  // Same limit as Refocus.
 
        assert(R >= 1);
        assert(R <= 25);  // Same limit as Refocus.
 
+       uniform_samples = new float[4 * (R + 1) * (R + 1)];
+       register_uniform_vec4_array("samples", uniform_samples, (R + 1) * (R + 1));
+
        last_R = R;
        return buf + read_file("deconvolution_sharpen_effect.frag");
 }
        last_R = R;
        return buf + read_file("deconvolution_sharpen_effect.frag");
 }
@@ -433,18 +442,15 @@ void DeconvolutionSharpenEffect::set_gl_state(GLuint glsl_program_num, const str
                update_deconvolution_kernel();
        }
        // Now encode it as uniforms, and pass it on to the shader.
                update_deconvolution_kernel();
        }
        // Now encode it as uniforms, and pass it on to the shader.
-       float samples[4 * (R + 1) * (R + 1)];
        for (int y = 0; y <= R; ++y) {
                for (int x = 0; x <= R; ++x) {
                        int i = y * (R + 1) + x;
        for (int y = 0; y <= R; ++y) {
                for (int x = 0; x <= R; ++x) {
                        int i = y * (R + 1) + x;
-                       samples[i * 4 + 0] = x / float(width);
-                       samples[i * 4 + 1] = y / float(height);
-                       samples[i * 4 + 2] = g(y, x);
-                       samples[i * 4 + 3] = 0.0f;
+                       uniform_samples[i * 4 + 0] = x / float(width);
+                       uniform_samples[i * 4 + 1] = y / float(height);
+                       uniform_samples[i * 4 + 2] = g(y, x);
+                       uniform_samples[i * 4 + 3] = 0.0f;
                }
        }
                }
        }
-
-       set_uniform_vec4_array(glsl_program_num, prefix, "samples", samples, (R + 1) * (R + 1));
 }
 
 }  // namespace movit
 }
 
 }  // namespace movit
index 75f249a2e896bb444b031fc880de205885eb0506..e9c560d543482b5276584b4426a567b33fc2a257 100644 (file)
@@ -1,4 +1,5 @@
-uniform vec4 PREFIX(samples)[(R + 1) * (R + 1)];
+// Implicit uniforms:
+// uniform vec4 PREFIX(samples)[(R + 1) * (R + 1)];
 
 vec4 FUNCNAME(vec2 tc) {
        // The full matrix has five different symmetry cases, that look like this:
 
 vec4 FUNCNAME(vec2 tc) {
        // The full matrix has five different symmetry cases, that look like this:
index 1f6807172d85444b6f77c4a93e89e0a0ea6144a3..c2ccbcb608ccd7916d7bf3763712bef2b06bc348 100644 (file)
@@ -30,6 +30,7 @@ namespace movit {
 class DeconvolutionSharpenEffect : public Effect {
 public:
        DeconvolutionSharpenEffect();
 class DeconvolutionSharpenEffect : public Effect {
 public:
        DeconvolutionSharpenEffect();
+       virtual ~DeconvolutionSharpenEffect();
        virtual std::string effect_type_id() const { return "DeconvolutionSharpenEffect"; }
        std::string output_fragment_shader();
 
        virtual std::string effect_type_id() const { return "DeconvolutionSharpenEffect"; }
        std::string output_fragment_shader();
 
@@ -66,6 +67,8 @@ private:
        Eigen::MatrixXf g;
        int last_R;
        float last_circle_radius, last_gaussian_radius, last_correlation, last_noise;
        Eigen::MatrixXf g;
        int last_R;
        float last_circle_radius, last_gaussian_radius, last_correlation, last_noise;
+
+       float *uniform_samples;
        
        void update_deconvolution_kernel();
 };
        
        void update_deconvolution_kernel();
 };
index 41ea9b432b80d3c94bf093a184f2632721dcbbcd..574d70a5cf82bcfc1adac94b8e8a50a5a00d1668 100644 (file)
@@ -35,6 +35,10 @@ DitherEffect::DitherEffect()
        register_int("output_width", &width);
        register_int("output_height", &height);
        register_int("num_bits", &num_bits);
        register_int("output_width", &width);
        register_int("output_height", &height);
        register_int("num_bits", &num_bits);
+       register_uniform_float("round_fac", &uniform_round_fac);
+       register_uniform_float("inv_round_fac", &uniform_inv_round_fac);
+       register_uniform_vec2("tc_scale", uniform_tc_scale);
+       register_uniform_sampler2d("dither_tex", &uniform_dither_tex);
 
        glGenTextures(1, &texnum);
 }
 
        glGenTextures(1, &texnum);
 }
@@ -110,19 +114,19 @@ void DitherEffect::set_gl_state(GLuint glsl_program_num, const string &prefix, u
        glBindTexture(GL_TEXTURE_2D, texnum);
        check_error();
 
        glBindTexture(GL_TEXTURE_2D, texnum);
        check_error();
 
-       set_uniform_int(glsl_program_num, prefix, "dither_tex", *sampler_num);
+       uniform_dither_tex = *sampler_num;
        ++*sampler_num;
 
        // In theory, we should adjust for the texel centers that have moved here as well,
        // but since we use GL_NEAREST and we don't really care a lot what texel we sample,
        // we don't have to worry about it.     
        ++*sampler_num;
 
        // In theory, we should adjust for the texel centers that have moved here as well,
        // but since we use GL_NEAREST and we don't really care a lot what texel we sample,
        // we don't have to worry about it.     
-       float tc_scale[] = { float(width) / float(texture_width), float(height) / float(texture_height) };
-       set_uniform_vec2(glsl_program_num, prefix, "tc_scale", tc_scale);
+       uniform_tc_scale[0] = float(width) / float(texture_width);
+       uniform_tc_scale[1] = float(height) / float(texture_height);
 
        // Used if the shader needs to do explicit rounding.
        int round_fac = (1 << num_bits) - 1;
 
        // Used if the shader needs to do explicit rounding.
        int round_fac = (1 << num_bits) - 1;
-       set_uniform_float(glsl_program_num, prefix, "round_fac", round_fac);
-       set_uniform_float(glsl_program_num, prefix, "inv_round_fac", 1.0f / round_fac);
+       uniform_round_fac = round_fac;
+       uniform_inv_round_fac = 1.0f / round_fac;
 }
 
 }  // namespace movit
 }
 
 }  // namespace movit
index 3b6b892d7606937867b4ab0c2b749926034d9f29..b12ecd7cedfd267d8a9935a2372303c9f62e3be9 100644 (file)
@@ -1,6 +1,7 @@
-uniform sampler2D PREFIX(dither_tex);
-uniform vec2 PREFIX(tc_scale);
-uniform float PREFIX(round_fac), PREFIX(inv_round_fac);
+// Implicit uniforms:
+// uniform sampler2D PREFIX(dither_tex);
+// uniform vec2 PREFIX(tc_scale);
+// uniform float PREFIX(round_fac), PREFIX(inv_round_fac);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 result = INPUT(tc);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 result = INPUT(tc);
index e5805862011c94b36c608fe804cb0f2a6a121bca..921a1ef5e1130ca6184e401fe06e8b267b4c67e2 100644 (file)
@@ -78,6 +78,9 @@ private:
        int texture_width, texture_height;
 
        GLuint texnum;
        int texture_width, texture_height;
 
        GLuint texnum;
+       float uniform_round_fac, uniform_inv_round_fac;
+       float uniform_tc_scale[2];
+       GLint uniform_dither_tex;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index fb66514a290d1cb780c6a87b2fae4b97a8d9627f..df73eeae2078b7834c7798a1afa9d30b83a26c4b 100644 (file)
@@ -7,6 +7,7 @@
 #include "effect.h"
 #include "effect_util.h"
 
 #include "effect.h"
 #include "effect_util.h"
 
+using namespace Eigen;
 using namespace std;
 
 namespace movit {
 using namespace std;
 
 namespace movit {
@@ -66,86 +67,132 @@ void Effect::register_float(const string &key, float *value)
 {
        assert(params_float.count(key) == 0);
        params_float[key] = value;
 {
        assert(params_float.count(key) == 0);
        params_float[key] = value;
+       register_uniform_float(key, value);
 }
 
 void Effect::register_vec2(const string &key, float *values)
 {
        assert(params_vec2.count(key) == 0);
        params_vec2[key] = values;
 }
 
 void Effect::register_vec2(const string &key, float *values)
 {
        assert(params_vec2.count(key) == 0);
        params_vec2[key] = values;
+       register_uniform_vec2(key, values);
 }
 
 void Effect::register_vec3(const string &key, float *values)
 {
        assert(params_vec3.count(key) == 0);
        params_vec3[key] = values;
 }
 
 void Effect::register_vec3(const string &key, float *values)
 {
        assert(params_vec3.count(key) == 0);
        params_vec3[key] = values;
+       register_uniform_vec3(key, values);
 }
 
 void Effect::register_vec4(const string &key, float *values)
 {
        assert(params_vec4.count(key) == 0);
        params_vec4[key] = values;
 }
 
 void Effect::register_vec4(const string &key, float *values)
 {
        assert(params_vec4.count(key) == 0);
        params_vec4[key] = values;
+       register_uniform_vec4(key, values);
 }
 
 }
 
-// Output convenience uniforms for each parameter.
-// These will be filled in per-frame.
-string Effect::output_convenience_uniforms() const
+void Effect::set_gl_state(GLuint glsl_program_num, const string& prefix, unsigned *sampler_num) {}
+
+void Effect::clear_gl_state() {}
+
+void Effect::register_uniform_bool(const std::string &key, const bool *value)
 {
 {
-       string output = "";
-       for (map<string, float*>::const_iterator it = params_float.begin();
-            it != params_float.end();
-            ++it) {
-               char buf[256];
-               sprintf(buf, "uniform float PREFIX(%s);\n", it->first.c_str());
-               output.append(buf);
-       }
-       for (map<string, float*>::const_iterator it = params_vec2.begin();
-            it != params_vec2.end();
-            ++it) {
-               char buf[256];
-               sprintf(buf, "uniform vec2 PREFIX(%s);\n", it->first.c_str());
-               output.append(buf);
-       }
-       for (map<string, float*>::const_iterator it = params_vec3.begin();
-            it != params_vec3.end();
-            ++it) {
-               char buf[256];
-               sprintf(buf, "uniform vec3 PREFIX(%s);\n", it->first.c_str());
-               output.append(buf);
-       }
-       for (map<string, float*>::const_iterator it = params_vec4.begin();
-            it != params_vec4.end();
-            ++it) {
-               char buf[256];
-               sprintf(buf, "uniform vec4 PREFIX(%s);\n", it->first.c_str());
-               output.append(buf);
-       }
-       return output;
+       Uniform<bool> uniform;
+       uniform.name = key;
+       uniform.value = value;
+       uniform.num_values = 1;
+       uniform.location = -1;
+       uniforms_bool.push_back(uniform);
 }
 
 }
 
-void Effect::set_gl_state(GLuint glsl_program_num, const string& prefix, unsigned *sampler_num)
+void Effect::register_uniform_int(const std::string &key, const int *value)
 {
 {
-       for (map<string, float*>::const_iterator it = params_float.begin();
-            it != params_float.end();
-            ++it) {
-               set_uniform_float(glsl_program_num, prefix, it->first, *it->second);
-       }
-       for (map<string, float*>::const_iterator it = params_vec2.begin();
-            it != params_vec2.end();
-            ++it) {
-               set_uniform_vec2(glsl_program_num, prefix, it->first, it->second);
-       }
-       for (map<string, float*>::const_iterator it = params_vec3.begin();
-            it != params_vec3.end();
-            ++it) {
-               set_uniform_vec3(glsl_program_num, prefix, it->first, it->second);
-       }
-       for (map<string, float*>::const_iterator it = params_vec4.begin();
-            it != params_vec4.end();
-            ++it) {
-               set_uniform_vec4(glsl_program_num, prefix, it->first, it->second);
-       }
+       Uniform<int> uniform;
+       uniform.name = key;
+       uniform.value = value;
+       uniform.num_values = 1;
+       uniform.location = -1;
+       uniforms_int.push_back(uniform);
 }
 
 }
 
-void Effect::clear_gl_state() {}
+void Effect::register_uniform_sampler2d(const std::string &key, const GLint *value)
+{
+       Uniform<int> uniform;
+       uniform.name = key;
+       uniform.value = value;
+       uniform.num_values = 1;
+       uniform.location = -1;
+       uniforms_sampler2d.push_back(uniform);
+}
+
+void Effect::register_uniform_float(const std::string &key, const float *value)
+{
+       Uniform<float> uniform;
+       uniform.name = key;
+       uniform.value = value;
+       uniform.num_values = 1;
+       uniform.location = -1;
+       uniforms_float.push_back(uniform);
+}
+
+void Effect::register_uniform_vec2(const std::string &key, const float *values)
+{
+       Uniform<float> uniform;
+       uniform.name = key;
+       uniform.value = values;
+       uniform.num_values = 1;
+       uniform.location = -1;
+       uniforms_vec2.push_back(uniform);
+}
+
+void Effect::register_uniform_vec3(const std::string &key, const float *values)
+{
+       Uniform<float> uniform;
+       uniform.name = key;
+       uniform.value = values;
+       uniform.num_values = 1;
+       uniform.location = -1;
+       uniforms_vec3.push_back(uniform);
+}
+
+void Effect::register_uniform_vec4(const std::string &key, const float *values)
+{
+       Uniform<float> uniform;
+       uniform.name = key;
+       uniform.value = values;
+       uniform.num_values = 1;
+       uniform.location = -1;
+       uniforms_vec4.push_back(uniform);
+}
+
+void Effect::register_uniform_vec2_array(const std::string &key, const float *values, size_t num_values)
+{
+       Uniform<float> uniform;
+       uniform.name = key;
+       uniform.value = values;
+       uniform.num_values = num_values;
+       uniform.location = -1;
+       uniforms_vec2_array.push_back(uniform);
+}
+
+void Effect::register_uniform_vec4_array(const std::string &key, const float *values, size_t num_values)
+{
+       Uniform<float> uniform;
+       uniform.name = key;
+       uniform.value = values;
+       uniform.num_values = num_values;
+       uniform.location = -1;
+       uniforms_vec4_array.push_back(uniform);
+}
+
+void Effect::register_uniform_mat3(const std::string &key, const Matrix3d *matrix)
+{
+       Uniform<Matrix3d> uniform;
+       uniform.name = key;
+       uniform.value = matrix;
+       uniform.num_values = 1;
+       uniform.location = -1;
+       uniforms_mat3.push_back(uniform);
+}
 
 }  // namespace movit
 
 }  // namespace movit
index 56c34d917c5c46084e89904ed76d938cc7782269..9d81a562e0aa8f53b18c8e0d6e8e5990076f0cfd 100644 (file)
--- a/effect.h
+++ b/effect.h
@@ -15,6 +15,8 @@
 #include <stddef.h>
 #include <map>
 #include <string>
 #include <stddef.h>
 #include <map>
 #include <string>
+#include <vector>
+#include <Eigen/Core>
 
 #include "defs.h"
 
 
 #include "defs.h"
 
@@ -50,6 +52,16 @@ struct RGBATuple {
        float r, g, b, a;
 };
 
        float r, g, b, a;
 };
 
+// Represents a registered uniform.
+template<class T>
+struct Uniform {
+       std::string name;  // Without prefix.
+       const T *value;  // Owner by the effect.
+       size_t num_values;  // Number of elements; for arrays only. _Not_ the vector length.
+       std::string prefix;  // Filled in only after phases have been constructed.
+       GLint location;  // Filled in only after phases have been constructed. -1 if no location.
+};
+
 class Effect {
 public:
        virtual ~Effect() {}
 class Effect {
 public:
        virtual ~Effect() {}
@@ -256,11 +268,6 @@ public:
        // itself from all other effects.
        virtual void rewrite_graph(EffectChain *graph, Node *self) {}
 
        // itself from all other effects.
        virtual void rewrite_graph(EffectChain *graph, Node *self) {}
 
-       // Outputs one GLSL uniform declaration for each registered parameter
-       // (see below), with the right prefix prepended to each uniform name.
-       // If you do not want this behavior, you can override this function.
-       virtual std::string output_convenience_uniforms() const;
-
        // Returns the GLSL fragment shader string for this effect.
        virtual std::string output_fragment_shader() = 0;
 
        // Returns the GLSL fragment shader string for this effect.
        virtual std::string output_fragment_shader() = 0;
 
@@ -289,7 +296,9 @@ public:
 protected:
        // Register a parameter. Whenever set_*() is called with the same key,
        // it will update the value in the given pointer (typically a pointer
 protected:
        // Register a parameter. Whenever set_*() is called with the same key,
        // it will update the value in the given pointer (typically a pointer
-       // to some private member variable in your effect).
+       // to some private member variable in your effect). It will also
+       // register a uniform of the same name (plus an arbitrary prefix
+       // which you can access using the PREFIX macro) that you can access.
        //
        // Neither of these take ownership of the pointer.
 
        //
        // Neither of these take ownership of the pointer.
 
@@ -303,12 +312,56 @@ protected:
        void register_vec3(const std::string &key, float *values);
        void register_vec4(const std::string &key, float *values);
 
        void register_vec3(const std::string &key, float *values);
        void register_vec4(const std::string &key, float *values);
 
+       // Register uniforms, such that they will automatically be set
+       // before the shader runs. This is more efficient than set_uniform_*
+       // in effect_util.h, because it doesn't need to do name lookups
+       // every time. Also, in the future, it will use uniform buffer objects
+       // (UBOs) if available to reduce the number of calls into the driver.
+       //
+       // May not be called after output_fragment_shader() has returned.
+       // The pointer must be valid for the entire lifetime of the Effect,
+       // since the value is pulled from it each execution. The value is
+       // guaranteed to be read after set_gl_state() for the effect has
+       // returned, so you can safely update its value from there.
+       //
+       // Note that this will also declare the uniform in the shader for you,
+       // so you should not do that yourself. (This is so it can be part of
+       // the right uniform block.) However, it is probably a good idea to
+       // have a commented-out declaration so that it is easier to see the
+       // type and thus understand the shader on its own.
+       //
+       // Calling register_* will automatically imply register_uniform_*,
+       // except for register_int as noted above.
+       void register_uniform_bool(const std::string &key, const bool *value);
+       void register_uniform_int(const std::string &key, const int *value);  // Note: Requires GLSL 1.30 or newer.
+       void register_uniform_sampler2d(const std::string &key, const int *value);
+       void register_uniform_float(const std::string &key, const float *value);
+       void register_uniform_vec2(const std::string &key, const float *values);
+       void register_uniform_vec3(const std::string &key, const float *values);
+       void register_uniform_vec4(const std::string &key, const float *values);
+       void register_uniform_vec2_array(const std::string &key, const float *values, size_t num_values);
+       void register_uniform_vec4_array(const std::string &key, const float *values, size_t num_values);
+       void register_uniform_mat3(const std::string &key, const Eigen::Matrix3d *matrix);
+
 private:
        std::map<std::string, int *> params_int;
        std::map<std::string, float *> params_float;
        std::map<std::string, float *> params_vec2;
        std::map<std::string, float *> params_vec3;
        std::map<std::string, float *> params_vec4;
 private:
        std::map<std::string, int *> params_int;
        std::map<std::string, float *> params_float;
        std::map<std::string, float *> params_vec2;
        std::map<std::string, float *> params_vec3;
        std::map<std::string, float *> params_vec4;
+
+       // Picked out by EffectChain during finalization.
+       std::vector<Uniform<bool> > uniforms_bool;
+       std::vector<Uniform<int> > uniforms_int;
+       std::vector<Uniform<int> > uniforms_sampler2d;
+       std::vector<Uniform<float> > uniforms_float;
+       std::vector<Uniform<float> > uniforms_vec2;
+       std::vector<Uniform<float> > uniforms_vec3;
+       std::vector<Uniform<float> > uniforms_vec4;
+       std::vector<Uniform<float> > uniforms_vec2_array;
+       std::vector<Uniform<float> > uniforms_vec4_array;
+       std::vector<Uniform<Eigen::Matrix3d> > uniforms_mat3;
+       friend class EffectChain;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index e1ae832e934a0deedb482b152e4a452f99f47b17..6e297dfeb49d44f7d0044f0c2cb46ef4eacbd6d2 100644 (file)
@@ -12,6 +12,7 @@
 #include <stack>
 #include <utility>
 #include <vector>
 #include <stack>
 #include <utility>
 #include <vector>
+#include <Eigen/Core>
 
 #include "alpha_division_effect.h"
 #include "alpha_multiplication_effect.h"
 
 #include "alpha_division_effect.h"
 #include "alpha_multiplication_effect.h"
@@ -19,6 +20,7 @@
 #include "dither_effect.h"
 #include "effect.h"
 #include "effect_chain.h"
 #include "dither_effect.h"
 #include "effect.h"
 #include "effect_chain.h"
+#include "effect_util.h"
 #include "gamma_compression_effect.h"
 #include "gamma_expansion_effect.h"
 #include "init.h"
 #include "gamma_compression_effect.h"
 #include "gamma_expansion_effect.h"
 #include "init.h"
@@ -27,6 +29,7 @@
 #include "util.h"
 #include "ycbcr_conversion_effect.h"
 
 #include "util.h"
 #include "ycbcr_conversion_effect.h"
 
+using namespace Eigen;
 using namespace std;
 
 namespace movit {
 using namespace std;
 
 namespace movit {
@@ -246,7 +249,8 @@ string replace_prefix(const string &text, const string &prefix)
 
 void EffectChain::compile_glsl_program(Phase *phase)
 {
 
 void EffectChain::compile_glsl_program(Phase *phase)
 {
-       string frag_shader = read_version_dependent_file("header", "frag");
+       string frag_shader_header = read_version_dependent_file("header", "frag");
+       string frag_shader = "";
 
        // Create functions for all the texture inputs that we need.
        for (unsigned i = 0; i < phase->inputs.size(); ++i) {
 
        // Create functions for all the texture inputs that we need.
        for (unsigned i = 0; i < phase->inputs.size(); ++i) {
@@ -262,12 +266,17 @@ void EffectChain::compile_glsl_program(Phase *phase)
                frag_shader += "\n";
        }
 
                frag_shader += "\n";
        }
 
+       // Give each effect in the phase its own ID.
        for (unsigned i = 0; i < phase->effects.size(); ++i) {
                Node *node = phase->effects[i];
                char effect_id[256];
                sprintf(effect_id, "eff%u", i);
                phase->effect_ids.insert(make_pair(node, effect_id));
        for (unsigned i = 0; i < phase->effects.size(); ++i) {
                Node *node = phase->effects[i];
                char effect_id[256];
                sprintf(effect_id, "eff%u", i);
                phase->effect_ids.insert(make_pair(node, effect_id));
+       }
 
 
+       for (unsigned i = 0; i < phase->effects.size(); ++i) {
+               Node *node = phase->effects[i];
+               const string effect_id = phase->effect_ids[node];
                if (node->incoming_links.size() == 1) {
                        frag_shader += string("#define INPUT ") + phase->effect_ids[node->incoming_links[0]] + "\n";
                } else {
                if (node->incoming_links.size() == 1) {
                        frag_shader += string("#define INPUT ") + phase->effect_ids[node->incoming_links[0]] + "\n";
                } else {
@@ -280,7 +289,6 @@ void EffectChain::compile_glsl_program(Phase *phase)
        
                frag_shader += "\n";
                frag_shader += string("#define FUNCNAME ") + effect_id + "\n";
        
                frag_shader += "\n";
                frag_shader += string("#define FUNCNAME ") + effect_id + "\n";
-               frag_shader += replace_prefix(node->effect->output_convenience_uniforms(), effect_id);
                frag_shader += replace_prefix(node->effect->output_fragment_shader(), effect_id);
                frag_shader += "#undef PREFIX\n";
                frag_shader += "#undef FUNCNAME\n";
                frag_shader += replace_prefix(node->effect->output_fragment_shader(), effect_id);
                frag_shader += "#undef PREFIX\n";
                frag_shader += "#undef FUNCNAME\n";
@@ -298,8 +306,119 @@ void EffectChain::compile_glsl_program(Phase *phase)
        frag_shader += string("#define INPUT ") + phase->effect_ids[phase->effects.back()] + "\n";
        frag_shader.append(read_version_dependent_file("footer", "frag"));
 
        frag_shader += string("#define INPUT ") + phase->effect_ids[phase->effects.back()] + "\n";
        frag_shader.append(read_version_dependent_file("footer", "frag"));
 
+       // Collect uniforms from all effects and output them. Note that this needs
+       // to happen after output_fragment_shader(), even though the uniforms come
+       // before in the output source, since output_fragment_shader() is allowed
+       // to register new uniforms (e.g. arrays that are of unknown length until
+       // finalization time).
+       // TODO: Make a uniform block for platforms that support it.
+       string frag_shader_uniforms = "";
+       for (unsigned i = 0; i < phase->effects.size(); ++i) {
+               Node *node = phase->effects[i];
+               Effect *effect = node->effect;
+               const string effect_id = phase->effect_ids[node];
+               for (unsigned j = 0; j < effect->uniforms_bool.size(); ++j) {
+                       phase->uniforms_bool.push_back(effect->uniforms_bool[j]);
+                       phase->uniforms_bool.back().prefix = effect_id;
+                       frag_shader_uniforms += string("uniform bool ") + effect_id
+                               + "_" + effect->uniforms_bool[j].name + ";\n";
+               }
+               for (unsigned j = 0; j < effect->uniforms_int.size(); ++j) {
+                       phase->uniforms_int.push_back(effect->uniforms_int[j]);
+                       phase->uniforms_int.back().prefix = effect_id;
+                       frag_shader_uniforms += string("uniform int ") + effect_id
+                               + "_" + effect->uniforms_int[j].name + ";\n";
+               }
+               for (unsigned j = 0; j < effect->uniforms_sampler2d.size(); ++j) {
+                       phase->uniforms_int.push_back(effect->uniforms_sampler2d[j]);
+                       phase->uniforms_int.back().prefix = effect_id;
+                       frag_shader_uniforms += string("uniform sampler2D ") + effect_id
+                               + "_" + effect->uniforms_sampler2d[j].name + ";\n";
+               }
+               for (unsigned j = 0; j < effect->uniforms_float.size(); ++j) {
+                       phase->uniforms_float.push_back(effect->uniforms_float[j]);
+                       phase->uniforms_float.back().prefix = effect_id;
+                       frag_shader_uniforms += string("uniform float ") + effect_id
+                               + "_" + effect->uniforms_float[j].name + ";\n";
+               }
+               for (unsigned j = 0; j < effect->uniforms_vec2.size(); ++j) {
+                       phase->uniforms_vec2.push_back(effect->uniforms_vec2[j]);
+                       phase->uniforms_vec2.back().prefix = effect_id;
+                       frag_shader_uniforms += string("uniform vec2 ") + effect_id
+                               + "_" + effect->uniforms_vec2[j].name + ";\n";
+               }
+               for (unsigned j = 0; j < effect->uniforms_vec3.size(); ++j) {
+                       phase->uniforms_vec3.push_back(effect->uniforms_vec3[j]);
+                       phase->uniforms_vec3.back().prefix = effect_id;
+                       frag_shader_uniforms += string("uniform vec3 ") + effect_id
+                               + "_" + effect->uniforms_vec3[j].name + ";\n";
+               }
+               for (unsigned j = 0; j < effect->uniforms_vec4.size(); ++j) {
+                       phase->uniforms_vec4.push_back(effect->uniforms_vec4[j]);
+                       phase->uniforms_vec4.back().prefix = effect_id;
+                       frag_shader_uniforms += string("uniform vec4 ") + effect_id
+                               + "_" + effect->uniforms_vec4[j].name + ";\n";
+               }
+               for (unsigned j = 0; j < effect->uniforms_vec2_array.size(); ++j) {
+                       char buf[256];
+                       phase->uniforms_vec2.push_back(effect->uniforms_vec2_array[j]);
+                       phase->uniforms_vec2.back().prefix = effect_id;
+                       snprintf(buf, sizeof(buf), "uniform vec2 %s_%s[%d];\n",
+                               effect_id.c_str(), effect->uniforms_vec2_array[j].name.c_str(),
+                               int(effect->uniforms_vec2_array[j].num_values));
+                       frag_shader_uniforms += buf;
+               }
+               for (unsigned j = 0; j < effect->uniforms_vec4_array.size(); ++j) {
+                       char buf[256];
+                       phase->uniforms_vec4.push_back(effect->uniforms_vec4_array[j]);
+                       phase->uniforms_vec4.back().prefix = effect_id;
+                       snprintf(buf, sizeof(buf), "uniform vec4 %s_%s[%d];\n",
+                               effect_id.c_str(), effect->uniforms_vec4_array[j].name.c_str(),
+                               int(effect->uniforms_vec4_array[j].num_values));
+                       frag_shader_uniforms += buf;
+               }
+               for (unsigned j = 0; j < effect->uniforms_mat3.size(); ++j) {
+                       phase->uniforms_mat3.push_back(effect->uniforms_mat3[j]);
+                       phase->uniforms_mat3.back().prefix = effect_id;
+                       frag_shader_uniforms += string("uniform mat3 ") + effect_id
+                               + "_" + effect->uniforms_mat3[j].name + ";\n";
+               }
+       }
+
+       frag_shader = frag_shader_header + frag_shader_uniforms + frag_shader;
+
        string vert_shader = read_version_dependent_file("vs", "vert");
        phase->glsl_program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader);
        string vert_shader = read_version_dependent_file("vs", "vert");
        phase->glsl_program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader);
+
+       // Collect the resulting program numbers for each uniform.
+       for (unsigned i = 0; i < phase->uniforms_bool.size(); ++i) {
+               Uniform<bool> &uniform = phase->uniforms_bool[i];
+               uniform.location = get_uniform_location(phase->glsl_program_num, uniform.prefix, uniform.name);
+       }
+       for (unsigned i = 0; i < phase->uniforms_int.size(); ++i) {
+               Uniform<int> &uniform = phase->uniforms_int[i];
+               uniform.location = get_uniform_location(phase->glsl_program_num, uniform.prefix, uniform.name);
+       }
+       for (unsigned i = 0; i < phase->uniforms_float.size(); ++i) {
+               Uniform<float> &uniform = phase->uniforms_float[i];
+               uniform.location = get_uniform_location(phase->glsl_program_num, uniform.prefix, uniform.name);
+       }
+       for (unsigned i = 0; i < phase->uniforms_vec2.size(); ++i) {
+               Uniform<float> &uniform = phase->uniforms_vec2[i];
+               uniform.location = get_uniform_location(phase->glsl_program_num, uniform.prefix, uniform.name);
+       }
+       for (unsigned i = 0; i < phase->uniforms_vec3.size(); ++i) {
+               Uniform<float> &uniform = phase->uniforms_vec3[i];
+               uniform.location = get_uniform_location(phase->glsl_program_num, uniform.prefix, uniform.name);
+       }
+       for (unsigned i = 0; i < phase->uniforms_vec4.size(); ++i) {
+               Uniform<float> &uniform = phase->uniforms_vec4[i];
+               uniform.location = get_uniform_location(phase->glsl_program_num, uniform.prefix, uniform.name);
+       }
+       for (unsigned i = 0; i < phase->uniforms_mat3.size(); ++i) {
+               Uniform<Matrix3d> &uniform = phase->uniforms_mat3[i];
+               uniform.location = get_uniform_location(phase->glsl_program_num, uniform.prefix, uniform.name);
+       }
 }
 
 // Construct GLSL programs, starting at the given effect and following
 }
 
 // Construct GLSL programs, starting at the given effect and following
@@ -1671,6 +1790,10 @@ void EffectChain::execute_phase(Phase *phase, bool last_phase, map<Phase *, GLui
                }
        }
 
                }
        }
 
+       // Uniforms need to come after set_gl_state(), since they can be updated
+       // from there.
+       setup_uniforms(phase);
+
        // Now draw!
        float vertices[] = {
                0.0f, 2.0f,
        // Now draw!
        float vertices[] = {
                0.0f, 2.0f,
@@ -1709,6 +1832,62 @@ void EffectChain::execute_phase(Phase *phase, bool last_phase, map<Phase *, GLui
        check_error();
 }
 
        check_error();
 }
 
+void EffectChain::setup_uniforms(Phase *phase)
+{
+       // TODO: Use UBO blocks.
+       for (size_t i = 0; i < phase->uniforms_bool.size(); ++i) {
+               const Uniform<bool> &uniform = phase->uniforms_bool[i];
+               assert(uniform.num_values == 1);
+               if (uniform.location != -1) {
+                       glUniform1i(uniform.location, *uniform.value);
+               }
+       }
+       for (size_t i = 0; i < phase->uniforms_int.size(); ++i) {
+               const Uniform<int> &uniform = phase->uniforms_int[i];
+               if (uniform.location != -1) {
+                       glUniform1iv(uniform.location, uniform.num_values, uniform.value);
+               }
+       }
+       for (size_t i = 0; i < phase->uniforms_float.size(); ++i) {
+               const Uniform<float> &uniform = phase->uniforms_float[i];
+               if (uniform.location != -1) {
+                       glUniform1fv(uniform.location, uniform.num_values, uniform.value);
+               }
+       }
+       for (size_t i = 0; i < phase->uniforms_vec2.size(); ++i) {
+               const Uniform<float> &uniform = phase->uniforms_vec2[i];
+               if (uniform.location != -1) {
+                       glUniform2fv(uniform.location, uniform.num_values, uniform.value);
+               }
+       }
+       for (size_t i = 0; i < phase->uniforms_vec3.size(); ++i) {
+               const Uniform<float> &uniform = phase->uniforms_vec3[i];
+               if (uniform.location != -1) {
+                       glUniform3fv(uniform.location, uniform.num_values, uniform.value);
+               }
+       }
+       for (size_t i = 0; i < phase->uniforms_vec4.size(); ++i) {
+               const Uniform<float> &uniform = phase->uniforms_vec4[i];
+               if (uniform.location != -1) {
+                       glUniform4fv(uniform.location, uniform.num_values, uniform.value);
+               }
+       }
+       for (size_t i = 0; i < phase->uniforms_mat3.size(); ++i) {
+               const Uniform<Matrix3d> &uniform = phase->uniforms_mat3[i];
+               assert(uniform.num_values == 1);
+               if (uniform.location != -1) {
+                       // Convert to float (GLSL has no double matrices).
+                       float matrixf[9];
+                       for (unsigned y = 0; y < 3; ++y) {
+                               for (unsigned x = 0; x < 3; ++x) {
+                                       matrixf[y + x * 3] = (*uniform.value)(y, x);
+                               }
+                       }
+                       glUniformMatrix3fv(uniform.location, 1, GL_FALSE, matrixf);
+               }
+       }
+}
+
 void EffectChain::setup_rtt_sampler(GLuint glsl_program_num, int sampler_num, const string &effect_id, bool use_mipmaps)
 {
        glActiveTexture(GL_TEXTURE0 + sampler_num);
 void EffectChain::setup_rtt_sampler(GLuint glsl_program_num, int sampler_num, const string &effect_id, bool use_mipmaps)
 {
        glActiveTexture(GL_TEXTURE0 + sampler_num);
index d1ab0a205148bd9d8a22e285a448d758a5fd7e00..ee4c7ba94542a20795e2c9660f0debf860a36f7e 100644 (file)
@@ -27,7 +27,9 @@
 #include <set>
 #include <string>
 #include <vector>
 #include <set>
 #include <string>
 #include <vector>
+#include <Eigen/Core>
 
 
+#include "effect.h"
 #include "image_format.h"
 #include "ycbcr.h"
 
 #include "image_format.h"
 #include "ycbcr.h"
 
@@ -114,6 +116,15 @@ struct Phase {
        // Unique per-phase to increase cacheability of compiled shaders.
        std::map<Node *, std::string> effect_ids;
 
        // Unique per-phase to increase cacheability of compiled shaders.
        std::map<Node *, std::string> effect_ids;
 
+       // Uniforms for this phase; combined from all the effects.
+       std::vector<Uniform<bool> > uniforms_bool;
+       std::vector<Uniform<int> > uniforms_int;
+       std::vector<Uniform<float> > uniforms_float;
+       std::vector<Uniform<float> > uniforms_vec2;
+       std::vector<Uniform<float> > uniforms_vec3;
+       std::vector<Uniform<float> > uniforms_vec4;
+       std::vector<Uniform<Eigen::Matrix3d> > uniforms_mat3;
+
        // For measurement of GPU time used.
        GLuint timer_query_object;
        uint64_t time_elapsed_ns;
        // For measurement of GPU time used.
        GLuint timer_query_object;
        uint64_t time_elapsed_ns;
@@ -265,6 +276,9 @@ private:
        // Execute one phase, ie. set up all inputs, effects and outputs, and render the quad.
        void execute_phase(Phase *phase, bool last_phase, std::map<Phase *, GLuint> *output_textures, std::set<Phase *> *generated_mipmaps);
 
        // Execute one phase, ie. set up all inputs, effects and outputs, and render the quad.
        void execute_phase(Phase *phase, bool last_phase, std::map<Phase *, GLuint> *output_textures, std::set<Phase *> *generated_mipmaps);
 
+       // Set up uniforms for one phase. The program must already be bound.
+       void setup_uniforms(Phase *phase);
+
        // Set up the given sampler number for sampling from an RTT texture,
        // and bind it to "tex_" plus the given GLSL variable.
        void setup_rtt_sampler(GLuint glsl_program_num, int sampler_num, const std::string &effect_id, bool use_mipmaps);
        // Set up the given sampler number for sampling from an RTT texture,
        // and bind it to "tex_" plus the given GLSL variable.
        void setup_rtt_sampler(GLuint glsl_program_num, int sampler_num, const std::string &effect_id, bool use_mipmaps);
index a1588efd71da6203a3cb137e1e1c9c38b62409b6..1a8f04ae91476dfa904729a46ae0cb6a094c65ea 100644 (file)
@@ -20,6 +20,8 @@ class EffectChain;
 class Node;
 
 // Convenience functions that deal with prepending the prefix.
 class Node;
 
 // Convenience functions that deal with prepending the prefix.
+// Note that using EffectChain::register_uniform_*() is more efficient
+// than calling these from set_gl_state().
 GLint get_uniform_location(GLuint glsl_program_num, const std::string &prefix, const std::string &key);
 void set_uniform_int(GLuint glsl_program_num, const std::string &prefix, const std::string &key, int value);
 void set_uniform_float(GLuint glsl_program_num, const std::string &prefix, const std::string &key, float value);
 GLint get_uniform_location(GLuint glsl_program_num, const std::string &prefix, const std::string &key);
 void set_uniform_int(GLuint glsl_program_num, const std::string &prefix, const std::string &key, int value);
 void set_uniform_float(GLuint glsl_program_num, const std::string &prefix, const std::string &key, float value);
index c88a7c4b12fe9947cc6cd2a43f3b4ff0ba2d6e01..b37d52039b77c7b15aa4a13242af328d6a54d4f2 100644 (file)
@@ -23,6 +23,7 @@ FFTInput::FFTInput(unsigned width, unsigned height)
 {
        register_int("fft_width", &fft_width);
        register_int("fft_height", &fft_height);
 {
        register_int("fft_width", &fft_width);
        register_int("fft_height", &fft_height);
+       register_uniform_sampler2d("tex", &uniform_tex);
 }
 
 FFTInput::~FFTInput()
 }
 
 FFTInput::~FFTInput()
@@ -98,7 +99,7 @@ void FFTInput::set_gl_state(GLuint glsl_program_num, const string& prefix, unsig
        }
 
        // Bind it to a sampler.
        }
 
        // Bind it to a sampler.
-       set_uniform_int(glsl_program_num, prefix, "tex", *sampler_num);
+       uniform_tex = *sampler_num;
        ++*sampler_num;
 }
 
        ++*sampler_num;
 }
 
index a75414cb473ce181ebb3717229cc970a17e00a4e..472a218a7f892cc7bb1ceccef1726eab811ca4d3 100644 (file)
@@ -75,6 +75,7 @@ private:
        unsigned convolve_width, convolve_height;
        const float *pixel_data;
        ResourcePool *resource_pool;
        unsigned convolve_width, convolve_height;
        const float *pixel_data;
        ResourcePool *resource_pool;
+       GLint uniform_tex;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index 48e2677576735c5577f3989705cee61a55f4adc4..434ce22a79d7baf7877e61a0bb3b00bce3414421 100644 (file)
@@ -25,6 +25,8 @@ FFTPassEffect::FFTPassEffect()
        register_int("direction", (int *)&direction);
        register_int("pass_number", &pass_number);
        register_int("inverse", &inverse);
        register_int("direction", (int *)&direction);
        register_int("pass_number", &pass_number);
        register_int("inverse", &inverse);
+       register_uniform_float("num_repeats", &uniform_num_repeats);
+       register_uniform_sampler2d("support_tex", &uniform_support_tex);
        glGenTextures(1, &tex);
 }
 
        glGenTextures(1, &tex);
 }
 
@@ -83,11 +85,11 @@ void FFTPassEffect::set_gl_state(GLuint glsl_program_num, const string &prefix,
                generate_support_texture();
        }
 
                generate_support_texture();
        }
 
-       set_uniform_int(glsl_program_num, prefix, "support_tex", *sampler_num);
+       uniform_support_tex = *sampler_num;
        ++*sampler_num;
 
        assert(input_size % fft_size == 0);
        ++*sampler_num;
 
        assert(input_size % fft_size == 0);
-       set_uniform_float(glsl_program_num, prefix, "num_repeats", input_size / fft_size);
+       uniform_num_repeats = input_size / fft_size;
 }
 
 void FFTPassEffect::generate_support_texture()
 }
 
 void FFTPassEffect::generate_support_texture()
index eb26f33442ff8baed342d89cfcbbc7f217175b67..9750e8b045199b6005d44f0d9cf4e62ebdf1c974 100644 (file)
@@ -1,8 +1,9 @@
 // DIRECTION_VERTICAL will be #defined to 1 if we are doing a vertical FFT,
 // and 0 otherwise.
 
 // DIRECTION_VERTICAL will be #defined to 1 if we are doing a vertical FFT,
 // and 0 otherwise.
 
-uniform float PREFIX(num_repeats);
-uniform sampler2D PREFIX(support_tex);
+// Implicit uniforms:
+// uniform float PREFIX(num_repeats);
+// uniform sampler2D PREFIX(support_tex);
 
 vec4 FUNCNAME(vec2 tc) {
 #if DIRECTION_VERTICAL
 
 vec4 FUNCNAME(vec2 tc) {
 #if DIRECTION_VERTICAL
index 561bc6dd20788a6605a5d55230171cba9c5a40b8..53428bd8d31a3f82360615a2ec20b0cac3653cd5 100644 (file)
@@ -110,6 +110,8 @@ private:
        EffectChain *chain;
        int input_width, input_height;
        GLuint tex;
        EffectChain *chain;
        int input_width, input_height;
        GLuint tex;
+       float uniform_num_repeats;
+       GLint uniform_support_tex;
 
        int fft_size;
        Direction direction;
 
        int fft_size;
        Direction direction;
index f6ae827338d7f75c9b76c4c9fe1612dedc75fbfc..1795902bcc23448741427e190772f371fe720a55 100644 (file)
@@ -28,6 +28,7 @@ FlatInput::FlatInput(ImageFormat image_format, MovitPixelFormat pixel_format_in,
        assert(type == GL_FLOAT || type == GL_HALF_FLOAT || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE);
        register_int("output_linear_gamma", &output_linear_gamma);
        register_int("needs_mipmaps", &needs_mipmaps);
        assert(type == GL_FLOAT || type == GL_HALF_FLOAT || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE);
        register_int("output_linear_gamma", &output_linear_gamma);
        register_int("needs_mipmaps", &needs_mipmaps);
+       register_uniform_sampler2d("tex", &uniform_tex);
 
        // Some types are not supported in all GL versions (e.g. GLES),
        // and will corrected into the right format in the shader.
 
        // Some types are not supported in all GL versions (e.g. GLES),
        // and will corrected into the right format in the shader.
@@ -168,7 +169,7 @@ void FlatInput::set_gl_state(GLuint glsl_program_num, const string& prefix, unsi
        }
 
        // Bind it to a sampler.
        }
 
        // Bind it to a sampler.
-       set_uniform_int(glsl_program_num, prefix, "tex", *sampler_num);
+       uniform_tex = *sampler_num;
        ++*sampler_num;
 }
 
        ++*sampler_num;
 }
 
index 855d4fbbfe1c1b888ae52ee24112eb3868131996..78d4edd8224e4fc13e80411d51c088b5261b6d02 100644 (file)
@@ -1,4 +1,5 @@
-uniform sampler2D PREFIX(tex);
+// Implicit uniforms:
+// uniform sampler2D PREFIX(tex);
 
 vec4 FUNCNAME(vec2 tc) {
        // OpenGL's origin is bottom-left, but most graphics software assumes
 
 vec4 FUNCNAME(vec2 tc) {
        // OpenGL's origin is bottom-left, but most graphics software assumes
index 25b9091abc837baa699d5d36bc2c0b94253dc97a..495a36cbdc10f5be9f0d22484dc018cbbb236316 100644 (file)
@@ -127,6 +127,7 @@ private:
        const void *pixel_data;
        ResourcePool *resource_pool;
        bool fixup_swap_rb, fixup_red_to_grayscale;
        const void *pixel_data;
        ResourcePool *resource_pool;
        bool fixup_swap_rb, fixup_red_to_grayscale;
+       GLint uniform_tex;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index 079f849e16a62445c6862f6477fa84a511f920be..b0f6372d4b9560ac9fb59c8c438feb022974189e 100644 (file)
@@ -12,6 +12,13 @@ GammaCompressionEffect::GammaCompressionEffect()
        : destination_curve(GAMMA_LINEAR)
 {
        register_int("destination_curve", (int *)&destination_curve);
        : destination_curve(GAMMA_LINEAR)
 {
        register_int("destination_curve", (int *)&destination_curve);
+       register_uniform_float("linear_scale", &uniform_linear_scale);
+       register_uniform_float("c0", &uniform_c0);
+       register_uniform_float("c1", &uniform_c1);
+       register_uniform_float("c2", &uniform_c2);
+       register_uniform_float("c3", &uniform_c3);
+       register_uniform_float("c4", &uniform_c4);
+       register_uniform_float("beta", &uniform_beta);
 }
 
 string GammaCompressionEffect::output_fragment_shader()
 }
 
 string GammaCompressionEffect::output_fragment_shader()
@@ -73,25 +80,25 @@ void GammaCompressionEffect::set_gl_state(GLuint glsl_program_num, const string
                // β = 0.0031308, ɣ = 1/2.4.
                // maxerror      = 0.000785 = 0.200 * 255
                // error at 1.0  = 0.000078 = 0.020 * 255
                // β = 0.0031308, ɣ = 1/2.4.
                // maxerror      = 0.000785 = 0.200 * 255
                // error at 1.0  = 0.000078 = 0.020 * 255
-               set_uniform_float(glsl_program_num, prefix, "linear_scale", 12.92);
-               set_uniform_float(glsl_program_num, prefix, "c0", -0.03679675939);
-               set_uniform_float(glsl_program_num, prefix, "c1", 1.443803073);
-               set_uniform_float(glsl_program_num, prefix, "c2", -0.9239780987);
-               set_uniform_float(glsl_program_num, prefix, "c3", 0.8060491596);
-               set_uniform_float(glsl_program_num, prefix, "c4", -0.2891558568);
-               set_uniform_float(glsl_program_num, prefix, "beta", 0.0031308);
+               uniform_linear_scale = 12.92;
+               uniform_c0 = -0.03679675939;
+               uniform_c1 = 1.443803073;
+               uniform_c2 = -0.9239780987;
+               uniform_c3 = 0.8060491596;
+               uniform_c4 = -0.2891558568;
+               uniform_beta = 0.0031308;
        }
        if (destination_curve == GAMMA_REC_709) {  // Also includes Rec. 601, and 10-bit Rec. 2020.
                // Rec. 2020, page 3; ɑ = 1.099, β = 0.018, ɣ = 0.45.
                // maxerror      = 0.000131 = 0.033 * 255 = 0.134 * 1023
                // error at 1.0  = 0.000013 = 0.003 * 255 = 0.013 * 1023
        }
        if (destination_curve == GAMMA_REC_709) {  // Also includes Rec. 601, and 10-bit Rec. 2020.
                // Rec. 2020, page 3; ɑ = 1.099, β = 0.018, ɣ = 0.45.
                // maxerror      = 0.000131 = 0.033 * 255 = 0.134 * 1023
                // error at 1.0  = 0.000013 = 0.003 * 255 = 0.013 * 1023
-               set_uniform_float(glsl_program_num, prefix, "linear_scale", 4.5);
-               set_uniform_float(glsl_program_num, prefix, "c0", -0.08541688528);
-               set_uniform_float(glsl_program_num, prefix, "c1", 1.292793370);
-               set_uniform_float(glsl_program_num, prefix, "c2", -0.4070417645);
-               set_uniform_float(glsl_program_num, prefix, "c3", 0.2923891828);
-               set_uniform_float(glsl_program_num, prefix, "c4", -0.09273699351);
-               set_uniform_float(glsl_program_num, prefix, "beta", 0.018);
+               uniform_linear_scale = 4.5;
+               uniform_c0 = -0.08541688528;
+               uniform_c1 = 1.292793370;
+               uniform_c2 = -0.4070417645;
+               uniform_c3 = 0.2923891828;
+               uniform_c4 = -0.09273699351;
+               uniform_beta = 0.018;
        }
        if (destination_curve == GAMMA_REC_2020_12_BIT) {
                // Rec. 2020, page 3; ɑ = 1.0993, β = 0.0181, ɣ = 0.45.
        }
        if (destination_curve == GAMMA_REC_2020_12_BIT) {
                // Rec. 2020, page 3; ɑ = 1.0993, β = 0.0181, ɣ = 0.45.
@@ -103,13 +110,13 @@ void GammaCompressionEffect::set_gl_state(GLuint glsl_program_num, const string
                // bit. (Removing the constraint for x=1 will only take this down
                // from 0.553 to 0.501; adding a fifth order can get it down to
                // 0.167, although this assumes working in fp64 and not fp32.)
                // bit. (Removing the constraint for x=1 will only take this down
                // from 0.553 to 0.501; adding a fifth order can get it down to
                // 0.167, although this assumes working in fp64 and not fp32.)
-               set_uniform_float(glsl_program_num, prefix, "linear_scale", 4.5);
-               set_uniform_float(glsl_program_num, prefix, "c0", -0.08569685663);
-               set_uniform_float(glsl_program_num, prefix, "c1", 1.293000900);
-               set_uniform_float(glsl_program_num, prefix, "c2", -0.4067291321);
-               set_uniform_float(glsl_program_num, prefix, "c3", 0.2919741179);
-               set_uniform_float(glsl_program_num, prefix, "c4", -0.09256205770);
-               set_uniform_float(glsl_program_num, prefix, "beta", 0.0181);
+               uniform_linear_scale = 4.5;
+               uniform_c0 = -0.08569685663;
+               uniform_c1 = 1.293000900;
+               uniform_c2 = -0.4067291321;
+               uniform_c3 = 0.2919741179;
+               uniform_c4 = -0.09256205770;
+               uniform_beta = 0.0181;
        }
 }
 
        }
 }
 
index e1e786cdf91426174011568b1367b913f3ff9d80..2d84f326dd054a23908b3ef1ecdcd5e71f0bb2f1 100644 (file)
@@ -1,8 +1,9 @@
 // Compress gamma curve.
 
 // Compress gamma curve.
 
-uniform float PREFIX(linear_scale);
-uniform float PREFIX(c0), PREFIX(c1), PREFIX(c2), PREFIX(c3), PREFIX(c4);
-uniform float PREFIX(beta);
+// Implicit uniforms:
+// uniform float PREFIX(linear_scale);
+// uniform float PREFIX(c0), PREFIX(c1), PREFIX(c2), PREFIX(c3), PREFIX(c4);
+// uniform float PREFIX(beta);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 x = INPUT(tc);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 x = INPUT(tc);
index 52a8654a63015652204c0b9fb82d506f3eb04db7..08fa1940adfdf58e6b37dcd35780361fd299a904 100644 (file)
@@ -37,6 +37,7 @@ public:
 
 private:
        GammaCurve destination_curve;
 
 private:
        GammaCurve destination_curve;
+       float uniform_linear_scale, uniform_c0, uniform_c1, uniform_c2, uniform_c3, uniform_c4, uniform_beta;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index 95437906f4c63134232e7775ba630016b2b6748f..15e0bffb8f03ed0a1bf034c29b9fbbcd6245be38 100644 (file)
@@ -12,6 +12,13 @@ GammaExpansionEffect::GammaExpansionEffect()
        : source_curve(GAMMA_LINEAR)
 {
        register_int("source_curve", (int *)&source_curve);
        : source_curve(GAMMA_LINEAR)
 {
        register_int("source_curve", (int *)&source_curve);
+       register_uniform_float("linear_scale", &uniform_linear_scale);
+       register_uniform_float("c0", &uniform_c0);
+       register_uniform_float("c1", &uniform_c1);
+       register_uniform_float("c2", &uniform_c2);
+       register_uniform_float("c3", &uniform_c3);
+       register_uniform_float("c4", &uniform_c4);
+       register_uniform_float("beta", &uniform_beta);
 }
 
 string GammaExpansionEffect::output_fragment_shader()
 }
 
 string GammaExpansionEffect::output_fragment_shader()
@@ -80,13 +87,13 @@ void GammaExpansionEffect::set_gl_state(GLuint glsl_program_num, const string &p
                //
                // Note that the worst _relative_ error by far is just at the beginning
                // of the exponential curve, ie., just around β.
                //
                // Note that the worst _relative_ error by far is just at the beginning
                // of the exponential curve, ie., just around β.
-               set_uniform_float(glsl_program_num, prefix, "linear_scale", 1.0 / 12.92);
-               set_uniform_float(glsl_program_num, prefix, "c0", 0.001324469581);
-               set_uniform_float(glsl_program_num, prefix, "c1", 0.02227416690);
-               set_uniform_float(glsl_program_num, prefix, "c2", 0.5917615253);
-               set_uniform_float(glsl_program_num, prefix, "c3", 0.4733532353);
-               set_uniform_float(glsl_program_num, prefix, "c4", -0.08880738120);
-               set_uniform_float(glsl_program_num, prefix, "beta", 0.04045);
+               uniform_linear_scale = 1.0 / 12.92;
+               uniform_c0 = 0.001324469581;
+               uniform_c1 = 0.02227416690;
+               uniform_c2 = 0.5917615253;
+               uniform_c3 = 0.4733532353;
+               uniform_c4 = -0.08880738120;
+               uniform_beta = 0.04045;
        }
        if (source_curve == GAMMA_REC_709) {  // Also includes Rec. 601, and 10-bit Rec. 2020.
                // Rec. 2020, page 3; ɑ = 1.099, β = 0.018 * 4.5, ɣ = 1/0.45.
        }
        if (source_curve == GAMMA_REC_709) {  // Also includes Rec. 601, and 10-bit Rec. 2020.
                // Rec. 2020, page 3; ɑ = 1.099, β = 0.018 * 4.5, ɣ = 1/0.45.
@@ -97,13 +104,13 @@ void GammaExpansionEffect::set_gl_state(GLuint glsl_program_num, const string &p
                // Note that Rec. 2020 only gives the other direction, which is why
                // our beta and gamma are different from the numbers mentioned
                // (we've inverted the formula).
                // Note that Rec. 2020 only gives the other direction, which is why
                // our beta and gamma are different from the numbers mentioned
                // (we've inverted the formula).
-               set_uniform_float(glsl_program_num, prefix, "linear_scale", 1.0 / 4.5);
-               set_uniform_float(glsl_program_num, prefix, "c0", 0.005137028744);
-               set_uniform_float(glsl_program_num, prefix, "c1", 0.09802596889);
-               set_uniform_float(glsl_program_num, prefix, "c2", 0.7255768864);
-               set_uniform_float(glsl_program_num, prefix, "c3", 0.2135067966);
-               set_uniform_float(glsl_program_num, prefix, "c4", -0.04225094667);
-               set_uniform_float(glsl_program_num, prefix, "beta", 0.018 * 4.5);
+               uniform_linear_scale = 1.0 / 4.5;
+               uniform_c0 = 0.005137028744;
+               uniform_c1 = 0.09802596889;
+               uniform_c2 = 0.7255768864;
+               uniform_c3 = 0.2135067966;
+               uniform_c4 = -0.04225094667;
+               uniform_beta = 0.018 * 4.5;
        }
        if (source_curve == GAMMA_REC_2020_12_BIT) {
                // Rec. 2020, page 3; ɑ = 1.0993, β = 0.0181 * 4.5, ɣ = 1/0.45.
        }
        if (source_curve == GAMMA_REC_2020_12_BIT) {
                // Rec. 2020, page 3; ɑ = 1.0993, β = 0.0181 * 4.5, ɣ = 1/0.45.
@@ -114,13 +121,13 @@ void GammaExpansionEffect::set_gl_state(GLuint glsl_program_num, const string &p
                // Note that Rec. 2020 only gives the other direction, which is why
                // our beta and gamma are different from the numbers mentioned
                // (we've inverted the formula).
                // Note that Rec. 2020 only gives the other direction, which is why
                // our beta and gamma are different from the numbers mentioned
                // (we've inverted the formula).
-               set_uniform_float(glsl_program_num, prefix, "linear_scale", 1.0 / 4.5);
-               set_uniform_float(glsl_program_num, prefix, "c0", 0.005167545928);
-               set_uniform_float(glsl_program_num, prefix, "c1", 0.09835585809);
-               set_uniform_float(glsl_program_num, prefix, "c2", 0.7254820139);
-               set_uniform_float(glsl_program_num, prefix, "c3", 0.2131291155);
-               set_uniform_float(glsl_program_num, prefix, "c4", -0.04213877222);
-               set_uniform_float(glsl_program_num, prefix, "beta", 0.0181 * 4.5);
+               uniform_linear_scale = 1.0 / 4.5;
+               uniform_c0 = 0.005167545928;
+               uniform_c1 = 0.09835585809;
+               uniform_c2 = 0.7254820139;
+               uniform_c3 = 0.2131291155;
+               uniform_c4 = -0.04213877222;
+               uniform_beta = 0.0181 * 4.5;
        }
 }
 
        }
 }
 
index 359b026450c916f52d9f486bac11c2f6dcff3b71..051d2faf1042cc47e0be4b3b715dba67c0333794 100644 (file)
@@ -1,8 +1,9 @@
 // Expand gamma curve.
 
 // Expand gamma curve.
 
-uniform float PREFIX(linear_scale);
-uniform float PREFIX(c0), PREFIX(c1), PREFIX(c2), PREFIX(c3), PREFIX(c4);
-uniform float PREFIX(beta);
+// Implicit uniforms:
+// uniform float PREFIX(linear_scale);
+// uniform float PREFIX(c0), PREFIX(c1), PREFIX(c2), PREFIX(c3), PREFIX(c4);
+// uniform float PREFIX(beta);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 x = INPUT(tc);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 x = INPUT(tc);
index 1025695d88cdb60d192b4aeefcc1278f2f6c0483..20a5a76fba04315d74f9aa09502eaac3e196e658 100644 (file)
@@ -38,6 +38,7 @@ public:
 
 private:
        GammaCurve source_curve;
 
 private:
        GammaCurve source_curve;
+       float uniform_linear_scale, uniform_c0, uniform_c1, uniform_c2, uniform_c3, uniform_c4, uniform_beta;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index 60cd7df5f2b1c2cef74128fdab446335aa945fbb..ac8ccb6347b3ae9f7e9f574854551a271f26518e 100644 (file)
@@ -17,6 +17,8 @@ LiftGammaGainEffect::LiftGammaGainEffect()
        register_vec3("lift", (float *)&lift);
        register_vec3("gamma", (float *)&gamma);
        register_vec3("gain", (float *)&gain);
        register_vec3("lift", (float *)&lift);
        register_vec3("gamma", (float *)&gamma);
        register_vec3("gain", (float *)&gain);
+       register_uniform_vec3("gain_pow_inv_gamma", (float *)&uniform_gain_pow_inv_gamma);
+       register_uniform_vec3("inv_gamma_22", (float *)&uniform_inv_gamma22);
 }
 
 string LiftGammaGainEffect::output_fragment_shader()
 }
 
 string LiftGammaGainEffect::output_fragment_shader()
@@ -28,17 +30,15 @@ void LiftGammaGainEffect::set_gl_state(GLuint glsl_program_num, const string &pr
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
 
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
 
-       RGBTriplet gain_pow_inv_gamma(
+       uniform_gain_pow_inv_gamma = RGBTriplet(
                pow(gain.r, 1.0f / gamma.r),
                pow(gain.g, 1.0f / gamma.g),
                pow(gain.b, 1.0f / gamma.b));
                pow(gain.r, 1.0f / gamma.r),
                pow(gain.g, 1.0f / gamma.g),
                pow(gain.b, 1.0f / gamma.b));
-       set_uniform_vec3(glsl_program_num, prefix, "gain_pow_inv_gamma", (float *)&gain_pow_inv_gamma);
 
 
-       RGBTriplet inv_gamma_22(
+       uniform_inv_gamma22 = RGBTriplet(
                2.2f / gamma.r,
                2.2f / gamma.g,
                2.2f / gamma.b);
                2.2f / gamma.r,
                2.2f / gamma.g,
                2.2f / gamma.b);
-       set_uniform_vec3(glsl_program_num, prefix, "inv_gamma_22", (float *)&inv_gamma_22);
 }
 
 }  // namespace movit
 }
 
 }  // namespace movit
index 9047d64bbc2230c263e6fb5a6025642435cf8cd0..7342d7505eb53da6e66167b4921138ef2f5a68dc 100644 (file)
@@ -1,6 +1,8 @@
+// Implicit uniforms:
+//
 // These are calculated in the host code to save some arithmetic.
 // These are calculated in the host code to save some arithmetic.
-uniform vec3 PREFIX(gain_pow_inv_gamma);  // gain^(1/gamma).
-uniform vec3 PREFIX(inv_gamma_22);  // 2.2 / gamma.
+// uniform vec3 PREFIX(gain_pow_inv_gamma);  // gain^(1/gamma).
+// uniform vec3 PREFIX(inv_gamma_22);  // 2.2 / gamma.
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 x = INPUT(tc);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 x = INPUT(tc);
index 9183c580e080b7294cbb3f94bf4e20c7c4de3d6e..7967448d935105e3de78a19c9b5ab07ef23a5137 100644 (file)
@@ -39,6 +39,7 @@ public:
 
 private:
        RGBTriplet lift, gamma, gain;
 
 private:
        RGBTriplet lift, gamma, gain;
+       RGBTriplet uniform_gain_pow_inv_gamma, uniform_inv_gamma22;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index 92c599e06993830de78b92a3c826cc13d164e4a3..6d5af7321f34025780c755d4f8a677d0b84a8ad8 100644 (file)
@@ -12,6 +12,8 @@ LumaMixEffect::LumaMixEffect()
        register_float("transition_width", &transition_width);
        register_float("progress", &progress);
        register_int("inverse", &inverse);
        register_float("transition_width", &transition_width);
        register_float("progress", &progress);
        register_int("inverse", &inverse);
+       register_uniform_bool("inverse", &uniform_inverse);
+       register_uniform_float("progress_mul_w_plus_one", &uniform_progress_mul_w_plus_one);
 }
 
 string LumaMixEffect::output_fragment_shader()
 }
 
 string LumaMixEffect::output_fragment_shader()
@@ -22,8 +24,8 @@ string LumaMixEffect::output_fragment_shader()
 void LumaMixEffect::set_gl_state(GLuint glsl_program_num, const string &prefix, unsigned *sampler_num)
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
 void LumaMixEffect::set_gl_state(GLuint glsl_program_num, const string &prefix, unsigned *sampler_num)
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
-       set_uniform_float(glsl_program_num, prefix, "progress_mul_w_plus_one", progress * (transition_width + 1.0));
-       set_uniform_int(glsl_program_num, prefix, "inverse", inverse);
+       uniform_progress_mul_w_plus_one = progress * (transition_width + 1.0);
+       uniform_inverse = inverse;
 }
 
 }  // namespace movit
 }
 
 }  // namespace movit
index c8a05c1e976b3a614f5b0af0a654e8758c2520bf..e721a885892a17ea9ff303570169292d978aa830 100644 (file)
@@ -1,5 +1,6 @@
-uniform float PREFIX(progress_mul_w_plus_one);
-uniform bool PREFIX(inverse);
+// Implicit uniforms:
+// uniform float PREFIX(progress_mul_w_plus_one);
+// uniform bool PREFIX(inverse);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 first = INPUT1(tc);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 first = INPUT1(tc);
index c4b2476a6f45a3689ea1cb4d7baa30e50a6177a7..3ff81bf6b1641794c2d6db379027d50f0737615e 100644 (file)
@@ -32,6 +32,8 @@ public:
 private:
        float transition_width, progress;
        int inverse;  // 0 or 1.
 private:
        float transition_width, progress;
        int inverse;  // 0 or 1.
+       bool uniform_inverse;
+       float uniform_progress_mul_w_plus_one;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index 5ca976c2f9fca6d8d606a469e981456c7141c56a..d96d1046f37b9615c873ff23618eabfe4d6ee531 100644 (file)
@@ -29,6 +29,11 @@ PaddingEffect::PaddingEffect()
        register_float("border_offset_left", &border_offset_left);
        register_float("border_offset_bottom", &border_offset_bottom);
        register_float("border_offset_right", &border_offset_right);
        register_float("border_offset_left", &border_offset_left);
        register_float("border_offset_bottom", &border_offset_bottom);
        register_float("border_offset_right", &border_offset_right);
+       register_uniform_vec2("offset", uniform_offset);
+       register_uniform_vec2("scale", uniform_scale);
+       register_uniform_vec2("normalized_coords_to_texels", uniform_normalized_coords_to_texels);
+       register_uniform_vec2("offset_bottomleft", uniform_offset_bottomleft);
+       register_uniform_vec2("offset_topright", uniform_offset_topright);
 }
 
 string PaddingEffect::output_fragment_shader()
 }
 
 string PaddingEffect::output_fragment_shader()
@@ -40,36 +45,23 @@ void PaddingEffect::set_gl_state(GLuint glsl_program_num, const string &prefix,
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
 
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
 
-       float offset[2] = {
-               left / output_width,
-               (output_height - input_height - top) / output_height
-       };
-       set_uniform_vec2(glsl_program_num, prefix, "offset", offset);
+       uniform_offset[0] = left / output_width;
+       uniform_offset[1] = (output_height - input_height - top) / output_height;
 
 
-       float scale[2] = {
-               float(output_width) / input_width,
-               float(output_height) / input_height
-       };
-       set_uniform_vec2(glsl_program_num, prefix, "scale", scale);
+       uniform_scale[0] = float(output_width) / input_width;
+       uniform_scale[1] = float(output_height) / input_height;
 
 
-       float normalized_coords_to_texels[2] = {
-               float(input_width), float(input_height)
-       };
-       set_uniform_vec2(glsl_program_num, prefix, "normalized_coords_to_texels", normalized_coords_to_texels);
+       uniform_normalized_coords_to_texels[0] = float(input_width);
+       uniform_normalized_coords_to_texels[1] = float(input_height);
 
        // Texels -0.5..0.5 should map to light level 0..1 (and then we
        // clamp the rest).
 
        // Texels -0.5..0.5 should map to light level 0..1 (and then we
        // clamp the rest).
-       float offset_bottomleft[2] = {
-               0.5f - border_offset_left, 0.5f + border_offset_bottom,
-       };
+       uniform_offset_bottomleft[0] = 0.5f - border_offset_left;
+       uniform_offset_bottomleft[1] = 0.5f + border_offset_bottom;
 
        // Texels size-0.5..size+0.5 should map to light level 1..0 (and then clamp).
 
        // Texels size-0.5..size+0.5 should map to light level 1..0 (and then clamp).
-       float offset_topright[2] = {
-               input_width + 0.5f + border_offset_right, input_height + 0.5f - border_offset_top,
-       };
-
-       set_uniform_vec2(glsl_program_num, prefix, "offset_bottomleft", offset_bottomleft);
-       set_uniform_vec2(glsl_program_num, prefix, "offset_topright", offset_topright);
+       uniform_offset_topright[0] = input_width + 0.5f + border_offset_right;
+       uniform_offset_topright[1] = input_height + 0.5f - border_offset_top;
 }
        
 // We don't change the pixels of the image itself, so the only thing that 
 }
        
 // We don't change the pixels of the image itself, so the only thing that 
index 32ae84067503b395ecf6d27d9e90bcf75e5e091f..80b9633bb17e9f71fb5b6cce6c41a7ae6bad1838 100644 (file)
@@ -1,9 +1,10 @@
-uniform vec2 PREFIX(offset);
-uniform vec2 PREFIX(scale);
-
-uniform vec2 PREFIX(normalized_coords_to_texels);
-uniform vec2 PREFIX(offset_bottomleft);
-uniform vec2 PREFIX(offset_topright);
+// Implicit uniforms:
+// uniform vec2 PREFIX(offset);
+// uniform vec2 PREFIX(scale);
+//
+// uniform vec2 PREFIX(normalized_coords_to_texels);
+// uniform vec2 PREFIX(offset_bottomleft);
+// uniform vec2 PREFIX(offset_topright);
 
 vec4 FUNCNAME(vec2 tc) {
        tc -= PREFIX(offset);
 
 vec4 FUNCNAME(vec2 tc) {
        tc -= PREFIX(offset);
index 16ed17930aa9bcafff002ebb8cdf2931620d6fd3..d922944f81703f5847cc21e36778bdecfba59e42 100644 (file)
@@ -56,6 +56,9 @@ private:
        float top, left;
        float border_offset_top, border_offset_left;
        float border_offset_bottom, border_offset_right;
        float top, left;
        float border_offset_top, border_offset_left;
        float border_offset_bottom, border_offset_right;
+       float uniform_offset[2], uniform_scale[2];
+       float uniform_normalized_coords_to_texels[2];
+       float uniform_offset_bottomleft[2], uniform_offset_topright[2];
 };
 
 class IntegralPaddingEffect : public PaddingEffect {
 };
 
 class IntegralPaddingEffect : public PaddingEffect {
index 0ec611af75bd9bff87e85837410387816e5f9e5a..4dd3ea87e261086939a91e2d26d51ef52c813168 100644 (file)
@@ -390,6 +390,13 @@ SingleResamplePassEffect::SingleResamplePassEffect(ResampleEffect *parent)
        register_int("output_height", &output_height);
        register_float("offset", &offset);
        register_float("zoom", &zoom);
        register_int("output_height", &output_height);
        register_float("offset", &offset);
        register_float("zoom", &zoom);
+       register_uniform_sampler2d("sample_tex", &uniform_sample_tex);
+       register_uniform_int("num_samples", &uniform_num_samples);  // FIXME: What about GLSL pre-1.30?
+       register_uniform_float("num_loops", &uniform_num_loops);
+       register_uniform_float("slice_height", &uniform_slice_height);
+       register_uniform_float("sample_x_scale", &uniform_sample_x_scale);
+       register_uniform_float("sample_x_offset", &uniform_sample_x_offset);
+       register_uniform_float("whole_pixel_offset", &uniform_whole_pixel_offset);
 
        glGenTextures(1, &texnum);
 }
 
        glGenTextures(1, &texnum);
 }
@@ -625,23 +632,21 @@ void SingleResamplePassEffect::set_gl_state(GLuint glsl_program_num, const strin
        glBindTexture(GL_TEXTURE_2D, texnum);
        check_error();
 
        glBindTexture(GL_TEXTURE_2D, texnum);
        check_error();
 
-       set_uniform_int(glsl_program_num, prefix, "sample_tex", *sampler_num);
+       uniform_sample_tex = *sampler_num;
        ++*sampler_num;
        ++*sampler_num;
-       set_uniform_int(glsl_program_num, prefix, "num_samples", src_bilinear_samples);
-       set_uniform_float(glsl_program_num, prefix, "num_loops", num_loops);
-       set_uniform_float(glsl_program_num, prefix, "slice_height", slice_height);
+       uniform_num_samples = src_bilinear_samples;
+       uniform_num_loops = num_loops;
+       uniform_slice_height = slice_height;
 
        // Instructions for how to convert integer sample numbers to positions in the weight texture.
 
        // Instructions for how to convert integer sample numbers to positions in the weight texture.
-       set_uniform_float(glsl_program_num, prefix, "sample_x_scale", 1.0f / src_bilinear_samples);
-       set_uniform_float(glsl_program_num, prefix, "sample_x_offset", 0.5f / src_bilinear_samples);
+       uniform_sample_x_scale = 1.0f / src_bilinear_samples;
+       uniform_sample_x_offset = 0.5f / src_bilinear_samples;
 
 
-       float whole_pixel_offset;
        if (direction == SingleResamplePassEffect::VERTICAL) {
        if (direction == SingleResamplePassEffect::VERTICAL) {
-               whole_pixel_offset = lrintf(offset) / float(input_height);
+               uniform_whole_pixel_offset = lrintf(offset) / float(input_height);
        } else {
        } else {
-               whole_pixel_offset = lrintf(offset) / float(input_width);
+               uniform_whole_pixel_offset = lrintf(offset) / float(input_width);
        }
        }
-       set_uniform_float(glsl_program_num, prefix, "whole_pixel_offset", whole_pixel_offset);
 
        // We specifically do not want mipmaps on the input texture;
        // they break minification.
 
        // We specifically do not want mipmaps on the input texture;
        // they break minification.
index f54a8be28b35a23a21e3128175ad5098992b1501..015bc981727524ca193850df8c857ddaaf780510 100644 (file)
@@ -1,12 +1,13 @@
 // DIRECTION_VERTICAL will be #defined to 1 if we are scaling vertically,
 // and 0 otherwise.
 
 // DIRECTION_VERTICAL will be #defined to 1 if we are scaling vertically,
 // and 0 otherwise.
 
-uniform sampler2D PREFIX(sample_tex);
-uniform int PREFIX(num_samples);
-uniform float PREFIX(num_loops);
-uniform float PREFIX(sample_x_scale);
-uniform float PREFIX(sample_x_offset);
-uniform float PREFIX(slice_height);
+// Implicit uniforms:
+// uniform sampler2D PREFIX(sample_tex);
+// uniform int PREFIX(num_samples);
+// uniform float PREFIX(num_loops);
+// uniform float PREFIX(sample_x_scale);
+// uniform float PREFIX(sample_x_offset);
+// uniform float PREFIX(slice_height);
 
 // We put the fractional part of the offset (-0.5 to 0.5 pixels) in the weights
 // because we have to (otherwise they'd do nothing). However, the support texture
 
 // We put the fractional part of the offset (-0.5 to 0.5 pixels) in the weights
 // because we have to (otherwise they'd do nothing). However, the support texture
@@ -24,7 +25,9 @@ uniform float PREFIX(slice_height);
 // measured in _input_ pixels and tc is in _output_ pixels, although we could
 // compensate for that.) However, the shader should be mostly bandwidth bound
 // and not ALU bound, so an extra add per sample shouldn't be too hopeless.
 // measured in _input_ pixels and tc is in _output_ pixels, although we could
 // compensate for that.) However, the shader should be mostly bandwidth bound
 // and not ALU bound, so an extra add per sample shouldn't be too hopeless.
-uniform float PREFIX(whole_pixel_offset);
+//
+// Implicitly declared:
+// uniform float PREFIX(whole_pixel_offset);
 
 // Sample a single weight. First fetch information about where to sample
 // and the weight from sample_tex, and then read the pixel itself.
 
 // Sample a single weight. First fetch information about where to sample
 // and the weight from sample_tex, and then read the pixel itself.
index 73dfc210e9732388e193ed2dcd0eb6cdb31d50a8..b06b09b57ae9af67f18e938396adc8ab8ddbdd0d 100644 (file)
@@ -103,6 +103,11 @@ private:
        EffectChain *chain;
        Direction direction;
        GLuint texnum;
        EffectChain *chain;
        Direction direction;
        GLuint texnum;
+       GLint uniform_sample_tex;
+       float uniform_num_loops, uniform_slice_height, uniform_sample_x_scale, uniform_sample_x_offset;
+       float uniform_whole_pixel_offset;
+       int uniform_num_samples;
+
        int input_width, input_height, output_width, output_height;
        float offset, zoom;
        int last_input_width, last_input_height, last_output_width, last_output_height;
        int input_width, input_height, output_width, output_height;
        float offset, zoom;
        int last_input_width, last_input_height, last_output_width, last_output_height;
index 50504fecbf0a4851af6c59d69fac02ad92349558..66fed5167f8578561bd1688b10b280105bde575f 100644 (file)
@@ -19,6 +19,10 @@ SliceEffect::SliceEffect()
        register_int("output_slice_size", &output_slice_size);
        register_int("offset", &offset);
        register_int("direction", (int *)&direction);
        register_int("output_slice_size", &output_slice_size);
        register_int("offset", &offset);
        register_int("direction", (int *)&direction);
+       register_uniform_float("output_coord_to_slice_num", &uniform_output_coord_to_slice_num);
+       register_uniform_float("slice_num_to_input_coord", &uniform_slice_num_to_input_coord);
+       register_uniform_float("slice_offset_to_input_coord", &uniform_slice_offset_to_input_coord);
+       register_uniform_float("offset", &uniform_offset);
 }
 
 string SliceEffect::output_fragment_shader()
 }
 
 string SliceEffect::output_fragment_shader()
@@ -57,15 +61,15 @@ void SliceEffect::set_gl_state(GLuint glsl_program_num, const string &prefix, un
        get_output_size(&output_width, &output_height, &output_width, &output_height);
 
        if (direction == HORIZONTAL) {
        get_output_size(&output_width, &output_height, &output_width, &output_height);
 
        if (direction == HORIZONTAL) {
-               set_uniform_float(glsl_program_num, prefix, "output_coord_to_slice_num", float(output_width) / float(output_slice_size));
-               set_uniform_float(glsl_program_num, prefix, "slice_num_to_input_coord", float(input_slice_size) / float(input_width));
-               set_uniform_float(glsl_program_num, prefix, "slice_offset_to_input_coord", float(output_slice_size) / float(input_width));
-               set_uniform_float(glsl_program_num, prefix, "offset", float(offset) / float(input_width));
+               uniform_output_coord_to_slice_num = float(output_width) / float(output_slice_size);
+               uniform_slice_num_to_input_coord = float(input_slice_size) / float(input_width);
+               uniform_slice_offset_to_input_coord = float(output_slice_size) / float(input_width);
+               uniform_offset = float(offset) / float(input_width);
        } else {
        } else {
-               set_uniform_float(glsl_program_num, prefix, "output_coord_to_slice_num", float(output_height) / float(output_slice_size));
-               set_uniform_float(glsl_program_num, prefix, "slice_num_to_input_coord", float(input_slice_size) / float(input_height));
-               set_uniform_float(glsl_program_num, prefix, "slice_offset_to_input_coord", float(output_slice_size) / float(input_height));
-               set_uniform_float(glsl_program_num, prefix, "offset", float(offset) / float(input_height));
+               uniform_output_coord_to_slice_num = float(output_height) / float(output_slice_size);
+               uniform_slice_num_to_input_coord = float(input_slice_size) / float(input_height);
+               uniform_slice_offset_to_input_coord = float(output_slice_size) / float(input_height);
+               uniform_offset = float(offset) / float(input_height);
        }
 
        // Normalized coordinates could potentially cause blurring of the image.
        }
 
        // Normalized coordinates could potentially cause blurring of the image.
index e77c9fad7bf39e38444724d5879df64710f074f4..e9c2c373aea8cf3af28dc25852c67bfd2e94fa48 100644 (file)
@@ -1,7 +1,8 @@
-uniform float PREFIX(output_coord_to_slice_num);
-uniform float PREFIX(slice_num_to_input_coord);
-uniform float PREFIX(slice_offset_to_input_coord);
-uniform float PREFIX(offset);
+// Implicit uniforms:
+// uniform float PREFIX(output_coord_to_slice_num);
+// uniform float PREFIX(slice_num_to_input_coord);
+// uniform float PREFIX(slice_offset_to_input_coord);
+// uniform float PREFIX(offset);
  
 vec4 FUNCNAME(vec2 tc) {
        // DIRECTION_VERTICAL will be #defined to 1 if we are expanding vertically,
  
 vec4 FUNCNAME(vec2 tc) {
        // DIRECTION_VERTICAL will be #defined to 1 if we are expanding vertically,
index ccca527922d314d40e895b15e5d79b04d909164f..ef96dddcb1e8474a07f037862fd37afe4a41951a 100644 (file)
@@ -40,6 +40,9 @@ private:
        int input_slice_size, output_slice_size;
        int offset;
        Direction direction;
        int input_slice_size, output_slice_size;
        int offset;
        Direction direction;
+
+       float uniform_output_coord_to_slice_num, uniform_slice_num_to_input_coord;
+       float uniform_slice_offset_to_input_coord, uniform_offset;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index a4b368385065a5ce56c8169a7af491286855f3ad..616c4be07d56061f05e574d3058e598d2c93adb7 100644 (file)
--- a/version.h
+++ b/version.h
@@ -5,6 +5,6 @@
 // changes, even within git versions. There is no specific version
 // documentation outside the regular changelogs, though.
 
 // changes, even within git versions. There is no specific version
 // documentation outside the regular changelogs, though.
 
-#define MOVIT_VERSION 1
+#define MOVIT_VERSION 2
 
 #endif // !defined(_MOVIT_VERSION_H)
 
 #endif // !defined(_MOVIT_VERSION_H)
index d8b4f9bf24d674fc1cf6b815e7e6f07c16e8ff78..088406b78779e49afbb0dccf4f41a274b4620be7 100644 (file)
@@ -12,13 +12,17 @@ namespace movit {
 
 VignetteEffect::VignetteEffect()
        : center(0.5f, 0.5f),
 
 VignetteEffect::VignetteEffect()
        : center(0.5f, 0.5f),
-         aspect_correction(1.0f, 1.0f),
+         uniform_aspect_correction(1.0f, 1.0f),
+         uniform_flipped_center(0.5f, 0.5f),
          radius(0.3f),
          inner_radius(0.3f)
 {
        register_vec2("center", (float *)&center);
        register_float("radius", (float *)&radius);
        register_float("inner_radius", (float *)&inner_radius);
          radius(0.3f),
          inner_radius(0.3f)
 {
        register_vec2("center", (float *)&center);
        register_float("radius", (float *)&radius);
        register_float("inner_radius", (float *)&inner_radius);
+       register_uniform_float("pihalf_div_radius", &uniform_pihalf_div_radius);
+       register_uniform_vec2("aspect_correction", (float *)&uniform_aspect_correction);
+       register_uniform_vec2("flipped_center", (float *)&uniform_flipped_center);
 }
 
 string VignetteEffect::output_fragment_shader()
 }
 
 string VignetteEffect::output_fragment_shader()
@@ -29,9 +33,9 @@ string VignetteEffect::output_fragment_shader()
 void VignetteEffect::inform_input_size(unsigned input_num, unsigned width, unsigned height) {
        assert(input_num == 0);
        if (width >= height) {
 void VignetteEffect::inform_input_size(unsigned input_num, unsigned width, unsigned height) {
        assert(input_num == 0);
        if (width >= height) {
-               aspect_correction = Point2D(float(width) / float(height), 1.0f);
+               uniform_aspect_correction = Point2D(float(width) / float(height), 1.0f);
        } else {
        } else {
-               aspect_correction = Point2D(1.0f, float(height) / float(width));
+               uniform_aspect_correction = Point2D(1.0f, float(height) / float(width));
        }
 }
 
        }
 }
 
@@ -39,11 +43,8 @@ void VignetteEffect::set_gl_state(GLuint glsl_program_num, const string &prefix,
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
 
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
 
-       set_uniform_float(glsl_program_num, prefix, "pihalf_div_radius", 0.5 * M_PI / radius);
-       set_uniform_vec2(glsl_program_num, prefix, "aspect_correction", (float *)&aspect_correction);
-
-       Point2D flipped_center(center.x, 1.0f - center.y);
-       set_uniform_vec2(glsl_program_num, prefix, "flipped_center", (float *)&flipped_center);
+       uniform_pihalf_div_radius = 0.5 * M_PI / radius;
+       uniform_flipped_center = Point2D(center.x, 1.0f - center.y);
 }
 
 }  // namespace movit
 }
 
 }  // namespace movit
index 60d4b335858ba33a2522fce2f49db891ee68a042..e8d185f6165f912b325fd61e3caef7e4c8cd5b68 100644 (file)
@@ -1,8 +1,10 @@
 // A simple, circular vignette, with a cos² falloff.
 // A simple, circular vignette, with a cos² falloff.
-       
-uniform float PREFIX(pihalf_div_radius);
-uniform vec2 PREFIX(aspect_correction);
-uniform vec2 PREFIX(flipped_center);
+
+// Implicit uniforms:
+// uniform float PREFIX(pihalf_div_radius);
+//
+// uniform vec2 PREFIX(aspect_correction);
+// uniform vec2 PREFIX(flipped_center);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 x = INPUT(tc);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 x = INPUT(tc);
index 582e67687ef42bf67699980337ad71d430f5259a..926a5be0e0e5dd794c72b2ee0c7c507bedbee919 100644 (file)
@@ -25,8 +25,10 @@ public:
        void set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num);
 
 private:
        void set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num);
 
 private:
-       Point2D center, aspect_correction;
+       Point2D center;
+       Point2D uniform_aspect_correction, uniform_flipped_center;
        float radius, inner_radius;
        float radius, inner_radius;
+       float uniform_pihalf_div_radius;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index 69759adfc6148379698998674109a5ae17213e4b..07c95cac4ca473b52dda9f9d80ddbf9fda918a52 100644 (file)
@@ -105,6 +105,7 @@ WhiteBalanceEffect::WhiteBalanceEffect()
 {
        register_vec3("neutral_color", (float *)&neutral_color);
        register_float("output_color_temperature", &output_color_temperature);
 {
        register_vec3("neutral_color", (float *)&neutral_color);
        register_float("output_color_temperature", &output_color_temperature);
+       register_uniform_mat3("correction_matrix", &uniform_correction_matrix);
 }
 
 string WhiteBalanceEffect::output_fragment_shader()
 }
 
 string WhiteBalanceEffect::output_fragment_shader()
@@ -142,13 +143,12 @@ void WhiteBalanceEffect::set_gl_state(GLuint glsl_program_num, const string &pre
         * Note that since we postmultiply our vectors, the order of the matrices
         * has to be the opposite of the execution order.
         */
         * Note that since we postmultiply our vectors, the order of the matrices
         * has to be the opposite of the execution order.
         */
-       Matrix3d corr_matrix =
+       uniform_correction_matrix =
                rgb_to_xyz_matrix.inverse() *
                Map<const Matrix3d>(xyz_to_lms_matrix).inverse() *
                lms_scale.asDiagonal() *
                Map<const Matrix3d>(xyz_to_lms_matrix) *
                rgb_to_xyz_matrix;
                rgb_to_xyz_matrix.inverse() *
                Map<const Matrix3d>(xyz_to_lms_matrix).inverse() *
                lms_scale.asDiagonal() *
                Map<const Matrix3d>(xyz_to_lms_matrix) *
                rgb_to_xyz_matrix;
-       set_uniform_mat3(glsl_program_num, prefix, "correction_matrix", corr_matrix);
 }
 
 }  // namespace movit
 }
 
 }  // namespace movit
index 926e0de71b5beed2b9e7027f99f1b4b367a35ff6..2d196a4bfe76e71c2b7fc31f675e7b2fc34e154b 100644 (file)
@@ -1,4 +1,5 @@
-uniform mat3 PREFIX(correction_matrix);
+// Implicit uniforms:
+// uniform mat3 PREFIX(correction_matrix);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 ret = INPUT(tc);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 ret = INPUT(tc);
index 342426beee9e514ae1b16debe2a6181c37d09079..2370847e966872746e0a75e967550bedd9979e45 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <epoxy/gl.h>
 #include <string>
 
 #include <epoxy/gl.h>
 #include <string>
+#include <Eigen/Core>
 
 #include "effect.h"
 
 
 #include "effect.h"
 
@@ -27,6 +28,8 @@ private:
        // Output color temperature (in Kelvins).
        // Choosing 6500 will lead to no color cast (ie., the neutral color becomes perfectly gray).
        float output_color_temperature;
        // Output color temperature (in Kelvins).
        // Choosing 6500 will lead to no color cast (ie., the neutral color becomes perfectly gray).
        float output_color_temperature;
+
+       Eigen::Matrix3d uniform_correction_matrix;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index b6342893b73ffd89e9d1e50aeb423d76c8e32c4a..c345f8d805ae83a69923c21f01ff601b616341a1 100644 (file)
@@ -36,6 +36,9 @@ YCbCr422InterleavedInput::YCbCr422InterleavedInput(const ImageFormat &image_form
        pitches[CHANNEL_CHROMA] = width / ycbcr_format.chroma_subsampling_x;
 
        pixel_data = NULL;
        pitches[CHANNEL_CHROMA] = width / ycbcr_format.chroma_subsampling_x;
 
        pixel_data = NULL;
+
+       register_uniform_sampler2d("tex_y", &uniform_tex_y);
+       register_uniform_sampler2d("tex_cbcr", &uniform_tex_cbcr);
 }
 
 YCbCr422InterleavedInput::~YCbCr422InterleavedInput()
 }
 
 YCbCr422InterleavedInput::~YCbCr422InterleavedInput()
@@ -94,8 +97,8 @@ void YCbCr422InterleavedInput::set_gl_state(GLuint glsl_program_num, const strin
        check_error();
 
        // Bind samplers.
        check_error();
 
        // Bind samplers.
-       set_uniform_int(glsl_program_num, prefix, "tex_y", *sampler_num + 0);
-       set_uniform_int(glsl_program_num, prefix, "tex_cbcr", *sampler_num + 1);
+       uniform_tex_y = *sampler_num + 0;
+       uniform_tex_cbcr = *sampler_num + 1;
 
        *sampler_num += 2;
 }
 
        *sampler_num += 2;
 }
index 66762a8c7d685060d75a2feff2e82a7058482aac..96b93f8ba32b9bd3c5bb862701147dfae4996dfc 100644 (file)
@@ -1,5 +1,6 @@
-uniform sampler2D PREFIX(tex_y);
-uniform sampler2D PREFIX(tex_cbcr);
+// Implicit uniforms:
+// uniform sampler2D PREFIX(tex_y);
+// uniform sampler2D PREFIX(tex_cbcr);
 
 vec4 FUNCNAME(vec2 tc) {
        // OpenGL's origin is bottom-left, but most graphics software assumes
 
 vec4 FUNCNAME(vec2 tc) {
        // OpenGL's origin is bottom-left, but most graphics software assumes
index b3469864d5024373b9c301d73243e4cd3fac0c81..b7000a04166a0ee13fd89e96b6481659efd62e74 100644 (file)
@@ -123,6 +123,8 @@ private:
        unsigned width, height;
        const unsigned char *pixel_data;
        ResourcePool *resource_pool;
        unsigned width, height;
        const unsigned char *pixel_data;
        ResourcePool *resource_pool;
+
+       GLint uniform_tex_y, uniform_tex_cbcr;
 };
 
 }  // namespace movit
 };
 
 }  // namespace movit
index 091880fdade7f0dd2ee778b9bc74366dc668a637..ed1f5694faa65e0567116b9977cb71cc78175eaa 100644 (file)
@@ -39,6 +39,10 @@ YCbCrInput::YCbCrInput(const ImageFormat &image_format,
        heights[2] = height / ycbcr_format.chroma_subsampling_y;
 
        pixel_data[0] = pixel_data[1] = pixel_data[2] = NULL;
        heights[2] = height / ycbcr_format.chroma_subsampling_y;
 
        pixel_data[0] = pixel_data[1] = pixel_data[2] = NULL;
+
+       register_uniform_sampler2d("tex_y", &uniform_tex_y);
+       register_uniform_sampler2d("tex_cb", &uniform_tex_cb);
+       register_uniform_sampler2d("tex_cr", &uniform_tex_cr);
 }
 
 YCbCrInput::~YCbCrInput()
 }
 
 YCbCrInput::~YCbCrInput()
@@ -87,9 +91,9 @@ void YCbCrInput::set_gl_state(GLuint glsl_program_num, const string& prefix, uns
        check_error();
 
        // Bind samplers.
        check_error();
 
        // Bind samplers.
-       set_uniform_int(glsl_program_num, prefix, "tex_y", *sampler_num + 0);
-       set_uniform_int(glsl_program_num, prefix, "tex_cb", *sampler_num + 1);
-       set_uniform_int(glsl_program_num, prefix, "tex_cr", *sampler_num + 2);
+       uniform_tex_y = *sampler_num + 0;
+       uniform_tex_cb = *sampler_num + 1;
+       uniform_tex_cr = *sampler_num + 2;
 
        *sampler_num += 3;
 }
 
        *sampler_num += 3;
 }
index bd6ff766569730287af70152ef58dc679ef9d867..b84499d4408b4c1a97ce41785f4e7104573b7ebb 100644 (file)
@@ -1,6 +1,7 @@
-uniform sampler2D PREFIX(tex_y);
-uniform sampler2D PREFIX(tex_cb);
-uniform sampler2D PREFIX(tex_cr);
+// Implicit uniforms:
+// uniform sampler2D PREFIX(tex_y);
+// uniform sampler2D PREFIX(tex_cb);
+// uniform sampler2D PREFIX(tex_cr);
 
 vec4 FUNCNAME(vec2 tc) {
        // OpenGL's origin is bottom-left, but most graphics software assumes
 
 vec4 FUNCNAME(vec2 tc) {
        // OpenGL's origin is bottom-left, but most graphics software assumes
index 97ad5266bb3b0c9942f39dd3a2964aceedf848c1..7db5375c187cc4c035aab31cdc0065f4551aefcd 100644 (file)
@@ -79,6 +79,7 @@ private:
        ImageFormat image_format;
        YCbCrFormat ycbcr_format;
        GLuint pbos[3], texture_num[3];
        ImageFormat image_format;
        YCbCrFormat ycbcr_format;
        GLuint pbos[3], texture_num[3];
+       GLint uniform_tex_y, uniform_tex_cb, uniform_tex_cr;
 
        unsigned width, height, widths[3], heights[3];
        const unsigned char *pixel_data[3];
 
        unsigned width, height, widths[3], heights[3];
        const unsigned char *pixel_data[3];