Merge branch 'master' into epoxy
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 10 Mar 2014 00:28:46 +0000 (01:28 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 10 Mar 2014 00:31:54 +0000 (01:31 +0100)
1  2 
Makefile.in
flat_input.cpp
flat_input.h
slice_effect.cpp
slice_effect.h
slice_effect_test.cpp
test_util.cpp
test_util.h
util.cpp
util.h

diff --cc Makefile.in
Simple merge
diff --cc flat_input.cpp
Simple merge
diff --cc flat_input.h
Simple merge
index 0000000,09b91b9..3cdd415
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,76 +1,76 @@@
 -#include <GL/glew.h>
++#include <epoxy/gl.h>
+ #include "slice_effect.h"
+ #include "effect_util.h"
+ #include "util.h"
+ using namespace std;
+ namespace movit {
+ SliceEffect::SliceEffect()
+ {
+       register_int("input_slice_size", &input_slice_size);
+       register_int("output_slice_size", &output_slice_size);
+       register_int("direction", (int *)&direction);
+ }
+ string SliceEffect::output_fragment_shader()
+ {
+       char buf[256];
+       sprintf(buf, "#define DIRECTION_VERTICAL %d\n", (direction == VERTICAL));
+       return buf + read_file("slice_effect.frag");
+ }
+       
+ void SliceEffect::inform_input_size(unsigned input_num, unsigned width, unsigned height)
+ {
+       assert(input_num == 0);
+       input_width = width;
+       input_height = height;
+ }
+ void SliceEffect::get_output_size(unsigned *width, unsigned *height,
+                                   unsigned *virtual_width, unsigned *virtual_height) const
+ {
+       if (direction == HORIZONTAL) {
+               *width = div_round_up(input_width, input_slice_size) * output_slice_size;
+               *height = input_height; 
+       } else {
+               *width = input_width;   
+               *height = div_round_up(input_height, input_slice_size) * output_slice_size;
+       }
+       *virtual_width = *width;
+       *virtual_height = *height;
+ }
+ void SliceEffect::set_gl_state(GLuint glsl_program_num, const string &prefix, unsigned *sampler_num)
+ {
+       Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
+       unsigned output_width, output_height;
+       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));
+       } 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));
+       }
+       // Normalized coordinates could potentially cause blurring of the
+       // image; it's not critical, but we have set changes_output_size()
+       // and needs_texture_bounce(), so simply turning off the interpolation
+       // is allowed.
+       assert(*sampler_num == 1);
+       glActiveTexture(GL_TEXTURE0);
+       check_error();
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       check_error();
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+       check_error();
+ }
+ }  // namespace movit
diff --cc slice_effect.h
index 0000000,6380c16..3448941
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,43 +1,43 @@@
 -#include <GL/glew.h>
+ #ifndef _MOVIT_SLICE_EFFECT_H
+ #define _MOVIT_SLICE_EFFECT_H 1
+ // SliceEffect takes an image, cuts it into (potentially overlapping) slices,
+ // and puts those slices back together again consecutively. It is primarily
+ // useful in an overlap-discard setting, where it can do both the overlap and
+ // discard roles, where one does convolutions by means of many small FFTs, but
+ // could also work as a (relatively boring) video effect on its own.
+ //
+ // Note that vertical slices happen from the bottom, not the top, due to the
+ // OpenGL coordinate system.
++#include <epoxy/gl.h>
+ #include <string>
+ #include "effect.h"
+ namespace movit {
+ class SliceEffect : public Effect {
+ public:
+       SliceEffect();
+       virtual std::string effect_type_id() const { return "SliceEffect"; }
+       std::string output_fragment_shader();
+       virtual bool needs_texture_bounce() const { return true; }
+       virtual bool changes_output_size() const { return true; }
+       virtual void inform_input_size(unsigned input_num, unsigned width, unsigned height);
+       virtual void get_output_size(unsigned *width, unsigned *height,
+                                    unsigned *virtual_width, unsigned *virtual_height) const;
+       void set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num);
+       
+       enum Direction { HORIZONTAL = 0, VERTICAL = 1 };
+ private:
+       int input_width, input_height;
+       int input_slice_size, output_slice_size;
+       Direction direction;
+ };
+ }  // namespace movit
+ #endif // !defined(_MOVIT_SLICE_EFFECT_H)
index 0000000,efa6803..410439a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,117 +1,117 @@@
 -#include <GL/glew.h>
+ // Unit tests for SliceEffect.
++#include <epoxy/gl.h>
+ #include "effect_chain.h"
+ #include "flat_input.h"
+ #include "gtest/gtest.h"
+ #include "image_format.h"
+ #include "input.h"
+ #include "slice_effect.h"
+ #include "test_util.h"
+ namespace movit {
+ TEST(SliceEffectTest, Identity) {
+       const int size = 3, output_size = 4;
+       float data[size * size] = {
+               0.0f, 0.1f, 0.2f,
+               0.4f, 0.3f, 0.8f,
+               0.5f, 0.2f, 0.1f,
+       };
+       float expected_data[output_size * size] = {
+               0.0f, 0.1f, 0.2f, 0.2f,
+               0.4f, 0.3f, 0.8f, 0.8f,
+               0.5f, 0.2f, 0.1f, 0.1f,
+       };
+       float out_data[output_size * size];
+       EffectChainTester tester(NULL, output_size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
+       Effect *slice_effect = tester.get_chain()->add_effect(new SliceEffect());
+       ASSERT_TRUE(slice_effect->set_int("input_slice_size", 2));
+       ASSERT_TRUE(slice_effect->set_int("output_slice_size", 2));
+       ASSERT_TRUE(slice_effect->set_int("direction", SliceEffect::HORIZONTAL));
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+       expect_equal(expected_data, out_data, output_size, size);
+ }
+ TEST(SliceEffectTest, HorizontalOverlap) {
+       float data[5 * 2] = {
+               0.0f, 0.1f,  0.2f, 0.3f,  0.4f,
+               0.4f, 0.3f,  0.2f, 0.1f,  0.0f,
+       };
+       float expected_data[9 * 2] = {
+               0.0f, 0.1f, 0.2f,  0.2f, 0.3f, 0.4f,  0.4f, 0.4f, 0.4f,
+               0.4f, 0.3f, 0.2f,  0.2f, 0.1f, 0.0f,  0.0f, 0.0f, 0.0f,
+       };
+       float out_data[9 * 2];
+       EffectChainTester tester(NULL, 9, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 5, 2);
+       Effect *slice_effect = tester.get_chain()->add_effect(new SliceEffect());
+       ASSERT_TRUE(slice_effect->set_int("input_slice_size", 2));
+       ASSERT_TRUE(slice_effect->set_int("output_slice_size", 3));
+       ASSERT_TRUE(slice_effect->set_int("direction", SliceEffect::HORIZONTAL));
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+       expect_equal(expected_data, out_data, 9, 2);
+ }
+ TEST(SliceEffectTest, HorizontalDiscard) {
+       float data[6 * 2] = {
+               0.0f, 0.1f, 0.2f,  0.2f, 0.3f, 0.4f,
+               0.4f, 0.3f, 0.2f,  0.2f, 0.1f, 0.0f,
+       };
+       float expected_data[4 * 2] = {
+               0.0f, 0.1f,  0.2f, 0.3f,
+               0.4f, 0.3f,  0.2f, 0.1f,
+       };
+       float out_data[4 * 2];
+       EffectChainTester tester(NULL, 4, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 6, 2);
+       Effect *slice_effect = tester.get_chain()->add_effect(new SliceEffect());
+       ASSERT_TRUE(slice_effect->set_int("input_slice_size", 3));
+       ASSERT_TRUE(slice_effect->set_int("output_slice_size", 2));
+       ASSERT_TRUE(slice_effect->set_int("direction", SliceEffect::HORIZONTAL));
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+       expect_equal(expected_data, out_data, 4, 2);
+ }
+ TEST(SliceEffectTest, VerticalOverlapSlicesFromBottom) {
+       float data[2 * 3] = {
+               0.0f, 0.1f,
+               0.4f, 0.3f,
+               0.6f, 0.2f,
+       };
+       float expected_data[2 * 6] = {
+               0.0f, 0.1f,
+               0.0f, 0.1f,
+               0.0f, 0.1f,
+               0.0f, 0.1f,
+               0.4f, 0.3f,
+               0.6f, 0.2f,
+       };
+       float out_data[2 * 6];
+       EffectChainTester tester(NULL, 2, 6, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 2, 3);
+       Effect *slice_effect = tester.get_chain()->add_effect(new SliceEffect());
+       ASSERT_TRUE(slice_effect->set_int("input_slice_size", 2));
+       ASSERT_TRUE(slice_effect->set_int("output_slice_size", 3));
+       ASSERT_TRUE(slice_effect->set_int("direction", SliceEffect::VERTICAL));
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+       expect_equal(expected_data, out_data, 2, 6);
+ }
+ }  // namespace movit
diff --cc test_util.cpp
Simple merge
diff --cc test_util.h
Simple merge
diff --cc util.cpp
Simple merge
diff --cc util.h
Simple merge