aspect_denom(aspect_denom),
dither_effect(NULL),
num_dither_bits(0),
+ output_origin(OUTPUT_ORIGIN_BOTTOM_LEFT),
finalized(false),
resource_pool(resource_pool),
do_phase_timing(false) {
frag_shader = frag_shader_header + frag_shader_uniforms + frag_shader;
string vert_shader = read_version_dependent_file("vs", "vert");
+
+ // If we're the last phase and need to flip the picture to compensate for
+ // the origin, tell the vertex shader so.
+ if (phase->output_node->outgoing_links.empty() && output_origin == OUTPUT_ORIGIN_TOP_LEFT) {
+ const string needle = "#define FLIP_ORIGIN 0";
+ size_t pos = vert_shader.find(needle);
+ assert(pos != string::npos);
+
+ vert_shader[pos + needle.size() - 1] = '1';
+ }
+
phase->glsl_program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader);
// Collect the resulting location numbers for each uniform.
YCBCR_OUTPUT_PLANAR,
};
+// Where (0,0) is taken to be in the output. If you want to render to an
+// OpenGL screen, you should keep the default of bottom-left, as that is
+// OpenGL's natural coordinate system. However, there are cases, such as if you
+// render to an FBO and read the pixels back into some other system, where
+// you'd want a top-left origin; if so, an additional flip step will be added
+// at the very end (but done in a vertex shader, so it will have zero extra
+// cost).
+//
+// Note that Movit's coordinate system in general consistently puts (0,0) in
+// the top left for _input_, no matter what you set as output origin.
+enum OutputOrigin {
+ OUTPUT_ORIGIN_BOTTOM_LEFT,
+ OUTPUT_ORIGIN_TOP_LEFT,
+};
+
// A node in the graph; basically an effect and some associated information.
class Node {
public:
this->num_dither_bits = num_bits;
}
+ // Set where (0,0) is taken to be in the output. The default is
+ // OUTPUT_ORIGIN_BOTTOM_LEFT, which is usually what you want
+ // (see OutputOrigin above for more details).
+ void set_output_origin(OutputOrigin output_origin)
+ {
+ this->output_origin = output_origin;
+ }
+
void finalize();
// Measure the GPU time used for each actual phase during rendering.
std::vector<Phase *> phases;
unsigned num_dither_bits;
+ OutputOrigin output_origin;
bool finalized;
ResourcePool *resource_pool;
expect_equal(expected_data, out_data, 3, 2);
}
+TEST(EffectChainTest, TopLeftOrigin) {
+ float data[] = {
+ 0.0f, 0.25f, 0.3f,
+ 0.75f, 1.0f, 1.0f,
+ };
+ // Note that EffectChainTester assumes bottom-left origin, so by setting
+ // top-left, we will get flipped data back.
+ float expected_data[6] = {
+ 0.75f, 1.0f, 1.0f,
+ 0.0f, 0.25f, 0.3f,
+ };
+ float out_data[6];
+ EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+ tester.get_chain()->set_output_origin(OUTPUT_ORIGIN_TOP_LEFT);
+ tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+
+ expect_equal(expected_data, out_data, 3, 2);
+}
+
// A dummy effect that inverts its input.
class InvertEffect : public Effect {
public:
// changes, even within git versions. There is no specific version
// documentation outside the regular changelogs, though.
-#define MOVIT_VERSION 4
+#define MOVIT_VERSION 5
#endif // !defined(_MOVIT_VERSION_H)
in vec2 texcoord;
out vec2 tc;
+// Will be overridden by compile_glsl_program() if needed.
+// (It cannot just be prepended, as #version must be before everything.)
+#define FLIP_ORIGIN 0
+
void main()
{
// The result of glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0) is:
// 0.000 0.000 0.000 1.000
gl_Position = vec4(2.0 * position.x - 1.0, 2.0 * position.y - 1.0, -1.0, 1.0);
tc = texcoord;
+#if FLIP_ORIGIN
+ tc.y = 1.0f - tc.y;
+#endif
}
in vec2 texcoord;
out vec2 tc;
+// Will be overridden by compile_glsl_program() if needed.
+// (It cannot just be prepended, as #version must be before everything.)
+#define FLIP_ORIGIN 0
+
void main()
{
// The result of glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0) is:
// 0.000 0.000 0.000 1.000
gl_Position = vec4(2.0 * position.x - 1.0, 2.0 * position.y - 1.0, -1.0, 1.0);
tc = texcoord;
+#if FLIP_ORIGIN
+ tc.y = 1.0f - tc.y;
+#endif
}
attribute vec2 texcoord;
varying vec2 tc;
+// Will be overridden by compile_glsl_program() if needed.
+// (It cannot just be prepended, as #version must be before everything.)
+#define FLIP_ORIGIN 0
+
void main()
{
// The result of glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0) is:
// 0.000 0.000 0.000 1.000
gl_Position = vec4(2.0 * position.x - 1.0, 2.0 * position.y - 1.0, -1.0, 1.0);
tc = texcoord;
+#if FLIP_ORIGIN
+ tc.y = 1.0f - tc.y;
+#endif
}