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"); }
336 TEST(FlatInput, ExternalTextureMipmapState) {
338 const int height = 4;
340 float data[width * height] = {
346 float expected_data[] = {
351 EffectChainTester tester(nullptr, 1, 1, FORMAT_RGB, COLORSPACE_sRGB, GAMMA_LINEAR);
354 format.color_space = COLORSPACE_sRGB;
355 format.gamma_curve = GAMMA_LINEAR;
358 GLuint tex = pool.create_2d_texture(GL_R8, width, height);
360 glBindTexture(GL_TEXTURE_2D, tex);
362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
364 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
366 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_FLOAT, data);
368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
372 glGenerateMipmap(GL_TEXTURE_2D);
375 // Turn off mipmaps, so that we verify that Movit turns it back on.
376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
379 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
380 input->set_texture_num(tex);
381 tester.get_chain()->add_input(input);
382 tester.get_chain()->add_effect(new MipmapNeedingEffect);
384 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
386 pool.release_2d_texture(tex);
388 expect_equal(expected_data, out_data, 1, 1);
391 TEST(FlatInput, NoData) {
393 const int height = 4;
395 float out_data[width * height];
397 EffectChainTester tester(nullptr, width, height);
400 format.color_space = COLORSPACE_sRGB;
401 format.gamma_curve = GAMMA_LINEAR;
403 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
404 tester.get_chain()->add_input(input);
406 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
408 // Don't care what the output was, just that it does not crash.