fix the spelling in whole piglit
[piglit.git] / tests / texturing / teximage-colors.c
blob0827502a3880a99d4880dacf2c7b8959bba5cfbe
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_SR8_EXT, GL_RED, GL_UNSIGNED_BYTE },
48 { GL_R16, GL_RED, GL_UNSIGNED_SHORT },
49 { GL_R16_SNORM, GL_RED, GL_SHORT },
50 { GL_R16F, GL_RED, GL_NONE },
51 { GL_R32F, GL_RED, GL_FLOAT },
53 { GL_RG, GL_RG, GL_NONE },
54 { GL_RG8, GL_RG, GL_UNSIGNED_BYTE },
55 { GL_RG8_SNORM, GL_RG, GL_BYTE },
56 { GL_SRG8_EXT, GL_RG, GL_UNSIGNED_BYTE },
57 { GL_RG16, GL_RG, GL_UNSIGNED_SHORT },
58 { GL_RG16_SNORM, GL_RG, GL_SHORT },
59 { GL_RG16F, GL_RG, GL_NONE },
60 { GL_RG32F, GL_RG, GL_FLOAT },
62 { GL_RGB, GL_RGB, GL_NONE },
63 { GL_R3_G3_B2, GL_RGB, GL_UNSIGNED_BYTE_3_3_2 },
64 { GL_RGB4, GL_RGB, GL_NONE },
65 { GL_RGB5, GL_RGB, GL_NONE },
66 { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE },
67 { GL_RGB8_SNORM, GL_RGB, GL_BYTE },
68 { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE },
69 { GL_RGB10, GL_RGB, GL_NONE },
70 { GL_R11F_G11F_B10F, GL_RGB, GL_NONE },
71 { GL_RGB12, GL_RGB, GL_NONE },
72 { GL_RGB9_E5, GL_RGB, GL_NONE },
73 { GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT },
74 { GL_RGB16F, GL_RGB, GL_NONE },
75 { GL_RGB16_SNORM, GL_RGB, GL_SHORT },
76 { GL_RGB32F, GL_RGB, GL_FLOAT },
78 { GL_RGBA, GL_RGBA, GL_NONE },
79 { GL_RGBA2, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
80 { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
81 { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 },
82 { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE },
83 { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_10_10_10_2 },
84 { GL_RGBA8_SNORM, GL_RGBA, GL_BYTE },
85 { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE },
86 { GL_RGBA12, GL_RGBA, GL_NONE },
87 { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT },
88 { GL_RGBA16_SNORM, GL_RGBA, GL_SHORT },
89 { GL_RGBA32F, GL_RGBA, GL_FLOAT },
91 { GL_ALPHA, GL_ALPHA, GL_NONE },
92 { GL_ALPHA4, GL_ALPHA, GL_NONE },
93 { GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE },
94 { GL_ALPHA12, GL_ALPHA, GL_NONE },
95 { GL_ALPHA16, GL_ALPHA, GL_UNSIGNED_SHORT },
97 { GL_LUMINANCE, GL_LUMINANCE, GL_NONE },
98 { GL_LUMINANCE4, GL_LUMINANCE, GL_NONE },
99 { GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE },
100 { GL_SLUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE },
101 { GL_LUMINANCE12, GL_LUMINANCE, GL_NONE },
102 { GL_LUMINANCE16, GL_LUMINANCE, GL_UNSIGNED_SHORT },
104 { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_NONE },
105 { GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_NONE },
106 { GL_LUMINANCE6_ALPHA2, GL_LUMINANCE_ALPHA, GL_NONE },
107 { GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
108 { GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
109 { GL_LUMINANCE12_ALPHA4, GL_LUMINANCE_ALPHA, GL_NONE },
110 { GL_LUMINANCE12_ALPHA12, GL_LUMINANCE_ALPHA, GL_NONE },
111 { GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT },
114 #define ARRAY_LENGTH(arr) (sizeof(arr) / sizeof(*arr))
116 static struct texture_format *
117 find_format(const char *name)
119 int i;
121 const GLenum format = piglit_get_gl_enum_from_name(name);
122 for (i = 0; i < ARRAY_LENGTH(formats); ++i)
123 if (format == formats[i].internal_format)
124 return &formats[i];
126 return NULL;
129 static const GLenum gl_formats[] = {
130 GL_RED,
131 GL_GREEN,
132 GL_BLUE,
133 GL_ALPHA,
134 GL_RG,
135 GL_RGB,
136 GL_BGR,
137 GL_RGBA,
138 GL_BGRA,
139 GL_ABGR_EXT,
140 // GL_INTENSITY,
141 GL_LUMINANCE,
142 GL_LUMINANCE_ALPHA,
145 static const GLenum gl_types[] = {
146 GL_UNSIGNED_BYTE_3_3_2,
147 GL_UNSIGNED_BYTE_2_3_3_REV,
148 GL_UNSIGNED_SHORT_5_6_5,
149 GL_UNSIGNED_SHORT_5_6_5_REV,
150 GL_UNSIGNED_SHORT_4_4_4_4,
151 GL_UNSIGNED_SHORT_4_4_4_4_REV,
152 GL_UNSIGNED_SHORT_5_5_5_1,
153 GL_UNSIGNED_SHORT_1_5_5_5_REV,
154 GL_UNSIGNED_INT_10_10_10_2,
155 GL_UNSIGNED_INT_2_10_10_10_REV,
156 GL_UNSIGNED_INT_8_8_8_8,
157 GL_UNSIGNED_INT_8_8_8_8_REV,
158 GL_BYTE,
159 GL_UNSIGNED_BYTE,
160 GL_SHORT,
161 GL_UNSIGNED_SHORT,
162 GL_FLOAT,
163 GL_INT,
164 GL_UNSIGNED_INT,
167 static bool
168 valid_combination(GLenum format, GLenum type)
170 switch (type) {
171 case GL_UNSIGNED_BYTE_3_3_2:
172 case GL_UNSIGNED_BYTE_2_3_3_REV:
173 case GL_UNSIGNED_SHORT_5_6_5:
174 case GL_UNSIGNED_SHORT_5_6_5_REV:
175 return format == GL_RGB;
176 case GL_UNSIGNED_SHORT_4_4_4_4:
177 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
178 case GL_UNSIGNED_SHORT_5_5_5_1:
179 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
180 case GL_UNSIGNED_INT_10_10_10_2:
181 case GL_UNSIGNED_INT_2_10_10_10_REV:
182 case GL_UNSIGNED_INT_8_8_8_8:
183 case GL_UNSIGNED_INT_8_8_8_8_REV:
184 return format == GL_RGBA || format == GL_BGRA;
185 default:
186 return true;
190 static float
191 un_to_float(unsigned char bits, unsigned int color)
193 unsigned int max = ~0u >> (sizeof(max) * 8 - bits);
194 return (float)color / (float)max;
197 static float
198 sn_to_float(unsigned char bits, int color)
200 int max = ~(~0 << (bits-1));
201 if (color < -max)
202 color = -max;
203 return (float)color / (float)max;
206 static float
207 srgb_to_linear(float s)
209 if (s > 0.0405)
210 return pow((s + 0.055) / 1.055, 2.4);
211 else
212 return s / 12.92;
215 #define UNPACK(val, len, off) ((val) >> off) & ~(~0ul << len)
217 static void
218 to_float(void *data, int num_chan, GLenum type, float *out)
220 int i;
222 switch (type) {
223 case GL_UNSIGNED_BYTE_3_3_2:
224 assert(num_chan == 3);
225 out[0] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 5));
226 out[1] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 2));
227 out[2] = un_to_float(2, UNPACK(*(GLubyte *)data, 2, 0));
228 break;
229 case GL_UNSIGNED_BYTE_2_3_3_REV:
230 assert(num_chan == 3);
231 out[0] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 0));
232 out[1] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 3));
233 out[2] = un_to_float(2, UNPACK(*(GLubyte *)data, 2, 6));
234 break;
235 case GL_UNSIGNED_SHORT_5_6_5:
236 assert(num_chan == 3);
237 out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 11));
238 out[1] = un_to_float(6, UNPACK(*(GLushort *)data, 6, 5));
239 out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 0));
240 break;
241 case GL_UNSIGNED_SHORT_5_6_5_REV:
242 assert(num_chan == 3);
243 out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 0));
244 out[1] = un_to_float(6, UNPACK(*(GLushort *)data, 6, 5));
245 out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 11));
246 break;
247 case GL_UNSIGNED_SHORT_4_4_4_4:
248 assert(num_chan == 4);
249 out[0] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 12));
250 out[1] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 8));
251 out[2] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 4));
252 out[3] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 0));
253 break;
254 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
255 assert(num_chan == 4);
256 out[0] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 0));
257 out[1] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 4));
258 out[2] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 8));
259 out[3] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 12));
260 break;
261 case GL_UNSIGNED_SHORT_5_5_5_1:
262 assert(num_chan == 4);
263 out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 11));
264 out[1] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 6));
265 out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 1));
266 out[3] = un_to_float(1, UNPACK(*(GLushort *)data, 1, 0));
267 break;
268 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
269 assert(num_chan == 4);
270 out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 0));
271 out[1] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 5));
272 out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 10));
273 out[3] = un_to_float(1, UNPACK(*(GLushort *)data, 1, 15));
274 break;
275 case GL_UNSIGNED_INT_10_10_10_2:
276 assert(num_chan == 4);
277 out[0] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 22));
278 out[1] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 12));
279 out[2] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 2));
280 out[3] = un_to_float(2, UNPACK(*(GLuint *)data, 2, 0));
281 break;
282 case GL_UNSIGNED_INT_2_10_10_10_REV:
283 assert(num_chan == 4);
284 out[0] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 0));
285 out[1] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 10));
286 out[2] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 20));
287 out[3] = un_to_float(2, UNPACK(*(GLuint *)data, 2, 30));
288 break;
289 case GL_UNSIGNED_INT_8_8_8_8:
290 assert(num_chan == 4);
291 out[0] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 24));
292 out[1] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 16));
293 out[2] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 8));
294 out[3] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 0));
295 break;
296 case GL_UNSIGNED_INT_8_8_8_8_REV:
297 assert(num_chan == 4);
298 out[0] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 0));
299 out[1] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 8));
300 out[2] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 16));
301 out[3] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 24));
302 break;
303 case GL_BYTE:
304 for (i = 0; i < num_chan; ++i)
305 out[i] = sn_to_float(8, ((GLbyte *)data)[i]);
306 break;
307 case GL_UNSIGNED_BYTE:
308 for (i = 0; i < num_chan; ++i)
309 out[i] = un_to_float(8, ((GLubyte *)data)[i]);
310 break;
311 case GL_SHORT:
312 for (i = 0; i < num_chan; ++i)
313 out[i] = sn_to_float(16, ((GLshort *)data)[i]);
314 break;
315 case GL_UNSIGNED_SHORT:
316 for (i = 0; i < num_chan; ++i)
317 out[i] = un_to_float(16, ((GLushort *)data)[i]);
318 break;
319 case GL_FLOAT:
320 for (i = 0; i < num_chan; ++i)
321 out[i] = ((float *)data)[i];
322 break;
323 case GL_INT:
324 for (i = 0; i < num_chan; ++i)
325 out[i] = sn_to_float(32, ((GLint *)data)[i]);
326 break;
327 case GL_UNSIGNED_INT:
328 for (i = 0; i < num_chan; ++i)
329 out[i] = un_to_float(32, ((GLuint *)data)[i]);
330 break;
331 default:
332 assert(!"Invalid type");
336 static bool
337 is_format_signed(GLenum format)
339 switch (format) {
340 case GL_R8_SNORM:
341 case GL_R16_SNORM:
342 case GL_R32F:
343 case GL_RG8_SNORM:
344 case GL_RG16_SNORM:
345 case GL_RG32F:
346 case GL_RGB8_SNORM:
347 case GL_RGB16_SNORM:
348 case GL_RGB32F:
349 case GL_RGBA8_SNORM:
350 case GL_RGBA16_SNORM:
351 case GL_RGBA32F:
352 return true;
353 default:
354 return false;
358 static bool
359 is_format_srgb(GLenum format)
361 switch (format) {
362 case GL_SR8_EXT:
363 case GL_SRG8_EXT:
364 case GL_SRGB:
365 case GL_SRGB8:
366 case GL_SRGB_ALPHA:
367 case GL_SRGB8_ALPHA8:
368 case GL_SLUMINANCE:
369 case GL_SLUMINANCE8:
370 case GL_SLUMINANCE_ALPHA:
371 case GL_SLUMINANCE8_ALPHA8:
372 return true;
373 default:
374 return false;
378 static int
379 num_channels(GLenum format)
381 switch (format) {
382 case GL_RED:
383 case GL_GREEN:
384 case GL_BLUE:
385 case GL_ALPHA:
386 case GL_INTENSITY:
387 case GL_LUMINANCE:
388 return 1;
389 case GL_RG:
390 case GL_LUMINANCE_ALPHA:
391 return 2;
392 case GL_RGB:
393 case GL_BGR:
394 return 3;
395 case GL_RGBA:
396 case GL_BGRA:
397 case GL_ABGR_EXT:
398 return 4;
399 default:
400 assert(!"Invalid format");
401 return 0;
405 static int
406 bytes_per_pixel(GLenum format, GLenum type)
408 int channels = num_channels(format);
410 switch (type) {
411 case GL_UNSIGNED_BYTE_3_3_2:
412 case GL_UNSIGNED_BYTE_2_3_3_REV:
413 assert(channels == 3);
414 return 1;
415 case GL_UNSIGNED_SHORT_5_6_5:
416 case GL_UNSIGNED_SHORT_5_6_5_REV:
417 assert(channels == 3);
418 return 2;
419 case GL_UNSIGNED_SHORT_4_4_4_4:
420 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
421 case GL_UNSIGNED_SHORT_5_5_5_1:
422 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
423 assert(channels == 4);
424 return 2;
425 case GL_UNSIGNED_INT_10_10_10_2:
426 case GL_UNSIGNED_INT_2_10_10_10_REV:
427 case GL_UNSIGNED_INT_8_8_8_8:
428 case GL_UNSIGNED_INT_8_8_8_8_REV:
429 assert(channels == 4);
430 return 4;
431 case GL_BYTE:
432 case GL_UNSIGNED_BYTE:
433 return channels;
434 case GL_SHORT:
435 case GL_UNSIGNED_SHORT:
436 return channels * 2;
437 case GL_FLOAT:
438 case GL_INT:
439 case GL_UNSIGNED_INT:
440 return channels * 4;
441 default:
442 assert(!"Invalid type");
443 return 0;
447 static const char *frag_shader_unsigned_src =
448 "uniform sampler2D tex; \n"
449 "void main() \n"
450 "{ \n"
451 " gl_FragColor = texture2D(tex, gl_TexCoord[0].xy);\n"
452 "} \n";
454 static const char *frag_shader_signed_src =
455 "uniform sampler2D tex; \n"
456 "void main() \n"
457 "{ \n"
458 " gl_FragColor = 0.5 + 0.5 * texture2D(tex, gl_TexCoord[0].xy);\n"
459 "} \n";
461 int texture_size = 31;
462 struct texture_format *format = NULL;
463 GLuint unsigned_prog, signed_prog;
464 void *rand_data;
465 float tolerance[4];
466 bool benchmark = false;
468 void
469 piglit_init(int argc, char **argv)
471 int i, seed = 0;
473 for (i = 1; i < argc; ++i) {
474 if (sscanf(argv[i], "--seed=%d", &seed) > 0) {
475 srand(seed);
476 } else if (strcmp(argv[i], "--benchmark") == 0) {
477 benchmark = true;
478 texture_size = 128;
479 } else if (i == argc - 1) {
480 format = find_format(argv[i]);
481 break;
485 if (argc < 2) {
486 printf("usage: teximage-colors [--seed=seed] [--benchmark] format\n");
487 exit(1);
490 if (format == NULL) {
491 int i;
492 printf("Invalid format. Valid formats:\n");
494 for (i = 0; i < ARRAY_LENGTH(formats); i++)
495 printf(" %s\n", piglit_get_gl_enum_name(
496 formats[i].internal_format));
497 exit(1);
500 piglit_require_extension("GL_EXT_texture_integer");
501 if (format->internal_format == GL_SR8_EXT)
502 piglit_require_extension("GL_EXT_texture_sRGB_R8");
503 if (format->internal_format == GL_SRG8_EXT)
504 piglit_require_extension("GL_EXT_texture_sRGB_RG8");
506 signed_prog = piglit_build_simple_program(NULL, frag_shader_signed_src);
507 unsigned_prog = piglit_build_simple_program(NULL, frag_shader_unsigned_src);
509 srand(seed);
510 rand_data = malloc(texture_size * texture_size * 128);
511 for (i = 0; i < texture_size * texture_size * 128; ++i)
512 ((GLubyte *)rand_data)[i] = rand();
514 if (is_format_srgb(format->internal_format)) {
515 /* We loose a little precision in the high numbers */
516 tolerance[0] = 0.02;
517 tolerance[1] = 0.02;
518 tolerance[2] = 0.02;
519 tolerance[3] = 0.02;
520 } else {
521 tolerance[0] = 0.01;
522 tolerance[1] = 0.01;
523 tolerance[2] = 0.01;
524 tolerance[3] = 0.01;
527 if (format->internal_format == GL_R11F_G11F_B10F) {
528 tolerance[0] = 0.3;
529 tolerance[1] = 0.3;
530 tolerance[2] = 0.3;
533 switch (format->data_type) {
534 case GL_UNSIGNED_BYTE_3_3_2:
535 case GL_UNSIGNED_BYTE_2_3_3_REV:
536 tolerance[0] = 0.3;
537 tolerance[1] = 0.3;
538 tolerance[2] = 0.3;
539 break;
540 case GL_UNSIGNED_SHORT_5_5_5_1:
541 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
542 tolerance[3] = 0.6;
543 /* Fall through. */
544 case GL_UNSIGNED_SHORT_5_6_5:
545 case GL_UNSIGNED_SHORT_5_6_5_REV:
546 tolerance[0] = 0.05;
547 tolerance[1] = 0.05;
548 tolerance[2] = 0.05;
549 break;
550 case GL_UNSIGNED_SHORT_4_4_4_4:
551 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
552 tolerance[0] = 0.1;
553 tolerance[1] = 0.1;
554 tolerance[2] = 0.1;
555 tolerance[3] = 0.1;
556 break;
557 case GL_UNSIGNED_INT_10_10_10_2:
558 case GL_UNSIGNED_INT_2_10_10_10_REV:
559 tolerance[3] = 0.3;
560 break;
564 * The tolerance lowering above only works for formats which have
565 * explicit data types associated with them and even then it's fishy
566 * for some.
567 * The default sort of assumes at least 7 bits which doesn't make
568 * much sense in any case (for the specific formats with more bits).
569 * But just fix the cases which cannot pass (unless the driver encodes
570 * them with more bits).
572 switch (format->internal_format) {
573 case GL_RGB4:
574 tolerance[0] = 0.1;
575 tolerance[1] = 0.1;
576 tolerance[2] = 0.1;
577 tolerance[3] = 0.1;
578 break;
579 case GL_RGB5:
580 tolerance[0] = 0.05;
581 tolerance[1] = 0.05;
582 tolerance[2] = 0.05;
583 break;
584 case GL_LUMINANCE4_ALPHA4:
585 tolerance[0] = 0.1;
586 tolerance[1] = 0.1;
587 tolerance[2] = 0.1;
588 tolerance[3] = 0.1;
589 break;
590 case GL_LUMINANCE6_ALPHA2: /* broken but everybody uses 8+8 bits */
591 case GL_LUMINANCE4: /* broken but presumably no one uses just 4 bits */
592 case GL_ALPHA4: /* broken but presumably no one uses just 4 bits */
593 case GL_RGBA2: /* broken (4444) but everybody uses more bits anyway */
594 default:
595 break;
599 void
600 to_expected(GLenum test_format, GLenum test_type, void *up_raw, float *expected)
602 float up_rgba[4];
603 int num_chan = num_channels(test_format);
605 to_float(up_raw, num_chan, test_type, up_rgba);
607 expected[0] = 0.0f;
608 expected[1] = 0.0f;
609 expected[2] = 0.0f;
610 expected[3] = 1.0f;
612 switch (test_format) {
613 case GL_RED:
614 expected[0] = up_rgba[0];
615 break;
616 case GL_GREEN:
617 expected[1] = up_rgba[0];
618 break;
619 case GL_BLUE:
620 expected[2] = up_rgba[0];
621 break;
622 case GL_ALPHA:
623 expected[3] = up_rgba[0];
624 break;
625 case GL_RG:
626 expected[0] = up_rgba[0];
627 expected[1] = up_rgba[1];
628 break;
629 case GL_RGBA:
630 expected[3] = up_rgba[3];
631 case GL_RGB:
632 expected[0] = up_rgba[0];
633 expected[1] = up_rgba[1];
634 expected[2] = up_rgba[2];
635 break;
636 case GL_BGRA:
637 expected[3] = up_rgba[3];
638 case GL_BGR:
639 expected[0] = up_rgba[2];
640 expected[1] = up_rgba[1];
641 expected[2] = up_rgba[0];
642 break;
643 case GL_ABGR_EXT:
644 expected[0] = up_rgba[3];
645 expected[1] = up_rgba[2];
646 expected[2] = up_rgba[1];
647 expected[3] = up_rgba[0];
648 break;
649 case GL_INTENSITY:
650 expected[0] = up_rgba[0];
651 expected[1] = up_rgba[0];
652 expected[2] = up_rgba[0];
653 expected[3] = up_rgba[0];
654 break;
655 case GL_LUMINANCE_ALPHA:
656 expected[3] = up_rgba[1];
657 case GL_LUMINANCE:
658 expected[0] = up_rgba[0];
659 expected[1] = up_rgba[0];
660 expected[2] = up_rgba[0];
661 break;
662 default:
663 assert(!"Invalid color format");
666 switch (format->format) {
667 case GL_RED:
668 case GL_RED_INTEGER:
669 expected[1] = 0.0f;
670 case GL_RG:
671 case GL_RG_INTEGER:
672 expected[2] = 0.0f;
673 case GL_RGB:
674 case GL_RGB_INTEGER:
675 expected[3] = 1.0f;
676 break;
677 case GL_RGBA:
678 case GL_RGBA_INTEGER:
679 break;
680 case GL_ALPHA:
681 expected[0] = 0.0f;
682 expected[1] = 0.0f;
683 expected[2] = 0.0f;
684 break;
685 case GL_LUMINANCE:
686 expected[3] = 1.0f;
687 case GL_LUMINANCE_ALPHA:
688 expected[1] = expected[0];
689 expected[2] = expected[0];
690 break;
691 default:
692 assert(!"Invalid color format");
695 if (!is_format_signed(format->internal_format)) {
696 if (expected[0] < 0.0f)
697 expected[0] = 0.0f;
698 if (expected[1] < 0.0f)
699 expected[1] = 0.0f;
700 if (expected[2] < 0.0f)
701 expected[2] = 0.0f;
702 if (expected[3] < 0.0f)
703 expected[3] = 0.0f;
706 if (is_format_srgb(format->internal_format)) {
707 expected[0] = srgb_to_linear(expected[0]);
708 expected[1] = srgb_to_linear(expected[1]);
709 expected[2] = srgb_to_linear(expected[2]);
713 enum piglit_result
714 run_test(GLenum test_format, GLenum test_type, float *time_out)
716 bool pass = true;
717 int64_t time;
718 GLuint tex;
719 int i, Bpp, channels;
720 float *tmp, *expected, *observed;
721 void *data;
723 glGenTextures(1, &tex);
724 glBindTexture(GL_TEXTURE_2D, tex);
725 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
726 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
728 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
730 channels = num_channels(test_format);
731 Bpp = bytes_per_pixel(test_format, test_type);
733 if (test_type == GL_FLOAT) {
734 /* Sanitize so we don't get invalid floating point values */
735 tmp = malloc(texture_size * texture_size * channels * sizeof(float));
736 for (i = 0; i < texture_size * texture_size * channels; ++i)
737 tmp[i] = sn_to_float(32, ((GLint *)rand_data)[i]);
738 data = tmp;
739 } else {
740 tmp = NULL;
741 data = rand_data;
744 expected = malloc(texture_size * texture_size * 4 * sizeof(float));
745 for (i = 0; i < texture_size * texture_size; ++i)
746 to_expected(test_format, test_type, (GLubyte *)data + (i * Bpp),
747 expected + 4 * i);
749 if (benchmark) {
750 time = piglit_time_get_nano();
751 for (i = 0; i < BENCHMARK_ITERATIONS; ++i)
752 glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,
753 texture_size, texture_size, 0,
754 test_format, test_type, data);
755 time = piglit_time_get_nano() - time;
756 *time_out = (double)time / (double)(BENCHMARK_ITERATIONS*1000);
757 } else {
758 glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,
759 texture_size, texture_size, 0,
760 test_format, test_type, data);
762 pass &= piglit_check_gl_error(GL_NO_ERROR);
764 if (is_format_signed(format->internal_format)) {
765 glUseProgram(signed_prog);
767 for (i = 0; i < texture_size * texture_size * 4; ++i)
768 expected[i] = 0.5 + 0.5 * expected[i];
769 } else {
770 glUseProgram(unsigned_prog);
773 piglit_draw_rect_tex(0, 0, texture_size, texture_size, 0, 0, 1, 1);
775 observed = malloc(texture_size * texture_size * 4 * sizeof(float));
776 glReadPixels(0, 0, texture_size, texture_size,
777 GL_RGBA, GL_FLOAT, observed);
778 pass &= piglit_check_gl_error(GL_NO_ERROR);
780 pass &= piglit_compare_images_color(0, 0, texture_size, texture_size, 4,
781 tolerance, expected, observed);
783 free(observed);
784 free(expected);
785 free(tmp);
787 piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,
788 "%s texture with %s and %s",
789 piglit_get_gl_enum_name(format->internal_format),
790 piglit_get_gl_enum_name(test_format),
791 piglit_get_gl_enum_name(test_type));
793 glDeleteTextures(1, &tex);
795 return pass;
798 bool
799 test_exact()
801 int i, Bpp, channels;
802 float *tmp_float;
803 GLubyte *data, *observed;
804 GLint tex_width, tex_height;
805 bool pass = true;
807 if (format->data_type == GL_NONE) {
808 piglit_report_subtest_result(PIGLIT_SKIP,
809 "Exact upload-download of %s",
810 piglit_get_gl_enum_name(format->internal_format));
811 return true;
814 channels = num_channels(format->format);
815 Bpp = bytes_per_pixel(format->format, format->data_type);
817 if (format->data_type == GL_FLOAT) {
818 /* Sanitize so we don't get invalid floating point values */
819 tmp_float = malloc(texture_size * texture_size *
820 channels * sizeof(float));
821 for (i = 0; i < texture_size * texture_size * channels; ++i)
822 tmp_float[i] = sn_to_float(32, ((GLint *)rand_data)[i]);
823 data = (GLubyte *)tmp_float;
824 } else {
825 tmp_float = NULL;
826 data = rand_data;
829 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
830 glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,
831 texture_size, texture_size, 0, format->format,
832 format->data_type, data);
833 pass &= piglit_check_gl_error(GL_NO_ERROR);
835 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_width);
836 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_height);
837 glPixelStorei(GL_PACK_ALIGNMENT, 1);
838 observed = malloc(tex_width * tex_height * Bpp);
840 glGetTexImage(GL_TEXTURE_2D, 0, format->format, format->data_type,
841 observed);
842 pass &= piglit_check_gl_error(GL_NO_ERROR);
845 * For snorm formats, -127/-128 and -32767/-32768 represent the exact
846 * same value (-1.0). Therefore, it is quite reasonable to expect
847 * an implementation could return the other representation.
848 * (We'll assume it will happen only one way the other way seems rather
849 * unlikely.)
851 if (format->data_type == GL_BYTE) {
852 int j;
853 for (j = 0; j < texture_size; ++j) {
854 for (i = 0; i < tex_width * channels; i++) {
855 if (!(data[i] == observed[i] ||
856 ((GLbyte)data[i] == -128 &&
857 (GLbyte)observed[i] == -127))) {
858 pass = GL_FALSE;
862 } else if (format->data_type == GL_SHORT) {
863 int j;
864 for (j = 0; j < texture_size; ++j) {
865 for (i = 0; i < tex_width * channels; i++) {
866 GLshort data = ((GLshort *)data)[i];
867 GLshort obss = ((GLshort *)observed)[i];
868 if (!(data == obss ||
869 (data == -32768 && obss == -32767))) {
870 pass = GL_FALSE;
874 } else {
875 for (i = 0; i < texture_size; ++i)
876 pass &= memcmp(&data[i * texture_size * Bpp],
877 &observed[i * tex_width * Bpp],
878 texture_size * Bpp) == 0;
881 free(observed);
882 free(tmp_float);
884 piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,
885 "Exact upload-download of %s",
886 piglit_get_gl_enum_name(format->internal_format));
888 return pass;
891 enum piglit_result
892 piglit_display(void)
894 bool warn = false, pass = true;
895 GLuint rb, fbo;
896 int i, j;
897 float times[ARRAY_LENGTH(gl_formats)][ARRAY_LENGTH(gl_types)];
899 glGenRenderbuffersEXT(1, &rb);
900 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb);
901 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
902 GL_RGBA, texture_size, texture_size);
903 pass &= piglit_check_gl_error(GL_NO_ERROR);
905 glGenFramebuffersEXT(1, &fbo);
906 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
907 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
908 GL_COLOR_ATTACHMENT0_EXT,
909 GL_RENDERBUFFER_EXT, rb);
910 pass &= piglit_check_gl_error(GL_NO_ERROR);
912 /* Set up basic GL stuff */
913 glEnable(GL_TEXTURE_2D);
914 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
915 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
917 warn = !test_exact();
919 for (i = 0; i < ARRAY_LENGTH(gl_formats); ++i) {
920 for (j = 0; j < ARRAY_LENGTH(gl_types); ++j) {
921 if (!valid_combination(gl_formats[i], gl_types[j]))
922 continue;
924 pass &= run_test(gl_formats[i], gl_types[j],
925 &times[i][j]);
929 glDisable(GL_TEXTURE_2D);
930 glDeleteFramebuffers(1, &fbo);
931 glDeleteRenderbuffers(1, &rb);
933 if (benchmark) {
934 fprintf(stdout, "internalFormat, format, type, time (us/call)\n");
935 for (i = 0; i < ARRAY_LENGTH(gl_formats); ++i) {
936 for (j = 0; j < ARRAY_LENGTH(gl_types); ++j) {
937 if (!valid_combination(gl_formats[i], gl_types[j]))
938 continue;
940 fprintf(stdout, "%s, %s, %s, %.3f\n",
941 piglit_get_gl_enum_name(format->internal_format),
942 piglit_get_gl_enum_name(gl_formats[i]),
943 piglit_get_gl_enum_name(gl_types[j]),
944 times[i][j]);
949 if (pass) {
950 return warn ? PIGLIT_WARN : PIGLIT_PASS;
951 } else {
952 return PIGLIT_FAIL;