fix the spelling in whole piglit
[piglit.git] / tests / util / piglit-util-gl.c
blob02439087d77bb363f4f0e4907347197f86fe7139
1 /*
2 * Copyright (c) The Piglit project 2007
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include "piglit-util-gl.h"
25 #include <ctype.h>
27 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
29 /**
30 * An array of pointers to extension strings.
32 * Each extension is pointed to by a separate entry in the array.
34 * The end of the array is indicated by a NULL pointer.
36 static const char **gl_extensions = NULL;
38 static const float color_wheel[4][4] = {
39 {1, 0, 0, 1}, /* red */
40 {0, 1, 0, 1}, /* green */
41 {0, 0, 1, 1}, /* blue */
42 {1, 1, 1, 1}, /* white */
45 bool piglit_is_core_profile;
47 bool piglit_is_gles(void)
49 const char *version_string = (const char *) glGetString(GL_VERSION);
50 return strncmp("OpenGL ES", version_string, 9) == 0;
53 bool piglit_is_gles3(void)
55 const char *version_string = (const char *) glGetString(GL_VERSION);
56 return strncmp("OpenGL ES 3", version_string, 11) == 0;
59 int piglit_get_gl_version(void)
61 const char *version_string = (const char *) glGetString(GL_VERSION);
62 int scanf_count;
63 int major;
64 int minor;
66 /* skip to version number */
67 while (!isdigit(*version_string) && *version_string != '\0')
68 version_string++;
70 /* Interpret version number */
71 scanf_count = sscanf(version_string, "%i.%i", &major, &minor);
72 if (scanf_count != 2) {
73 printf("Unable to interpret GL_VERSION string: %s\n",
74 version_string);
75 piglit_report_result(PIGLIT_FAIL);
77 return 10*major+minor;
80 static const char** gl_extension_array_from_getstring()
82 const char *gl_extensions_string;
83 gl_extensions_string = (const char *) glGetString(GL_EXTENSIONS);
84 return piglit_split_string_to_array(gl_extensions_string, " ");
87 static const char** gl_extension_array_from_getstringi()
89 const char **strings;
90 int loop, num_extensions;
92 glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
93 strings = malloc (sizeof(char*) * (num_extensions + 1));
94 assert (strings != NULL);
96 for (loop = 0; loop < num_extensions; loop++) {
97 strings[loop] = (const char*) glGetStringi(GL_EXTENSIONS, loop);
100 strings[loop] = NULL;
102 return (const char**) strings;
105 static void initialize_piglit_extension_support(void)
107 if (gl_extensions != NULL) {
108 return;
111 if (piglit_get_gl_version() < 30) {
112 gl_extensions = gl_extension_array_from_getstring();
113 } else {
114 gl_extensions = gl_extension_array_from_getstringi();
118 void piglit_gl_invalidate_extensions()
120 if (gl_extensions != NULL) {
121 free(gl_extensions);
122 gl_extensions = NULL;
126 bool piglit_is_extension_supported(const char *name)
128 initialize_piglit_extension_support();
129 return piglit_is_extension_in_array(gl_extensions, name);
132 void piglit_require_gl_version(int required_version_times_10)
134 if (piglit_is_gles() ||
135 piglit_get_gl_version() < required_version_times_10) {
136 printf("Test requires GL version %g\n",
137 required_version_times_10 / 10.0);
138 piglit_report_result(PIGLIT_SKIP);
142 void piglit_require_extension(const char *name)
144 if (!piglit_is_extension_supported(name)) {
145 printf("Test requires %s\n", name);
146 piglit_report_result(PIGLIT_SKIP);
150 void piglit_require_not_extension(const char *name)
152 if (piglit_is_extension_supported(name)) {
153 piglit_report_result(PIGLIT_SKIP);
157 void piglit_require_draw_buffers(int count)
159 GLint max_targets;
160 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_targets);
161 if (max_targets < 2) {
162 printf("Test requires GL_MAX_DRAW_BUFFERS >= %d\n", count);
163 piglit_report_result(PIGLIT_SKIP);
167 const char* piglit_get_gl_error_name(GLenum error)
169 #define CASE(x) case x: return #x;
170 switch (error) {
171 CASE(GL_INVALID_ENUM)
172 CASE(GL_INVALID_OPERATION)
173 CASE(GL_INVALID_VALUE)
174 CASE(GL_NO_ERROR)
175 CASE(GL_OUT_OF_MEMORY)
176 CASE(GL_STACK_OVERFLOW)
177 CASE(GL_STACK_UNDERFLOW)
178 CASE(GL_INVALID_FRAMEBUFFER_OPERATION)
179 default:
180 return "(unrecognized error)";
182 #undef CASE
185 GLboolean
186 piglit_check_gl_error_(GLenum expected_error, const char *file, unsigned line)
188 GLenum actual_error;
190 actual_error = glGetError();
191 if (actual_error == expected_error) {
192 return GL_TRUE;
196 * If the lookup of the error's name is successful, then print
197 * Unexpected GL error: NAME 0xHEX
198 * Else, print
199 * Unexpected GL error: 0xHEX
201 printf("Unexpected GL error: %s 0x%x\n",
202 piglit_get_gl_error_name(actual_error), actual_error);
203 printf("(Error at %s:%u)\n", file, line);
205 /* Print the expected error, but only if an error was really expected. */
206 if (expected_error != GL_NO_ERROR) {
207 printf("Expected GL error: %s 0x%x\n",
208 piglit_get_gl_error_name(expected_error), expected_error);
211 return GL_FALSE;
214 void piglit_reset_gl_error(void)
216 while (glGetError() != GL_NO_ERROR) {
217 /* empty */
221 /* These texture coordinates should have 1 or -1 in the major axis selecting
222 * the face, and a nearly-1-or-negative-1 value in the other two coordinates
223 * which will be used to produce the s,t values used to sample that face's
224 * image.
226 GLfloat cube_face_texcoords[6][4][3] = {
227 { /* GL_TEXTURE_CUBE_MAP_POSITIVE_X */
228 {1.0, 0.99, 0.99},
229 {1.0, 0.99, -0.99},
230 {1.0, -0.99, -0.99},
231 {1.0, -0.99, 0.99},
233 { /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X */
234 {-1.0, 0.99, -0.99},
235 {-1.0, 0.99, 0.99},
236 {-1.0, -0.99, 0.99},
237 {-1.0, -0.99, -0.99},
239 { /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y */
240 {-0.99, 1.0, -0.99},
241 { 0.99, 1.0, -0.99},
242 { 0.99, 1.0, 0.99},
243 {-0.99, 1.0, 0.99},
245 { /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y */
246 {-0.99, -1.0, 0.99},
247 {-0.99, -1.0, -0.99},
248 { 0.99, -1.0, -0.99},
249 { 0.99, -1.0, 0.99},
251 { /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z */
252 {-0.99, 0.99, 1.0},
253 {-0.99, -0.99, 1.0},
254 { 0.99, -0.99, 1.0},
255 { 0.99, 0.99, 1.0},
257 { /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z */
258 { 0.99, 0.99, -1.0},
259 {-0.99, 0.99, -1.0},
260 {-0.99, -0.99, -1.0},
261 { 0.99, -0.99, -1.0},
265 const char *cube_face_names[6] = {
266 "POSITIVE_X",
267 "NEGATIVE_X",
268 "POSITIVE_Y",
269 "NEGATIVE_Y",
270 "POSITIVE_Z",
271 "NEGATIVE_Z",
274 const GLenum cube_face_targets[6] = {
275 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
276 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
277 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
278 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
279 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
280 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
283 float piglit_tolerance[4] = { 0.01, 0.01, 0.01, 0.01 };
285 void
286 piglit_set_tolerance_for_bits(int rbits, int gbits, int bbits, int abits)
288 int bits[4] = {rbits, gbits, bbits, abits};
289 int i;
291 for (i = 0; i < 4; i++) {
292 if (bits[i] == 0) {
293 /* With 0 bits of storage, we still want to
294 * validate expected results, (such as
295 * alpha==1.0 when targeting storage with no
296 * alpha bits). */
297 piglit_tolerance[i] = 3.0 / (1 << 8);
298 } else if (bits[i] == 1) {
299 /* Don't try to validate channels when there's only 1
300 * bit of precision.
302 piglit_tolerance[i] = 1.0;
303 } else {
304 piglit_tolerance[i] = 3.0 / (1 << bits[i]);
309 typedef union { GLfloat f; GLint i; } fi_type;
312 * Convert a 4-byte float to a 2-byte half float.
313 * Based on code from:
314 * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html
316 * Taken over from Mesa.
318 unsigned short
319 piglit_half_from_float(float val)
321 const fi_type fi = {val};
322 const int flt_m = fi.i & 0x7fffff;
323 const int flt_e = (fi.i >> 23) & 0xff;
324 const int flt_s = (fi.i >> 31) & 0x1;
325 int s, e, m = 0;
326 unsigned short result;
328 /* sign bit */
329 s = flt_s;
331 /* handle special cases */
332 if ((flt_e == 0) && (flt_m == 0)) {
333 /* zero */
334 /* m = 0; - already set */
335 e = 0;
337 else if ((flt_e == 0) && (flt_m != 0)) {
338 /* denorm -- denorm float maps to 0 half */
339 /* m = 0; - already set */
340 e = 0;
342 else if ((flt_e == 0xff) && (flt_m == 0)) {
343 /* infinity */
344 /* m = 0; - already set */
345 e = 31;
347 else if ((flt_e == 0xff) && (flt_m != 0)) {
348 /* NaN */
349 m = 1;
350 e = 31;
352 else {
353 /* regular number */
354 const int new_exp = flt_e - 127;
355 if (new_exp < -24) {
356 /* this maps to 0 */
357 /* m = 0; - already set */
358 e = 0;
360 else if (new_exp < -14) {
361 /* this maps to a denorm */
362 /* 2^-exp_val*/
363 unsigned int exp_val = (unsigned int) (-14 - new_exp);
365 e = 0;
366 switch (exp_val) {
367 case 0:
368 /* m = 0; - already set */
369 break;
370 case 1: m = 512 + (flt_m >> 14); break;
371 case 2: m = 256 + (flt_m >> 15); break;
372 case 3: m = 128 + (flt_m >> 16); break;
373 case 4: m = 64 + (flt_m >> 17); break;
374 case 5: m = 32 + (flt_m >> 18); break;
375 case 6: m = 16 + (flt_m >> 19); break;
376 case 7: m = 8 + (flt_m >> 20); break;
377 case 8: m = 4 + (flt_m >> 21); break;
378 case 9: m = 2 + (flt_m >> 22); break;
379 case 10: m = 1; break;
382 else if (new_exp > 15) {
383 /* map this value to infinity */
384 /* m = 0; - already set */
385 e = 31;
387 else {
388 /* regular */
389 e = new_exp + 15;
390 m = flt_m >> 13;
394 result = (s << 15) | (e << 10) | m;
395 return result;
400 * Return block size info for a specific texture compression format.
401 * \param bw returns the block width, in pixels
402 * \param bh returns the block height, in pixels
403 * \param return number of bytes per block
404 * \return true if format is a known compressed format, false otherwise
406 bool
407 piglit_get_compressed_block_size(GLenum format,
408 unsigned *bw, unsigned *bh, unsigned *bytes)
410 switch (format) {
411 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
412 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
413 *bw = *bh = 4;
414 *bytes = 8;
415 return true;
416 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
417 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
418 case GL_COMPRESSED_RED:
419 case GL_COMPRESSED_RED_RGTC1:
420 case GL_COMPRESSED_SIGNED_RED_RGTC1:
421 case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
422 case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
423 case GL_COMPRESSED_RGB8_ETC2:
424 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
425 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
426 case GL_COMPRESSED_R11_EAC:
427 case GL_COMPRESSED_SIGNED_R11_EAC:
428 case GL_COMPRESSED_SRGB8_ETC2:
429 *bw = *bh = 4;
430 *bytes = 8;
431 return true;
432 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
433 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
434 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
435 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
436 case GL_COMPRESSED_RG:
437 case GL_COMPRESSED_RG_RGTC2:
438 case GL_COMPRESSED_SIGNED_RG_RGTC2:
439 case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
440 case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
441 case GL_COMPRESSED_RGBA_BPTC_UNORM:
442 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
443 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
444 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
445 case GL_COMPRESSED_RGBA8_ETC2_EAC:
446 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
447 case GL_COMPRESSED_RG11_EAC:
448 case GL_COMPRESSED_SIGNED_RG11_EAC:
449 *bw = *bh = 4;
450 *bytes = 16;
451 return true;
452 case GL_COMPRESSED_RGB_FXT1_3DFX:
453 case GL_COMPRESSED_RGBA_FXT1_3DFX:
454 *bw = 8;
455 *bh = 4;
456 *bytes = 16;
457 return true;
458 default:
459 /* return something rather than uninitialized values */
460 *bw = *bh = *bytes = 1;
461 return false;
467 * Compute size (in bytes) needed to store an image in the given compressed
468 * format.
470 unsigned
471 piglit_compressed_image_size(GLenum format, unsigned width, unsigned height)
473 unsigned bw, bh, bytes;
474 bool b = piglit_get_compressed_block_size(format, &bw, &bh, &bytes);
476 (void)b;
477 assert(b);
478 return ((width + bw - 1) / bw) * ((height + bh - 1) / bh) * bytes;
483 * Return offset (in bytes) to the given texel in a compressed image.
484 * Note the x and y must be multiples of the compressed block size.
486 unsigned
487 piglit_compressed_pixel_offset(GLenum format, unsigned width,
488 unsigned x, unsigned y)
490 unsigned bw, bh, bytes, offset;
491 bool b = piglit_get_compressed_block_size(format, &bw, &bh, &bytes);
493 (void)b;
494 assert(b);
496 assert(x % bw == 0);
497 assert(y % bh == 0);
498 assert(width % bw == 0);
500 offset = (width / bw * bytes * y / bh) + (x / bw * bytes);
502 return offset;
505 void
506 piglit_escape_exit_key(unsigned char key, int x, int y)
508 (void) x;
509 (void) y;
510 switch (key) {
511 case 27:
512 exit(0);
513 break;
515 if (!piglit_is_gles())
516 piglit_post_redisplay();
520 * Convenience function to configure an abitrary orthogonal projection matrix
522 void
523 piglit_gen_ortho_projection(double left, double right, double bottom,
524 double top, double near_val, double far_val,
525 GLboolean push)
527 glMatrixMode(GL_PROJECTION);
528 glLoadIdentity();
529 if (push)
530 glPushMatrix();
532 if (piglit_is_gles())
533 glOrthof(left, right, bottom, top, near_val, far_val);
534 else
535 glOrtho(left, right, bottom, top, near_val, far_val);
537 glMatrixMode(GL_MODELVIEW);
538 if (push)
539 glPushMatrix();
540 glLoadIdentity();
544 * Convenience function to configure projection matrix for window coordinates
546 void
547 piglit_ortho_projection(int w, int h, GLboolean push)
549 /* Set up projection matrix so we can just draw using window
550 * coordinates.
552 piglit_gen_ortho_projection(0, w, 0, h, -1, 1, push);
556 * Convenience function to configure frustum projection.
558 void
559 piglit_frustum_projection(GLboolean push, double l, double r, double b,
560 double t, double n, double f)
562 glMatrixMode(GL_PROJECTION);
563 glLoadIdentity();
564 if (push)
565 glPushMatrix();
567 if (piglit_is_gles())
568 glFrustumf(l, r, b, t, n, f);
569 else
570 glFrustum(l, r, b, t, n, f);
572 glMatrixMode(GL_MODELVIEW);
573 if (push)
574 glPushMatrix();
575 glLoadIdentity();
579 * Convenience function to configure a shader uniform variable as an
580 * arbitrary orthogonal projection matrix.
582 void
583 piglit_gen_ortho_uniform(GLint location, double l, double r, double b,
584 double t, double n, double f)
586 const GLfloat values[4][4] = {
587 { 2/(r-l), 0, 0, 0 },
588 { 0, 2/(t-b), 0, 0 },
589 { 0, 0, -2/(f-n), 0 },
590 { -(r+l)/(r-l), -(t+b)/(t-b), -(f+n)/(f-n), 1 }
592 glUniformMatrix4fv(location, 1, GL_FALSE, (const GLfloat *)values);
597 * Convenience function to configure a shader uniform variable as a
598 * projection matrix for window coordinates.
600 void
601 piglit_ortho_uniform(GLint location, int w, int h)
603 /* Set up projection matrix so we can just draw using window
604 * coordinates.
606 piglit_gen_ortho_uniform(location, 0, w, 0, h, -1, 1);
610 unsigned
611 required_gl_version_from_glsl_version(unsigned glsl_version)
613 switch (glsl_version) {
614 case 110: return 20;
615 case 120: return 21;
616 /* GLSL 1.30 is naturally matched with GL3,
617 * but is usefully supportable on GL2.1 if
618 * EXT_gpu_shader4 is also supported.
620 case 130: return 21;
621 case 140: return 31;
622 case 150: return 32;
623 case 330: return 33;
624 case 400: return 40;
625 case 410: return 41;
626 case 420: return 42;
627 case 430: return 43;
628 case 440: return 44;
629 case 450: return 45;
630 case 460: return 46;
631 default: return 0;
636 * Call glDrawArrays. verts is expected to be
638 * float verts[4][4];
640 * if not NULL; tex is expected to be
642 * float tex[4][2];
644 * if not NULL.
646 void
647 piglit_draw_rect_from_arrays(const void *verts, const void *tex,
648 bool use_patches, unsigned instance_count)
650 bool use_fixed_function_attributes;
652 bool gles = piglit_is_gles();
653 int version = piglit_get_gl_version();
655 if (gles) {
656 use_fixed_function_attributes = (version < 20);
657 } else if (version >= 20 ||
658 piglit_is_extension_supported("GL_ARB_shader_objects")) {
659 GLuint prog;
661 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
663 if (!prog &&
664 piglit_is_extension_supported("GL_ARB_separate_shader_objects")) {
665 GLuint pipeline;
667 glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING,
668 (GLint*)&pipeline);
669 if (pipeline)
670 glGetProgramPipelineiv(pipeline, GL_VERTEX_SHADER,
671 (GLint*)&prog);
674 /* If there is a current program and that program has an
675 * active attribute named piglit_vertex, don't use the fixed
676 * function inputs. Never use fixed function inputs on core
677 * profile.
679 use_fixed_function_attributes = ((prog == 0)
680 || glGetAttribLocation(prog, "piglit_vertex") == -1)
681 && !piglit_is_core_profile;
682 } else {
683 use_fixed_function_attributes = true;
686 if (use_fixed_function_attributes) {
687 if (verts) {
688 glVertexPointer(4, GL_FLOAT, 0, verts);
689 glEnableClientState(GL_VERTEX_ARRAY);
692 if (tex) {
693 glTexCoordPointer(2, GL_FLOAT, 0, tex);
694 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
697 if (use_patches) {
698 GLint old_patch_vertices;
700 glGetIntegerv(GL_PATCH_VERTICES, &old_patch_vertices);
701 glPatchParameteri(GL_PATCH_VERTICES, 4);
702 if (instance_count > 1)
703 glDrawArraysInstanced(GL_PATCHES, 0, 4, instance_count);
704 else
705 glDrawArrays(GL_PATCHES, 0, 4);
706 glPatchParameteri(GL_PATCH_VERTICES, old_patch_vertices);
707 } else {
708 if (instance_count > 1)
709 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, instance_count);
710 else
711 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
714 if (verts)
715 glDisableClientState(GL_VERTEX_ARRAY);
716 if (tex)
717 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
718 } else {
719 GLuint buf = 0;
720 GLuint old_buf = 0;
721 GLuint vao = 0;
722 GLuint old_vao = 0;
724 /* Vertex array objects were added in both OpenGL 3.0 and
725 * OpenGL ES 3.0. The use of VAOs is required in desktop
726 * OpenGL 3.1 (without GL_ARB_compatibility) and all desktop
727 * OpenGL core profiles. If the functionality is supported,
728 * just use it.
730 if (piglit_get_gl_version() >= 30
731 || piglit_is_extension_supported("GL_OES_vertex_array_object")
732 || piglit_is_extension_supported("GL_ARB_vertex_array_object")) {
733 glGetIntegerv(GL_VERTEX_ARRAY_BINDING,
734 (GLint *) &old_vao);
735 glGenVertexArrays(1, &vao);
736 glBindVertexArray(vao);
739 /* Assume that VBOs are supported in any implementation that
740 * uses shaders.
742 glGetIntegerv(GL_ARRAY_BUFFER_BINDING,
743 (GLint *) &old_buf);
744 glGenBuffers(1, &buf);
745 glBindBuffer(GL_ARRAY_BUFFER, buf);
746 glBufferData(GL_ARRAY_BUFFER,
747 (sizeof(GLfloat) * 4 * 4)
748 + (sizeof(GLfloat) * 4 * 2),
749 NULL,
750 GL_STATIC_DRAW);
752 if (verts) {
753 glBufferSubData(GL_ARRAY_BUFFER,
755 sizeof(GLfloat) * 4 * 4,
756 verts);
757 glVertexAttribPointer(PIGLIT_ATTRIB_POS, 4, GL_FLOAT,
758 GL_FALSE, 0,
759 BUFFER_OFFSET(0));
760 glEnableVertexAttribArray(PIGLIT_ATTRIB_POS);
763 if (tex) {
764 glBufferSubData(GL_ARRAY_BUFFER,
765 sizeof(GLfloat) * 4 * 4,
766 sizeof(GLfloat) * 4 * 2,
767 tex);
768 glVertexAttribPointer(PIGLIT_ATTRIB_TEX, 2, GL_FLOAT,
769 GL_FALSE, 0,
770 BUFFER_OFFSET(sizeof(GLfloat) * 4 * 4));
771 glEnableVertexAttribArray(PIGLIT_ATTRIB_TEX);
774 if (use_patches) {
775 GLint old_patch_vertices;
777 glGetIntegerv(GL_PATCH_VERTICES, &old_patch_vertices);
778 glPatchParameteri(GL_PATCH_VERTICES, 4);
779 if (instance_count > 1)
780 glDrawArraysInstanced(GL_PATCHES, 0, 4, instance_count);
781 else
782 glDrawArrays(GL_PATCHES, 0, 4);
783 glPatchParameteri(GL_PATCH_VERTICES, old_patch_vertices);
785 else {
786 if (instance_count > 1)
787 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, instance_count);
788 else
789 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
792 if (verts)
793 glDisableVertexAttribArray(PIGLIT_ATTRIB_POS);
794 if (tex)
795 glDisableVertexAttribArray(PIGLIT_ATTRIB_TEX);
797 glBindBuffer(GL_ARRAY_BUFFER, old_buf);
798 glDeleteBuffers(1, &buf);
800 if (vao != 0) {
801 glBindVertexArray(old_vao);
802 glDeleteVertexArrays(1, &vao);
808 * Convenience function to draw an axis-aligned rectangle.
810 GLvoid
811 piglit_draw_rect_custom(float x, float y, float w, float h, bool use_patches,
812 unsigned instance_count)
814 float verts[4][4];
816 verts[0][0] = x;
817 verts[0][1] = y;
818 verts[0][2] = 0.0;
819 verts[0][3] = 1.0;
820 verts[1][0] = x + w;
821 verts[1][1] = y;
822 verts[1][2] = 0.0;
823 verts[1][3] = 1.0;
824 verts[2][0] = x;
825 verts[2][1] = y + h;
826 verts[2][2] = 0.0;
827 verts[2][3] = 1.0;
828 verts[3][0] = x + w;
829 verts[3][1] = y + h;
830 verts[3][2] = 0.0;
831 verts[3][3] = 1.0;
833 piglit_draw_rect_from_arrays(verts, NULL, use_patches, instance_count);
837 * Convenience function to draw an axis-aligned rectangle.
839 GLvoid
840 piglit_draw_rect(float x, float y, float w, float h)
842 piglit_draw_rect_custom(x, y, w, h, false, 1);
846 * Convenience function to draw an axis-aligned rectangle.
848 GLvoid
849 piglit_draw_rect_z(float z, float x, float y, float w, float h)
851 float verts[4][4];
853 verts[0][0] = x;
854 verts[0][1] = y;
855 verts[0][2] = z;
856 verts[0][3] = 1.0;
857 verts[1][0] = x + w;
858 verts[1][1] = y;
859 verts[1][2] = z;
860 verts[1][3] = 1.0;
861 verts[2][0] = x;
862 verts[2][1] = y + h;
863 verts[2][2] = z;
864 verts[2][3] = 1.0;
865 verts[3][0] = x + w;
866 verts[3][1] = y + h;
867 verts[3][2] = z;
868 verts[3][3] = 1.0;
870 piglit_draw_rect_from_arrays(verts, NULL, false, 1);
874 * Convenience function to draw an axis-aligned rectangle
875 * with texture coordinates.
877 GLvoid
878 piglit_draw_rect_tex(float x, float y, float w, float h,
879 float tx, float ty, float tw, float th)
881 float verts[4][4];
882 float tex[4][2];
884 verts[0][0] = x;
885 verts[0][1] = y;
886 verts[0][2] = 0.0;
887 verts[0][3] = 1.0;
888 tex[0][0] = tx;
889 tex[0][1] = ty;
890 verts[1][0] = x + w;
891 verts[1][1] = y;
892 verts[1][2] = 0.0;
893 verts[1][3] = 1.0;
894 tex[1][0] = tx + tw;
895 tex[1][1] = ty;
896 verts[2][0] = x;
897 verts[2][1] = y + h;
898 verts[2][2] = 0.0;
899 verts[2][3] = 1.0;
900 tex[2][0] = tx;
901 tex[2][1] = ty + th;
902 verts[3][0] = x + w;
903 verts[3][1] = y + h;
904 verts[3][2] = 0.0;
905 verts[3][3] = 1.0;
906 tex[3][0] = tx + tw;
907 tex[3][1] = ty + th;
909 piglit_draw_rect_from_arrays(verts, tex, false, 1);
912 unsigned
913 piglit_num_components(GLenum format)
915 switch (format) {
916 case GL_ALPHA:
917 case GL_DEPTH_COMPONENT:
918 case GL_INTENSITY:
919 case GL_LUMINANCE:
920 case GL_RED:
921 case GL_GREEN:
922 case GL_BLUE:
923 return 1;
924 case GL_DEPTH_STENCIL:
925 case GL_LUMINANCE_ALPHA:
926 case GL_RG:
927 return 2;
928 case GL_RGB:
929 case GL_BGR:
930 return 3;
931 case GL_RGBA:
932 case GL_BGRA:
933 case GL_ABGR_EXT:
934 return 4;
935 default:
936 printf("Unknown num_components for %s\n",
937 piglit_get_gl_enum_name(format));
938 piglit_report_result(PIGLIT_FAIL);
939 return 0;
943 /* This function only handles formats not supported by the OpenGL framebuffer
944 * size queries, which only support querying the R,G,B,A sizes.
946 * The function doesn't change the bits for formats it doesn't handle.
948 * The returned number of bits is an approximation but should be no less than
949 * the actual number of bits for the format chosen by OpenGL.
951 * The combination of the OpenGL framebuffer queries size and calling
952 * this function without checking the return value should give you reasonable
953 * values for any format.
955 bool
956 piglit_get_luminance_intensity_bits(GLenum internalformat, int *bits)
958 switch (internalformat) {
959 case GL_LUMINANCE4:
960 bits[0] = bits[1] = bits[2] = 4;
961 bits[3] = 0;
962 return true;
964 case GL_LUMINANCE:
965 case GL_LUMINANCE_SNORM:
966 case GL_LUMINANCE8:
967 case GL_LUMINANCE8_SNORM:
968 case GL_LUMINANCE8I_EXT:
969 case GL_LUMINANCE8UI_EXT:
970 bits[0] = bits[1] = bits[2] = 8;
971 bits[3] = 0;
972 return true;
974 case GL_LUMINANCE12:
975 bits[0] = bits[1] = bits[2] = 12;
976 bits[3] = 0;
977 return true;
979 case GL_LUMINANCE16:
980 case GL_LUMINANCE16_SNORM:
981 case GL_LUMINANCE16I_EXT:
982 case GL_LUMINANCE16UI_EXT:
983 case GL_LUMINANCE16F_ARB:
984 bits[0] = bits[1] = bits[2] = 16;
985 bits[3] = 0;
986 return true;
988 case GL_LUMINANCE32I_EXT:
989 case GL_LUMINANCE32UI_EXT:
990 case GL_LUMINANCE32F_ARB:
991 bits[0] = bits[1] = bits[2] = 32;
992 bits[3] = 0;
993 return true;
995 case GL_LUMINANCE4_ALPHA4:
996 case GL_INTENSITY4:
997 bits[0] = bits[1] = bits[2] = bits[3] = 4;
998 return true;
1000 case GL_LUMINANCE_ALPHA:
1001 case GL_LUMINANCE_ALPHA_SNORM:
1002 case GL_LUMINANCE8_ALPHA8:
1003 case GL_LUMINANCE8_ALPHA8_SNORM:
1004 case GL_LUMINANCE_ALPHA8I_EXT:
1005 case GL_LUMINANCE_ALPHA8UI_EXT:
1006 case GL_INTENSITY:
1007 case GL_INTENSITY_SNORM:
1008 case GL_INTENSITY8:
1009 case GL_INTENSITY8_SNORM:
1010 case GL_INTENSITY8I_EXT:
1011 case GL_INTENSITY8UI_EXT:
1012 bits[0] = bits[1] = bits[2] = bits[3] = 8;
1013 return true;
1015 case GL_LUMINANCE12_ALPHA12:
1016 case GL_INTENSITY12:
1017 bits[0] = bits[1] = bits[2] = bits[3] = 12;
1018 return true;
1020 case GL_LUMINANCE16_ALPHA16:
1021 case GL_LUMINANCE16_ALPHA16_SNORM:
1022 case GL_LUMINANCE_ALPHA16I_EXT:
1023 case GL_LUMINANCE_ALPHA16UI_EXT:
1024 case GL_LUMINANCE_ALPHA16F_ARB:
1025 case GL_INTENSITY16:
1026 case GL_INTENSITY16_SNORM:
1027 case GL_INTENSITY16I_EXT:
1028 case GL_INTENSITY16UI_EXT:
1029 case GL_INTENSITY16F_ARB:
1030 bits[0] = bits[1] = bits[2] = bits[3] = 16;
1031 return true;
1033 case GL_LUMINANCE_ALPHA32I_EXT:
1034 case GL_LUMINANCE_ALPHA32UI_EXT:
1035 case GL_LUMINANCE_ALPHA32F_ARB:
1036 case GL_INTENSITY32I_EXT:
1037 case GL_INTENSITY32UI_EXT:
1038 case GL_INTENSITY32F_ARB:
1039 bits[0] = bits[1] = bits[2] = bits[3] = 32;
1040 return true;
1042 return false;
1045 /* Wrapper around glReadPixels that always returns floats; reads and converts
1046 * GL_UNSIGNED_BYTE on GLES. If pixels == NULL, malloc a float array of the
1047 * appropriate size, otherwise use the one provided. */
1048 GLfloat *
1049 piglit_read_pixels_float(GLint x, GLint y, GLsizei width, GLsizei height,
1050 GLenum format, GLfloat *pixels)
1052 GLubyte *pixels_b;
1053 unsigned i, j, k;
1054 int comps = piglit_num_components(format);
1056 if (!pixels)
1057 pixels = malloc(width * height * comps * sizeof(GLfloat));
1059 if (!piglit_is_gles()) {
1060 glReadPixels(x, y, width, height, format, GL_FLOAT, pixels);
1061 return pixels;
1064 pixels_b = malloc(width * height * 4 * sizeof(GLubyte));
1065 glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels_b);
1066 k = 0;
1067 for (i = 0; i < width * height; i++) {
1068 for (j = 0; j < comps; j++) {
1069 pixels[k++] = pixels_b[i*4+j] / 255.0f;
1072 free(pixels_b);
1073 return pixels;
1076 static bool
1077 can_probe_ubyte()
1079 int r,g,b,a,read;
1081 if (!piglit_is_extension_supported("GL_ARB_framebuffer_object"))
1082 return false;
1084 glGetIntegerv(GL_READ_BUFFER, &read);
1085 if (read == GL_FRONT)
1086 read = GL_FRONT_LEFT;
1087 if (read == GL_BACK)
1088 read = GL_BACK_LEFT;
1090 glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER, read,
1091 GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &r);
1092 glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER, read,
1093 GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, &g);
1094 glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER, read,
1095 GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &b);
1096 glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER, read,
1097 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &a);
1099 /* it could be LUMINANCE32F, etc. */
1100 if (!r && !g && !b && !a)
1101 return false;
1103 return r <= 8 && g <= 8 && b <= 8 && a <= 8;
1106 static void
1107 print_components_ubyte(const GLubyte *pixel, unsigned components)
1109 int p;
1110 for (p = 0; p < components; ++p)
1111 printf(" %u", pixel[p]);
1114 static void
1115 print_components_float(const float *pixel, unsigned components)
1117 int p;
1118 for (p = 0; p < components; ++p)
1119 printf(" %f", pixel[p]);
1122 static void
1123 print_bad_pixel_ubyte(int x, int y, int num_components,
1124 const GLubyte *expected, const GLubyte *observed)
1126 printf("Probe color at (%i,%i)\n", x, y);
1127 printf(" Expected:");
1128 print_components_ubyte(expected, num_components);
1129 printf("\n Observed:");
1130 print_components_ubyte(observed, num_components);
1131 printf("\n");
1134 static void
1135 print_bad_pixel_float(int x, int y, int num_components,
1136 const float *expected, const float *observed)
1138 printf("Probe color at (%i,%i)\n", x, y);
1139 printf(" Expected:");
1140 print_components_float(expected, num_components);
1141 printf("\n Observed:");
1142 print_components_float(observed, num_components);
1143 printf("\n");
1146 static bool
1147 compare_pixels_ubyte(const GLubyte *color1, const GLubyte *color2,
1148 const GLubyte *tolerance, int components)
1150 for (int p = 0; p < components; ++p)
1151 if (abs((int)color1[p] - (int)color2[p]) > tolerance[p])
1152 return false;
1153 return true;
1156 bool
1157 piglit_compare_pixels_float(const float *color1, const float *color2,
1158 const float *tolerance, int components)
1160 for (int p = 0; p < components; ++p)
1161 if (fabsf(color1[p] - color2[p]) > tolerance[p])
1162 return false;
1163 return true;
1167 piglit_probe_pixel_rgb_silent(int x, int y, const float* expected, float *out_probe)
1169 GLfloat probe[3];
1171 piglit_read_pixels_float(x, y, 1, 1, GL_RGB, probe);
1173 bool pass =
1174 piglit_compare_pixels_float(probe, expected, piglit_tolerance, 3);
1176 if (out_probe)
1177 memcpy(out_probe, probe, sizeof(probe));
1179 return pass;
1183 piglit_probe_pixel_rgba_silent(int x, int y, const float* expected, float *out_probe)
1185 GLfloat probe[4];
1187 piglit_read_pixels_float(x, y, 1, 1, GL_RGBA, probe);
1189 bool pass =
1190 piglit_compare_pixels_float(probe, expected, piglit_tolerance, 4);
1192 if (out_probe)
1193 memcpy(out_probe, probe, sizeof(probe));
1195 return pass;
1199 * Read a pixel from the given location and compare its RGB value to the
1200 * given expected values.
1202 * Print a log message if the color value deviates from the expected value.
1203 * \return true if the color values match, false otherwise
1206 piglit_probe_pixel_rgb(int x, int y, const float* expected)
1208 GLfloat probe[3];
1210 piglit_read_pixels_float(x, y, 1, 1, GL_RGB, probe);
1212 if (piglit_compare_pixels_float(probe, expected, piglit_tolerance, 3))
1213 return 1;
1215 print_bad_pixel_float(x, y, 3, expected, probe);
1217 return 0;
1221 * Read a pixel from the given location and compare its RGBA value to the
1222 * given expected values.
1224 * Print a log message if the color value deviates from the expected value.
1225 * \return true if the color values match, false otherwise
1228 piglit_probe_pixel_rgba(int x, int y, const float* expected)
1230 GLfloat probe[4];
1232 piglit_read_pixels_float(x, y, 1, 1, GL_RGBA, probe);
1234 if (piglit_compare_pixels_float(probe, expected, piglit_tolerance, 4))
1235 return 1;
1237 print_bad_pixel_float(x, y, 4, expected, probe);
1239 return 0;
1242 static void
1243 array_float_to_ubyte(int n, const float *f, GLubyte *b)
1245 int i;
1247 for (i = 0; i < n; i++)
1248 b[i] = f[i] * 255;
1251 static void
1252 array_float_to_ubyte_roundup(int n, const float *f, GLubyte *b)
1254 int i;
1256 for (i = 0; i < n; i++)
1257 b[i] = ceil(f[i] * 255);
1260 static bool
1261 probe_rect_ubyte(int x, int y, int w, int h, int num_components,
1262 const float *fexpected, size_t x_pitch, size_t y_pitch,
1263 bool silent)
1265 int i, j;
1266 GLubyte *probe;
1267 GLubyte *pixels;
1268 GLubyte tolerance[4];
1269 GLubyte expected[4];
1271 array_float_to_ubyte_roundup(num_components, piglit_tolerance,
1272 tolerance);
1273 if (x_pitch == 0 && y_pitch == 0)
1274 array_float_to_ubyte(num_components, fexpected, expected);
1276 /* RGBA readbacks are likely to be faster */
1277 pixels = malloc(w*h*4);
1278 glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1280 for (j = 0; j < h; j++) {
1281 for (i = 0; i < w; i++) {
1282 probe = &pixels[(j*w+i)*4];
1284 if (x_pitch != 0 || y_pitch != 0) {
1285 const float *pexp = fexpected + i * x_pitch +
1286 j * y_pitch;
1287 array_float_to_ubyte(num_components,
1288 pexp, expected);
1291 if (compare_pixels_ubyte(probe, expected, tolerance,
1292 num_components))
1293 continue;
1295 if (!silent) {
1296 print_bad_pixel_ubyte(
1297 x + i, y + j, num_components,
1298 expected, probe);
1300 free(pixels);
1301 return false;
1305 free(pixels);
1306 return true;
1309 static bool
1310 probe_rect_float(int x, int y, int w, int h, int num_components,
1311 const float *fexpected, size_t x_pitch, size_t y_pitch,
1312 bool silent)
1314 float *pixels = piglit_read_pixels_float(x, y, w, h, GL_RGBA, NULL);
1316 for (int j = 0; j < h; j++) {
1317 for (int i = 0; i < w; i++) {
1318 float *probe = &pixels[(j*w+i)*4];
1319 const float *pexp = fexpected + i * x_pitch +
1320 j * y_pitch;
1322 if (piglit_compare_pixels_float(probe, pexp,
1323 piglit_tolerance,
1324 num_components))
1325 continue;
1327 if (!silent) {
1328 print_bad_pixel_float(x + i, y + j,
1329 num_components,
1330 fexpected, probe);
1332 free(pixels);
1333 return false;
1337 free(pixels);
1338 return true;
1341 static bool
1342 probe_rect(int x, int y, int w, int h, int num_components,
1343 const float *fexpected, size_t x_pitch, size_t y_pitch,
1344 bool silent)
1346 if (can_probe_ubyte()) {
1347 return probe_rect_ubyte(x, y, w, h, num_components, fexpected,
1348 x_pitch, y_pitch, silent);
1349 } else {
1350 return probe_rect_float(x, y, w, h, num_components, fexpected,
1351 x_pitch, y_pitch, silent);
1357 piglit_probe_rect_rgb_silent(int x, int y, int w, int h, const float *expected)
1359 return probe_rect(x, y, w, h, 3, expected, 0, 0, true);
1362 /* More efficient variant if you don't know need floats and GBA channels. */
1364 piglit_probe_rect_r_ubyte(int x, int y, int w, int h, GLubyte expected)
1366 int i, j, w_aligned;
1367 GLubyte *pixels;
1368 GLubyte tolerance = ceil(piglit_tolerance[0] * 255);
1370 w_aligned = ALIGN(w, 4);
1371 pixels = malloc(w_aligned * h);
1373 glReadPixels(x, y, w, h, GL_RED, GL_UNSIGNED_BYTE, pixels);
1375 for (j = 0; j < h; j++) {
1376 for (i = 0; i < w; i++) {
1377 GLubyte probe = pixels[j*w_aligned+i];
1379 if (abs((int)probe - (int)expected) >= tolerance) {
1380 print_bad_pixel_ubyte(x + i, y + j, 1,
1381 &expected, &probe);
1383 free(pixels);
1384 return 0;
1389 free(pixels);
1390 return 1;
1394 piglit_probe_rect_rgb(int x, int y, int w, int h, const float *expected)
1396 return probe_rect(x, y, w, h, 3, expected, 0, 0, false);
1400 piglit_probe_rects_equal(int x1, int y1, int x2, int y2,
1401 int w, int h, GLenum format)
1403 int retval;
1404 int ncomponents;
1406 /* Allocate buffer large enough for two rectangles */
1407 ncomponents = piglit_num_components(format);
1409 /* Load the pixels into the buffer and compare */
1410 /* We only need to do one glReadPixels if the images are adjacent */
1411 if ((x1 + w) == x2 && y1 == y2) {
1412 float *pixels =
1413 piglit_read_pixels_float(x1, y1, 2 * w, h, format, NULL);
1414 retval = piglit_compare_image_halves_color(2*w, h,
1415 ncomponents,
1416 piglit_tolerance,
1417 pixels);
1418 free(pixels);
1419 } else {
1420 float *pixels1 =
1421 piglit_read_pixels_float(x1, y1, w, h, format, NULL);
1422 float *pixels2 =
1423 piglit_read_pixels_float(x2, y2, w, h, format, NULL);
1424 retval = piglit_compare_images_color(0, 0, w, h,
1425 ncomponents,
1426 piglit_tolerance,
1427 pixels1, pixels2);
1428 free(pixels1);
1429 free(pixels2);
1432 return retval;
1436 piglit_probe_rect_halves_equal_rgba(int x, int y, int w, int h)
1438 int i, j, p;
1439 GLfloat probe1[4];
1440 GLfloat probe2[4];
1441 GLubyte *pixels = malloc(w*h*4*sizeof(GLubyte));
1443 glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1445 for (j = 0; j < h; j++) {
1446 for (i = 0; i < w / 2; i++) {
1447 GLubyte *pixel1 = &pixels[4 * (j * w + i)];
1448 GLubyte *pixel2 = &pixels[4 * (j * w + w / 2 + i)];
1450 for (p = 0; p < 4; ++p) {
1451 probe1[p] = pixel1[p] / 255.0f;
1452 probe2[p] = pixel2[p] / 255.0f;
1455 if (piglit_compare_pixels_float(probe1, probe2,
1456 piglit_tolerance, 4))
1457 continue;
1459 printf("Probe color at (%i,%i)\n", x+i, x+j);
1460 printf(" Left: %f %f %f %f\n",
1461 probe1[0], probe1[1], probe1[2], probe1[3]);
1462 printf(" Right: %f %f %f %f\n",
1463 probe2[0], probe2[1], probe2[2], probe2[3]);
1465 free(pixels);
1466 return 0;
1470 free(pixels);
1471 return 1;
1475 piglit_probe_rect_rgba(int x, int y, int w, int h, const float *expected)
1477 return probe_rect(x, y, w, h, 4, expected, 0, 0, false);
1480 int piglit_probe_rect_rgba_varying(int x, int y, int w, int h,
1481 const float* expected, size_t stride)
1483 assert(stride % sizeof(float) == 0);
1484 return probe_rect(x, y, w, h, 4, expected,
1485 4, stride / sizeof(float), false);
1489 piglit_probe_rect_rgba_int(int x, int y, int w, int h, const int *expected)
1491 int i, j, p;
1492 GLint *probe;
1493 GLint *pixels = malloc(w*h*4*sizeof(int));
1495 glReadPixels(x, y, w, h, GL_RGBA_INTEGER, GL_INT, pixels);
1497 for (j = 0; j < h; j++) {
1498 for (i = 0; i < w; i++) {
1499 probe = &pixels[(j*w+i)*4];
1501 for (p = 0; p < 4; ++p) {
1502 if (probe[p] != expected[p]) {
1503 printf("Probe color at (%d,%d)\n", x+i, y+j);
1504 printf(" Expected: %d %d %d %d\n",
1505 expected[0], expected[1], expected[2], expected[3]);
1506 printf(" Observed: %d %d %d %d\n",
1507 probe[0], probe[1], probe[2], probe[3]);
1509 free(pixels);
1510 return 0;
1516 free(pixels);
1517 return 1;
1521 piglit_probe_rect_rgba_uint(int x, int y, int w, int h,
1522 const unsigned int *expected)
1524 int i, j, p;
1525 GLuint *probe;
1526 GLuint *pixels = malloc(w*h*4*sizeof(unsigned int));
1528 glReadPixels(x, y, w, h, GL_RGBA_INTEGER, GL_UNSIGNED_INT, pixels);
1530 for (j = 0; j < h; j++) {
1531 for (i = 0; i < w; i++) {
1532 probe = &pixels[(j*w+i)*4];
1534 for (p = 0; p < 4; ++p) {
1535 if (probe[p] != expected[p]) {
1536 printf("Probe color at (%d,%d)\n", x+i, y+j);
1537 printf(" Expected: %u %u %u %u\n",
1538 expected[0], expected[1], expected[2], expected[3]);
1539 printf(" Observed: %u %u %u %u\n",
1540 probe[0], probe[1], probe[2], probe[3]);
1542 free(pixels);
1543 return 0;
1549 free(pixels);
1550 return 1;
1554 * Read color data from the given rectangle and compare its RGB value to the
1555 * given two expected values.
1557 * Print a log message if the color value deviates from both expected values.
1558 * \return true if the color values match, false otherwise
1560 bool
1561 piglit_probe_rect_two_rgb(int x, int y, int w, int h,
1562 const float *expected1, const float *expected2)
1564 /* RGBA readbacks are likely to be faster */
1565 float *pixels = piglit_read_pixels_float(x, y, w, h, GL_RGBA, NULL);
1567 for (int j = 0; j < h; j++) {
1568 for (int i = 0; i < w; i++) {
1569 float *probe = &pixels[(j * w + i) * 4];
1571 if (piglit_compare_pixels_float(probe, expected1,
1572 piglit_tolerance, 3) ||
1573 piglit_compare_pixels_float(probe, expected2,
1574 piglit_tolerance, 3))
1575 continue;
1577 printf("Probe color at (%i,%i)\n", x + i, y + j);
1578 printf(" Expected either:");
1579 print_components_float(expected1, 3);
1580 printf("\n or:");
1581 print_components_float(expected2, 3);
1582 printf("\n Observed:");
1583 print_components_float(probe, 3);
1584 printf("\n");
1586 free(pixels);
1587 return false;
1591 free(pixels);
1592 return true;
1596 * Compute the appropriate tolerance for comparing images of the given
1597 * base format.
1599 void
1600 piglit_compute_probe_tolerance(GLenum format, float *tolerance)
1602 int num_components, component;
1603 switch (format) {
1604 case GL_LUMINANCE_ALPHA:
1605 tolerance[0] = piglit_tolerance[0];
1606 tolerance[1] = piglit_tolerance[3];
1607 break;
1608 case GL_ALPHA:
1609 tolerance[0] = piglit_tolerance[3];
1610 break;
1611 default:
1612 num_components = piglit_num_components(format);
1613 for (component = 0; component < num_components; ++component)
1614 tolerance[component] = piglit_tolerance[component];
1615 break;
1620 piglit_compare_pixels(int x, int y, const float *expected, const float *probe,
1621 const float *tolerance, int num_components)
1623 if (piglit_compare_pixels_float(probe, expected, tolerance, num_components))
1624 return 1;
1626 printf("Probe at (%i,%i)\n", x, y);
1627 printf(" Expected:");
1628 print_components_float(expected, num_components);
1629 printf("\n Observed:");
1630 print_components_float(probe, num_components);
1631 printf("\n");
1633 return 0;
1637 piglit_compare_image_halves_color(int w, int h, int num_components,
1638 const float *tolerance,
1639 const float *image)
1641 int i, j, half_width;
1643 half_width = w/2;
1644 for (j = 0; j < h; j++) {
1645 for (i = 0; i < half_width; i++) {
1646 const float *probe =
1647 &image[(j*w+i)*num_components];
1648 const float *expected =
1649 &image[(j*w+half_width+i)*num_components];
1650 if (!piglit_compare_pixels(i, j, expected, probe,
1651 tolerance,
1652 num_components))
1653 return 0;
1657 return 1;
1661 * Compare two in-memory floating-point images.
1664 piglit_compare_images_color(int x, int y, int w, int h, int num_components,
1665 const float *tolerance,
1666 const float *expected_image,
1667 const float *observed_image)
1669 int i, j;
1670 for (j = 0; j < h; j++) {
1671 for (i = 0; i < w; i++) {
1672 const float *expected =
1673 &expected_image[((j + y) * w + i + x) *
1674 num_components];
1675 const float *probe =
1676 &observed_image[((j + y) * w + i + x) *
1677 num_components];
1679 if (piglit_compare_pixels_float(probe, expected, tolerance,
1680 num_components))
1681 continue;
1683 printf("Probe at (%i,%i)\n", x+i, y+j);
1684 printf(" Expected:");
1685 print_components_float(expected, num_components);
1686 printf("\n Observed:");
1687 print_components_float(probe, num_components);
1688 printf("\n");
1690 return 0;
1694 return 1;
1698 * Compare the region indicated by x, y, w and h of the current read
1699 * framebuffer with the given in-memory floating-point image of
1700 * dimensions w*h.
1703 piglit_probe_image_color(int x, int y, int w, int h, GLenum format,
1704 const float *image)
1706 int c = piglit_num_components(format);
1707 GLfloat *pixels;
1708 float tolerance[4];
1709 int result;
1711 piglit_compute_probe_tolerance(format, tolerance);
1713 if (format == GL_INTENSITY) {
1714 /* GL_INTENSITY is not allowed for ReadPixels so
1715 * substitute GL_LUMINANCE.
1717 format = GL_LUMINANCE;
1720 pixels = piglit_read_pixels_float(x, y, w, h, format, NULL);
1722 result = piglit_compare_images_color(0, 0, w, h, c, tolerance, image,
1723 pixels);
1725 free(pixels);
1726 return result;
1730 piglit_probe_image_rgb(int x, int y, int w, int h, const float *image)
1732 return piglit_probe_image_color(x, y, w, h, GL_RGB, image);
1736 piglit_probe_image_rgba(int x, int y, int w, int h, const float *image)
1738 return piglit_probe_image_color(x, y, w, h, GL_RGBA, image);
1742 * Compare two in-memory unsigned-byte images.
1745 piglit_compare_images_ubyte(int x, int y, int w, int h,
1746 const GLubyte *expected_image,
1747 const GLubyte *observed_image)
1749 int i, j;
1750 for (j = 0; j < h; j++) {
1751 for (i = 0; i < w; i++) {
1752 const GLubyte expected = expected_image[j*w+i];
1753 const GLubyte probe = observed_image[j*w+i];
1755 if (probe != expected) {
1756 printf("Probe at (%i,%i)\n", x+i, y+j);
1757 printf(" Expected: %d\n", expected);
1758 printf(" Observed: %d\n", probe);
1760 return 0;
1765 return 1;
1769 * Compare the image (array) stored in \p observed with the image obtained from
1770 * \p expected_original with the box described by ux,uy,uz and uw,uh,ud
1771 * replaced by \p expected_updated.
1773 * Only the highest \p bits bits of all four channels are compared.
1776 piglit_equal_images_update_rgba8(const GLubyte *expected_original,
1777 const GLubyte *expected_updated,
1778 const GLubyte *observed,
1779 unsigned w, unsigned h, unsigned d,
1780 unsigned ux, unsigned uy, unsigned uz,
1781 unsigned uw, unsigned uh, unsigned ud,
1782 unsigned bits)
1784 assert(bits > 0 && bits <= 8);
1786 unsigned x, y, z;
1787 const uint8_t compare_mask = 0xff << (8 - bits);
1789 for (z = 0; z < d; ++z) {
1790 for (y = 0; y < h; y++) {
1791 for (x = 0; x < w; x++) {
1792 const GLubyte *ref;
1794 if (x >= ux && x < ux + uw &&
1795 y >= uy && y < uy + uh &&
1796 z >= uz && z < uz + ud)
1797 ref = expected_updated;
1798 else
1799 ref = expected_original;
1801 bool fail =
1802 ((ref[0] ^ observed[0]) |
1803 (ref[1] ^ observed[1]) |
1804 (ref[2] ^ observed[2]) |
1805 (ref[3] ^ observed[3])) &
1806 compare_mask;
1807 if (fail) {
1808 printf("%u,%u,%u: test = %u,%u,%u,%u "
1809 "ref = %u,%u,%u,%u (comparing %u bits)\n",
1810 x, y, z,
1811 observed[0], observed[1],
1812 observed[2], observed[3],
1813 ref[0], ref[1], ref[2], ref[3],
1814 bits);
1815 return 0;
1818 observed += 4;
1819 expected_original += 4;
1820 expected_updated += 4;
1825 return 1;
1829 * Compare the contents of the current read framebuffer's stencil
1830 * buffer with the given in-memory byte image.
1833 piglit_probe_image_stencil(int x, int y, int w, int h,
1834 const GLubyte *image)
1836 GLubyte *pixels = malloc(w*h*sizeof(GLubyte));
1837 int result;
1838 GLint old_pack_alignment;
1840 /* Temporarily set pack alignment to 1 so that glReadPixels
1841 * won't put any padding at the end of the row.
1843 glGetIntegerv(GL_PACK_ALIGNMENT, &old_pack_alignment);
1844 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1846 glReadPixels(x, y, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, pixels);
1848 glPixelStorei(GL_PACK_ALIGNMENT, old_pack_alignment);
1850 result = piglit_compare_images_ubyte(x, y, w, h, image, pixels);
1852 free(pixels);
1853 return result;
1857 piglit_probe_image_ubyte(int x, int y, int w, int h, GLenum format,
1858 const GLubyte *image)
1860 const int c = piglit_num_components(format);
1861 GLubyte *pixels = malloc(w * h * 4 * sizeof(GLubyte));
1862 int i, j;
1863 GLubyte tolerance[4];
1865 array_float_to_ubyte_roundup(4, piglit_tolerance, tolerance);
1867 glReadPixels(x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
1869 for (j = 0; j < h; j++) {
1870 for (i = 0; i < w; i++) {
1871 const GLubyte *expected = &image[(j * w + i) * c];
1872 const GLubyte *probe = &pixels[(j * w + i) * c];
1874 if (compare_pixels_ubyte(probe, expected, tolerance,
1876 continue;
1878 printf("Probe at (%i,%i)\n", x + i, y + j);
1879 printf(" Expected:");
1880 print_components_ubyte(expected, c);
1881 printf("\n Observed:");
1882 print_components_ubyte(probe, c);
1883 printf("\n");
1885 free(pixels);
1886 return 0;
1890 free(pixels);
1891 return 1;
1894 #ifndef PIGLIT_USE_OPENGL
1895 static GLuint
1896 create_fbo_from_texture(GLenum target, GLint texture, GLint level, GLint layer)
1898 GLuint fbo;
1900 glGenFramebuffers(1, &fbo);
1901 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1903 if (layer > 0) {
1904 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1905 texture, level, layer);
1906 } else {
1907 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1908 target, texture, level);
1911 assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) ==
1912 GL_FRAMEBUFFER_COMPLETE);
1913 return fbo;
1916 static GLenum
1917 binding_from_target(GLenum target)
1919 switch (target) {
1920 case GL_TEXTURE_2D:
1921 return GL_TEXTURE_BINDING_2D;
1922 case GL_TEXTURE_2D_ARRAY:
1923 return GL_TEXTURE_BINDING_2D_ARRAY;
1924 default:
1925 fprintf(stderr, "%s: unsupported target 0x%x\n",
1926 __func__, target);
1927 return 0;
1932 * Read texels in OpenGL ES compatible way.
1934 * Currently bound texture is attached to a framebuffer object and
1935 * contents are read using glReadPixels. Supported targets are
1936 * GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY.
1938 static GLfloat *
1939 read_texture_via_fbo(int target, int level, int x, int y, int layer, int w,
1940 int h)
1942 GLint width, height, depth;
1943 GLint current_read_fbo, current_draw_fbo, current_texture;
1944 GLenum binding = binding_from_target(target);
1945 unsigned char *buf;
1946 GLfloat *buffer;
1947 unsigned offset;
1949 assert(binding != 0);
1951 glGetIntegerv(binding, &current_texture);
1952 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &current_read_fbo);
1953 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &current_draw_fbo);
1955 assert(target == GL_TEXTURE_2D || target == GL_TEXTURE_2D_ARRAY);
1957 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
1958 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
1959 glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
1961 /* Depth equals 1 in case of GL_TEXTURE_2D, in case of
1962 * GL_TEXTURE_2D_ARRAY we allocate space for many layers.
1964 buffer = malloc(width * height * depth * 4 * sizeof(GLfloat));
1965 buf = malloc(width * height * depth * 4 * sizeof(unsigned char));
1967 /* Read all layers. */
1968 for (int i = layer; i >= 0; i--) {
1969 GLuint fbo =
1970 create_fbo_from_texture(target, current_texture, level,
1972 assert(fbo != 0);
1974 /* Offset to the layer we are expected to read. Note, in case
1975 * of GL_TEXTURE_2D, offset will be always 0 as i equals 0.
1977 offset = i * (width * height * 4);
1978 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
1979 buf + offset);
1981 glDeleteFramebuffers(1, &fbo);
1984 /* Convert the result, callers expect floating point. */
1985 for (unsigned k = 0; k < (layer + 1) * width * height * 4; k++)
1986 buffer[k] = ((float) buf[k]) / 255.0;
1988 free(buf);
1990 /* Restore FBO state. */
1991 glBindFramebuffer(GL_READ_FRAMEBUFFER, current_read_fbo);
1992 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_draw_fbo);
1994 return buffer;
1996 #endif
2000 * Read a texel rectangle from the given location and compare its RGB value to
2001 * the given expected values.
2003 * Print a log message if the color value deviates from the expected value.
2004 * \return true if the color values match, false otherwise
2006 int piglit_probe_texel_rect_rgb(int target, int level, int x, int y,
2007 int w, int h, const float* expected)
2009 GLfloat *buffer;
2010 GLfloat *probe;
2011 int i, j;
2012 GLint width;
2013 GLint height;
2015 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
2016 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
2017 buffer = malloc(width * height * 3 * sizeof(GLfloat));
2019 glGetTexImage(target, level, GL_RGB, GL_FLOAT, buffer);
2021 assert(x >= 0);
2022 assert(y >= 0);
2023 assert(x+w <= width);
2024 assert(y+h <= height);
2026 for (j = y; j < y+h; ++j) {
2027 for (i = x; i < x+w; ++i) {
2028 probe = &buffer[(j * width + i) * 3];
2030 if (piglit_compare_pixels_float(probe, expected,
2031 piglit_tolerance, 3))
2032 continue;
2034 free(buffer);
2035 return 0;
2039 free(buffer);
2040 return 1;
2044 * Read a texel from the given location and compare its RGB value to the
2045 * given expected values.
2047 * Print a log message if the color value deviates from the expected value.
2048 * \return true if the color values match, false otherwise
2050 int piglit_probe_texel_rgb(int target, int level, int x, int y,
2051 const float *expected)
2053 return piglit_probe_texel_rect_rgb(target, level, x, y, 1, 1, expected);
2057 * Read a texel rectangle from the given location and compare its RGBA value to
2058 * the given expected values.
2060 * Print a log message if the color value deviates from the expected value.
2061 * \return true if the color values match, false otherwise
2063 int piglit_probe_texel_rect_rgba(int target, int level, int x, int y,
2064 int w, int h, const float* expected)
2066 GLfloat *buffer;
2067 GLfloat *probe;
2068 int i, j;
2069 GLint width;
2070 GLint height;
2072 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
2073 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
2075 #ifndef PIGLIT_USE_OPENGL
2076 if (target == GL_TEXTURE_2D) {
2077 buffer = read_texture_via_fbo(target, level, x, y, 0, w, h);
2078 } else {
2079 #else
2080 buffer = malloc(width * height * 4 * sizeof(GLfloat));
2081 glGetTexImage(target, level, GL_RGBA, GL_FLOAT, buffer);
2082 #endif
2083 #ifndef PIGLIT_USE_OPENGL
2085 #endif
2086 assert(x >= 0);
2087 assert(y >= 0);
2088 assert(x+w <= width);
2089 assert(y+h <= height);
2091 for (j = y; j < y+h; ++j) {
2092 for (i = x; i < x+w; ++i) {
2093 probe = &buffer[(j * width + i) * 4];
2095 if (piglit_compare_pixels_float(probe, expected,
2096 piglit_tolerance, 4))
2097 continue;
2099 print_bad_pixel_float(i, j, 4,
2100 expected,
2101 probe);
2103 free(buffer);
2104 return 0;
2108 free(buffer);
2109 return 1;
2113 * Read a texel from the given location and compare its RGBA value to the
2114 * given expected values.
2116 * Print a log message if the color value deviates from the expected value.
2117 * \return true if the color values match, false otherwise
2119 int piglit_probe_texel_rgba(int target, int level, int x, int y,
2120 const float* expected)
2122 return piglit_probe_texel_rect_rgba(target, level, x, y, 1, 1,
2123 expected);
2127 * Read a texel rectangle from the given location and compare its RGBA value to
2128 * the given expected values.
2130 * Print a log message if the color value deviates from the expected value.
2131 * \return true if the color values match, false otherwise
2133 int piglit_probe_texel_volume_rgba(int target, int level, int x, int y, int z,
2134 int w, int h, int d, const float* expected)
2136 GLfloat *buffer;
2137 GLfloat *probe;
2138 int i, j, k;
2139 GLint width;
2140 GLint height;
2141 GLint depth;
2143 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
2144 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
2145 glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
2147 #ifndef PIGLIT_USE_OPENGL
2148 if (target == GL_TEXTURE_2D_ARRAY) {
2149 buffer = read_texture_via_fbo(target, level, x, y, z, w, h);
2150 } else {
2151 #else
2152 buffer = malloc(width * height * depth * 4 * sizeof(GLfloat));
2153 glGetTexImage(target, level, GL_RGBA, GL_FLOAT, buffer);
2154 #endif
2155 #ifndef PIGLIT_USE_OPENGL
2157 #endif
2158 assert(x >= 0);
2159 assert(y >= 0);
2160 assert(d >= 0);
2161 assert(x+w <= width);
2162 assert(y+h <= height);
2163 assert(z+d <= depth);
2165 for (k = z; k < z+d; ++k) {
2166 for (j = y; j < y+h; ++j) {
2167 for (i = x; i < x+w; ++i) {
2168 probe = &buffer[(k * width * height + j * width + i) * 4];
2170 if (piglit_compare_pixels_float(probe, expected,
2171 piglit_tolerance, 4))
2172 continue;
2174 printf("Probe color at (%i,%i,%i)\n",
2175 i, j, k);
2176 printf(" Expected: ");
2177 print_components_float(expected, 4);
2178 printf("\n Observed: ");
2179 print_components_float(probe, 4);
2180 printf("\n");
2182 free(buffer);
2183 return 0;
2188 free(buffer);
2189 return 1;
2193 * Read a pixel from the given location and compare its depth value to the
2194 * given expected value.
2196 * Print a log message if the depth value deviates from the expected value.
2197 * \return true if the depth value matches, false otherwise
2199 int piglit_probe_pixel_depth(int x, int y, float expected)
2201 GLfloat probe;
2202 GLfloat delta;
2204 glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &probe);
2206 delta = probe - expected;
2207 if (fabs(delta) < 0.01)
2208 return 1;
2210 printf("Probe depth at (%i,%i)\n", x, y);
2211 printf(" Expected: %f\n", expected);
2212 printf(" Observed: %f\n", probe);
2214 return 0;
2217 int piglit_probe_rect_depth(int x, int y, int w, int h, float expected)
2219 int i, j;
2220 GLfloat *probe;
2221 GLfloat *pixels = malloc(w*h*sizeof(float));
2223 glReadPixels(x, y, w, h, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);
2225 for (j = 0; j < h; j++) {
2226 for (i = 0; i < w; i++) {
2227 probe = &pixels[j*w+i];
2229 if (fabs(*probe - expected) >= 0.01) {
2230 printf("Probe depth at (%i,%i)\n", x+i, y+j);
2231 printf(" Expected: %f\n", expected);
2232 printf(" Observed: %f\n", *probe);
2234 free(pixels);
2235 return 0;
2240 free(pixels);
2241 return 1;
2244 int piglit_probe_pixel_stencil(int x, int y, unsigned expected)
2246 GLuint probe;
2247 glReadPixels(x, y, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT, &probe);
2249 if (probe == expected)
2250 return 1;
2252 printf("Probe stencil at (%i, %i)\n", x, y);
2253 printf(" Expected: %u\n", expected);
2254 printf(" Observed: %u\n", probe);
2256 return 0;
2259 int piglit_probe_rect_stencil(int x, int y, int w, int h, unsigned expected)
2261 int i, j;
2262 GLuint *pixels = malloc(w*h*sizeof(GLuint));
2264 glReadPixels(x, y, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_INT, pixels);
2266 for (j = 0; j < h; j++) {
2267 for (i = 0; i < w; i++) {
2268 GLuint probe = pixels[j * w + i];
2269 if (probe != expected) {
2270 printf("Probe stencil at (%i, %i)\n", x + i, y + j);
2271 printf(" Expected: %u\n", expected);
2272 printf(" Observed: %u\n", probe);
2273 free(pixels);
2274 return 0;
2279 free(pixels);
2280 return 1;
2283 bool piglit_probe_buffer(GLuint buf, GLenum target, const char *label,
2284 unsigned n, unsigned num_components,
2285 const float *expected)
2287 float *ptr;
2288 unsigned i;
2289 bool status = true;
2291 glBindBuffer(target, buf);
2292 ptr = glMapBuffer(target, GL_READ_ONLY);
2294 for (i = 0; i < n * num_components; i++) {
2295 if (fabs(ptr[i] - expected[i % num_components]) > 0.01) {
2296 printf("%s[%i]: %f, Expected: %f\n", label, i, ptr[i],
2297 expected[i % num_components]);
2298 status = false;
2302 glUnmapBuffer(target);
2304 return status;
2307 bool piglit_probe_buffer_doubles(GLuint buf, GLenum target, const char *label,
2308 unsigned n, unsigned num_components,
2309 const double *expected)
2311 double *ptr;
2312 unsigned i;
2313 bool status = true;
2315 glBindBuffer(target, buf);
2316 ptr = glMapBuffer(target, GL_READ_ONLY);
2318 for (i = 0; i < n * num_components; i++) {
2319 if (fabs(ptr[i] - expected[i % num_components]) > 0.01) {
2320 printf("%s[%i]: %f, Expected: %f\n", label, i, ptr[i],
2321 expected[i % num_components]);
2322 status = false;
2326 glUnmapBuffer(target);
2328 return status;
2331 int piglit_use_fragment_program(void)
2333 return piglit_is_extension_supported("GL_ARB_fragment_program");
2336 void piglit_require_fragment_program(void)
2338 if (!piglit_use_fragment_program()) {
2339 printf("GL_ARB_fragment_program not supported.\n");
2340 piglit_report_result(PIGLIT_SKIP);
2344 int piglit_use_vertex_program(void)
2346 return piglit_is_extension_supported("GL_ARB_vertex_program");
2349 void piglit_require_vertex_program(void)
2351 if (!piglit_use_vertex_program()) {
2352 printf("GL_ARB_vertex_program not supported.\n");
2353 piglit_report_result(PIGLIT_SKIP);
2357 GLuint piglit_compile_program(GLenum target, const char* text)
2359 GLuint program;
2360 GLint errorPos;
2362 glGenProgramsARB(1, &program);
2363 glBindProgramARB(target, program);
2364 glProgramStringARB(
2365 target,
2366 GL_PROGRAM_FORMAT_ASCII_ARB,
2367 strlen(text),
2368 (const GLubyte *)text);
2369 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
2370 if (glGetError() != GL_NO_ERROR || errorPos != -1) {
2371 int l = piglit_find_line(text, errorPos);
2372 int a;
2374 fprintf(stderr, "Compiler Error (pos=%d line=%d): %s\n",
2375 errorPos, l,
2376 (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
2378 for (a=-10; a<10; a++)
2380 if (errorPos+a < 0)
2381 continue;
2382 if (errorPos+a >= strlen(text))
2383 break;
2384 fprintf(stderr, "%c", text[errorPos+a]);
2386 fprintf(stderr, "\nin program:\n%s", text);
2387 piglit_report_result(PIGLIT_FAIL);
2389 if (!glIsProgramARB(program)) {
2390 fprintf(stderr, "glIsProgramARB failed\n");
2391 piglit_report_result(PIGLIT_FAIL);
2394 return program;
2398 * Convenience function to draw a triangle.
2400 GLvoid
2401 piglit_draw_triangle(float x1, float y1, float x2, float y2,
2402 float x3, float y3)
2404 piglit_draw_triangle_z(0.0, x1, y1, x2, y2, x3, y3);
2408 * Convenience function to draw a triangle at a given depth.
2410 GLvoid
2411 piglit_draw_triangle_z(float z, float x1, float y1, float x2, float y2,
2412 float x3, float y3)
2414 float verts[3][4];
2416 verts[0][0] = x1;
2417 verts[0][1] = y1;
2418 verts[0][2] = z;
2419 verts[0][3] = 1.0;
2420 verts[1][0] = x2;
2421 verts[1][1] = y2;
2422 verts[1][2] = z;
2423 verts[1][3] = 1.0;
2424 verts[2][0] = x3;
2425 verts[2][1] = y3;
2426 verts[2][2] = z;
2427 verts[2][3] = 1.0;
2429 glVertexPointer(4, GL_FLOAT, 0, verts);
2430 glEnableClientState(GL_VERTEX_ARRAY);
2432 glDrawArrays(GL_TRIANGLES, 0, 3);
2434 glDisableClientState(GL_VERTEX_ARRAY);
2438 * Generate an extended checkerboard texture where the color of each quadrant
2439 * in a 2x2 block of tiles can be specified individually.
2441 * \param tex Name of the texture to be used. If \c tex is
2442 * zero, a new texture name will be generated.
2443 * \param level Mipmap level the checkerboard should be written to
2444 * \param width Width of the texture image
2445 * \param height Height of the texture image
2446 * \param horiz_square_size Size of each checkerboard tile along the X axis
2447 * \param vert_square_size Size of each checkerboard tile along the Y axis
2448 * \param bl RGBA color to be used for "bottom-left" tiles
2449 * \param br RGBA color to be used for "bottom-right" tiles
2450 * \param tl RGBA color to be used for "top-left" tiles
2451 * \param tr RGBA color to be used for "top-right" tiles
2453 * The texture data is written to LOD \c level of the texture \c tex.
2455 * If \c tex is zero, a new texture created. This texture will have several
2456 * texture parameters set to non-default values:
2458 * - Min and mag filter will be set to \c GL_NEAREST.
2459 * - For GL:
2460 * - S and T wrap modes will be set to \c GL_CLAMP_TO_BORDER.
2461 * - Border color will be set to { 1.0, 0.0, 0.0, 1.0 }.
2462 * - For GLES:
2463 * - S and T wrap modes will be set to \c GL_CLAMP_TO_EDGE.
2465 * \return
2466 * Name of the texture. In addition, this texture will be bound to the
2467 * \c GL_TEXTURE_2D target of the currently active texture unit.
2469 GLuint
2470 piglit_quads_texture(GLuint tex, unsigned level,
2471 unsigned width, unsigned height,
2472 unsigned horiz_square_size,
2473 unsigned vert_square_size,
2474 const float *bl, const float *br,
2475 const float *tl, const float *tr)
2477 static const GLfloat border_color[4] = { 1.0, 0.0, 0.0, 1.0 };
2478 unsigned i;
2479 unsigned j;
2480 void *tex_data;
2481 char *texel;
2482 unsigned pixel_size;
2483 GLubyte bl_b[4], br_b[4], tl_b[4], tr_b[4];
2484 const void *bl_data, *br_data, *tl_data, *tr_data;
2486 if (piglit_is_gles()) {
2487 pixel_size = 4 * sizeof(GLubyte);
2488 for (i = 0; i < 4; i++) {
2489 bl_b[i] = bl[i] * 255;
2490 br_b[i] = br[i] * 255;
2491 tl_b[i] = tl[i] * 255;
2492 tr_b[i] = tr[i] * 255;
2494 bl_data = bl_b;
2495 br_data = br_b;
2496 tl_data = tl_b;
2497 tr_data = tr_b;
2498 } else {
2499 pixel_size = 4 * sizeof(float);
2500 bl_data = bl;
2501 br_data = br;
2502 tl_data = tl;
2503 tr_data = tr;
2505 texel = tex_data = malloc(width * height * pixel_size);
2507 for (i = 0; i < height; i++) {
2508 const unsigned row = i / vert_square_size;
2510 for (j = 0; j < width; j++) {
2511 const unsigned col = j / horiz_square_size;
2513 if (row & 1) {
2514 if (col & 1)
2515 memcpy(texel, tr_data, pixel_size);
2516 else
2517 memcpy(texel, tl_data, pixel_size);
2518 } else {
2519 if (col & 1)
2520 memcpy(texel, br_data, pixel_size);
2521 else
2522 memcpy(texel, bl_data, pixel_size);
2525 texel += pixel_size;
2529 if (tex == 0) {
2530 glGenTextures(1, &tex);
2532 glBindTexture(GL_TEXTURE_2D, tex);
2533 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2534 GL_NEAREST);
2535 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2536 GL_NEAREST);
2537 if (piglit_is_gles()) {
2538 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
2539 GL_CLAMP_TO_EDGE);
2540 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
2541 GL_CLAMP_TO_EDGE);
2542 } else {
2543 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
2544 GL_CLAMP_TO_BORDER);
2545 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
2546 GL_CLAMP_TO_BORDER);
2547 glTexParameterfv(GL_TEXTURE_2D,
2548 GL_TEXTURE_BORDER_COLOR,
2549 border_color);
2551 } else {
2552 glBindTexture(GL_TEXTURE_2D, tex);
2555 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, 0, GL_RGBA,
2556 piglit_is_gles() ? GL_UNSIGNED_BYTE : GL_FLOAT, tex_data);
2558 free(tex_data);
2560 return tex;
2564 * Generate a checkerboard texture
2566 * \param tex Name of the texture to be used. If \c tex is
2567 * zero, a new texture name will be generated.
2568 * \param level Mipmap level the checkerboard should be written to
2569 * \param width Width of the texture image
2570 * \param height Height of the texture image
2571 * \param horiz_square_size Size of each checkerboard tile along the X axis
2572 * \param vert_square_size Size of each checkerboard tile along the Y axis
2573 * \param black RGBA color to be used for "black" tiles
2574 * \param white RGBA color to be used for "white" tiles
2576 * A texture with alternating black and white squares in a checkerboard
2577 * pattern is generated. The texture data is written to LOD \c level of
2578 * the texture \c tex.
2580 * If \c tex is zero, a new texture created. This texture will have several
2581 * texture parameters set to non-default values:
2583 * - Min and mag filter will be set to \c GL_NEAREST.
2584 * - For GL:
2585 * - S and T wrap modes will be set to \c GL_CLAMP_TO_BORDER.
2586 * - Border color will be set to { 1.0, 0.0, 0.0, 1.0 }.
2587 * - For GLES:
2588 * - S and T wrap modes will be set to \c GL_CLAMP_TO_EDGE.
2590 * \return
2591 * Name of the texture. In addition, this texture will be bound to the
2592 * \c GL_TEXTURE_2D target of the currently active texture unit.
2594 GLuint
2595 piglit_checkerboard_texture(GLuint tex, unsigned level,
2596 unsigned width, unsigned height,
2597 unsigned horiz_square_size,
2598 unsigned vert_square_size,
2599 const float *black, const float *white)
2601 return piglit_quads_texture(tex, level, width, height,
2602 horiz_square_size, vert_square_size,
2603 black, white, white, black);
2607 * Generates a 8x8 mipmapped texture whose layers contain solid r, g, b, and w.
2609 GLuint
2610 piglit_miptree_texture()
2612 GLfloat *data;
2613 int size, i, level;
2614 GLuint tex;
2616 glGenTextures(1, &tex);
2617 glBindTexture(GL_TEXTURE_2D, tex);
2618 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2619 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2620 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2621 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2622 GL_NEAREST_MIPMAP_NEAREST);
2624 for (level = 0; level < 4; ++level) {
2625 size = 8 >> level;
2627 data = malloc(size*size*4*sizeof(GLfloat));
2628 for (i = 0; i < size * size; ++i) {
2629 memcpy(data + 4 * i, color_wheel[level],
2630 4 * sizeof(GLfloat));
2632 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA,
2633 size, size, 0, GL_RGBA, GL_FLOAT, data);
2634 free(data);
2636 return tex;
2640 * Generates an image of the given size with quadrants of red, green,
2641 * blue and white.
2642 * Note that for compressed teximages, where the blocking would be
2643 * problematic, we assign the whole layers at w == 4 to red, w == 2 to
2644 * green, and w == 1 to blue.
2646 * \param internalFormat either GL_RGBA or a specific compressed format
2647 * \param w the width in texels
2648 * \param h the height in texels
2649 * \param alpha if TRUE, use varied alpha values, else all alphas = 1
2650 * \param basetype either GL_UNSIGNED_NORMALIZED, GL_SIGNED_NORMALIZED
2651 * or GL_FLOAT
2653 GLfloat *
2654 piglit_rgbw_image(GLenum internalFormat, int w, int h,
2655 GLboolean alpha, GLenum basetype)
2657 float red[4] = {1.0, 0.0, 0.0, 0.0};
2658 float green[4] = {0.0, 1.0, 0.0, 0.25};
2659 float blue[4] = {0.0, 0.0, 1.0, 0.5};
2660 float white[4] = {1.0, 1.0, 1.0, 1.0};
2661 GLfloat *data;
2662 int x, y;
2664 if (!alpha) {
2665 red[3] = 1.0;
2666 green[3] = 1.0;
2667 blue[3] = 1.0;
2668 white[3] = 1.0;
2671 switch (basetype) {
2672 case GL_UNSIGNED_NORMALIZED:
2673 break;
2675 case GL_SIGNED_NORMALIZED:
2676 for (x = 0; x < 4; x++) {
2677 red[x] = red[x] * 2 - 1;
2678 green[x] = green[x] * 2 - 1;
2679 blue[x] = blue[x] * 2 - 1;
2680 white[x] = white[x] * 2 - 1;
2682 break;
2684 case GL_FLOAT:
2685 for (x = 0; x < 4; x++) {
2686 red[x] = red[x] * 10 - 5;
2687 green[x] = green[x] * 10 - 5;
2688 blue[x] = blue[x] * 10 - 5;
2689 white[x] = white[x] * 10 - 5;
2691 break;
2693 default:
2694 assert(0);
2697 data = malloc(w * h * 4 * sizeof(GLfloat));
2699 for (y = 0; y < h; y++) {
2700 for (x = 0; x < w; x++) {
2701 const int size = w > h ? w : h;
2702 const float *color;
2704 if (x < w / 2 && y < h / 2)
2705 color = red;
2706 else if (y < h / 2)
2707 color = green;
2708 else if (x < w / 2)
2709 color = blue;
2710 else
2711 color = white;
2713 switch (internalFormat) {
2714 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
2715 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
2716 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
2717 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
2718 case GL_COMPRESSED_RGB_FXT1_3DFX:
2719 case GL_COMPRESSED_RGBA_FXT1_3DFX:
2720 case GL_COMPRESSED_RED_RGTC1:
2721 case GL_COMPRESSED_SIGNED_RED_RGTC1:
2722 case GL_COMPRESSED_RG_RGTC2:
2723 case GL_COMPRESSED_SIGNED_RG_RGTC2:
2724 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
2725 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
2726 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
2727 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
2728 case GL_COMPRESSED_RGBA_BPTC_UNORM:
2729 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
2730 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
2731 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
2732 if (size == 4)
2733 color = red;
2734 else if (size == 2)
2735 color = green;
2736 else if (size == 1)
2737 color = blue;
2738 break;
2739 default:
2740 break;
2743 memcpy(data + (y * w + x) * 4, color,
2744 4 * sizeof(float));
2748 return data;
2751 GLubyte *
2752 piglit_rgbw_image_ubyte(int w, int h, GLboolean alpha)
2754 GLubyte red[4] = {255, 0, 0, 0};
2755 GLubyte green[4] = {0, 255, 0, 64};
2756 GLubyte blue[4] = {0, 0, 255, 128};
2757 GLubyte white[4] = {255, 255, 255, 255};
2758 GLubyte *data;
2759 int x, y;
2761 if (!alpha) {
2762 red[3] = 255;
2763 green[3] = 255;
2764 blue[3] = 255;
2765 white[3] = 255;
2768 data = malloc(w * h * 4 * sizeof(GLubyte));
2770 for (y = 0; y < h; y++) {
2771 for (x = 0; x < w; x++) {
2772 const GLubyte *color;
2774 if (x < w / 2 && y < h / 2)
2775 color = red;
2776 else if (y < h / 2)
2777 color = green;
2778 else if (x < w / 2)
2779 color = blue;
2780 else
2781 color = white;
2783 memcpy(data + (y * w + x) * 4, color,
2784 4 * sizeof(GLubyte));
2788 return data;
2792 * Generates a texture with the given internalFormat, w, h with a
2793 * teximage of r, g, b, w quadrants.
2795 * Note that for compressed teximages, where the blocking would be
2796 * problematic, we assign the whole layers at w == 4 to red, w == 2 to
2797 * green, and w == 1 to blue.
2799 GLuint
2800 piglit_rgbw_texture(GLenum internalFormat, int w, int h, GLboolean mip,
2801 GLboolean alpha, GLenum basetype)
2803 int size, level;
2804 GLuint tex;
2805 GLenum teximage_type;
2807 switch (basetype) {
2808 case GL_UNSIGNED_NORMALIZED:
2809 case GL_SIGNED_NORMALIZED:
2810 case GL_FLOAT:
2811 teximage_type = GL_FLOAT;
2812 break;
2813 case GL_UNSIGNED_BYTE:
2814 teximage_type = GL_UNSIGNED_BYTE;
2815 break;
2816 default:
2817 assert(0);
2818 return 0;
2821 glGenTextures(1, &tex);
2822 glBindTexture(GL_TEXTURE_2D, tex);
2823 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2824 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2825 if (mip) {
2826 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2827 GL_LINEAR);
2828 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2829 GL_LINEAR_MIPMAP_NEAREST);
2830 } else {
2831 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2832 GL_NEAREST);
2833 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2834 GL_NEAREST);
2837 for (level = 0, size = w > h ? w : h; size > 0; level++, size >>= 1) {
2838 void *data;
2840 if (teximage_type == GL_UNSIGNED_BYTE)
2841 data = piglit_rgbw_image_ubyte(w, h, alpha);
2842 else
2843 data = piglit_rgbw_image(internalFormat, w, h,
2844 alpha, basetype);
2846 glTexImage2D(GL_TEXTURE_2D, level,
2847 internalFormat,
2848 w, h, 0,
2849 GL_RGBA, teximage_type, data);
2850 free(data);
2852 if (!mip)
2853 break;
2855 if (w > 1)
2856 w >>= 1;
2857 if (h > 1)
2858 h >>= 1;
2861 return tex;
2865 * Generate a 4 texel RGBA 1D texture with texels red, green, blue, white,
2866 * edge clamping and NEAREST filtering.
2868 GLuint
2869 piglit_rgbw_texture_1d(void)
2871 GLuint tex;
2872 glGenTextures(1, &tex);
2873 glBindTexture(GL_TEXTURE_1D, tex);
2874 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2875 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2876 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2877 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2879 static const float img[] = {1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1};
2880 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 4, 0, GL_RGBA, GL_FLOAT, img);
2882 return tex;
2886 * Generate a 2 by 2 by 2 texel RGBA 3D texture with texels red, green, blue,
2887 * white, yellow, magenta, cyan, black, edge clamping and NEAREST filtering.
2889 GLuint
2890 piglit_rgbw_texture_3d(void)
2892 GLuint tex;
2893 glGenTextures(1, &tex);
2894 glBindTexture(GL_TEXTURE_3D, tex);
2895 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2896 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2897 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
2898 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2899 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2901 static const float img[] = {1, 0, 0, 1, 0, 1, 0, 1,
2902 0, 0, 1, 1, 1, 1, 1, 1,
2903 1, 1, 0, 1, 1, 0, 1, 1,
2904 0, 1, 1, 1, 0, 0, 0, 1};
2905 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_FLOAT, img);
2907 return tex;
2911 * Maps a given integer internalformat to a valid format, including
2912 * the num_components info.
2914 static void
2915 map_integer_internalformat(GLenum internalformat, GLenum *format, int *num_components)
2917 switch(internalformat) {
2918 case GL_R32I:
2919 *format = GL_RED_INTEGER;
2920 *num_components = 1;
2921 break;
2922 case GL_RG32I:
2923 *format = GL_RG_INTEGER;
2924 *num_components = 2;
2925 break;
2926 case GL_RGB32I:
2927 *format = GL_RGB_INTEGER;
2928 *num_components = 3;
2929 break;
2930 case GL_RGBA32I:
2931 *format = GL_RGBA_INTEGER;
2932 *num_components = 4;
2933 break;
2934 default:
2935 printf("piglit_integer_texture only supports 32-bit integer"
2936 " internalformats\n");
2937 piglit_report_result(PIGLIT_FAIL);
2942 * Generates a texture with the given integer internal format.
2943 * It tries to use all the 4 data references (x, y, b, a) to fill the data. So:
2944 * * For 4 components: R = x, G = y, B = b, A = a.
2945 * * For 3 components: R = x, G = y, B = b + a
2946 * * For 2 components: R = x + b, G = y + a
2947 * * For 1 components: R = x + y * b + a
2948 * Note that it assumes internalformats using 32 bit integer, so we would use GL_INT.
2950 GLuint piglit_integer_texture(GLenum internalFormat, int w, int h, int b, int a)
2952 int *img;
2953 int *p;
2954 GLuint tex;
2955 GLenum format;
2956 int num_components;
2957 int x, y;
2959 map_integer_internalformat(internalFormat, &format, &num_components);
2961 img = malloc(w * h * num_components * sizeof(int));
2963 for (y = 0, p = img; y < h; ++y) {
2964 for (x = 0; x < w; ++x) {
2965 switch(num_components) {
2966 case 4:
2967 p[0] = x;
2968 p[1] = y;
2969 p[2] = b;
2970 p[3] = a;
2971 break;
2972 case 3:
2973 p[0] = x;
2974 p[1] = y;
2975 p[2] = b + a;
2976 break;
2977 case 2:
2978 p[0] = x + b;
2979 p[1] = y + a;
2980 break;
2981 case 1:
2982 p[0] = x + y * b + a;
2983 break;
2986 p += num_components;
2990 glGenTextures(1, &tex);
2991 glBindTexture(GL_TEXTURE_2D, tex);
2992 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2993 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2994 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2995 GL_NEAREST);
2996 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2997 GL_NEAREST);
2999 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, w, h);
3000 glTexSubImage2D(GL_TEXTURE_2D,
3001 0, 0, 0, w, h, format, GL_INT, img);
3002 free(img);
3004 return tex;
3008 * Create a depth texture. The depth texture will be a gradient which varies
3009 * from 0.0 at the left side to 1.0 at the right side. For a 2D array texture,
3010 * all the texture layers will have the same gradient.
3012 * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_1D_ARRAY,
3013 * GL_TEXTURE_2D_ARRAY or GL_TEXTURE_RECTANGLE.
3014 * \param internalformat either GL_DEPTH_STENCIL, GL_DEPTH_COMPONENT,
3015 * GL_DEPTH24_STENCIL8_EXT or GL_DEPTH32F_STENCIL8.
3016 * \param w, h, d level 0 image width, height and depth
3017 * \param mip if true, create a full mipmap. Else, create single-level texture.
3018 * \return the new texture object id
3020 GLuint
3021 piglit_depth_texture(GLenum target, GLenum internalformat, int w, int h, int d, GLboolean mip)
3023 void *data;
3024 float *f = NULL, *f2 = NULL;
3025 unsigned int *i = NULL;
3026 int size, x, y, level, layer;
3027 GLuint tex;
3028 GLenum type, format;
3030 glGenTextures(1, &tex);
3031 glBindTexture(target, tex);
3032 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3033 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3034 if (mip) {
3035 glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
3036 GL_LINEAR);
3037 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
3038 GL_LINEAR_MIPMAP_NEAREST);
3039 } else {
3040 glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
3041 GL_NEAREST);
3042 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
3043 GL_NEAREST);
3045 data = malloc(w * h * 4 * sizeof(GLfloat));
3047 if (internalformat == GL_DEPTH_STENCIL_EXT ||
3048 internalformat == GL_DEPTH24_STENCIL8_EXT) {
3049 format = GL_DEPTH_STENCIL_EXT;
3050 type = GL_UNSIGNED_INT_24_8_EXT;
3051 i = data;
3052 } else if (internalformat == GL_DEPTH32F_STENCIL8) {
3053 format = GL_DEPTH_STENCIL;
3054 type = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
3055 f2 = data;
3056 } else {
3057 format = GL_DEPTH_COMPONENT;
3058 type = GL_FLOAT;
3059 f = data;
3062 for (level = 0, size = w > h ? w : h; size > 0; level++, size >>= 1) {
3063 for (y = 0; y < h; y++) {
3064 for (x = 0; x < w; x++) {
3065 float val = (float)(x) / (w - 1);
3066 if (f)
3067 f[y * w + x] = val;
3068 else if (f2)
3069 f2[(y * w + x)*2] = val;
3070 else if (i)
3071 i[y * w + x] = 0xffffff00 * val;
3075 switch (target) {
3076 case GL_TEXTURE_1D:
3077 glTexImage1D(target, level,
3078 internalformat,
3079 w, 0,
3080 format, type, data);
3081 break;
3083 case GL_TEXTURE_1D_ARRAY:
3084 case GL_TEXTURE_2D:
3085 case GL_TEXTURE_RECTANGLE:
3086 glTexImage2D(target, level,
3087 internalformat,
3088 w, h, 0,
3089 format, type, data);
3090 break;
3092 case GL_TEXTURE_2D_ARRAY:
3093 glTexImage3D(target, level,
3094 internalformat,
3095 w, h, d, 0,
3096 format, type, NULL);
3097 for (layer = 0; layer < d; layer++) {
3098 glTexSubImage3D(target, level,
3099 0, 0, layer, w, h, 1,
3100 format, type, data);
3102 break;
3104 default:
3105 assert(0);
3108 if (!mip)
3109 break;
3111 if (w > 1)
3112 w >>= 1;
3113 if (target != GL_TEXTURE_1D &&
3114 target != GL_TEXTURE_1D_ARRAY &&
3115 h > 1)
3116 h >>= 1;
3118 free(data);
3119 return tex;
3123 * Create 1D or 2D array texture in which each slice is a different color.
3124 * the color pattern is red, green, blue, white, red, green, ...
3126 GLuint
3127 piglit_array_texture(GLenum target, GLenum internalformat,
3128 int w, int h, int d, GLboolean mip)
3130 float *data;
3131 int size, i, level, layer;
3132 GLuint tex;
3133 GLenum type = GL_FLOAT, format = GL_RGBA;
3135 if (target == GL_TEXTURE_1D_ARRAY) {
3136 assert(h == 1);
3138 else {
3139 assert(target == GL_TEXTURE_2D_ARRAY);
3142 glGenTextures(1, &tex);
3143 glBindTexture(target, tex);
3144 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3145 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3146 if (mip) {
3147 glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
3148 GL_LINEAR);
3149 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
3150 GL_LINEAR_MIPMAP_NEAREST);
3151 } else {
3152 glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
3153 GL_NEAREST);
3154 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
3155 GL_NEAREST);
3157 data = malloc(w * h * 4 * sizeof(GLfloat));
3159 size = w > h ? w : h;
3161 for (level = 0; size > 0; level++, size >>= 1) {
3163 /* Create mipmap level */
3164 if (target == GL_TEXTURE_1D_ARRAY) {
3165 glTexImage2D(target, level, internalformat,
3166 w, d, 0, format, type, NULL);
3168 else {
3169 glTexImage3D(target, level, internalformat,
3170 w, h, d, 0, format, type, NULL);
3173 for (layer = 0; layer < d; layer++) {
3174 /* Set whole layer to one color */
3175 for (i = 0; i < w * h; i++) {
3176 memcpy(data + 4 * i,
3177 color_wheel[layer %
3178 ARRAY_SIZE(color_wheel)],
3179 sizeof(color_wheel[0]));
3182 if (target == GL_TEXTURE_1D_ARRAY) {
3183 glTexSubImage2D(target, level,
3184 0, layer, w, 1,
3185 format, type, data);
3187 else {
3188 glTexSubImage3D(target, level,
3189 0, 0, layer, w, h, 1,
3190 format, type, data);
3194 if (!mip)
3195 break;
3197 if (w > 1)
3198 w >>= 1;
3199 if (h > 1)
3200 h >>= 1;
3202 free(data);
3203 return tex;
3206 static const char multisample_texture_vs_source[] =
3207 "#version 130\n"
3208 "in vec2 vertex;\n"
3209 "out vec2 tex_coords;\n"
3210 "void main()\n"
3211 "{\n"
3212 " tex_coords = vertex;\n"
3213 " vec2 pos = (vertex.xy * 2) - vec2(1, 1);\n"
3214 " gl_Position = vec4(pos, 0, 1);\n"
3215 "}\n";
3217 static const char multisample_texture_fs_source[] =
3218 "#version 130\n"
3219 "#extension GL_ARB_sample_shading : enable\n"
3220 "in vec2 tex_coords;\n"
3221 "uniform sampler2DArray tex;\n"
3222 "uniform int tex_depth;\n"
3223 "uniform int z;\n"
3224 "void main()\n"
3225 "{\n"
3226 " int layer = (gl_SampleID * tex_depth) + z;\n"
3227 " gl_FragColor = texture(tex, vec3(tex_coords, layer));\n"
3228 "}\n";
3231 * Uploads an arbitrary multisample texture.
3233 * This function acts like glTexImage for multisample textures. If the
3234 * input texture is zero, it will create one. Otherwise, it will use the
3235 * texture given and assumes that glTexImage[23]DMultisample has already
3236 * been called to establish the storage.
3238 * When this function returns, multisample texture will be bound to the
3239 * currently active texture.
3241 * \param target either GL_TEXTURE_2D_MULTISAMPLE or
3242 * GL_TEXTURE2D_MULTISAMPLE_ARRAY
3243 * \param tex texture ID for existing texture, or zero
3244 * \param internalformat a renderable color format accepted by
3245 * glTexImage2DMultisample
3246 * \param width texture width
3247 * \param height texture height
3248 * \param depth texture depth. If target is
3249 * GL_TEXTURE_2D_MULTISAMPLE, this must be 1.
3250 * \param samples the number of samples
3251 * \param format format of the pixel data
3252 * \param type type of the pixel data
3253 * \param data pixel data with which to fill the texture
3255 * \return the new texture object id
3257 GLuint
3258 piglit_multisample_texture(GLenum target, GLuint tex, GLenum internalFormat,
3259 unsigned width, unsigned height,
3260 unsigned depth, unsigned samples,
3261 GLenum format, GLenum type, const void *data)
3263 static GLuint prog = 0;
3264 static GLint tex_loc, tex_depth_loc, z_loc;
3265 static GLuint fbo, array_tex, ms_tex;
3266 static const float verts[] = {
3267 0.0, 0.0,
3268 0.0, 1.0,
3269 1.0, 1.0,
3270 1.0, 1.0,
3271 1.0, 0.0,
3272 0.0, 0.0
3274 unsigned z;
3276 struct {
3277 GLint active_tex;
3278 GLint draw_fbo;
3279 GLint prog;
3280 GLint viewport[4];
3281 GLboolean arb_sample_shading;
3282 GLfloat min_sample_shading;
3283 GLint clamp_fragment_color;
3284 } backup;
3286 piglit_require_extension("GL_ARB_texture_multisample");
3287 piglit_require_extension("GL_ARB_sample_shading");
3289 if (target == GL_TEXTURE_2D_MULTISAMPLE) {
3290 assert(depth == 1);
3291 } else if (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
3292 } else {
3293 assert(!"Invalid texture target");
3294 return 0;
3297 if (prog == 0) {
3298 /* First-run setup */
3299 prog = piglit_build_simple_program_unlinked(
3300 multisample_texture_vs_source,
3301 multisample_texture_fs_source);
3302 glBindAttribLocation(prog, 0, "vertex");
3303 glLinkProgram(prog);
3304 if (!piglit_link_check_status(prog)) {
3305 prog = 0;
3306 return 0;
3309 tex_loc = glGetUniformLocation(prog, "tex");
3310 tex_depth_loc = glGetUniformLocation(prog, "tex_depth");
3311 z_loc = glGetUniformLocation(prog, "z");
3313 glGenFramebuffers(1, &fbo);
3314 glGenTextures(1, &array_tex);
3317 /* Backup client values so we can restore them later */
3318 glGetIntegerv(GL_ACTIVE_TEXTURE, &backup.active_tex);
3319 glGetIntegerv(GL_CURRENT_PROGRAM, &backup.prog);
3320 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &backup.draw_fbo);
3321 glGetIntegerv(GL_CLAMP_FRAGMENT_COLOR, &backup.clamp_fragment_color);
3322 glGetIntegerv(GL_VIEWPORT, backup.viewport);
3323 glGetBooleanv(GL_SAMPLE_SHADING_ARB, &backup.arb_sample_shading);
3324 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_ARB, &backup.min_sample_shading);
3326 glEnable(GL_SAMPLE_SHADING_ARB);
3327 glMinSampleShadingARB(1.0f);
3329 if (tex) {
3330 ms_tex = tex;
3331 } else {
3332 glGenTextures(1, &ms_tex);
3333 glBindTexture(target, ms_tex);
3334 if (target == GL_TEXTURE_2D_MULTISAMPLE) {
3335 assert(depth == 1);
3336 glTexImage2DMultisample(target, samples, internalFormat,
3337 width, height, GL_TRUE);
3338 } else {
3339 glTexImage3DMultisample(target, samples, internalFormat,
3340 width, height, depth, GL_TRUE);
3344 glBindTexture(GL_TEXTURE_2D_ARRAY, array_tex);
3345 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3346 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3347 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalFormat, width, height,
3348 depth * samples, 0, format, type, data);
3350 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
3351 glViewport(0, 0, width, height);
3353 glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
3355 glUseProgram(prog);
3356 glUniform1i(tex_loc, backup.active_tex - GL_TEXTURE0);
3357 glUniform1i(tex_depth_loc, depth);
3359 glEnableVertexAttribArray(0);
3360 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
3362 if (target == GL_TEXTURE_2D_MULTISAMPLE) {
3363 glUniform1i(z_loc, 0);
3364 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
3365 GL_COLOR_ATTACHMENT0,
3366 target, ms_tex, 0);
3367 if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) !=
3368 GL_FRAMEBUFFER_COMPLETE)
3369 goto error;
3371 glDrawArrays(GL_TRIANGLES, 0, 6);
3372 } else {
3373 for (z = 0; z < depth; ++z) {
3374 glUniform1i(z_loc, z);
3375 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER,
3376 GL_COLOR_ATTACHMENT0,
3377 ms_tex, 0, z);
3378 if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) !=
3379 GL_FRAMEBUFFER_COMPLETE)
3380 goto error;
3382 glDrawArrays(GL_TRIANGLES, 0, 6);
3386 glDisableVertexAttribArray(0);
3388 /* Restore values for the client */
3389 if (!backup.arb_sample_shading)
3390 glDisable(GL_SAMPLE_SHADING_ARB);
3391 glMinSampleShadingARB(backup.min_sample_shading);
3393 glUseProgram(backup.prog);
3394 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, backup.draw_fbo);
3395 glViewport(backup.viewport[0], backup.viewport[1],
3396 backup.viewport[2], backup.viewport[3]);
3397 glBindTexture(target, ms_tex);
3398 glClampColor(GL_CLAMP_FRAGMENT_COLOR, backup.clamp_fragment_color);
3400 return ms_tex;
3402 error:
3403 if (tex == 0) /* We created it, clean it up */
3404 glDeleteTextures(1, &ms_tex);
3406 return 0;
3410 * Require transform feedback.
3412 * Transform feedback may either be provided by GL 3.0 or
3413 * EXT_transform_feedback.
3415 void
3416 piglit_require_transform_feedback(void)
3418 if (!(piglit_get_gl_version() >= 30 ||
3419 piglit_is_extension_supported("GL_EXT_transform_feedback"))) {
3420 printf("Transform feedback not supported.\n");
3421 piglit_report_result(PIGLIT_SKIP);
3426 * Convert the image into a format that can be easily understood by
3427 * visual inspection, and display it on the screen.
3429 * Luminance and intensity values are converted to a grayscale value.
3430 * Alpha values are visualized by blending the image with a grayscale
3431 * checkerboard.
3433 * Pass image_count = 0 to disable drawing multiple images to window
3434 * system framebuffer.
3436 void
3437 piglit_visualize_image(float *img, GLenum base_internal_format,
3438 int image_width, int image_height,
3439 int image_count, bool rhs)
3441 int x, y;
3442 float checker;
3443 unsigned components = piglit_num_components(base_internal_format);
3444 float *visualization =
3445 (float *) malloc(sizeof(float)*3*image_width*image_height);
3446 for (y = 0; y < image_height; ++y) {
3447 for ( x = 0; x < image_width; ++x) {
3448 float r = 0, g = 0, b = 0, a = 1;
3449 float *pixel =
3450 &img[(y * image_width + x) * components];
3451 switch (base_internal_format) {
3452 case GL_ALPHA:
3453 a = pixel[0];
3454 break;
3455 case GL_RGBA:
3456 a = pixel[3];
3457 /* Fall through */
3458 case GL_RGB:
3459 b = pixel[2];
3460 /* Fall through */
3461 case GL_RG:
3462 g = pixel[1];
3463 /* Fall through */
3464 case GL_RED:
3465 r = pixel[0];
3466 break;
3467 case GL_LUMINANCE_ALPHA:
3468 a = pixel[1];
3469 /* Fall through */
3470 case GL_INTENSITY:
3471 case GL_LUMINANCE:
3472 r = pixel[0];
3473 g = pixel[0];
3474 b = pixel[0];
3475 break;
3477 checker = ((x ^ y) & 0x10) ? 0.75 : 0.25;
3478 r = r * a + checker * (1 - a);
3479 g = g * a + checker * (1 - a);
3480 b = b * a + checker * (1 - a);
3481 visualization[(y * image_width + x) * 3] = r;
3482 visualization[(y * image_width + x) * 3 + 1] = g;
3483 visualization[(y * image_width + x) * 3 + 2] = b;
3486 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
3487 glUseProgram(0);
3489 /* To simultaneously display multiple images on window system
3490 * framebuffer.
3492 if(image_count) {
3493 /* Use glWindowPos to directly update x, y coordinates of
3494 * current raster position without getting transformed by
3495 * modelview projection matrix and viewport-to-window
3496 * transform.
3498 glWindowPos2f(rhs ? image_width : 0,
3499 (image_count - 1) * image_height);
3501 else {
3502 glRasterPos2f(rhs ? 0 : -1, -1);
3504 glDrawPixels(image_width, image_height, GL_RGB, GL_FLOAT,
3505 visualization);
3506 free(visualization);
3510 * Convert from sRGB color space to linear color space, using the
3511 * formula from the GL 3.0 spec, section 4.1.8 (sRGB Texture Color
3512 * Conversion).
3514 float
3515 piglit_srgb_to_linear(float x)
3517 if (x <= 0.0405)
3518 return x / 12.92;
3519 else
3520 return pow((x + 0.055) / 1.055, 2.4);
3523 /* Convert from linear color space to sRGB color space. */
3524 float
3525 piglit_linear_to_srgb(float x)
3527 if (x < 0.0f)
3528 return 0.0f;
3529 else if (x < 0.0031308f)
3530 return 12.92f * x;
3531 else if (x < 1.0f)
3532 return 1.055f * powf(x, 0.41666f) - 0.055f;
3533 else
3534 return 1.0f;