Fix an issue where a (cached) shader program could be used from multiple
[movit] / flat_input_test.cpp
1 // Unit tests for FlatInput.
2
3 #include <epoxy/gl.h>
4 #include <stddef.h>
5
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"
11 #include "util.h"
12
13 namespace movit {
14
15 TEST(FlatInput, SimpleGrayscale) {
16         const int size = 4;
17
18         float data[size] = {
19                 0.0,
20                 0.5,
21                 0.7,
22                 1.0,
23         };
24         float expected_data[4 * size] = {
25                 0.0, 0.0, 0.0, 1.0,
26                 0.5, 0.5, 0.5, 1.0,
27                 0.7, 0.7, 0.7, 1.0,
28                 1.0, 1.0, 1.0, 1.0,
29         };
30         float out_data[4 * size];
31
32         EffectChainTester tester(data, 1, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
33         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
34
35         expect_equal(expected_data, out_data, 4, size);
36 }
37
38 TEST(FlatInput, RGB) {
39         const int size = 5;
40
41         float data[3 * size] = {
42                 0.0, 0.0, 0.0,
43                 0.5, 0.0, 0.0,
44                 0.0, 0.5, 0.0,
45                 0.0, 0.0, 0.7,
46                 0.0, 0.3, 0.7,
47         };
48         float expected_data[4 * size] = {
49                 0.0, 0.0, 0.0, 1.0,
50                 0.5, 0.0, 0.0, 1.0,
51                 0.0, 0.5, 0.0, 1.0,
52                 0.0, 0.0, 0.7, 1.0,
53                 0.0, 0.3, 0.7, 1.0,
54         };
55         float out_data[4 * size];
56
57         EffectChainTester tester(data, 1, size, FORMAT_RGB, COLORSPACE_sRGB, GAMMA_LINEAR);
58         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
59
60         expect_equal(expected_data, out_data, 4, size);
61 }
62
63 TEST(FlatInput, RGBA) {
64         const int size = 5;
65
66         float data[4 * size] = {
67                 0.0, 0.0, 0.0, 1.0,
68                 0.5, 0.0, 0.0, 0.3,
69                 0.0, 0.5, 0.0, 0.7,
70                 0.0, 0.0, 0.7, 1.0,
71                 0.0, 0.3, 0.7, 0.2,
72         };
73         float expected_data[4 * size] = {
74                 0.0, 0.0, 0.0, 1.0,
75                 0.5, 0.0, 0.0, 0.3,
76                 0.0, 0.5, 0.0, 0.7,
77                 0.0, 0.0, 0.7, 1.0,
78                 0.0, 0.3, 0.7, 0.2,
79         };
80         float out_data[4 * size];
81
82         EffectChainTester tester(data, 1, size, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
83         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
84
85         expect_equal(expected_data, out_data, 4, size);
86 }
87
88 // Note: The sRGB conversion itself is tested in EffectChainTester,
89 // since it also wants to test the chain building itself.
90 // Here, we merely test that alpha is left alone; the test will usually
91 // run using the sRGB OpenGL extension, but might be run with a
92 // GammaExpansionEffect if the card/driver happens not to support that.
93 TEST(FlatInput, AlphaIsNotModifiedBySRGBConversion) {
94         const int size = 5;
95
96         unsigned char data[4 * size] = {
97                 0, 0, 0, 0,
98                 0, 0, 0, 63,
99                 0, 0, 0, 127,
100                 0, 0, 0, 191,
101                 0, 0, 0, 255,
102         };
103         float expected_data[4 * size] = {
104                 0, 0, 0, 0.0 / 255.0,
105                 0, 0, 0, 63.0 / 255.0,
106                 0, 0, 0, 127.0 / 255.0,
107                 0, 0, 0, 191.0 / 255.0,
108                 0, 0, 0, 255.0 / 255.0,
109         };
110         float out_data[4 * size];
111
112         EffectChainTester tester(NULL, 1, size);
113         tester.add_input(data, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_sRGB);
114         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
115
116         expect_equal(expected_data, out_data, 4, size);
117 }
118
119 TEST(FlatInput, BGR) {
120         const int size = 5;
121
122         float data[3 * size] = {
123                 0.0, 0.0, 0.0,
124                 0.5, 0.0, 0.0,
125                 0.0, 0.5, 0.0,
126                 0.0, 0.0, 0.7,
127                 0.0, 0.3, 0.7,
128         };
129         float expected_data[4 * size] = {
130                 0.0, 0.0, 0.0, 1.0,
131                 0.0, 0.0, 0.5, 1.0,
132                 0.0, 0.5, 0.0, 1.0,
133                 0.7, 0.0, 0.0, 1.0,
134                 0.7, 0.3, 0.0, 1.0,
135         };
136         float out_data[4 * size];
137
138         EffectChainTester tester(data, 1, size, FORMAT_BGR, COLORSPACE_sRGB, GAMMA_LINEAR);
139         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
140
141         expect_equal(expected_data, out_data, 4, size);
142 }
143
144 TEST(FlatInput, BGRA) {
145         const int size = 5;
146
147         float data[4 * size] = {
148                 0.0, 0.0, 0.0, 1.0,
149                 0.5, 0.0, 0.0, 0.3,
150                 0.0, 0.5, 0.0, 0.7,
151                 0.0, 0.0, 0.7, 1.0,
152                 0.0, 0.3, 0.7, 0.2,
153         };
154         float expected_data[4 * size] = {
155                 0.0, 0.0, 0.0, 1.0,
156                 0.0, 0.0, 0.5, 0.3,
157                 0.0, 0.5, 0.0, 0.7,
158                 0.7, 0.0, 0.0, 1.0,
159                 0.7, 0.3, 0.0, 0.2,
160         };
161         float out_data[4 * size];
162
163         EffectChainTester tester(data, 1, size, FORMAT_BGRA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
164         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
165
166         expect_equal(expected_data, out_data, 4, size);
167 }
168
169 TEST(FlatInput, Pitch) {
170         const int pitch = 3;
171         const int width = 2;
172         const int height = 4;
173
174         float data[pitch * height] = {
175                 0.0, 1.0, 999.0f,
176                 0.5, 0.5, 999.0f,
177                 0.7, 0.2, 999.0f,
178                 1.0, 0.6, 999.0f,
179         };
180         float expected_data[4 * width * height] = {
181                 0.0, 0.0, 0.0, 1.0,  1.0, 1.0, 1.0, 1.0,
182                 0.5, 0.5, 0.5, 1.0,  0.5, 0.5, 0.5, 1.0,
183                 0.7, 0.7, 0.7, 1.0,  0.2, 0.2, 0.2, 1.0,
184                 1.0, 1.0, 1.0, 1.0,  0.6, 0.6, 0.6, 1.0,
185         };
186         float out_data[4 * width * height];
187
188         EffectChainTester tester(NULL, width, height);
189
190         ImageFormat format;
191         format.color_space = COLORSPACE_sRGB;
192         format.gamma_curve = GAMMA_LINEAR;
193
194         FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
195         input->set_pitch(pitch);
196         input->set_pixel_data(data);
197         tester.get_chain()->add_input(input);
198
199         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
200         expect_equal(expected_data, out_data, 4 * width, height);
201 }
202
203 TEST(FlatInput, UpdatedData) {
204         const int width = 2;
205         const int height = 4;
206
207         float data[width * height] = {
208                 0.0, 1.0,
209                 0.5, 0.5,
210                 0.7, 0.2,
211                 1.0, 0.6,
212         };
213         float out_data[width * height];
214
215         EffectChainTester tester(NULL, width, height);
216
217         ImageFormat format;
218         format.color_space = COLORSPACE_sRGB;
219         format.gamma_curve = GAMMA_LINEAR;
220
221         FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
222         input->set_pixel_data(data);
223         tester.get_chain()->add_input(input);
224
225         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
226         expect_equal(data, out_data, width, height);
227
228         data[6] = 0.3;
229         input->invalidate_pixel_data();
230
231         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
232         expect_equal(data, out_data, width, height);
233 }
234
235 TEST(FlatInput, PBO) {
236         const int width = 3;
237         const int height = 2;
238
239         float data[width * height] = {
240                 0.0, 1.0, 0.5,
241                 0.5, 0.5, 0.2,
242         };
243         float expected_data[4 * width * height] = {
244                 0.0, 0.0, 0.0, 1.0,  1.0, 1.0, 1.0, 1.0,  0.5, 0.5, 0.5, 1.0,
245                 0.5, 0.5, 0.5, 1.0,  0.5, 0.5, 0.5, 1.0,  0.2, 0.2, 0.2, 1.0,
246         };
247         float out_data[4 * width * height];
248
249         GLuint pbo;
250         glGenBuffers(1, &pbo);
251         glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
252         glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * sizeof(float), data, GL_STREAM_DRAW);
253         glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
254
255         EffectChainTester tester(NULL, width, height);
256
257         ImageFormat format;
258         format.color_space = COLORSPACE_sRGB;
259         format.gamma_curve = GAMMA_LINEAR;
260
261         FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
262         input->set_pixel_data((float *)BUFFER_OFFSET(0), pbo);
263         tester.get_chain()->add_input(input);
264
265         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
266         expect_equal(expected_data, out_data, 4 * width, height);
267
268         glDeleteBuffers(1, &pbo);
269 }
270
271 TEST(FlatInput, ExternalTexture) {
272         const int size = 5;
273
274         float data[3 * size] = {
275                 0.0, 0.0, 0.0,
276                 0.5, 0.0, 0.0,
277                 0.0, 0.5, 0.0,
278                 0.0, 0.0, 0.7,
279                 0.0, 0.3, 0.7,
280         };
281         float expected_data[4 * size] = {
282                 0.0, 0.0, 0.0, 1.0,
283                 0.5, 0.0, 0.0, 1.0,
284                 0.0, 0.5, 0.0, 1.0,
285                 0.0, 0.0, 0.7, 1.0,
286                 0.0, 0.3, 0.7, 1.0,
287         };
288         float out_data[4 * size];
289
290         EffectChainTester tester(NULL, 1, size, FORMAT_RGB, COLORSPACE_sRGB, GAMMA_LINEAR);
291
292         ImageFormat format;
293         format.color_space = COLORSPACE_sRGB;
294         format.gamma_curve = GAMMA_LINEAR;
295
296         ResourcePool pool;
297         GLuint tex = pool.create_2d_texture(GL_RGB8, 1, size);
298         check_error();
299         glBindTexture(GL_TEXTURE_2D, tex);
300         check_error();
301         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
302         check_error();
303         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
304         check_error();
305         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, size, GL_RGB, GL_FLOAT, data);
306         check_error();
307         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
308         check_error();
309         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
310         check_error();
311
312         FlatInput *input = new FlatInput(format, FORMAT_RGB, GL_FLOAT, 1, size);
313         input->set_texture_num(tex);
314         tester.get_chain()->add_input(input);
315
316         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
317
318         pool.release_2d_texture(tex);
319
320         expect_equal(expected_data, out_data, 4, size);
321 }
322
323 TEST(FlatInput, NoData) {
324         const int width = 2;
325         const int height = 4;
326
327         float out_data[width * height];
328
329         EffectChainTester tester(NULL, width, height);
330
331         ImageFormat format;
332         format.color_space = COLORSPACE_sRGB;
333         format.gamma_curve = GAMMA_LINEAR;
334
335         FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, width, height);
336         tester.get_chain()->add_input(input);
337
338         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
339
340         // Don't care what the output was, just that it does not crash.
341 }
342
343 }  // namespace movit