add pbobench: a benchmark for pbo functions
[piglit.git] / tests / texturing / teximage-colors.c
blobfc966bc3385df9d64f37c21d58489c8d64d1499a
1 /*
2 * Copyright 2014 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
24 #include "piglit-util-gl.h"
26 #define BENCHMARK_ITERATIONS 1000
28 PIGLIT_GL_TEST_CONFIG_BEGIN
30 config.supports_gl_compat_version = 13;
32 config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
33 config.khr_no_error_support = PIGLIT_NO_ERRORS;
35 PIGLIT_GL_TEST_CONFIG_END
37 struct texture_format {
38 GLenum internal_format;
39 GLenum format;
40 GLenum data_type;
43 struct texture_format formats[] = {
44 { GL_RED, GL_RED, GL_NONE },
45 { GL_R8, GL_RED, GL_UNSIGNED_BYTE },
46 { GL_R8_SNORM, GL_RED, GL_BYTE },
47 { GL_R16, GL_RED, GL_UNSIGNED_SHORT },
48 { GL_R16_SNORM, GL_RED, GL_SHORT },
49 { GL_R16F, GL_RED, GL_NONE },
50 { GL_R32F, GL_RED, GL_FLOAT },
52 { GL_RG, GL_RG, GL_NONE },
53 { GL_RG8, GL_RG, GL_UNSIGNED_BYTE },
54 { GL_RG8_SNORM, GL_RG, GL_BYTE },
55 { GL_RG16, GL_RG, GL_UNSIGNED_SHORT },
56 { GL_RG16_SNORM, GL_RG, GL_SHORT },
57 { GL_RG16F, GL_RG, GL_NONE },
58 { GL_RG32F, GL_RG, GL_FLOAT },
60 { GL_RGB, GL_RGB, GL_NONE },
61 { GL_R3_G3_B2, GL_RGB, GL_UNSIGNED_BYTE_3_3_2 },
62 { GL_RGB4, GL_RGB, GL_NONE },
63 { GL_RGB5, GL_RGB, GL_NONE },
64 { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE },
65 { GL_RGB8_SNORM, GL_RGB, GL_BYTE },
66 { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE },
67 { GL_RGB10, GL_RGB, GL_NONE },
68 { GL_R11F_G11F_B10F, GL_RGB, GL_NONE },
69 { GL_RGB12, GL_RGB, GL_NONE },
70 { GL_RGB9_E5, GL_RGB, GL_NONE },
71 { GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT },
72 { GL_RGB16F, GL_RGB, GL_NONE },
73 { GL_RGB16_SNORM, GL_RGB, GL_SHORT },
74 { GL_RGB32F, GL_RGB, GL_FLOAT },
76 { GL_RGBA, GL_RGBA, GL_NONE },
77 { GL_RGBA2, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
78 { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
79 { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 },
80 { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE },
81 { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_10_10_10_2 },
82 { GL_RGBA8_SNORM, GL_RGBA, GL_BYTE },
83 { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE },
84 { GL_RGBA12, GL_RGBA, GL_NONE },
85 { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT },
86 { GL_RGBA16_SNORM, GL_RGBA, GL_SHORT },
87 { GL_RGBA32F, GL_RGBA, GL_FLOAT },
89 { GL_ALPHA, GL_ALPHA, GL_NONE },
90 { GL_ALPHA4, GL_ALPHA, GL_NONE },
91 { GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE },
92 { GL_ALPHA12, GL_ALPHA, GL_NONE },
93 { GL_ALPHA16, GL_ALPHA, GL_UNSIGNED_SHORT },
95 { GL_LUMINANCE, GL_LUMINANCE, GL_NONE },
96 { GL_LUMINANCE4, GL_LUMINANCE, GL_NONE },
97 { GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE },
98 { GL_SLUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE },
99 { GL_LUMINANCE12, GL_LUMINANCE, GL_NONE },
100 { GL_LUMINANCE16, GL_LUMINANCE, GL_UNSIGNED_SHORT },
102 { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_NONE },
103 { GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_NONE },
104 { GL_LUMINANCE6_ALPHA2, GL_LUMINANCE_ALPHA, GL_NONE },
105 { GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
106 { GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
107 { GL_LUMINANCE12_ALPHA4, GL_LUMINANCE_ALPHA, GL_NONE },
108 { GL_LUMINANCE12_ALPHA12, GL_LUMINANCE_ALPHA, GL_NONE },
109 { GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT },
112 #define ARRAY_LENGTH(arr) (sizeof(arr) / sizeof(*arr))
114 static struct texture_format *
115 find_format(const char *name)
117 int i;
119 const GLenum format = piglit_get_gl_enum_from_name(name);
120 for (i = 0; i < ARRAY_LENGTH(formats); ++i)
121 if (format == formats[i].internal_format)
122 return &formats[i];
124 return NULL;
127 static const GLenum gl_formats[] = {
128 GL_RED,
129 GL_GREEN,
130 GL_BLUE,
131 GL_ALPHA,
132 GL_RG,
133 GL_RGB,
134 GL_BGR,
135 GL_RGBA,
136 GL_BGRA,
137 GL_ABGR_EXT,
138 // GL_INTENSITY,
139 GL_LUMINANCE,
140 GL_LUMINANCE_ALPHA,
143 static const GLenum gl_types[] = {
144 GL_UNSIGNED_BYTE_3_3_2,
145 GL_UNSIGNED_BYTE_2_3_3_REV,
146 GL_UNSIGNED_SHORT_5_6_5,
147 GL_UNSIGNED_SHORT_5_6_5_REV,
148 GL_UNSIGNED_SHORT_4_4_4_4,
149 GL_UNSIGNED_SHORT_4_4_4_4_REV,
150 GL_UNSIGNED_SHORT_5_5_5_1,
151 GL_UNSIGNED_SHORT_1_5_5_5_REV,
152 GL_UNSIGNED_INT_10_10_10_2,
153 GL_UNSIGNED_INT_2_10_10_10_REV,
154 GL_UNSIGNED_INT_8_8_8_8,
155 GL_UNSIGNED_INT_8_8_8_8_REV,
156 GL_BYTE,
157 GL_UNSIGNED_BYTE,
158 GL_SHORT,
159 GL_UNSIGNED_SHORT,
160 GL_FLOAT,
161 GL_INT,
162 GL_UNSIGNED_INT,
165 static bool
166 valid_combination(GLenum format, GLenum type)
168 switch (type) {
169 case GL_UNSIGNED_BYTE_3_3_2:
170 case GL_UNSIGNED_BYTE_2_3_3_REV:
171 case GL_UNSIGNED_SHORT_5_6_5:
172 case GL_UNSIGNED_SHORT_5_6_5_REV:
173 return format == GL_RGB;
174 case GL_UNSIGNED_SHORT_4_4_4_4:
175 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
176 case GL_UNSIGNED_SHORT_5_5_5_1:
177 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
178 case GL_UNSIGNED_INT_10_10_10_2:
179 case GL_UNSIGNED_INT_2_10_10_10_REV:
180 case GL_UNSIGNED_INT_8_8_8_8:
181 case GL_UNSIGNED_INT_8_8_8_8_REV:
182 return format == GL_RGBA || format == GL_BGRA;
183 default:
184 return true;
188 static float
189 un_to_float(unsigned char bits, unsigned int color)
191 unsigned int max = ~0u >> (sizeof(max) * 8 - bits);
192 return (float)color / (float)max;
195 static float
196 sn_to_float(unsigned char bits, int color)
198 int max = ~(~0 << (bits-1));
199 if (color < -max)
200 color = -max;
201 return (float)color / (float)max;
204 static float
205 srgb_to_linear(float s)
207 if (s > 0.0405)
208 return pow((s + 0.055) / 1.055, 2.4);
209 else
210 return s / 12.92;
213 #define UNPACK(val, len, off) ((val) >> off) & ~(~0ul << len)
215 static void
216 to_float(void *data, int num_chan, GLenum type, float *out)
218 int i;
220 switch (type) {
221 case GL_UNSIGNED_BYTE_3_3_2:
222 assert(num_chan == 3);
223 out[0] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 5));
224 out[1] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 2));
225 out[2] = un_to_float(2, UNPACK(*(GLubyte *)data, 2, 0));
226 break;
227 case GL_UNSIGNED_BYTE_2_3_3_REV:
228 assert(num_chan == 3);
229 out[0] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 0));
230 out[1] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 3));
231 out[2] = un_to_float(2, UNPACK(*(GLubyte *)data, 2, 6));
232 break;
233 case GL_UNSIGNED_SHORT_5_6_5:
234 assert(num_chan == 3);
235 out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 11));
236 out[1] = un_to_float(6, UNPACK(*(GLushort *)data, 6, 5));
237 out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 0));
238 break;
239 case GL_UNSIGNED_SHORT_5_6_5_REV:
240 assert(num_chan == 3);
241 out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 0));
242 out[1] = un_to_float(6, UNPACK(*(GLushort *)data, 6, 5));
243 out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 11));
244 break;
245 case GL_UNSIGNED_SHORT_4_4_4_4:
246 assert(num_chan == 4);
247 out[0] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 12));
248 out[1] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 8));
249 out[2] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 4));
250 out[3] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 0));
251 break;
252 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
253 assert(num_chan == 4);
254 out[0] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 0));
255 out[1] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 4));
256 out[2] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 8));
257 out[3] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 12));
258 break;
259 case GL_UNSIGNED_SHORT_5_5_5_1:
260 assert(num_chan == 4);
261 out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 11));
262 out[1] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 6));
263 out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 1));
264 out[3] = un_to_float(1, UNPACK(*(GLushort *)data, 1, 0));
265 break;
266 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
267 assert(num_chan == 4);
268 out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 0));
269 out[1] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 5));
270 out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 10));
271 out[3] = un_to_float(1, UNPACK(*(GLushort *)data, 1, 15));
272 break;
273 case GL_UNSIGNED_INT_10_10_10_2:
274 assert(num_chan == 4);
275 out[0] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 22));
276 out[1] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 12));
277 out[2] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 2));
278 out[3] = un_to_float(2, UNPACK(*(GLuint *)data, 2, 0));
279 break;
280 case GL_UNSIGNED_INT_2_10_10_10_REV:
281 assert(num_chan == 4);
282 out[0] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 0));
283 out[1] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 10));
284 out[2] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 20));
285 out[3] = un_to_float(2, UNPACK(*(GLuint *)data, 2, 30));
286 break;
287 case GL_UNSIGNED_INT_8_8_8_8:
288 assert(num_chan == 4);
289 out[0] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 24));
290 out[1] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 16));
291 out[2] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 8));
292 out[3] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 0));
293 break;
294 case GL_UNSIGNED_INT_8_8_8_8_REV:
295 assert(num_chan == 4);
296 out[0] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 0));
297 out[1] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 8));
298 out[2] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 16));
299 out[3] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 24));
300 break;
301 case GL_BYTE:
302 for (i = 0; i < num_chan; ++i)
303 out[i] = sn_to_float(8, ((GLbyte *)data)[i]);
304 break;
305 case GL_UNSIGNED_BYTE:
306 for (i = 0; i < num_chan; ++i)
307 out[i] = un_to_float(8, ((GLubyte *)data)[i]);
308 break;
309 case GL_SHORT:
310 for (i = 0; i < num_chan; ++i)
311 out[i] = sn_to_float(16, ((GLshort *)data)[i]);
312 break;
313 case GL_UNSIGNED_SHORT:
314 for (i = 0; i < num_chan; ++i)
315 out[i] = un_to_float(16, ((GLushort *)data)[i]);
316 break;
317 case GL_FLOAT:
318 for (i = 0; i < num_chan; ++i)
319 out[i] = ((float *)data)[i];
320 break;
321 case GL_INT:
322 for (i = 0; i < num_chan; ++i)
323 out[i] = sn_to_float(32, ((GLint *)data)[i]);
324 break;
325 case GL_UNSIGNED_INT:
326 for (i = 0; i < num_chan; ++i)
327 out[i] = un_to_float(32, ((GLuint *)data)[i]);
328 break;
329 default:
330 assert(!"Invalid type");
334 static bool
335 is_format_signed(GLenum format)
337 switch (format) {
338 case GL_R8_SNORM:
339 case GL_R16_SNORM:
340 case GL_R32F:
341 case GL_RG8_SNORM:
342 case GL_RG16_SNORM:
343 case GL_RG32F:
344 case GL_RGB8_SNORM:
345 case GL_RGB16_SNORM:
346 case GL_RGB32F:
347 case GL_RGBA8_SNORM:
348 case GL_RGBA16_SNORM:
349 case GL_RGBA32F:
350 return true;
351 default:
352 return false;
356 static bool
357 is_format_srgb(GLenum format)
359 switch (format) {
360 case GL_SRGB:
361 case GL_SRGB8:
362 case GL_SRGB_ALPHA:
363 case GL_SRGB8_ALPHA8:
364 case GL_SLUMINANCE:
365 case GL_SLUMINANCE8:
366 case GL_SLUMINANCE_ALPHA:
367 case GL_SLUMINANCE8_ALPHA8:
368 return true;
369 default:
370 return false;
374 static int
375 num_channels(GLenum format)
377 switch (format) {
378 case GL_RED:
379 case GL_GREEN:
380 case GL_BLUE:
381 case GL_ALPHA:
382 case GL_INTENSITY:
383 case GL_LUMINANCE:
384 return 1;
385 case GL_RG:
386 case GL_LUMINANCE_ALPHA:
387 return 2;
388 case GL_RGB:
389 case GL_BGR:
390 return 3;
391 case GL_RGBA:
392 case GL_BGRA:
393 case GL_ABGR_EXT:
394 return 4;
395 default:
396 assert(!"Invalid format");
397 return 0;
401 static int
402 bytes_per_pixel(GLenum format, GLenum type)
404 int channels = num_channels(format);
406 switch (type) {
407 case GL_UNSIGNED_BYTE_3_3_2:
408 case GL_UNSIGNED_BYTE_2_3_3_REV:
409 assert(channels == 3);
410 return 1;
411 case GL_UNSIGNED_SHORT_5_6_5:
412 case GL_UNSIGNED_SHORT_5_6_5_REV:
413 assert(channels == 3);
414 return 2;
415 case GL_UNSIGNED_SHORT_4_4_4_4:
416 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
417 case GL_UNSIGNED_SHORT_5_5_5_1:
418 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
419 assert(channels == 4);
420 return 2;
421 case GL_UNSIGNED_INT_10_10_10_2:
422 case GL_UNSIGNED_INT_2_10_10_10_REV:
423 case GL_UNSIGNED_INT_8_8_8_8:
424 case GL_UNSIGNED_INT_8_8_8_8_REV:
425 assert(channels == 4);
426 return 4;
427 case GL_BYTE:
428 case GL_UNSIGNED_BYTE:
429 return channels;
430 case GL_SHORT:
431 case GL_UNSIGNED_SHORT:
432 return channels * 2;
433 case GL_FLOAT:
434 case GL_INT:
435 case GL_UNSIGNED_INT:
436 return channels * 4;
437 default:
438 assert(!"Invalid type");
439 return 0;
443 static const char *frag_shader_unsigned_src =
444 "uniform sampler2D tex; \n"
445 "void main() \n"
446 "{ \n"
447 " gl_FragColor = texture2D(tex, gl_TexCoord[0].xy);\n"
448 "} \n";
450 static const char *frag_shader_signed_src =
451 "uniform sampler2D tex; \n"
452 "void main() \n"
453 "{ \n"
454 " gl_FragColor = 0.5 + 0.5 * texture2D(tex, gl_TexCoord[0].xy);\n"
455 "} \n";
457 int texture_size = 31;
458 struct texture_format *format = NULL;
459 GLuint unsigned_prog, signed_prog;
460 void *rand_data;
461 float tolerance[4];
462 bool benchmark = false;
464 void
465 piglit_init(int argc, char **argv)
467 int i, seed = 0;
469 for (i = 1; i < argc; ++i) {
470 if (sscanf(argv[i], "--seed=%d", &seed) > 0) {
471 srand(seed);
472 } else if (strcmp(argv[i], "--benchmark") == 0) {
473 benchmark = true;
474 texture_size = 128;
475 } else if (i == argc - 1) {
476 format = find_format(argv[i]);
477 break;
481 if (argc < 2) {
482 printf("usage: teximage-colors [--seed=seed] [--benchmark] format\n");
483 exit(1);
486 piglit_require_extension("GL_EXT_texture_integer");
488 if (format == NULL) {
489 int i;
490 printf("Invalid format. Valid formats:\n");
492 for (i = 0; i < ARRAY_LENGTH(formats); i++)
493 printf(" %s\n", piglit_get_gl_enum_name(
494 formats[i].internal_format));
495 exit(1);
498 signed_prog = piglit_build_simple_program(NULL, frag_shader_signed_src);
499 unsigned_prog = piglit_build_simple_program(NULL, frag_shader_unsigned_src);
501 srand(seed);
502 rand_data = malloc(texture_size * texture_size * 128);
503 for (i = 0; i < texture_size * texture_size * 128; ++i)
504 ((GLubyte *)rand_data)[i] = rand();
506 if (is_format_srgb(format->internal_format)) {
507 /* We loose a little precision in the high numbers */
508 tolerance[0] = 0.02;
509 tolerance[1] = 0.02;
510 tolerance[2] = 0.02;
511 tolerance[3] = 0.02;
512 } else {
513 tolerance[0] = 0.01;
514 tolerance[1] = 0.01;
515 tolerance[2] = 0.01;
516 tolerance[3] = 0.01;
519 if (format->internal_format == GL_R11F_G11F_B10F) {
520 tolerance[0] = 0.3;
521 tolerance[1] = 0.3;
522 tolerance[2] = 0.3;
525 switch (format->data_type) {
526 case GL_UNSIGNED_BYTE_3_3_2:
527 case GL_UNSIGNED_BYTE_2_3_3_REV:
528 tolerance[0] = 0.3;
529 tolerance[1] = 0.3;
530 tolerance[2] = 0.3;
531 break;
532 case GL_UNSIGNED_SHORT_5_5_5_1:
533 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
534 tolerance[3] = 0.6;
535 /* Fall through. */
536 case GL_UNSIGNED_SHORT_5_6_5:
537 case GL_UNSIGNED_SHORT_5_6_5_REV:
538 tolerance[0] = 0.05;
539 tolerance[1] = 0.05;
540 tolerance[2] = 0.05;
541 break;
542 case GL_UNSIGNED_SHORT_4_4_4_4:
543 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
544 tolerance[0] = 0.1;
545 tolerance[1] = 0.1;
546 tolerance[2] = 0.1;
547 tolerance[3] = 0.1;
548 break;
549 case GL_UNSIGNED_INT_10_10_10_2:
550 case GL_UNSIGNED_INT_2_10_10_10_REV:
551 tolerance[3] = 0.3;
552 break;
556 * The tolerance lowering above only works for formats which have
557 * explicit data types associated with them and even then it's fishy
558 * for some.
559 * The default sort of assumes at least 7 bits which doesn't make
560 * much sense in any case (for the specific formats with more bits).
561 * But just fix the cases which cannot pass (unless the driver encodes
562 * them with more bits).
564 switch (format->internal_format) {
565 case GL_RGB4:
566 tolerance[0] = 0.1;
567 tolerance[1] = 0.1;
568 tolerance[2] = 0.1;
569 tolerance[3] = 0.1;
570 break;
571 case GL_RGB5:
572 tolerance[0] = 0.05;
573 tolerance[1] = 0.05;
574 tolerance[2] = 0.05;
575 break;
576 case GL_LUMINANCE4_ALPHA4:
577 tolerance[0] = 0.1;
578 tolerance[1] = 0.1;
579 tolerance[2] = 0.1;
580 tolerance[3] = 0.1;
581 break;
582 case GL_LUMINANCE6_ALPHA2: /* broken but everybody uses 8+8 bits */
583 case GL_LUMINANCE4: /* broken but presumably noone uses just 4 bits */
584 case GL_ALPHA4: /* broken but presumably noone uses just 4 bits */
585 case GL_RGBA2: /* broken (4444) but everybody uses more bits anyway */
586 default:
587 break;
591 void
592 to_expected(GLenum test_format, GLenum test_type, void *up_raw, float *expected)
594 float up_rgba[4];
595 int num_chan = num_channels(test_format);
597 to_float(up_raw, num_chan, test_type, up_rgba);
599 expected[0] = 0.0f;
600 expected[1] = 0.0f;
601 expected[2] = 0.0f;
602 expected[3] = 1.0f;
604 switch (test_format) {
605 case GL_RED:
606 expected[0] = up_rgba[0];
607 break;
608 case GL_GREEN:
609 expected[1] = up_rgba[0];
610 break;
611 case GL_BLUE:
612 expected[2] = up_rgba[0];
613 break;
614 case GL_ALPHA:
615 expected[3] = up_rgba[0];
616 break;
617 case GL_RG:
618 expected[0] = up_rgba[0];
619 expected[1] = up_rgba[1];
620 break;
621 case GL_RGBA:
622 expected[3] = up_rgba[3];
623 case GL_RGB:
624 expected[0] = up_rgba[0];
625 expected[1] = up_rgba[1];
626 expected[2] = up_rgba[2];
627 break;
628 case GL_BGRA:
629 expected[3] = up_rgba[3];
630 case GL_BGR:
631 expected[0] = up_rgba[2];
632 expected[1] = up_rgba[1];
633 expected[2] = up_rgba[0];
634 break;
635 case GL_ABGR_EXT:
636 expected[0] = up_rgba[3];
637 expected[1] = up_rgba[2];
638 expected[2] = up_rgba[1];
639 expected[3] = up_rgba[0];
640 break;
641 case GL_INTENSITY:
642 expected[0] = up_rgba[0];
643 expected[1] = up_rgba[0];
644 expected[2] = up_rgba[0];
645 expected[3] = up_rgba[0];
646 break;
647 case GL_LUMINANCE_ALPHA:
648 expected[3] = up_rgba[1];
649 case GL_LUMINANCE:
650 expected[0] = up_rgba[0];
651 expected[1] = up_rgba[0];
652 expected[2] = up_rgba[0];
653 break;
654 default:
655 assert(!"Invalid color format");
658 switch (format->format) {
659 case GL_RED:
660 case GL_RED_INTEGER:
661 expected[1] = 0.0f;
662 case GL_RG:
663 case GL_RG_INTEGER:
664 expected[2] = 0.0f;
665 case GL_RGB:
666 case GL_RGB_INTEGER:
667 expected[3] = 1.0f;
668 break;
669 case GL_RGBA:
670 case GL_RGBA_INTEGER:
671 break;
672 case GL_ALPHA:
673 expected[0] = 0.0f;
674 expected[1] = 0.0f;
675 expected[2] = 0.0f;
676 break;
677 case GL_LUMINANCE:
678 expected[3] = 1.0f;
679 case GL_LUMINANCE_ALPHA:
680 expected[1] = expected[0];
681 expected[2] = expected[0];
682 break;
683 default:
684 assert(!"Invalid color format");
687 if (!is_format_signed(format->internal_format)) {
688 if (expected[0] < 0.0f)
689 expected[0] = 0.0f;
690 if (expected[1] < 0.0f)
691 expected[1] = 0.0f;
692 if (expected[2] < 0.0f)
693 expected[2] = 0.0f;
694 if (expected[3] < 0.0f)
695 expected[3] = 0.0f;
698 if (is_format_srgb(format->internal_format)) {
699 expected[0] = srgb_to_linear(expected[0]);
700 expected[1] = srgb_to_linear(expected[1]);
701 expected[2] = srgb_to_linear(expected[2]);
705 enum piglit_result
706 run_test(GLenum test_format, GLenum test_type, float *time_out)
708 bool pass = true;
709 int64_t time;
710 GLuint tex;
711 int i, Bpp, channels;
712 float *tmp, *expected, *observed;
713 void *data;
715 glGenTextures(1, &tex);
716 glBindTexture(GL_TEXTURE_2D, tex);
717 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
718 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
720 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
722 channels = num_channels(test_format);
723 Bpp = bytes_per_pixel(test_format, test_type);
725 if (test_type == GL_FLOAT) {
726 /* Sanitize so we don't get invalid floating point values */
727 tmp = malloc(texture_size * texture_size * channels * sizeof(float));
728 for (i = 0; i < texture_size * texture_size * channels; ++i)
729 tmp[i] = sn_to_float(32, ((GLint *)rand_data)[i]);
730 data = tmp;
731 } else {
732 tmp = NULL;
733 data = rand_data;
736 expected = malloc(texture_size * texture_size * 4 * sizeof(float));
737 for (i = 0; i < texture_size * texture_size; ++i)
738 to_expected(test_format, test_type, (GLubyte *)data + (i * Bpp),
739 expected + 4 * i);
741 if (benchmark) {
742 time = piglit_time_get_nano();
743 for (i = 0; i < BENCHMARK_ITERATIONS; ++i)
744 glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,
745 texture_size, texture_size, 0,
746 test_format, test_type, data);
747 time = piglit_time_get_nano() - time;
748 *time_out = (double)time / (double)(BENCHMARK_ITERATIONS*1000);
749 } else {
750 glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,
751 texture_size, texture_size, 0,
752 test_format, test_type, data);
754 pass &= piglit_check_gl_error(GL_NO_ERROR);
756 if (is_format_signed(format->internal_format)) {
757 glUseProgram(signed_prog);
759 for (i = 0; i < texture_size * texture_size * 4; ++i)
760 expected[i] = 0.5 + 0.5 * expected[i];
761 } else {
762 glUseProgram(unsigned_prog);
765 piglit_draw_rect_tex(0, 0, texture_size, texture_size, 0, 0, 1, 1);
767 observed = malloc(texture_size * texture_size * 4 * sizeof(float));
768 glReadPixels(0, 0, texture_size, texture_size,
769 GL_RGBA, GL_FLOAT, observed);
770 pass &= piglit_check_gl_error(GL_NO_ERROR);
772 pass &= piglit_compare_images_color(0, 0, texture_size, texture_size, 4,
773 tolerance, expected, observed);
775 free(observed);
776 free(expected);
777 free(tmp);
779 piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,
780 "%s texture with %s and %s",
781 piglit_get_gl_enum_name(format->internal_format),
782 piglit_get_gl_enum_name(test_format),
783 piglit_get_gl_enum_name(test_type));
785 glDeleteTextures(1, &tex);
787 return pass;
790 bool
791 test_exact()
793 int i, Bpp, channels;
794 float *tmp_float;
795 GLubyte *data, *observed;
796 GLint tex_width, tex_height;
797 bool pass = true;
799 if (format->data_type == GL_NONE) {
800 piglit_report_subtest_result(PIGLIT_SKIP,
801 "Exact upload-download of %s",
802 piglit_get_gl_enum_name(format->internal_format));
803 return true;
806 channels = num_channels(format->format);
807 Bpp = bytes_per_pixel(format->format, format->data_type);
809 if (format->data_type == GL_FLOAT) {
810 /* Sanitize so we don't get invalid floating point values */
811 tmp_float = malloc(texture_size * texture_size *
812 channels * sizeof(float));
813 for (i = 0; i < texture_size * texture_size * channels; ++i)
814 tmp_float[i] = sn_to_float(32, ((GLint *)rand_data)[i]);
815 data = (GLubyte *)tmp_float;
816 } else {
817 tmp_float = NULL;
818 data = rand_data;
821 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
822 glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,
823 texture_size, texture_size, 0, format->format,
824 format->data_type, data);
825 pass &= piglit_check_gl_error(GL_NO_ERROR);
827 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_width);
828 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_height);
829 glPixelStorei(GL_PACK_ALIGNMENT, 1);
830 observed = malloc(tex_width * tex_height * Bpp);
832 glGetTexImage(GL_TEXTURE_2D, 0, format->format, format->data_type,
833 observed);
834 pass &= piglit_check_gl_error(GL_NO_ERROR);
837 * For snorm formats, -127/-128 and -32767/-32768 represent the exact
838 * same value (-1.0). Therefore, it is quite reasonable to expect
839 * an implementation could return the other representation.
840 * (We'll assume it will happen only one way the other way seems rather
841 * unlikely.)
843 if (format->data_type == GL_BYTE) {
844 int j;
845 for (j = 0; j < texture_size; ++j) {
846 for (i = 0; i < tex_width * channels; i++) {
847 if (!(data[i] == observed[i] ||
848 ((GLbyte)data[i] == -128 &&
849 (GLbyte)observed[i] == -127))) {
850 pass = GL_FALSE;
854 } else if (format->data_type == GL_SHORT) {
855 int j;
856 for (j = 0; j < texture_size; ++j) {
857 for (i = 0; i < tex_width * channels; i++) {
858 GLshort datas = ((GLshort *)data)[i];
859 GLshort obss = ((GLshort *)observed)[i];
860 if (!(datas == obss ||
861 (datas == -32768 && obss == -32767))) {
862 pass = GL_FALSE;
866 } else {
867 for (i = 0; i < texture_size; ++i)
868 pass &= memcmp(&data[i * texture_size * Bpp],
869 &observed[i * tex_width * Bpp],
870 texture_size * Bpp) == 0;
873 free(observed);
874 free(tmp_float);
876 piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,
877 "Exact upload-download of %s",
878 piglit_get_gl_enum_name(format->internal_format));
880 return pass;
883 enum piglit_result
884 piglit_display(void)
886 bool warn = false, pass = true;
887 GLuint rb, fbo;
888 int i, j;
889 float times[ARRAY_LENGTH(gl_formats)][ARRAY_LENGTH(gl_types)];
891 glGenRenderbuffersEXT(1, &rb);
892 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb);
893 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
894 GL_RGBA, texture_size, texture_size);
895 pass &= piglit_check_gl_error(GL_NO_ERROR);
897 glGenFramebuffersEXT(1, &fbo);
898 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
899 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
900 GL_COLOR_ATTACHMENT0_EXT,
901 GL_RENDERBUFFER_EXT, rb);
902 pass &= piglit_check_gl_error(GL_NO_ERROR);
904 /* Set up basic GL stuff */
905 glEnable(GL_TEXTURE_2D);
906 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
907 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
909 warn = !test_exact();
911 for (i = 0; i < ARRAY_LENGTH(gl_formats); ++i) {
912 for (j = 0; j < ARRAY_LENGTH(gl_types); ++j) {
913 if (!valid_combination(gl_formats[i], gl_types[j]))
914 continue;
916 pass &= run_test(gl_formats[i], gl_types[j],
917 &times[i][j]);
921 glDisable(GL_TEXTURE_2D);
922 glDeleteFramebuffers(1, &fbo);
923 glDeleteRenderbuffers(1, &rb);
925 if (benchmark) {
926 fprintf(stdout, "internalFormat, format, type, time (us/call)\n");
927 for (i = 0; i < ARRAY_LENGTH(gl_formats); ++i) {
928 for (j = 0; j < ARRAY_LENGTH(gl_types); ++j) {
929 if (!valid_combination(gl_formats[i], gl_types[j]))
930 continue;
932 fprintf(stdout, "%s, %s, %s, %.3f\n",
933 piglit_get_gl_enum_name(format->internal_format),
934 piglit_get_gl_enum_name(gl_formats[i]),
935 piglit_get_gl_enum_name(gl_types[j]),
936 times[i][j]);
941 if (pass) {
942 return warn ? PIGLIT_WARN : PIGLIT_PASS;
943 } else {
944 return PIGLIT_FAIL;