1 // Unit tests for FlatInput.
6 #include "effect_chain.h"
7 #include "flat_input.h"
8 #include "gtest/gtest.h"
9 #include "resource_pool.h"
10 #include "test_util.h"
17 TEST(FlatInput, SimpleGrayscale) {
26 float expected_data[4 * size] = {
32 float out_data[4 * size];
34 EffectChainTester tester(data, 1, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
35 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
37 expect_equal(expected_data, out_data, 4, size);
40 TEST(FlatInput, RGB) {
43 float data[3 * size] = {
50 float expected_data[4 * size] = {
57 float out_data[4 * size];
59 EffectChainTester tester(data, 1, size, FORMAT_RGB, COLORSPACE_sRGB, GAMMA_LINEAR);
60 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
62 expect_equal(expected_data, out_data, 4, size);
65 TEST(FlatInput, RGBA) {
68 float data[4 * size] = {
75 float expected_data[4 * size] = {
82 float out_data[4 * size];
84 EffectChainTester tester(data, 1, size, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
85 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
87 expect_equal(expected_data, out_data, 4, size);
90 // Note: The sRGB conversion itself is tested in EffectChainTester,
91 // since it also wants to test the chain building itself.
92 // Here, we merely test that alpha is left alone; the test will usually
93 // run using the sRGB OpenGL extension, but might be run with a
94 // GammaExpansionEffect if the card/driver happens not to support that.
95 TEST(FlatInput, AlphaIsNotModifiedBySRGBConversion) {
98 unsigned char data[4 * size] = {
105 float expected_data[4 * size] = {
106 0, 0, 0, 0.0 / 255.0,
107 0, 0, 0, 63.0 / 255.0,
108 0, 0, 0, 127.0 / 255.0,
109 0, 0, 0, 191.0 / 255.0,
110 0, 0, 0, 255.0 / 255.0,
112 float out_data[4 * size];
114 EffectChainTester tester(nullptr, 1, size);
115 tester.add_input(data, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_sRGB);
116 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
118 expect_equal(expected_data, out_data, 4, size);
121 TEST(FlatInput, BGR) {
124 float data[3 * size] = {
131 float expected_data[4 * size] = {
138 float out_data[4 * size];
140 EffectChainTester tester(data, 1, size, FORMAT_BGR, COLORSPACE_sRGB, GAMMA_LINEAR);
141 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
143 expect_equal(expected_data, out_data, 4, size);
146 TEST(FlatInput, BGRA) {
149 float data[4 * size] = {
156 float expected_data[4 * size] = {
163 float out_data[4 * size];
165 EffectChainTester tester(data, 1, size, FORMAT_BGRA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
166 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
168 expect_equal(expected_data, out_data, 4, size);
171 TEST(FlatInput, Pitch) {
174 const int height = 4;
176 float data[pitch * height] = {
182 float expected_data[4 * width * height] = {
183 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0,
184 0.5, 0.5, 0.5, 1.0, 0.5, 0.5, 0.5, 1.0,
185 0.7, 0.7, 0.7, 1.0, 0.2, 0.2, 0.2, 1.0,
186 1.0, 1.0, 1.0, 1.0, 0.6, 0.6, 0.6, 1.0,
188 float out_data[4 * width * height];
190 EffectChainTester tester(nullptr, width, height);
193 format.color_space = COLORSPACE_sRGB;
194 format.gamma_curve = GAMMA_LINEAR;
196 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
197 input->set_pitch(pitch);
198 input->set_pixel_data(data);
199 tester.get_chain()->add_input(input);
201 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
202 expect_equal(expected_data, out_data, 4 * width, height);
205 TEST(FlatInput, UpdatedData) {
207 const int height = 4;
209 float data[width * height] = {
215 float out_data[width * height];
217 EffectChainTester tester(nullptr, width, height);
220 format.color_space = COLORSPACE_sRGB;
221 format.gamma_curve = GAMMA_LINEAR;
223 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
224 input->set_pixel_data(data);
225 tester.get_chain()->add_input(input);
227 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
228 expect_equal(data, out_data, width, height);
231 input->invalidate_pixel_data();
233 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
234 expect_equal(data, out_data, width, height);
237 TEST(FlatInput, PBO) {
239 const int height = 2;
241 float data[width * height] = {
245 float expected_data[4 * width * height] = {
246 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.5, 0.5, 1.0,
247 0.5, 0.5, 0.5, 1.0, 0.5, 0.5, 0.5, 1.0, 0.2, 0.2, 0.2, 1.0,
249 float out_data[4 * width * height];
252 glGenBuffers(1, &pbo);
253 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
254 glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * sizeof(float), data, GL_STREAM_DRAW);
255 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
257 EffectChainTester tester(nullptr, width, height);
260 format.color_space = COLORSPACE_sRGB;
261 format.gamma_curve = GAMMA_LINEAR;
263 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
264 input->set_pixel_data((float *)BUFFER_OFFSET(0), pbo);
265 tester.get_chain()->add_input(input);
267 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
268 expect_equal(expected_data, out_data, 4 * width, height);
270 glDeleteBuffers(1, &pbo);
273 TEST(FlatInput, ExternalTexture) {
276 float data[3 * size] = {
283 float expected_data[4 * size] = {
290 float out_data[4 * size];
292 EffectChainTester tester(nullptr, 1, size, FORMAT_RGB, COLORSPACE_sRGB, GAMMA_LINEAR);
295 format.color_space = COLORSPACE_sRGB;
296 format.gamma_curve = GAMMA_LINEAR;
299 GLuint tex = pool.create_2d_texture(GL_RGB8, 1, size);
301 glBindTexture(GL_TEXTURE_2D, tex);
303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
305 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
307 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, size, GL_RGB, GL_FLOAT, data);
309 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
314 FlatInput *input = new FlatInput(format, FORMAT_RGB, GL_FLOAT, 1, size);
315 input->set_texture_num(tex);
316 tester.get_chain()->add_input(input);
318 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
320 pool.release_2d_texture(tex);
322 expect_equal(expected_data, out_data, 4, size);
325 // Just an IdentityEffect, but marks as needing mipmaps, so that we can use it
326 // for downscaling to verify mipmaps were used.
327 class MipmapNeedingEffect : public Effect {
329 MipmapNeedingEffect() {}
330 MipmapRequirements needs_mipmaps() const override { return NEEDS_MIPMAPS; }
332 string effect_type_id() const override { return "MipmapNeedingEffect"; }
333 string output_fragment_shader() override { return read_file("identity.frag"); }
339 TEST(FlatInput, ExternalTextureMipmapState) {
341 const int height = 4;
343 float data[width * height] = {
349 float expected_data[] = {
354 EffectChainTester tester(nullptr, 1, 1, FORMAT_RGB, COLORSPACE_sRGB, GAMMA_LINEAR);
357 format.color_space = COLORSPACE_sRGB;
358 format.gamma_curve = GAMMA_LINEAR;
361 GLuint tex = pool.create_2d_texture(GL_R8, width, height);
363 glBindTexture(GL_TEXTURE_2D, tex);
365 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
367 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
369 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_FLOAT, data);
371 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
375 glGenerateMipmap(GL_TEXTURE_2D);
378 // Turn off mipmaps, so that we verify that Movit turns it back on.
379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
382 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
383 input->set_texture_num(tex);
384 tester.get_chain()->add_input(input);
385 tester.get_chain()->add_effect(new MipmapNeedingEffect);
387 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
389 pool.release_2d_texture(tex);
391 expect_equal(expected_data, out_data, 1, 1);
394 TEST(FlatInput, NoData) {
396 const int height = 4;
398 float out_data[width * height];
400 EffectChainTester tester(nullptr, width, height);
403 format.color_space = COLORSPACE_sRGB;
404 format.gamma_curve = GAMMA_LINEAR;
406 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
407 tester.get_chain()->add_input(input);
409 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
411 // Don't care what the output was, just that it does not crash.