1 /*
2 * Copyright (c) The Piglit project 2007
3 *
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:
10 *
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.
14 *
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.
22 */
23
24 #include "piglit-util-gl.h"
25 #include <ctype.h>
26
27 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
28
29 /**
30 * An array of pointers to extension strings.
31 *
32 * Each extension is pointed to by a separate entry in the array.
33 *
34 * The end of the array is indicated by a NULL pointer.
35 */
36 static const char **gl_extensions = NULL;
37
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 */
43 };
44
45 bool piglit_is_core_profile;
46
piglit_is_gles(void)47 bool piglit_is_gles(void)
48 {
49 const char *version_string = (const char *) glGetString(GL_VERSION);
50 return strncmp("OpenGL ES", version_string, 9) == 0;
51 }
52
piglit_is_gles3(void)53 bool piglit_is_gles3(void)
54 {
55 const char *version_string = (const char *) glGetString(GL_VERSION);
56 return strncmp("OpenGL ES 3", version_string, 11) == 0;
57 }
58
piglit_get_gl_version(void)59 int piglit_get_gl_version(void)
60 {
61 const char *version_string = (const char *) glGetString(GL_VERSION);
62 int scanf_count;
63 int major;
64 int minor;
65
66 /* skip to version number */
67 while (!isdigit(*version_string) && *version_string != '\0')
68 version_string++;
69
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);
76 }
77 return 10*major+minor;
78 }
79
gl_extension_array_from_getstring()80 static const char** gl_extension_array_from_getstring()
81 {
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, " ");
85 }
86
gl_extension_array_from_getstringi()87 static const char** gl_extension_array_from_getstringi()
88 {
89 const char **strings;
90 int loop, num_extensions;
91
92 glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
93 strings = malloc (sizeof(char*) * (num_extensions + 1));
94 assert (strings != NULL);
95
96 for (loop = 0; loop < num_extensions; loop++) {
97 strings[loop] = (const char*) glGetStringi(GL_EXTENSIONS, loop);
98 }
99
100 strings[loop] = NULL;
101
102 return (const char**) strings;
103 }
104
initialize_piglit_extension_support(void)105 static void initialize_piglit_extension_support(void)
106 {
107 if (gl_extensions != NULL) {
108 return;
109 }
110
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();
115 }
116 }
117
piglit_gl_invalidate_extensions()118 void piglit_gl_invalidate_extensions()
119 {
120 if (gl_extensions != NULL) {
121 free(gl_extensions);
122 gl_extensions = NULL;
123 }
124 }
125
piglit_is_extension_supported(const char * name)126 bool piglit_is_extension_supported(const char *name)
127 {
128 initialize_piglit_extension_support();
129 return piglit_is_extension_in_array(gl_extensions, name);
130 }
131
piglit_require_gl_version(int required_version_times_10)132 void piglit_require_gl_version(int required_version_times_10)
133 {
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);
139 }
140 }
141
piglit_require_extension(const char * name)142 void piglit_require_extension(const char *name)
143 {
144 if (!piglit_is_extension_supported(name)) {
145 printf("Test requires %s\n", name);
146 piglit_report_result(PIGLIT_SKIP);
147 }
148 }
149
piglit_require_not_extension(const char * name)150 void piglit_require_not_extension(const char *name)
151 {
152 if (piglit_is_extension_supported(name)) {
153 piglit_report_result(PIGLIT_SKIP);
154 }
155 }
156
piglit_get_gl_error_name(GLenum error)157 const char* piglit_get_gl_error_name(GLenum error)
158 {
159 #define CASE(x) case x: return #x;
160 switch (error) {
161 CASE(GL_INVALID_ENUM)
162 CASE(GL_INVALID_OPERATION)
163 CASE(GL_INVALID_VALUE)
164 CASE(GL_NO_ERROR)
165 CASE(GL_OUT_OF_MEMORY)
166 CASE(GL_STACK_OVERFLOW)
167 CASE(GL_STACK_UNDERFLOW)
168 CASE(GL_INVALID_FRAMEBUFFER_OPERATION)
169 default:
170 return "(unrecognized error)";
171 }
172 #undef CASE
173 }
174
175 GLboolean
piglit_check_gl_error_(GLenum expected_error,const char * file,unsigned line)176 piglit_check_gl_error_(GLenum expected_error, const char *file, unsigned line)
177 {
178 GLenum actual_error;
179
180 actual_error = glGetError();
181 if (actual_error == expected_error) {
182 return GL_TRUE;
183 }
184
185 /*
186 * If the lookup of the error's name is successful, then print
187 * Unexpected GL error: NAME 0xHEX
188 * Else, print
189 * Unexpected GL error: 0xHEX
190 */
191 printf("Unexpected GL error: %s 0x%x\n",
192 piglit_get_gl_error_name(actual_error), actual_error);
193 printf("(Error at %s:%u)\n", file, line);
194
195 /* Print the expected error, but only if an error was really expected. */
196 if (expected_error != GL_NO_ERROR) {
197 printf("Expected GL error: %s 0x%x\n",
198 piglit_get_gl_error_name(expected_error), expected_error);
199 }
200
201 return GL_FALSE;
202 }
203
piglit_reset_gl_error(void)204 void piglit_reset_gl_error(void)
205 {
206 while (glGetError() != GL_NO_ERROR) {
207 /* empty */
208 }
209 }
210
211 /* These texture coordinates should have 1 or -1 in the major axis selecting
212 * the face, and a nearly-1-or-negative-1 value in the other two coordinates
213 * which will be used to produce the s,t values used to sample that face's
214 * image.
215 */
216 GLfloat cube_face_texcoords[6][4][3] = {
217 { /* GL_TEXTURE_CUBE_MAP_POSITIVE_X */
218 {1.0, 0.99, 0.99},
219 {1.0, 0.99, -0.99},
220 {1.0, -0.99, -0.99},
221 {1.0, -0.99, 0.99},
222 },
223 { /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X */
224 {-1.0, 0.99, -0.99},
225 {-1.0, 0.99, 0.99},
226 {-1.0, -0.99, 0.99},
227 {-1.0, -0.99, -0.99},
228 },
229 { /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y */
230 {-0.99, 1.0, -0.99},
231 { 0.99, 1.0, -0.99},
232 { 0.99, 1.0, 0.99},
233 {-0.99, 1.0, 0.99},
234 },
235 { /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y */
236 {-0.99, -1.0, 0.99},
237 {-0.99, -1.0, -0.99},
238 { 0.99, -1.0, -0.99},
239 { 0.99, -1.0, 0.99},
240 },
241 { /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z */
242 {-0.99, 0.99, 1.0},
243 {-0.99, -0.99, 1.0},
244 { 0.99, -0.99, 1.0},
245 { 0.99, 0.99, 1.0},
246 },
247 { /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z */
248 { 0.99, 0.99, -1.0},
249 {-0.99, 0.99, -1.0},
250 {-0.99, -0.99, -1.0},
251 { 0.99, -0.99, -1.0},
252 },
253 };
254
255 const char *cube_face_names[6] = {
256 "POSITIVE_X",
257 "NEGATIVE_X",
258 "POSITIVE_Y",
259 "NEGATIVE_Y",
260 "POSITIVE_Z",
261 "NEGATIVE_Z",
262 };
263
264 const GLenum cube_face_targets[6] = {
265 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
266 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
267 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
268 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
269 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
270 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
271 };
272
273 float piglit_tolerance[4] = { 0.01, 0.01, 0.01, 0.01 };
274
275 void
piglit_set_tolerance_for_bits(int rbits,int gbits,int bbits,int abits)276 piglit_set_tolerance_for_bits(int rbits, int gbits, int bbits, int abits)
277 {
278 int bits[4] = {rbits, gbits, bbits, abits};
279 int i;
280
281 for (i = 0; i < 4; i++) {
282 if (bits[i] == 0) {
283 /* With 0 bits of storage, we still want to
284 * validate expected results, (such as
285 * alpha==1.0 when targeting storage with no
286 * alpha bits). */
287 piglit_tolerance[i] = 3.0 / (1 << 8);
288 } else if (bits[i] == 1) {
289 /* Don't try to validate channels when there's only 1
290 * bit of precision.
291 */
292 piglit_tolerance[i] = 1.0;
293 } else {
294 piglit_tolerance[i] = 3.0 / (1 << bits[i]);
295 }
296 }
297 }
298
299 typedef union { GLfloat f; GLint i; } fi_type;
300
301 /**
302 * Convert a 4-byte float to a 2-byte half float.
303 * Based on code from:
304 * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html
305 *
306 * Taken over from Mesa.
307 */
308 unsigned short
piglit_half_from_float(float val)309 piglit_half_from_float(float val)
310 {
311 const fi_type fi = {val};
312 const int flt_m = fi.i & 0x7fffff;
313 const int flt_e = (fi.i >> 23) & 0xff;
314 const int flt_s = (fi.i >> 31) & 0x1;
315 int s, e, m = 0;
316 unsigned short result;
317
318 /* sign bit */
319 s = flt_s;
320
321 /* handle special cases */
322 if ((flt_e == 0) && (flt_m == 0)) {
323 /* zero */
324 /* m = 0; - already set */
325 e = 0;
326 }
327 else if ((flt_e == 0) && (flt_m != 0)) {
328 /* denorm -- denorm float maps to 0 half */
329 /* m = 0; - already set */
330 e = 0;
331 }
332 else if ((flt_e == 0xff) && (flt_m == 0)) {
333 /* infinity */
334 /* m = 0; - already set */
335 e = 31;
336 }
337 else if ((flt_e == 0xff) && (flt_m != 0)) {
338 /* NaN */
339 m = 1;
340 e = 31;
341 }
342 else {
343 /* regular number */
344 const int new_exp = flt_e - 127;
345 if (new_exp < -24) {
346 /* this maps to 0 */
347 /* m = 0; - already set */
348 e = 0;
349 }
350 else if (new_exp < -14) {
351 /* this maps to a denorm */
352 /* 2^-exp_val*/
353 unsigned int exp_val = (unsigned int) (-14 - new_exp);
354
355 e = 0;
356 switch (exp_val) {
357 case 0:
358 /* m = 0; - already set */
359 break;
360 case 1: m = 512 + (flt_m >> 14); break;
361 case 2: m = 256 + (flt_m >> 15); break;
362 case 3: m = 128 + (flt_m >> 16); break;
363 case 4: m = 64 + (flt_m >> 17); break;
364 case 5: m = 32 + (flt_m >> 18); break;
365 case 6: m = 16 + (flt_m >> 19); break;
366 case 7: m = 8 + (flt_m >> 20); break;
367 case 8: m = 4 + (flt_m >> 21); break;
368 case 9: m = 2 + (flt_m >> 22); break;
369 case 10: m = 1; break;
370 }
371 }
372 else if (new_exp > 15) {
373 /* map this value to infinity */
374 /* m = 0; - already set */
375 e = 31;
376 }
377 else {
378 /* regular */
379 e = new_exp + 15;
380 m = flt_m >> 13;
381 }
382 }
383
384 result = (s << 15) | (e << 10) | m;
385 return result;
386 }
387
388
389 /**
390 * Return block size info for a specific texture compression format.
391 * \param bw returns the block width, in pixels
392 * \param bh returns the block height, in pixels
393 * \param return number of bytes per block
394 * \return true if format is a known compressed format, false otherwise
395 */
396 bool
piglit_get_compressed_block_size(GLenum format,unsigned * bw,unsigned * bh,unsigned * bytes)397 piglit_get_compressed_block_size(GLenum format,
398 unsigned *bw, unsigned *bh, unsigned *bytes)
399 {
400 switch (format) {
401 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
402 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
403 *bw = *bh = 4;
404 *bytes = 8;
405 return true;
406 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
407 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
408 case GL_COMPRESSED_RED:
409 case GL_COMPRESSED_RED_RGTC1:
410 case GL_COMPRESSED_SIGNED_RED_RGTC1:
411 case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
412 case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
413 case GL_COMPRESSED_RGB8_ETC2:
414 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
415 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
416 case GL_COMPRESSED_R11_EAC:
417 case GL_COMPRESSED_SIGNED_R11_EAC:
418 case GL_COMPRESSED_SRGB8_ETC2:
419 *bw = *bh = 4;
420 *bytes = 8;
421 return true;
422 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
423 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
424 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
425 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
426 case GL_COMPRESSED_RG:
427 case GL_COMPRESSED_RG_RGTC2:
428 case GL_COMPRESSED_SIGNED_RG_RGTC2:
429 case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
430 case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
431 case GL_COMPRESSED_RGBA_BPTC_UNORM:
432 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
433 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
434 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
435 case GL_COMPRESSED_RGBA8_ETC2_EAC:
436 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
437 case GL_COMPRESSED_RG11_EAC:
438 case GL_COMPRESSED_SIGNED_RG11_EAC:
439 *bw = *bh = 4;
440 *bytes = 16;
441 return true;
442 case GL_COMPRESSED_RGB_FXT1_3DFX:
443 case GL_COMPRESSED_RGBA_FXT1_3DFX:
444 *bw = 8;
445 *bh = 4;
446 *bytes = 16;
447 return true;
448 default:
449 /* return something rather than uninitialized values */
450 *bw = *bh = *bytes = 1;
451 return false;
452 }
453 }
454
455
456 /**
457 * Compute size (in bytes) neede to store an image in the given compressed
458 * format.
459 */
460 unsigned
piglit_compressed_image_size(GLenum format,unsigned width,unsigned height)461 piglit_compressed_image_size(GLenum format, unsigned width, unsigned height)
462 {
463 unsigned bw, bh, bytes;
464 bool b = piglit_get_compressed_block_size(format, &bw, &bh, &bytes);
465
466 (void)b;
467 assert(b);
468 return ((width + bw - 1) / bw) * ((height + bh - 1) / bh) * bytes;
469 }
470
471
472 /**
473 * Return offset (in bytes) to the given texel in a compressed image.
474 * Note the x and y must be multiples of the compressed block size.
475 */
476 unsigned
piglit_compressed_pixel_offset(GLenum format,unsigned width,unsigned x,unsigned y)477 piglit_compressed_pixel_offset(GLenum format, unsigned width,
478 unsigned x, unsigned y)
479 {
480 unsigned bw, bh, bytes, offset;
481 bool b = piglit_get_compressed_block_size(format, &bw, &bh, &bytes);
482
483 (void)b;
484 assert(b);
485
486 assert(x % bw == 0);
487 assert(y % bh == 0);
488 assert(width % bw == 0);
489
490 offset = (width / bw * bytes * y / bh) + (x / bw * bytes);
491
492 return offset;
493 }
494
495 void
piglit_escape_exit_key(unsigned char key,int x,int y)496 piglit_escape_exit_key(unsigned char key, int x, int y)
497 {
498 (void) x;
499 (void) y;
500 switch (key) {
501 case 27:
502 exit(0);
503 break;
504 }
505 if (!piglit_is_gles())
506 piglit_post_redisplay();
507 }
508
509 /**
510 * Convenience function to configure an abitrary orthogonal projection matrix
511 */
512 void
piglit_gen_ortho_projection(double left,double right,double bottom,double top,double near_val,double far_val,GLboolean push)513 piglit_gen_ortho_projection(double left, double right, double bottom,
514 double top, double near_val, double far_val,
515 GLboolean push)
516 {
517 glMatrixMode(GL_PROJECTION);
518 glLoadIdentity();
519 if (push)
520 glPushMatrix();
521
522 if (piglit_is_gles())
523 glOrthof(left, right, bottom, top, near_val, far_val);
524 else
525 glOrtho(left, right, bottom, top, near_val, far_val);
526
527 glMatrixMode(GL_MODELVIEW);
528 if (push)
529 glPushMatrix();
530 glLoadIdentity();
531 }
532
533 /**
534 * Convenience function to configure projection matrix for window coordinates
535 */
536 void
piglit_ortho_projection(int w,int h,GLboolean push)537 piglit_ortho_projection(int w, int h, GLboolean push)
538 {
539 /* Set up projection matrix so we can just draw using window
540 * coordinates.
541 */
542 piglit_gen_ortho_projection(0, w, 0, h, -1, 1, push);
543 }
544
545 /**
546 * Convenience function to configure frustum projection.
547 */
548 void
piglit_frustum_projection(GLboolean push,double l,double r,double b,double t,double n,double f)549 piglit_frustum_projection(GLboolean push, double l, double r, double b,
550 double t, double n, double f)
551 {
552 glMatrixMode(GL_PROJECTION);
553 glLoadIdentity();
554 if (push)
555 glPushMatrix();
556
557 if (piglit_is_gles())
558 glFrustumf(l, r, b, t, n, f);
559 else
560 glFrustum(l, r, b, t, n, f);
561
562 glMatrixMode(GL_MODELVIEW);
563 if (push)
564 glPushMatrix();
565 glLoadIdentity();
566 }
567
568 /**
569 * Convenience function to configure a shader uniform variable as an
570 * arbitrary orthogonal projection matrix.
571 */
572 void
piglit_gen_ortho_uniform(GLint location,double l,double r,double b,double t,double n,double f)573 piglit_gen_ortho_uniform(GLint location, double l, double r, double b,
574 double t, double n, double f)
575 {
576 const GLfloat values[4][4] = {
577 { 2/(r-l), 0, 0, 0 },
578 { 0, 2/(t-b), 0, 0 },
579 { 0, 0, -2/(f-n), 0 },
580 { -(r+l)/(r-l), -(t+b)/(t-b), -(f+n)/(f-n), 1 }
581 };
582 glUniformMatrix4fv(location, 1, GL_FALSE, (const GLfloat *)values);
583 }
584
585
586 /**
587 * Convenience function to configure a shader uniform variable as a
588 * projection matrix for window coordinates.
589 */
590 void
piglit_ortho_uniform(GLint location,int w,int h)591 piglit_ortho_uniform(GLint location, int w, int h)
592 {
593 /* Set up projection matrix so we can just draw using window
594 * coordinates.
595 */
596 piglit_gen_ortho_uniform(location, 0, w, 0, h, -1, 1);
597 }
598
599
600 unsigned
required_gl_version_from_glsl_version(unsigned glsl_version)601 required_gl_version_from_glsl_version(unsigned glsl_version)
602 {
603 switch (glsl_version) {
604 case 110: return 20;
605 case 120: return 21;
606 /* GLSL 1.30 is naturally matched with GL3,
607 * but is usefully supportable on GL2.1 if
608 * EXT_gpu_shader4 is also supported.
609 */
610 case 130: return 21;
611 case 140: return 31;
612 case 150: return 32;
613 case 330: return 33;
614 case 400: return 40;
615 case 410: return 41;
616 case 420: return 42;
617 case 430: return 43;
618 case 440: return 44;
619 case 450: return 45;
620 case 460: return 46;
621 default: return 0;
622 }
623 }
624
625 /**
626 * Call glDrawArrays. verts is expected to be
627 *
628 * float verts[4][4];
629 *
630 * if not NULL; tex is expected to be
631 *
632 * float tex[4][2];
633 *
634 * if not NULL.
635 */
636 void
piglit_draw_rect_from_arrays(const void * verts,const void * tex,bool use_patches,unsigned instance_count)637 piglit_draw_rect_from_arrays(const void *verts, const void *tex,
638 bool use_patches, unsigned instance_count)
639 {
640 bool use_fixed_function_attributes;
641
642 bool gles = piglit_is_gles();
643 int version = piglit_get_gl_version();
644
645 if (gles) {
646 use_fixed_function_attributes = (version < 20);
647 } else if (version >= 20 ||
648 piglit_is_extension_supported("GL_ARB_shader_objects")) {
649 GLuint prog;
650
651 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &prog);
652
653 if (!prog &&
654 piglit_is_extension_supported("GL_ARB_separate_shader_objects")) {
655 GLuint pipeline;
656
657 glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING,
658 (GLint*)&pipeline);
659 if (pipeline)
660 glGetProgramPipelineiv(pipeline, GL_VERTEX_SHADER,
661 (GLint*)&prog);
662 }
663
664 /* If there is a current program and that program has an
665 * active attribute named piglit_vertex, don't use the fixed
666 * function inputs. Never use fixed function inputs on core
667 * profile.
668 */
669 use_fixed_function_attributes = ((prog == 0)
670 || glGetAttribLocation(prog, "piglit_vertex") == -1)
671 && !piglit_is_core_profile;
672 } else {
673 use_fixed_function_attributes = true;
674 }
675
676 if (use_fixed_function_attributes) {
677 if (verts) {
678 glVertexPointer(4, GL_FLOAT, 0, verts);
679 glEnableClientState(GL_VERTEX_ARRAY);
680 }
681
682 if (tex) {
683 glTexCoordPointer(2, GL_FLOAT, 0, tex);
684 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
685 }
686
687 if (use_patches) {
688 GLint old_patch_vertices;
689
690 glGetIntegerv(GL_PATCH_VERTICES, &old_patch_vertices);
691 glPatchParameteri(GL_PATCH_VERTICES, 4);
692 if (instance_count > 1)
693 glDrawArraysInstanced(GL_PATCHES, 0, 4, instance_count);
694 else
695 glDrawArrays(GL_PATCHES, 0, 4);
696 glPatchParameteri(GL_PATCH_VERTICES, old_patch_vertices);
697 } else {
698 if (instance_count > 1)
699 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, instance_count);
700 else
701 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
702 }
703
704 if (verts)
705 glDisableClientState(GL_VERTEX_ARRAY);
706 if (tex)
707 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
708 } else {
709 GLuint buf = 0;
710 GLuint old_buf = 0;
711 GLuint vao = 0;
712 GLuint old_vao = 0;
713
714 /* Vertex array objects were added in both OpenGL 3.0 and
715 * OpenGL ES 3.0. The use of VAOs is required in desktop
716 * OpenGL 3.1 (without GL_ARB_compatibility) and all desktop
717 * OpenGL core profiles. If the functionality is supported,
718 * just use it.
719 */
720 if (piglit_get_gl_version() >= 30
721 || piglit_is_extension_supported("GL_OES_vertex_array_object")
722 || piglit_is_extension_supported("GL_ARB_vertex_array_object")) {
723 glGetIntegerv(GL_VERTEX_ARRAY_BINDING,
724 (GLint *) &old_vao);
725 glGenVertexArrays(1, &vao);
726 glBindVertexArray(vao);
727 }
728
729 /* Assume that VBOs are supported in any implementation that
730 * uses shaders.
731 */
732 glGetIntegerv(GL_ARRAY_BUFFER_BINDING,
733 (GLint *) &old_buf);
734 glGenBuffers(1, &buf);
735 glBindBuffer(GL_ARRAY_BUFFER, buf);
736 glBufferData(GL_ARRAY_BUFFER,
737 (sizeof(GLfloat) * 4 * 4)
738 + (sizeof(GLfloat) * 4 * 2),
739 NULL,
740 GL_STATIC_DRAW);
741
742 if (verts) {
743 glBufferSubData(GL_ARRAY_BUFFER,
744 0,
745 sizeof(GLfloat) * 4 * 4,
746 verts);
747 glVertexAttribPointer(PIGLIT_ATTRIB_POS, 4, GL_FLOAT,
748 GL_FALSE, 0,
749 BUFFER_OFFSET(0));
750 glEnableVertexAttribArray(PIGLIT_ATTRIB_POS);
751 }
752
753 if (tex) {
754 glBufferSubData(GL_ARRAY_BUFFER,
755 sizeof(GLfloat) * 4 * 4,
756 sizeof(GLfloat) * 4 * 2,
757 tex);
758 glVertexAttribPointer(PIGLIT_ATTRIB_TEX, 2, GL_FLOAT,
759 GL_FALSE, 0,
760 BUFFER_OFFSET(sizeof(GLfloat) * 4 * 4));
761 glEnableVertexAttribArray(PIGLIT_ATTRIB_TEX);
762 }
763
764 if (use_patches) {
765 GLint old_patch_vertices;
766
767 glGetIntegerv(GL_PATCH_VERTICES, &old_patch_vertices);
768 glPatchParameteri(GL_PATCH_VERTICES, 4);
769 if (instance_count > 1)
770 glDrawArraysInstanced(GL_PATCHES, 0, 4, instance_count);
771 else
772 glDrawArrays(GL_PATCHES, 0, 4);
773 glPatchParameteri(GL_PATCH_VERTICES, old_patch_vertices);
774 }
775 else {
776 if (instance_count > 1)
777 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, instance_count);
778 else
779 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
780 }
781
782 if (verts)
783 glDisableVertexAttribArray(PIGLIT_ATTRIB_POS);
784 if (tex)
785 glDisableVertexAttribArray(PIGLIT_ATTRIB_TEX);
786
787 glBindBuffer(GL_ARRAY_BUFFER, old_buf);
788 glDeleteBuffers(1, &buf);
789
790 if (vao != 0) {
791 glBindVertexArray(old_vao);
792 glDeleteVertexArrays(1, &vao);
793 }
794 }
795 }
796
797 /**
798 * Convenience function to draw an axis-aligned rectangle.
799 */
800 GLvoid
piglit_draw_rect_custom(float x,float y,float w,float h,bool use_patches,unsigned instance_count)801 piglit_draw_rect_custom(float x, float y, float w, float h, bool use_patches,
802 unsigned instance_count)
803 {
804 float verts[4][4];
805
806 verts[0][0] = x;
807 verts[0][1] = y;
808 verts[0][2] = 0.0;
809 verts[0][3] = 1.0;
810 verts[1][0] = x + w;
811 verts[1][1] = y;
812 verts[1][2] = 0.0;
813 verts[1][3] = 1.0;
814 verts[2][0] = x;
815 verts[2][1] = y + h;
816 verts[2][2] = 0.0;
817 verts[2][3] = 1.0;
818 verts[3][0] = x + w;
819 verts[3][1] = y + h;
820 verts[3][2] = 0.0;
821 verts[3][3] = 1.0;
822
823 piglit_draw_rect_from_arrays(verts, NULL, use_patches, instance_count);
824 }
825
826 /**
827 * Convenience function to draw an axis-aligned rectangle.
828 */
829 GLvoid
piglit_draw_rect(float x,float y,float w,float h)830 piglit_draw_rect(float x, float y, float w, float h)
831 {
832 piglit_draw_rect_custom(x, y, w, h, false, 1);
833 }
834
835 /**
836 * Convenience function to draw an axis-aligned rectangle.
837 */
838 GLvoid
piglit_draw_rect_z(float z,float x,float y,float w,float h)839 piglit_draw_rect_z(float z, float x, float y, float w, float h)
840 {
841 float verts[4][4];
842
843 verts[0][0] = x;
844 verts[0][1] = y;
845 verts[0][2] = z;
846 verts[0][3] = 1.0;
847 verts[1][0] = x + w;
848 verts[1][1] = y;
849 verts[1][2] = z;
850 verts[1][3] = 1.0;
851 verts[2][0] = x;
852 verts[2][1] = y + h;
853 verts[2][2] = z;
854 verts[2][3] = 1.0;
855 verts[3][0] = x + w;
856 verts[3][1] = y + h;
857 verts[3][2] = z;
858 verts[3][3] = 1.0;
859
860 piglit_draw_rect_from_arrays(verts, NULL, false, 1);
861 }
862
863 /**
864 * Convenience function to draw an axis-aligned rectangle
865 * with texture coordinates.
866 */
867 GLvoid
piglit_draw_rect_tex(float x,float y,float w,float h,float tx,float ty,float tw,float th)868 piglit_draw_rect_tex(float x, float y, float w, float h,
869 float tx, float ty, float tw, float th)
870 {
871 float verts[4][4];
872 float tex[4][2];
873
874 verts[0][0] = x;
875 verts[0][1] = y;
876 verts[0][2] = 0.0;
877 verts[0][3] = 1.0;
878 tex[0][0] = tx;
879 tex[0][1] = ty;
880 verts[1][0] = x + w;
881 verts[1][1] = y;
882 verts[1][2] = 0.0;
883 verts[1][3] = 1.0;
884 tex[1][0] = tx + tw;
885 tex[1][1] = ty;
886 verts[2][0] = x;
887 verts[2][1] = y + h;
888 verts[2][2] = 0.0;
889 verts[2][3] = 1.0;
890 tex[2][0] = tx;
891 tex[2][1] = ty + th;
892 verts[3][0] = x + w;
893 verts[3][1] = y + h;
894 verts[3][2] = 0.0;
895 verts[3][3] = 1.0;
896 tex[3][0] = tx + tw;
897 tex[3][1] = ty + th;
898
899 piglit_draw_rect_from_arrays(verts, tex, false, 1);
900 }
901
902 unsigned
piglit_num_components(GLenum format)903 piglit_num_components(GLenum format)
904 {
905 switch (format) {
906 case GL_ALPHA:
907 case GL_DEPTH_COMPONENT:
908 case GL_INTENSITY:
909 case GL_LUMINANCE:
910 case GL_RED:
911 case GL_GREEN:
912 case GL_BLUE:
913 return 1;
914 case GL_DEPTH_STENCIL:
915 case GL_LUMINANCE_ALPHA:
916 case GL_RG:
917 return 2;
918 case GL_RGB:
919 case GL_BGR:
920 return 3;
921 case GL_RGBA:
922 case GL_BGRA:
923 case GL_ABGR_EXT:
924 return 4;
925 default:
926 printf("Unknown num_components for %s\n",
927 piglit_get_gl_enum_name(format));
928 piglit_report_result(PIGLIT_FAIL);
929 return 0;
930 }
931 }
932
933 /* This function only handles formats not supported by the OpenGL framebuffer
934 * size queries, which only support querying the R,G,B,A sizes.
935 *
936 * The function doesn't change the bits for formats it doesn't handle.
937 *
938 * The returned number of bits is an approximation but should be no less than
939 * the actual number of bits for the format chosen by OpenGL.
940 *
941 * The combination of the OpenGL framebuffer queries size and calling
942 * this function without checking the return value should give you reasonable
943 * values for any format.
944 */
945 bool
piglit_get_luminance_intensity_bits(GLenum internalformat,int * bits)946 piglit_get_luminance_intensity_bits(GLenum internalformat, int *bits)
947 {
948 switch (internalformat) {
949 case GL_LUMINANCE4:
950 bits[0] = bits[1] = bits[2] = 4;
951 bits[3] = 0;
952 return true;
953
954 case GL_LUMINANCE:
955 case GL_LUMINANCE_SNORM:
956 case GL_LUMINANCE8:
957 case GL_LUMINANCE8_SNORM:
958 case GL_LUMINANCE8I_EXT:
959 case GL_LUMINANCE8UI_EXT:
960 bits[0] = bits[1] = bits[2] = 8;
961 bits[3] = 0;
962 return true;
963
964 case GL_LUMINANCE12:
965 bits[0] = bits[1] = bits[2] = 12;
966 bits[3] = 0;
967 return true;
968
969 case GL_LUMINANCE16:
970 case GL_LUMINANCE16_SNORM:
971 case GL_LUMINANCE16I_EXT:
972 case GL_LUMINANCE16UI_EXT:
973 case GL_LUMINANCE16F_ARB:
974 bits[0] = bits[1] = bits[2] = 16;
975 bits[3] = 0;
976 return true;
977
978 case GL_LUMINANCE32I_EXT:
979 case GL_LUMINANCE32UI_EXT:
980 case GL_LUMINANCE32F_ARB:
981 bits[0] = bits[1] = bits[2] = 32;
982 bits[3] = 0;
983 return true;
984
985 case GL_LUMINANCE4_ALPHA4:
986 case GL_INTENSITY4:
987 bits[0] = bits[1] = bits[2] = bits[3] = 4;
988 return true;
989
990 case GL_LUMINANCE_ALPHA:
991 case GL_LUMINANCE_ALPHA_SNORM:
992 case GL_LUMINANCE8_ALPHA8:
993 case GL_LUMINANCE8_ALPHA8_SNORM:
994 case GL_LUMINANCE_ALPHA8I_EXT:
995 case GL_LUMINANCE_ALPHA8UI_EXT:
996 case GL_INTENSITY:
997 case GL_INTENSITY_SNORM:
998 case GL_INTENSITY8:
999 case GL_INTENSITY8_SNORM:
1000 case GL_INTENSITY8I_EXT:
1001 case GL_INTENSITY8UI_EXT:
1002 bits[0] = bits[1] = bits[2] = bits[3] = 8;
1003 return true;
1004
1005 case GL_LUMINANCE12_ALPHA12:
1006 case GL_INTENSITY12:
1007 bits[0] = bits[1] = bits[2] = bits[3] = 12;
1008 return true;
1009
1010 case GL_LUMINANCE16_ALPHA16:
1011 case GL_LUMINANCE16_ALPHA16_SNORM:
1012 case GL_LUMINANCE_ALPHA16I_EXT:
1013 case GL_LUMINANCE_ALPHA16UI_EXT:
1014 case GL_LUMINANCE_ALPHA16F_ARB:
1015 case GL_INTENSITY16:
1016 case GL_INTENSITY16_SNORM:
1017 case GL_INTENSITY16I_EXT:
1018 case GL_INTENSITY16UI_EXT:
1019 case GL_INTENSITY16F_ARB:
1020 bits[0] = bits[1] = bits[2] = bits[3] = 16;
1021 return true;
1022
1023 case GL_LUMINANCE_ALPHA32I_EXT:
1024 case GL_LUMINANCE_ALPHA32UI_EXT:
1025 case GL_LUMINANCE_ALPHA32F_ARB:
1026 case GL_INTENSITY32I_EXT:
1027 case GL_INTENSITY32UI_EXT:
1028 case GL_INTENSITY32F_ARB:
1029 bits[0] = bits[1] = bits[2] = bits[3] = 32;
1030 return true;
1031 }
1032 return false;
1033 }
1034
1035 /* Wrapper around glReadPixels that always returns floats; reads and converts
1036 * GL_UNSIGNED_BYTE on GLES. If pixels == NULL, malloc a float array of the
1037 * appropriate size, otherwise use the one provided. */
1038 static GLfloat *
read_pixels_float(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLfloat * pixels)1039 read_pixels_float(GLint x, GLint y, GLsizei width, GLsizei height,
1040 GLenum format, GLfloat *pixels)
1041 {
1042 GLubyte *pixels_b;
1043 unsigned i, j, k;
1044 int comps = piglit_num_components(format);
1045
1046 if (!pixels)
1047 pixels = malloc(width * height * comps * sizeof(GLfloat));
1048
1049 if (!piglit_is_gles()) {
1050 glReadPixels(x, y, width, height, format, GL_FLOAT, pixels);
1051 return pixels;
1052 }
1053
1054 pixels_b = malloc(width * height * 4 * sizeof(GLubyte));
1055 glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels_b);
1056 k = 0;
1057 for (i = 0; i < width * height; i++) {
1058 for (j = 0; j < comps; j++) {
1059 pixels[k++] = pixels_b[i*4+j] / 255.0f;
1060 }
1061 }
1062 free(pixels_b);
1063 return pixels;
1064 }
1065
1066 static bool
can_probe_ubyte()1067 can_probe_ubyte()
1068 {
1069 int r,g,b,a,read;
1070
1071 if (!piglit_is_extension_supported("GL_ARB_framebuffer_object"))
1072 return false;
1073
1074 glGetIntegerv(GL_READ_BUFFER, &read);
1075 if (read == GL_FRONT)
1076 read = GL_FRONT_LEFT;
1077 if (read == GL_BACK)
1078 read = GL_BACK_LEFT;
1079
1080 glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER, read,
1081 GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &r);
1082 glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER, read,
1083 GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, &g);
1084 glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER, read,
1085 GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &b);
1086 glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER, read,
1087 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &a);
1088
1089 /* it could be LUMINANCE32F, etc. */
1090 if (!r && !g && !b && !a)
1091 return false;
1092
1093 return r <= 8 && g <= 8 && b <= 8 && a <= 8;
1094 }
1095
1096 static void
print_components_ubyte(const GLubyte * pixel,unsigned components)1097 print_components_ubyte(const GLubyte *pixel, unsigned components)
1098 {
1099 int p;
1100 for (p = 0; p < components; ++p)
1101 printf(" %u", pixel[p]);
1102 }
1103
1104 static void
print_components_float(const float * pixel,unsigned components)1105 print_components_float(const float *pixel, unsigned components)
1106 {
1107 int p;
1108 for (p = 0; p < components; ++p)
1109 printf(" %f", pixel[p]);
1110 }
1111
1112 static void
print_bad_pixel_ubyte(int x,int y,int num_components,const GLubyte * expected,const GLubyte * observed)1113 print_bad_pixel_ubyte(int x, int y, int num_components,
1114 const GLubyte *expected, const GLubyte *observed)
1115 {
1116 printf("Probe color at (%i,%i)\n", x, y);
1117 printf(" Expected:");
1118 print_components_ubyte(expected, num_components);
1119 printf("\n Observed:");
1120 print_components_ubyte(observed, num_components);
1121 printf("\n");
1122 }
1123
1124 static void
print_bad_pixel_float(int x,int y,int num_components,const float * expected,const float * observed)1125 print_bad_pixel_float(int x, int y, int num_components,
1126 const float *expected, const float *observed)
1127 {
1128 printf("Probe color at (%i,%i)\n", x, y);
1129 printf(" Expected:");
1130 print_components_float(expected, num_components);
1131 printf("\n Observed:");
1132 print_components_float(observed, num_components);
1133 printf("\n");
1134 }
1135
1136 static bool
compare_pixels_ubyte(const GLubyte * color1,const GLubyte * color2,const GLubyte * tolerance,int components)1137 compare_pixels_ubyte(const GLubyte *color1, const GLubyte *color2,
1138 const GLubyte *tolerance, int components)
1139 {
1140 for (int p = 0; p < components; ++p)
1141 if (abs((int)color1[p] - (int)color2[p]) > tolerance[p])
1142 return false;
1143 return true;
1144 }
1145
1146 static bool
compare_pixels_float(const float * color1,const float * color2,const float * tolerance,int components)1147 compare_pixels_float(const float *color1, const float *color2,
1148 const float *tolerance, int components)
1149 {
1150 for (int p = 0; p < components; ++p)
1151 if (fabsf(color1[p] - color2[p]) > tolerance[p])
1152 return false;
1153 return true;
1154 }
1155
1156 int
piglit_probe_pixel_rgb_silent(int x,int y,const float * expected,float * out_probe)1157 piglit_probe_pixel_rgb_silent(int x, int y, const float* expected, float *out_probe)
1158 {
1159 GLfloat probe[3];
1160
1161 read_pixels_float(x, y, 1, 1, GL_RGB, probe);
1162
1163 bool pass =
1164 compare_pixels_float(probe, expected, piglit_tolerance, 3);
1165
1166 if (out_probe)
1167 memcpy(out_probe, probe, sizeof(probe));
1168
1169 return pass;
1170 }
1171
1172 int
piglit_probe_pixel_rgba_silent(int x,int y,const float * expected,float * out_probe)1173 piglit_probe_pixel_rgba_silent(int x, int y, const float* expected, float *out_probe)
1174 {
1175 GLfloat probe[4];
1176
1177 read_pixels_float(x, y, 1, 1, GL_RGBA, probe);
1178
1179 bool pass =
1180 compare_pixels_float(probe, expected, piglit_tolerance, 4);
1181
1182 if (out_probe)
1183 memcpy(out_probe, probe, sizeof(probe));
1184
1185 return pass;
1186 }
1187
1188 /**
1189 * Read a pixel from the given location and compare its RGB value to the
1190 * given expected values.
1191 *
1192 * Print a log message if the color value deviates from the expected value.
1193 * \return true if the color values match, false otherwise
1194 */
1195 int
piglit_probe_pixel_rgb(int x,int y,const float * expected)1196 piglit_probe_pixel_rgb(int x, int y, const float* expected)
1197 {
1198 GLfloat probe[3];
1199
1200 read_pixels_float(x, y, 1, 1, GL_RGB, probe);
1201
1202 if (compare_pixels_float(probe, expected, piglit_tolerance, 3))
1203 return 1;
1204
1205 print_bad_pixel_float(x, y, 3, expected, probe);
1206
1207 return 0;
1208 }
1209
1210 /**
1211 * Read a pixel from the given location and compare its RGBA value to the
1212 * given expected values.
1213 *
1214 * Print a log message if the color value deviates from the expected value.
1215 * \return true if the color values match, false otherwise
1216 */
1217 int
piglit_probe_pixel_rgba(int x,int y,const float * expected)1218 piglit_probe_pixel_rgba(int x, int y, const float* expected)
1219 {
1220 GLfloat probe[4];
1221
1222 read_pixels_float(x, y, 1, 1, GL_RGBA, probe);
1223
1224 if (compare_pixels_float(probe, expected, piglit_tolerance, 4))
1225 return 1;
1226
1227 print_bad_pixel_float(x, y, 4, expected, probe);
1228
1229 return 0;
1230 }
1231
1232 static void
array_float_to_ubyte(int n,const float * f,GLubyte * b)1233 array_float_to_ubyte(int n, const float *f, GLubyte *b)
1234 {
1235 int i;
1236
1237 for (i = 0; i < n; i++)
1238 b[i] = f[i] * 255;
1239 }
1240
1241 static void
array_float_to_ubyte_roundup(int n,const float * f,GLubyte * b)1242 array_float_to_ubyte_roundup(int n, const float *f, GLubyte *b)
1243 {
1244 int i;
1245
1246 for (i = 0; i < n; i++)
1247 b[i] = ceil(f[i] * 255);
1248 }
1249
1250 static bool
probe_rect_ubyte(int x,int y,int w,int h,int num_components,const float * fexpected,size_t x_pitch,size_t y_pitch,bool silent)1251 probe_rect_ubyte(int x, int y, int w, int h, int num_components,
1252 const float *fexpected, size_t x_pitch, size_t y_pitch,
1253 bool silent)
1254 {
1255 int i, j;
1256 GLubyte *probe;
1257 GLubyte *pixels;
1258 GLubyte tolerance[4];
1259 GLubyte expected[4];
1260
1261 array_float_to_ubyte_roundup(num_components, piglit_tolerance,
1262 tolerance);
1263 if (x_pitch == 0 && y_pitch == 0)
1264 array_float_to_ubyte(num_components, fexpected, expected);
1265
1266 /* RGBA readbacks are likely to be faster */
1267 pixels = malloc(w*h*4);
1268 glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1269
1270 for (j = 0; j < h; j++) {
1271 for (i = 0; i < w; i++) {
1272 probe = &pixels[(j*w+i)*4];
1273
1274 if (x_pitch != 0 || y_pitch != 0) {
1275 const float *pexp = fexpected + i * x_pitch +
1276 j * y_pitch;
1277 array_float_to_ubyte(num_components,
1278 pexp, expected);
1279 }
1280
1281 if (compare_pixels_ubyte(probe, expected, tolerance,
1282 num_components))
1283 continue;
1284
1285 if (!silent) {
1286 print_bad_pixel_ubyte(
1287 x + i, y + j, num_components,
1288 expected, probe);
1289 }
1290 free(pixels);
1291 return false;
1292 }
1293 }
1294
1295 free(pixels);
1296 return true;
1297 }
1298
1299 static bool
probe_rect_float(int x,int y,int w,int h,int num_components,const float * fexpected,size_t x_pitch,size_t y_pitch,bool silent)1300 probe_rect_float(int x, int y, int w, int h, int num_components,
1301 const float *fexpected, size_t x_pitch, size_t y_pitch,
1302 bool silent)
1303 {
1304 float *pixels = read_pixels_float(x, y, w, h, GL_RGBA, NULL);
1305
1306 for (int j = 0; j < h; j++) {
1307 for (int i = 0; i < w; i++) {
1308 float *probe = &pixels[(j*w+i)*4];
1309 const float *pexp = fexpected + i * x_pitch +
1310 j * y_pitch;
1311
1312 if (compare_pixels_float(probe, pexp,
1313 piglit_tolerance,
1314 num_components))
1315 continue;
1316
1317 if (!silent) {
1318 print_bad_pixel_float(x + i, y + j,
1319 num_components,
1320 fexpected, probe);
1321 }
1322 free(pixels);
1323 return false;
1324 }
1325 }
1326
1327 free(pixels);
1328 return true;
1329 }
1330
1331 static bool
probe_rect(int x,int y,int w,int h,int num_components,const float * fexpected,size_t x_pitch,size_t y_pitch,bool silent)1332 probe_rect(int x, int y, int w, int h, int num_components,
1333 const float *fexpected, size_t x_pitch, size_t y_pitch,
1334 bool silent)
1335 {
1336 if (can_probe_ubyte()) {
1337 return probe_rect_ubyte(x, y, w, h, num_components, fexpected,
1338 x_pitch, y_pitch, silent);
1339 } else {
1340 return probe_rect_float(x, y, w, h, num_components, fexpected,
1341 x_pitch, y_pitch, silent);
1342 }
1343 }
1344
1345
1346 int
piglit_probe_rect_rgb_silent(int x,int y,int w,int h,const float * expected)1347 piglit_probe_rect_rgb_silent(int x, int y, int w, int h, const float *expected)
1348 {
1349 return probe_rect(x, y, w, h, 3, expected, 0, 0, true);
1350 }
1351
1352 /* More efficient variant if you don't know need floats and GBA channels. */
1353 int
piglit_probe_rect_r_ubyte(int x,int y,int w,int h,GLubyte expected)1354 piglit_probe_rect_r_ubyte(int x, int y, int w, int h, GLubyte expected)
1355 {
1356 int i, j, w_aligned;
1357 GLubyte *pixels;
1358 GLubyte tolerance = ceil(piglit_tolerance[0] * 255);
1359
1360 w_aligned = ALIGN(w, 4);
1361 pixels = malloc(w_aligned * h);
1362
1363 glReadPixels(x, y, w, h, GL_RED, GL_UNSIGNED_BYTE, pixels);
1364
1365 for (j = 0; j < h; j++) {
1366 for (i = 0; i < w; i++) {
1367 GLubyte probe = pixels[j*w_aligned+i];
1368
1369 if (abs((int)probe - (int)expected) >= tolerance) {
1370 print_bad_pixel_ubyte(x + i, y + j, 1,
1371 &expected, &probe);
1372
1373 free(pixels);
1374 return 0;
1375 }
1376 }
1377 }
1378
1379 free(pixels);
1380 return 1;
1381 }
1382
1383 int
piglit_probe_rect_rgb(int x,int y,int w,int h,const float * expected)1384 piglit_probe_rect_rgb(int x, int y, int w, int h, const float *expected)
1385 {
1386 return probe_rect(x, y, w, h, 3, expected, 0, 0, false);
1387 }
1388
1389 int
piglit_probe_rects_equal(int x1,int y1,int x2,int y2,int w,int h,GLenum format)1390 piglit_probe_rects_equal(int x1, int y1, int x2, int y2,
1391 int w, int h, GLenum format)
1392 {
1393 int retval;
1394 int ncomponents;
1395
1396 /* Allocate buffer large enough for two rectangles */
1397 ncomponents = piglit_num_components(format);
1398
1399 /* Load the pixels into the buffer and compare */
1400 /* We only need to do one glReadPixels if the images are adjacent */
1401 if ((x1 + w) == x2 && y1 == y2) {
1402 float *pixels =
1403 read_pixels_float(x1, y1, 2 * w, h, format, NULL);
1404 retval = piglit_compare_image_halves_color(2*w, h,
1405 ncomponents,
1406 piglit_tolerance,
1407 pixels);
1408 free(pixels);
1409 } else {
1410 float *pixels1 =
1411 read_pixels_float(x1, y1, w, h, format, NULL);
1412 float *pixels2 =
1413 read_pixels_float(x2, y2, w, h, format, NULL);
1414 retval = piglit_compare_images_color(0, 0, w, h,
1415 ncomponents,
1416 piglit_tolerance,
1417 pixels1, pixels2);
1418 free(pixels1);
1419 free(pixels2);
1420 }
1421
1422 return retval;
1423 }
1424
1425 int
piglit_probe_rect_halves_equal_rgba(int x,int y,int w,int h)1426 piglit_probe_rect_halves_equal_rgba(int x, int y, int w, int h)
1427 {
1428 int i, j, p;
1429 GLfloat probe1[4];
1430 GLfloat probe2[4];
1431 GLubyte *pixels = malloc(w*h*4*sizeof(GLubyte));
1432
1433 glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1434
1435 for (j = 0; j < h; j++) {
1436 for (i = 0; i < w / 2; i++) {
1437 GLubyte *pixel1 = &pixels[4 * (j * w + i)];
1438 GLubyte *pixel2 = &pixels[4 * (j * w + w / 2 + i)];
1439
1440 for (p = 0; p < 4; ++p) {
1441 probe1[p] = pixel1[p] / 255.0f;
1442 probe2[p] = pixel2[p] / 255.0f;
1443 }
1444
1445 if (compare_pixels_float(probe1, probe2,
1446 piglit_tolerance, 4))
1447 continue;
1448
1449 printf("Probe color at (%i,%i)\n", x+i, x+j);
1450 printf(" Left: %f %f %f %f\n",
1451 probe1[0], probe1[1], probe1[2], probe1[3]);
1452 printf(" Right: %f %f %f %f\n",
1453 probe2[0], probe2[1], probe2[2], probe2[3]);
1454
1455 free(pixels);
1456 return 0;
1457 }
1458 }
1459
1460 free(pixels);
1461 return 1;
1462 }
1463
1464 int
piglit_probe_rect_rgba(int x,int y,int w,int h,const float * expected)1465 piglit_probe_rect_rgba(int x, int y, int w, int h, const float *expected)
1466 {
1467 return probe_rect(x, y, w, h, 4, expected, 0, 0, false);
1468 }
1469
piglit_probe_rect_rgba_varying(int x,int y,int w,int h,const float * expected,size_t stride)1470 int piglit_probe_rect_rgba_varying(int x, int y, int w, int h,
1471 const float* expected, size_t stride)
1472 {
1473 assert(stride % sizeof(float) == 0);
1474 return probe_rect(x, y, w, h, 4, expected,
1475 4, stride / sizeof(float), false);
1476 }
1477
1478 int
piglit_probe_rect_rgba_int(int x,int y,int w,int h,const int * expected)1479 piglit_probe_rect_rgba_int(int x, int y, int w, int h, const int *expected)
1480 {
1481 int i, j, p;
1482 GLint *probe;
1483 GLint *pixels = malloc(w*h*4*sizeof(int));
1484
1485 glReadPixels(x, y, w, h, GL_RGBA_INTEGER, GL_INT, pixels);
1486
1487 for (j = 0; j < h; j++) {
1488 for (i = 0; i < w; i++) {
1489 probe = &pixels[(j*w+i)*4];
1490
1491 for (p = 0; p < 4; ++p) {
1492 if (probe[p] != expected[p]) {
1493 printf("Probe color at (%d,%d)\n", x+i, y+j);
1494 printf(" Expected: %d %d %d %d\n",
1495 expected[0], expected[1], expected[2], expected[3]);
1496 printf(" Observed: %d %d %d %d\n",
1497 probe[0], probe[1], probe[2], probe[3]);
1498
1499 free(pixels);
1500 return 0;
1501 }
1502 }
1503 }
1504 }
1505
1506 free(pixels);
1507 return 1;
1508 }
1509
1510 int
piglit_probe_rect_rgba_uint(int x,int y,int w,int h,const unsigned int * expected)1511 piglit_probe_rect_rgba_uint(int x, int y, int w, int h,
1512 const unsigned int *expected)
1513 {
1514 int i, j, p;
1515 GLuint *probe;
1516 GLuint *pixels = malloc(w*h*4*sizeof(unsigned int));
1517
1518 glReadPixels(x, y, w, h, GL_RGBA_INTEGER, GL_UNSIGNED_INT, pixels);
1519
1520 for (j = 0; j < h; j++) {
1521 for (i = 0; i < w; i++) {
1522 probe = &pixels[(j*w+i)*4];
1523
1524 for (p = 0; p < 4; ++p) {
1525 if (probe[p] != expected[p]) {
1526 printf("Probe color at (%d,%d)\n", x+i, y+j);
1527 printf(" Expected: %u %u %u %u\n",
1528 expected[0], expected[1], expected[2], expected[3]);
1529 printf(" Observed: %u %u %u %u\n",
1530 probe[0], probe[1], probe[2], probe[3]);
1531
1532 free(pixels);
1533 return 0;
1534 }
1535 }
1536 }
1537 }
1538
1539 free(pixels);
1540 return 1;
1541 }
1542
1543 /**
1544 * Read color data from the given rectangle and compare its RGB value to the
1545 * given two expected values.
1546 *
1547 * Print a log message if the color value deviates from both expected values.
1548 * \return true if the color values match, false otherwise
1549 */
1550 bool
piglit_probe_rect_two_rgb(int x,int y,int w,int h,const float * expected1,const float * expected2)1551 piglit_probe_rect_two_rgb(int x, int y, int w, int h,
1552 const float *expected1, const float *expected2)
1553 {
1554 /* RGBA readbacks are likely to be faster */
1555 float *pixels = read_pixels_float(x, y, w, h, GL_RGBA, NULL);
1556
1557 for (int j = 0; j < h; j++) {
1558 for (int i = 0; i < w; i++) {
1559 float *probe = &pixels[(j * w + i) * 4];
1560
1561 if (compare_pixels_float(probe, expected1,
1562 piglit_tolerance, 3) ||
1563 compare_pixels_float(probe, expected2,
1564 piglit_tolerance, 3))
1565 continue;
1566
1567 printf("Probe color at (%i,%i)\n", x + i, y + j);
1568 printf(" Expected either:");
1569 print_components_float(expected1, 3);
1570 printf("\n or:");
1571 print_components_float(expected2, 3);
1572 printf("\n Observed:");
1573 print_components_float(probe, 3);
1574 printf("\n");
1575
1576 free(pixels);
1577 return false;
1578 }
1579 }
1580
1581 free(pixels);
1582 return true;
1583 }
1584
1585 /**
1586 * Compute the appropriate tolerance for comparing images of the given
1587 * base format.
1588 */
1589 void
piglit_compute_probe_tolerance(GLenum format,float * tolerance)1590 piglit_compute_probe_tolerance(GLenum format, float *tolerance)
1591 {
1592 int num_components, component;
1593 switch (format) {
1594 case GL_LUMINANCE_ALPHA:
1595 tolerance[0] = piglit_tolerance[0];
1596 tolerance[1] = piglit_tolerance[3];
1597 break;
1598 case GL_ALPHA:
1599 tolerance[0] = piglit_tolerance[3];
1600 break;
1601 default:
1602 num_components = piglit_num_components(format);
1603 for (component = 0; component < num_components; ++component)
1604 tolerance[component] = piglit_tolerance[component];
1605 break;
1606 }
1607 }
1608
1609 int
piglit_compare_pixels(int x,int y,const float * expected,const float * probe,const float * tolerance,int num_components)1610 piglit_compare_pixels(int x, int y, const float *expected, const float *probe,
1611 const float *tolerance, int num_components)
1612 {
1613 if (compare_pixels_float(probe, expected, tolerance, num_components))
1614 return 1;
1615
1616 printf("Probe at (%i,%i)\n", x, y);
1617 printf(" Expected:");
1618 print_components_float(expected, num_components);
1619 printf("\n Observed:");
1620 print_components_float(probe, num_components);
1621 printf("\n");
1622
1623 return 0;
1624 }
1625
1626 int
piglit_compare_image_halves_color(int w,int h,int num_components,const float * tolerance,const float * image)1627 piglit_compare_image_halves_color(int w, int h, int num_components,
1628 const float *tolerance,
1629 const float *image)
1630 {
1631 int i, j, half_width;
1632
1633 half_width = w/2;
1634 for (j = 0; j < h; j++) {
1635 for (i = 0; i < half_width; i++) {
1636 const float *probe =
1637 &image[(j*w+i)*num_components];
1638 const float *expected =
1639 &image[(j*w+half_width+i)*num_components];
1640 if (!piglit_compare_pixels(i, j, expected, probe,
1641 tolerance,
1642 num_components))
1643 return 0;
1644 }
1645 }
1646
1647 return 1;
1648 }
1649
1650 /**
1651 * Compare two in-memory floating-point images.
1652 */
1653 int
piglit_compare_images_color(int x,int y,int w,int h,int num_components,const float * tolerance,const float * expected_image,const float * observed_image)1654 piglit_compare_images_color(int x, int y, int w, int h, int num_components,
1655 const float *tolerance,
1656 const float *expected_image,
1657 const float *observed_image)
1658 {
1659 int i, j;
1660 for (j = 0; j < h; j++) {
1661 for (i = 0; i < w; i++) {
1662 const float *expected =
1663 &expected_image[((j + y) * w + i + x) *
1664 num_components];
1665 const float *probe =
1666 &observed_image[((j + y) * w + i + x) *
1667 num_components];
1668
1669 if (compare_pixels_float(probe, expected, tolerance,
1670 num_components))
1671 continue;
1672
1673 printf("Probe at (%i,%i)\n", x+i, y+j);
1674 printf(" Expected:");
1675 print_components_float(expected, num_components);
1676 printf("\n Observed:");
1677 print_components_float(probe, num_components);
1678 printf("\n");
1679
1680 return 0;
1681 }
1682 }
1683
1684 return 1;
1685 }
1686
1687 /**
1688 * Compare the region indicated by x, y, w and h of the current read
1689 * framebuffer with the given in-memory floating-point image of
1690 * dimensions w*h.
1691 */
1692 int
piglit_probe_image_color(int x,int y,int w,int h,GLenum format,const float * image)1693 piglit_probe_image_color(int x, int y, int w, int h, GLenum format,
1694 const float *image)
1695 {
1696 int c = piglit_num_components(format);
1697 GLfloat *pixels;
1698 float tolerance[4];
1699 int result;
1700
1701 piglit_compute_probe_tolerance(format, tolerance);
1702
1703 if (format == GL_INTENSITY) {
1704 /* GL_INTENSITY is not allowed for ReadPixels so
1705 * substitute GL_LUMINANCE.
1706 */
1707 format = GL_LUMINANCE;
1708 }
1709
1710 pixels = read_pixels_float(x, y, w, h, format, NULL);
1711
1712 result = piglit_compare_images_color(0, 0, w, h, c, tolerance, image,
1713 pixels);
1714
1715 free(pixels);
1716 return result;
1717 }
1718
1719 int
piglit_probe_image_rgb(int x,int y,int w,int h,const float * image)1720 piglit_probe_image_rgb(int x, int y, int w, int h, const float *image)
1721 {
1722 return piglit_probe_image_color(x, y, w, h, GL_RGB, image);
1723 }
1724
1725 int
piglit_probe_image_rgba(int x,int y,int w,int h,const float * image)1726 piglit_probe_image_rgba(int x, int y, int w, int h, const float *image)
1727 {
1728 return piglit_probe_image_color(x, y, w, h, GL_RGBA, image);
1729 }
1730
1731 /**
1732 * Compare two in-memory unsigned-byte images.
1733 */
1734 int
piglit_compare_images_ubyte(int x,int y,int w,int h,const GLubyte * expected_image,const GLubyte * observed_image)1735 piglit_compare_images_ubyte(int x, int y, int w, int h,
1736 const GLubyte *expected_image,
1737 const GLubyte *observed_image)
1738 {
1739 int i, j;
1740 for (j = 0; j < h; j++) {
1741 for (i = 0; i < w; i++) {
1742 const GLubyte expected = expected_image[j*w+i];
1743 const GLubyte probe = observed_image[j*w+i];
1744
1745 if (probe != expected) {
1746 printf("Probe at (%i,%i)\n", x+i, y+j);
1747 printf(" Expected: %d\n", expected);
1748 printf(" Observed: %d\n", probe);
1749
1750 return 0;
1751 }
1752 }
1753 }
1754
1755 return 1;
1756 }
1757
1758 /**
1759 * Compare the image (array) stored in \p observed with the image obtained from
1760 * \p expected_original with the box described by ux,uy,uz and uw,uh,ud
1761 * replaced by \p expected_updated.
1762 *
1763 * Only the highest \p bits bits of all four channels are compared.
1764 */
1765 int
piglit_equal_images_update_rgba8(const GLubyte * expected_original,const GLubyte * expected_updated,const GLubyte * observed,unsigned w,unsigned h,unsigned d,unsigned ux,unsigned uy,unsigned uz,unsigned uw,unsigned uh,unsigned ud,unsigned bits)1766 piglit_equal_images_update_rgba8(const GLubyte *expected_original,
1767 const GLubyte *expected_updated,
1768 const GLubyte *observed,
1769 unsigned w, unsigned h, unsigned d,
1770 unsigned ux, unsigned uy, unsigned uz,
1771 unsigned uw, unsigned uh, unsigned ud,
1772 unsigned bits)
1773 {
1774 assert(bits > 0 && bits <= 8);
1775
1776 unsigned x, y, z;
1777 const uint8_t compare_mask = 0xff << (8 - bits);
1778
1779 for (z = 0; z < d; ++z) {
1780 for (y = 0; y < h; y++) {
1781 for (x = 0; x < w; x++) {
1782 const GLubyte *ref;
1783
1784 if (x >= ux && x < ux + uw &&
1785 y >= uy && y < uy + uh &&
1786 z >= uz && z < uz + ud)
1787 ref = expected_updated;
1788 else
1789 ref = expected_original;
1790
1791 bool fail =
1792 ((ref[0] ^ observed[0]) |
1793 (ref[1] ^ observed[1]) |
1794 (ref[2] ^ observed[2]) |
1795 (ref[3] ^ observed[3])) &
1796 compare_mask;
1797 if (fail) {
1798 printf("%u,%u,%u: test = %u,%u,%u,%u "
1799 "ref = %u,%u,%u,%u (comparing %u bits)\n",
1800 x, y, z,
1801 observed[0], observed[1],
1802 observed[2], observed[3],
1803 ref[0], ref[1], ref[2], ref[3],
1804 bits);
1805 return 0;
1806 }
1807
1808 observed += 4;
1809 expected_original += 4;
1810 expected_updated += 4;
1811 }
1812 }
1813 }
1814
1815 return 1;
1816 }
1817
1818 /**
1819 * Compare the contents of the current read framebuffer's stencil
1820 * buffer with the given in-memory byte image.
1821 */
1822 int
piglit_probe_image_stencil(int x,int y,int w,int h,const GLubyte * image)1823 piglit_probe_image_stencil(int x, int y, int w, int h,
1824 const GLubyte *image)
1825 {
1826 GLubyte *pixels = malloc(w*h*sizeof(GLubyte));
1827 int result;
1828 GLint old_pack_alignment;
1829
1830 /* Temporarily set pack alignment to 1 so that glReadPixels
1831 * won't put any padding at the end of the row.
1832 */
1833 glGetIntegerv(GL_PACK_ALIGNMENT, &old_pack_alignment);
1834 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1835
1836 glReadPixels(x, y, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, pixels);
1837
1838 glPixelStorei(GL_PACK_ALIGNMENT, old_pack_alignment);
1839
1840 result = piglit_compare_images_ubyte(x, y, w, h, image, pixels);
1841
1842 free(pixels);
1843 return result;
1844 }
1845
1846 int
piglit_probe_image_ubyte(int x,int y,int w,int h,GLenum format,const GLubyte * image)1847 piglit_probe_image_ubyte(int x, int y, int w, int h, GLenum format,
1848 const GLubyte *image)
1849 {
1850 const int c = piglit_num_components(format);
1851 GLubyte *pixels = malloc(w * h * 4 * sizeof(GLubyte));
1852 int i, j;
1853 GLubyte tolerance[4];
1854
1855 array_float_to_ubyte_roundup(4, piglit_tolerance, tolerance);
1856
1857 glReadPixels(x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
1858
1859 for (j = 0; j < h; j++) {
1860 for (i = 0; i < w; i++) {
1861 const GLubyte *expected = &image[(j * w + i) * c];
1862 const GLubyte *probe = &pixels[(j * w + i) * c];
1863
1864 if (compare_pixels_ubyte(probe, expected, tolerance,
1865 c))
1866 continue;
1867
1868 printf("Probe at (%i,%i)\n", x + i, y + j);
1869 printf(" Expected:");
1870 print_components_ubyte(expected, c);
1871 printf("\n Observed:");
1872 print_components_ubyte(probe, c);
1873 printf("\n");
1874
1875 free(pixels);
1876 return 0;
1877 }
1878 }
1879
1880 free(pixels);
1881 return 1;
1882 }
1883
1884 #ifndef PIGLIT_USE_OPENGL
1885 static GLuint
create_fbo_from_texture(GLenum target,GLint texture,GLint level,GLint layer)1886 create_fbo_from_texture(GLenum target, GLint texture, GLint level, GLint layer)
1887 {
1888 GLuint fbo;
1889
1890 glGenFramebuffers(1, &fbo);
1891 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1892
1893 if (layer > 0) {
1894 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1895 texture, level, layer);
1896 } else {
1897 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1898 target, texture, level);
1899 }
1900
1901 assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) ==
1902 GL_FRAMEBUFFER_COMPLETE);
1903 return fbo;
1904 }
1905
1906 static GLenum
binding_from_target(GLenum target)1907 binding_from_target(GLenum target)
1908 {
1909 switch (target) {
1910 case GL_TEXTURE_2D:
1911 return GL_TEXTURE_BINDING_2D;
1912 case GL_TEXTURE_2D_ARRAY:
1913 return GL_TEXTURE_BINDING_2D_ARRAY;
1914 default:
1915 fprintf(stderr, "%s: unsupported target 0x%x\n",
1916 __func__, target);
1917 return 0;
1918 }
1919 }
1920
1921 /**
1922 * Read texels in OpenGL ES compatible way.
1923 *
1924 * Currently bound texture is attached to a framebuffer object and
1925 * contents are read using glReadPixels. Supported targets are
1926 * GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY.
1927 */
1928 static GLfloat *
read_texture_via_fbo(int target,int level,int x,int y,int layer,int w,int h)1929 read_texture_via_fbo(int target, int level, int x, int y, int layer, int w,
1930 int h)
1931 {
1932 GLint width, height, depth;
1933 GLint current_read_fbo, current_draw_fbo, current_texture;
1934 GLenum binding = binding_from_target(target);
1935 unsigned char *buf;
1936 GLfloat *buffer;
1937 unsigned offset;
1938
1939 assert(binding != 0);
1940
1941 glGetIntegerv(binding, ¤t_texture);
1942 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, ¤t_read_fbo);
1943 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_draw_fbo);
1944
1945 assert(target == GL_TEXTURE_2D || target == GL_TEXTURE_2D_ARRAY);
1946
1947 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
1948 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
1949 glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
1950
1951 /* Depth equals 1 in case of GL_TEXTURE_2D, in case of
1952 * GL_TEXTURE_2D_ARRAY we allocate space for many layers.
1953 */
1954 buffer = malloc(width * height * depth * 4 * sizeof(GLfloat));
1955 buf = malloc(width * height * depth * 4 * sizeof(unsigned char));
1956
1957 /* Read all layers. */
1958 for (int i = layer; i >= 0; i--) {
1959 GLuint fbo =
1960 create_fbo_from_texture(target, current_texture, level,
1961 i);
1962 assert(fbo != 0);
1963
1964 /* Offset to the layer we are expected to read. Note, in case
1965 * of GL_TEXTURE_2D, offset will be always 0 as i equals 0.
1966 */
1967 offset = i * (width * height * 4);
1968 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
1969 buf + offset);
1970
1971 glDeleteFramebuffers(1, &fbo);
1972 }
1973
1974 /* Convert the result, callers expect floating point. */
1975 for (unsigned k = 0; k < (layer + 1) * width * height * 4; k++)
1976 buffer[k] = ((float) buf[k]) / 255.0;
1977
1978 free(buf);
1979
1980 /* Restore FBO state. */
1981 glBindFramebuffer(GL_READ_FRAMEBUFFER, current_read_fbo);
1982 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_draw_fbo);
1983
1984 return buffer;
1985 }
1986 #endif
1987
1988
1989 /**
1990 * Read a texel rectangle from the given location and compare its RGB value to
1991 * the given expected values.
1992 *
1993 * Print a log message if the color value deviates from the expected value.
1994 * \return true if the color values match, false otherwise
1995 */
piglit_probe_texel_rect_rgb(int target,int level,int x,int y,int w,int h,const float * expected)1996 int piglit_probe_texel_rect_rgb(int target, int level, int x, int y,
1997 int w, int h, const float* expected)
1998 {
1999 GLfloat *buffer;
2000 GLfloat *probe;
2001 int i, j;
2002 GLint width;
2003 GLint height;
2004
2005 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
2006 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
2007 buffer = malloc(width * height * 3 * sizeof(GLfloat));
2008
2009 glGetTexImage(target, level, GL_RGB, GL_FLOAT, buffer);
2010
2011 assert(x >= 0);
2012 assert(y >= 0);
2013 assert(x+w <= width);
2014 assert(y+h <= height);
2015
2016 for (j = y; j < y+h; ++j) {
2017 for (i = x; i < x+w; ++i) {
2018 probe = &buffer[(j * width + i) * 3];
2019
2020 if (compare_pixels_float(probe, expected,
2021 piglit_tolerance, 3))
2022 continue;
2023
2024 free(buffer);
2025 return 0;
2026 }
2027 }
2028
2029 free(buffer);
2030 return 1;
2031 }
2032
2033 /**
2034 * Read a texel from the given location and compare its RGB value to the
2035 * given expected values.
2036 *
2037 * Print a log message if the color value deviates from the expected value.
2038 * \return true if the color values match, false otherwise
2039 */
piglit_probe_texel_rgb(int target,int level,int x,int y,const float * expected)2040 int piglit_probe_texel_rgb(int target, int level, int x, int y,
2041 const float *expected)
2042 {
2043 return piglit_probe_texel_rect_rgb(target, level, x, y, 1, 1, expected);
2044 }
2045
2046 /**
2047 * Read a texel rectangle from the given location and compare its RGBA value to
2048 * the given expected values.
2049 *
2050 * Print a log message if the color value deviates from the expected value.
2051 * \return true if the color values match, false otherwise
2052 */
piglit_probe_texel_rect_rgba(int target,int level,int x,int y,int w,int h,const float * expected)2053 int piglit_probe_texel_rect_rgba(int target, int level, int x, int y,
2054 int w, int h, const float* expected)
2055 {
2056 GLfloat *buffer;
2057 GLfloat *probe;
2058 int i, j;
2059 GLint width;
2060 GLint height;
2061
2062 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
2063 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
2064
2065 #ifndef PIGLIT_USE_OPENGL
2066 if (target == GL_TEXTURE_2D) {
2067 buffer = read_texture_via_fbo(target, level, x, y, 0, w, h);
2068 } else {
2069 #else
2070 buffer = malloc(width * height * 4 * sizeof(GLfloat));
2071 glGetTexImage(target, level, GL_RGBA, GL_FLOAT, buffer);
2072 #endif
2073 #ifndef PIGLIT_USE_OPENGL
2074 }
2075 #endif
2076 assert(x >= 0);
2077 assert(y >= 0);
2078 assert(x+w <= width);
2079 assert(y+h <= height);
2080
2081 for (j = y; j < y+h; ++j) {
2082 for (i = x; i < x+w; ++i) {
2083 probe = &buffer[(j * width + i) * 4];
2084
2085 if (compare_pixels_float(probe, expected,
2086 piglit_tolerance, 4))
2087 continue;
2088
2089 print_bad_pixel_float(i, j, 4,
2090 expected,
2091 probe);
2092
2093 free(buffer);
2094 return 0;
2095 }
2096 }
2097
2098 free(buffer);
2099 return 1;
2100 }
2101
2102 /**
2103 * Read a texel from the given location and compare its RGBA value to the
2104 * given expected values.
2105 *
2106 * Print a log message if the color value deviates from the expected value.
2107 * \return true if the color values match, false otherwise
2108 */
piglit_probe_texel_rgba(int target,int level,int x,int y,const float * expected)2109 int piglit_probe_texel_rgba(int target, int level, int x, int y,
2110 const float* expected)
2111 {
2112 return piglit_probe_texel_rect_rgba(target, level, x, y, 1, 1,
2113 expected);
2114 }
2115
2116 /**
2117 * Read a texel rectangle from the given location and compare its RGBA value to
2118 * the given expected values.
2119 *
2120 * Print a log message if the color value deviates from the expected value.
2121 * \return true if the color values match, false otherwise
2122 */
piglit_probe_texel_volume_rgba(int target,int level,int x,int y,int z,int w,int h,int d,const float * expected)2123 int piglit_probe_texel_volume_rgba(int target, int level, int x, int y, int z,
2124 int w, int h, int d, const float* expected)
2125 {
2126 GLfloat *buffer;
2127 GLfloat *probe;
2128 int i, j, k;
2129 GLint width;
2130 GLint height;
2131 GLint depth;
2132
2133 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
2134 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
2135 glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
2136
2137 #ifndef PIGLIT_USE_OPENGL
2138 if (target == GL_TEXTURE_2D_ARRAY) {
2139 buffer = read_texture_via_fbo(target, level, x, y, z, w, h);
2140 } else {
2141 #else
2142 buffer = malloc(width * height * depth * 4 * sizeof(GLfloat));
2143 glGetTexImage(target, level, GL_RGBA, GL_FLOAT, buffer);
2144 #endif
2145 #ifndef PIGLIT_USE_OPENGL
2146 }
2147 #endif
2148 assert(x >= 0);
2149 assert(y >= 0);
2150 assert(d >= 0);
2151 assert(x+w <= width);
2152 assert(y+h <= height);
2153 assert(z+d <= depth);
2154
2155 for (k = z; k < z+d; ++k) {
2156 for (j = y; j < y+h; ++j) {
2157 for (i = x; i < x+w; ++i) {
2158 probe = &buffer[(k * width * height + j * width + i) * 4];
2159
2160 if (compare_pixels_float(probe, expected,
2161 piglit_tolerance, 4))
2162 continue;
2163
2164 printf("Probe color at (%i,%i,%i)\n",
2165 i, j, k);
2166 printf(" Expected: ");
2167 print_components_float(expected, 4);
2168 printf("\n Observed: ");
2169 print_components_float(probe, 4);
2170 printf("\n");
2171
2172 free(buffer);
2173 return 0;
2174 }
2175 }
2176 }
2177
2178 free(buffer);
2179 return 1;
2180 }
2181
2182 /**
2183 * Read a pixel from the given location and compare its depth value to the
2184 * given expected value.
2185 *
2186 * Print a log message if the depth value deviates from the expected value.
2187 * \return true if the depth value matches, false otherwise
2188 */
piglit_probe_pixel_depth(int x,int y,float expected)2189 int piglit_probe_pixel_depth(int x, int y, float expected)
2190 {
2191 GLfloat probe;
2192 GLfloat delta;
2193
2194 glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &probe);
2195
2196 delta = probe - expected;
2197 if (fabs(delta) < 0.01)
2198 return 1;
2199
2200 printf("Probe depth at (%i,%i)\n", x, y);
2201 printf(" Expected: %f\n", expected);
2202 printf(" Observed: %f\n", probe);
2203
2204 return 0;
2205 }
2206
piglit_probe_rect_depth(int x,int y,int w,int h,float expected)2207 int piglit_probe_rect_depth(int x, int y, int w, int h, float expected)
2208 {
2209 int i, j;
2210 GLfloat *probe;
2211 GLfloat *pixels = malloc(w*h*sizeof(float));
2212
2213 glReadPixels(x, y, w, h, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);
2214
2215 for (j = 0; j < h; j++) {
2216 for (i = 0; i < w; i++) {
2217 probe = &pixels[j*w+i];
2218
2219 if (fabs(*probe - expected) >= 0.01) {
2220 printf("Probe depth at (%i,%i)\n", x+i, y+j);
2221 printf(" Expected: %f\n", expected);
2222 printf(" Observed: %f\n", *probe);
2223
2224 free(pixels);
2225 return 0;
2226 }
2227 }
2228 }
2229
2230 free(pixels);
2231 return 1;
2232 }
2233
piglit_probe_pixel_stencil(int x,int y,unsigned expected)2234 int piglit_probe_pixel_stencil(int x, int y, unsigned expected)
2235 {
2236 GLuint probe;
2237 glReadPixels(x, y, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT, &probe);
2238
2239 if (probe == expected)
2240 return 1;
2241
2242 printf("Probe stencil at (%i, %i)\n", x, y);
2243 printf(" Expected: %u\n", expected);
2244 printf(" Observed: %u\n", probe);
2245
2246 return 0;
2247 }
2248
piglit_probe_rect_stencil(int x,int y,int w,int h,unsigned expected)2249 int piglit_probe_rect_stencil(int x, int y, int w, int h, unsigned expected)
2250 {
2251 int i, j;
2252 GLuint *pixels = malloc(w*h*sizeof(GLuint));
2253
2254 glReadPixels(x, y, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_INT, pixels);
2255
2256 for (j = 0; j < h; j++) {
2257 for (i = 0; i < w; i++) {
2258 GLuint probe = pixels[j * w + i];
2259 if (probe != expected) {
2260 printf("Probe stencil at (%i, %i)\n", x + i, y + j);
2261 printf(" Expected: %u\n", expected);
2262 printf(" Observed: %u\n", probe);
2263 free(pixels);
2264 return 0;
2265 }
2266 }
2267 }
2268
2269 free(pixels);
2270 return 1;
2271 }
2272
piglit_probe_buffer(GLuint buf,GLenum target,const char * label,unsigned n,unsigned num_components,const float * expected)2273 bool piglit_probe_buffer(GLuint buf, GLenum target, const char *label,
2274 unsigned n, unsigned num_components,
2275 const float *expected)
2276 {
2277 float *ptr;
2278 unsigned i;
2279 bool status = true;
2280
2281 glBindBuffer(target, buf);
2282 ptr = glMapBuffer(target, GL_READ_ONLY);
2283
2284 for (i = 0; i < n * num_components; i++) {
2285 if (fabs(ptr[i] - expected[i % num_components]) > 0.01) {
2286 printf("%s[%i]: %f, Expected: %f\n", label, i, ptr[i],
2287 expected[i % num_components]);
2288 status = false;
2289 }
2290 }
2291
2292 glUnmapBuffer(target);
2293
2294 return status;
2295 }
2296
piglit_probe_buffer_doubles(GLuint buf,GLenum target,const char * label,unsigned n,unsigned num_components,const double * expected)2297 bool piglit_probe_buffer_doubles(GLuint buf, GLenum target, const char *label,
2298 unsigned n, unsigned num_components,
2299 const double *expected)
2300 {
2301 double *ptr;
2302 unsigned i;
2303 bool status = true;
2304
2305 glBindBuffer(target, buf);
2306 ptr = glMapBuffer(target, GL_READ_ONLY);
2307
2308 for (i = 0; i < n * num_components; i++) {
2309 if (fabs(ptr[i] - expected[i % num_components]) > 0.01) {
2310 printf("%s[%i]: %f, Expected: %f\n", label, i, ptr[i],
2311 expected[i % num_components]);
2312 status = false;
2313 }
2314 }
2315
2316 glUnmapBuffer(target);
2317
2318 return status;
2319 }
2320
piglit_use_fragment_program(void)2321 int piglit_use_fragment_program(void)
2322 {
2323 return piglit_is_extension_supported("GL_ARB_fragment_program");
2324 }
2325
piglit_require_fragment_program(void)2326 void piglit_require_fragment_program(void)
2327 {
2328 if (!piglit_use_fragment_program()) {
2329 printf("GL_ARB_fragment_program not supported.\n");
2330 piglit_report_result(PIGLIT_SKIP);
2331 }
2332 }
2333
piglit_use_vertex_program(void)2334 int piglit_use_vertex_program(void)
2335 {
2336 return piglit_is_extension_supported("GL_ARB_vertex_program");
2337 }
2338
piglit_require_vertex_program(void)2339 void piglit_require_vertex_program(void)
2340 {
2341 if (!piglit_use_vertex_program()) {
2342 printf("GL_ARB_vertex_program not supported.\n");
2343 piglit_report_result(PIGLIT_SKIP);
2344 }
2345 }
2346
piglit_compile_program(GLenum target,const char * text)2347 GLuint piglit_compile_program(GLenum target, const char* text)
2348 {
2349 GLuint program;
2350 GLint errorPos;
2351
2352 glGenProgramsARB(1, &program);
2353 glBindProgramARB(target, program);
2354 glProgramStringARB(
2355 target,
2356 GL_PROGRAM_FORMAT_ASCII_ARB,
2357 strlen(text),
2358 (const GLubyte *)text);
2359 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
2360 if (glGetError() != GL_NO_ERROR || errorPos != -1) {
2361 int l = piglit_find_line(text, errorPos);
2362 int a;
2363
2364 fprintf(stderr, "Compiler Error (pos=%d line=%d): %s\n",
2365 errorPos, l,
2366 (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
2367
2368 for (a=-10; a<10; a++)
2369 {
2370 if (errorPos+a < 0)
2371 continue;
2372 if (errorPos+a >= strlen(text))
2373 break;
2374 fprintf(stderr, "%c", text[errorPos+a]);
2375 }
2376 fprintf(stderr, "\nin program:\n%s", text);
2377 piglit_report_result(PIGLIT_FAIL);
2378 }
2379 if (!glIsProgramARB(program)) {
2380 fprintf(stderr, "glIsProgramARB failed\n");
2381 piglit_report_result(PIGLIT_FAIL);
2382 }
2383
2384 return program;
2385 }
2386
2387 /**
2388 * Convenience function to draw a triangle.
2389 */
2390 GLvoid
piglit_draw_triangle(float x1,float y1,float x2,float y2,float x3,float y3)2391 piglit_draw_triangle(float x1, float y1, float x2, float y2,
2392 float x3, float y3)
2393 {
2394 piglit_draw_triangle_z(0.0, x1, y1, x2, y2, x3, y3);
2395 }
2396
2397 /**
2398 * Convenience function to draw a triangle at a given depth.
2399 */
2400 GLvoid
piglit_draw_triangle_z(float z,float x1,float y1,float x2,float y2,float x3,float y3)2401 piglit_draw_triangle_z(float z, float x1, float y1, float x2, float y2,
2402 float x3, float y3)
2403 {
2404 float verts[3][4];
2405
2406 verts[0][0] = x1;
2407 verts[0][1] = y1;
2408 verts[0][2] = z;
2409 verts[0][3] = 1.0;
2410 verts[1][0] = x2;
2411 verts[1][1] = y2;
2412 verts[1][2] = z;
2413 verts[1][3] = 1.0;
2414 verts[2][0] = x3;
2415 verts[2][1] = y3;
2416 verts[2][2] = z;
2417 verts[2][3] = 1.0;
2418
2419 glVertexPointer(4, GL_FLOAT, 0, verts);
2420 glEnableClientState(GL_VERTEX_ARRAY);
2421
2422 glDrawArrays(GL_TRIANGLES, 0, 3);
2423
2424 glDisableClientState(GL_VERTEX_ARRAY);
2425 }
2426
2427 /**
2428 * Generate an extended checkerboard texture where the color of each quadrant
2429 * in a 2x2 block of tiles can be specified individually.
2430 *
2431 * \param tex Name of the texture to be used. If \c tex is
2432 * zero, a new texture name will be generated.
2433 * \param level Mipmap level the checkerboard should be written to
2434 * \param width Width of the texture image
2435 * \param height Height of the texture image
2436 * \param horiz_square_size Size of each checkerboard tile along the X axis
2437 * \param vert_square_size Size of each checkerboard tile along the Y axis
2438 * \param bl RGBA color to be used for "bottom-left" tiles
2439 * \param br RGBA color to be used for "bottom-right" tiles
2440 * \param tl RGBA color to be used for "top-left" tiles
2441 * \param tr RGBA color to be used for "top-right" tiles
2442 *
2443 * The texture data is written to LOD \c level of the texture \c tex.
2444 *
2445 * If \c tex is zero, a new texture created. This texture will have several
2446 * texture parameters set to non-default values:
2447 *
2448 * - Min and mag filter will be set to \c GL_NEAREST.
2449 * - For GL:
2450 * - S and T wrap modes will be set to \c GL_CLAMP_TO_BORDER.
2451 * - Border color will be set to { 1.0, 0.0, 0.0, 1.0 }.
2452 * - For GLES:
2453 * - S and T wrap modes will be set to \c GL_CLAMP_TO_EDGE.
2454 *
2455 * \return
2456 * Name of the texture. In addition, this texture will be bound to the
2457 * \c GL_TEXTURE_2D target of the currently active texture unit.
2458 */
2459 GLuint
piglit_quads_texture(GLuint tex,unsigned level,unsigned width,unsigned height,unsigned horiz_square_size,unsigned vert_square_size,const float * bl,const float * br,const float * tl,const float * tr)2460 piglit_quads_texture(GLuint tex, unsigned level,
2461 unsigned width, unsigned height,
2462 unsigned horiz_square_size,
2463 unsigned vert_square_size,
2464 const float *bl, const float *br,
2465 const float *tl, const float *tr)
2466 {
2467 static const GLfloat border_color[4] = { 1.0, 0.0, 0.0, 1.0 };
2468 unsigned i;
2469 unsigned j;
2470 void *tex_data;
2471 char *texel;
2472 unsigned pixel_size;
2473 GLubyte bl_b[4], br_b[4], tl_b[4], tr_b[4];
2474 const void *bl_data, *br_data, *tl_data, *tr_data;
2475
2476 if (piglit_is_gles()) {
2477 pixel_size = 4 * sizeof(GLubyte);
2478 for (i = 0; i < 4; i++) {
2479 bl_b[i] = bl[i] * 255;
2480 br_b[i] = br[i] * 255;
2481 tl_b[i] = tl[i] * 255;
2482 tr_b[i] = tr[i] * 255;
2483 }
2484 bl_data = bl_b;
2485 br_data = br_b;
2486 tl_data = tl_b;
2487 tr_data = tr_b;
2488 } else {
2489 pixel_size = 4 * sizeof(float);
2490 bl_data = bl;
2491 br_data = br;
2492 tl_data = tl;
2493 tr_data = tr;
2494 }
2495 texel = tex_data = malloc(width * height * pixel_size);
2496
2497 for (i = 0; i < height; i++) {
2498 const unsigned row = i / vert_square_size;
2499
2500 for (j = 0; j < width; j++) {
2501 const unsigned col = j / horiz_square_size;
2502
2503 if (row & 1) {
2504 if (col & 1)
2505 memcpy(texel, tr_data, pixel_size);
2506 else
2507 memcpy(texel, tl_data, pixel_size);
2508 } else {
2509 if (col & 1)
2510 memcpy(texel, br_data, pixel_size);
2511 else
2512 memcpy(texel, bl_data, pixel_size);
2513 }
2514
2515 texel += pixel_size;
2516 }
2517 }
2518
2519 if (tex == 0) {
2520 glGenTextures(1, &tex);
2521
2522 glBindTexture(GL_TEXTURE_2D, tex);
2523 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2524 GL_NEAREST);
2525 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2526 GL_NEAREST);
2527 if (piglit_is_gles()) {
2528 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
2529 GL_CLAMP_TO_EDGE);
2530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
2531 GL_CLAMP_TO_EDGE);
2532 } else {
2533 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
2534 GL_CLAMP_TO_BORDER);
2535 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
2536 GL_CLAMP_TO_BORDER);
2537 glTexParameterfv(GL_TEXTURE_2D,
2538 GL_TEXTURE_BORDER_COLOR,
2539 border_color);
2540 }
2541 } else {
2542 glBindTexture(GL_TEXTURE_2D, tex);
2543 }
2544
2545 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, 0, GL_RGBA,
2546 piglit_is_gles() ? GL_UNSIGNED_BYTE : GL_FLOAT, tex_data);
2547
2548 free(tex_data);
2549
2550 return tex;
2551 }
2552
2553 /**
2554 * Generate a checkerboard texture
2555 *
2556 * \param tex Name of the texture to be used. If \c tex is
2557 * zero, a new texture name will be generated.
2558 * \param level Mipmap level the checkerboard should be written to
2559 * \param width Width of the texture image
2560 * \param height Height of the texture image
2561 * \param horiz_square_size Size of each checkerboard tile along the X axis
2562 * \param vert_square_size Size of each checkerboard tile along the Y axis
2563 * \param black RGBA color to be used for "black" tiles
2564 * \param white RGBA color to be used for "white" tiles
2565 *
2566 * A texture with alternating black and white squares in a checkerboard
2567 * pattern is generated. The texture data is written to LOD \c level of
2568 * the texture \c tex.
2569 *
2570 * If \c tex is zero, a new texture created. This texture will have several
2571 * texture parameters set to non-default values:
2572 *
2573 * - Min and mag filter will be set to \c GL_NEAREST.
2574 * - For GL:
2575 * - S and T wrap modes will be set to \c GL_CLAMP_TO_BORDER.
2576 * - Border color will be set to { 1.0, 0.0, 0.0, 1.0 }.
2577 * - For GLES:
2578 * - S and T wrap modes will be set to \c GL_CLAMP_TO_EDGE.
2579 *
2580 * \return
2581 * Name of the texture. In addition, this texture will be bound to the
2582 * \c GL_TEXTURE_2D target of the currently active texture unit.
2583 */
2584 GLuint
piglit_checkerboard_texture(GLuint tex,unsigned level,unsigned width,unsigned height,unsigned horiz_square_size,unsigned vert_square_size,const float * black,const float * white)2585 piglit_checkerboard_texture(GLuint tex, unsigned level,
2586 unsigned width, unsigned height,
2587 unsigned horiz_square_size,
2588 unsigned vert_square_size,
2589 const float *black, const float *white)
2590 {
2591 return piglit_quads_texture(tex, level, width, height,
2592 horiz_square_size, vert_square_size,
2593 black, white, white, black);
2594 }
2595
2596 /**
2597 * Generates a 8x8 mipmapped texture whose layers contain solid r, g, b, and w.
2598 */
2599 GLuint
piglit_miptree_texture()2600 piglit_miptree_texture()
2601 {
2602 GLfloat *data;
2603 int size, i, level;
2604 GLuint tex;
2605
2606 glGenTextures(1, &tex);
2607 glBindTexture(GL_TEXTURE_2D, tex);
2608 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2609 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2610 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2611 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2612 GL_NEAREST_MIPMAP_NEAREST);
2613
2614 for (level = 0; level < 4; ++level) {
2615 size = 8 >> level;
2616
2617 data = malloc(size*size*4*sizeof(GLfloat));
2618 for (i = 0; i < size * size; ++i) {
2619 memcpy(data + 4 * i, color_wheel[level],
2620 4 * sizeof(GLfloat));
2621 }
2622 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA,
2623 size, size, 0, GL_RGBA, GL_FLOAT, data);
2624 free(data);
2625 }
2626 return tex;
2627 }
2628
2629 /**
2630 * Generates an image of the given size with quadrants of red, green,
2631 * blue and white.
2632 * Note that for compressed teximages, where the blocking would be
2633 * problematic, we assign the whole layers at w == 4 to red, w == 2 to
2634 * green, and w == 1 to blue.
2635 *
2636 * \param internalFormat either GL_RGBA or a specific compressed format
2637 * \param w the width in texels
2638 * \param h the height in texels
2639 * \param alpha if TRUE, use varied alpha values, else all alphas = 1
2640 * \param basetype either GL_UNSIGNED_NORMALIZED, GL_SIGNED_NORMALIZED
2641 * or GL_FLOAT
2642 */
2643 GLfloat *
piglit_rgbw_image(GLenum internalFormat,int w,int h,GLboolean alpha,GLenum basetype)2644 piglit_rgbw_image(GLenum internalFormat, int w, int h,
2645 GLboolean alpha, GLenum basetype)
2646 {
2647 float red[4] = {1.0, 0.0, 0.0, 0.0};
2648 float green[4] = {0.0, 1.0, 0.0, 0.25};
2649 float blue[4] = {0.0, 0.0, 1.0, 0.5};
2650 float white[4] = {1.0, 1.0, 1.0, 1.0};
2651 GLfloat *data;
2652 int x, y;
2653
2654 if (!alpha) {
2655 red[3] = 1.0;
2656 green[3] = 1.0;
2657 blue[3] = 1.0;
2658 white[3] = 1.0;
2659 }
2660
2661 switch (basetype) {
2662 case GL_UNSIGNED_NORMALIZED:
2663 break;
2664
2665 case GL_SIGNED_NORMALIZED:
2666 for (x = 0; x < 4; x++) {
2667 red[x] = red[x] * 2 - 1;
2668 green[x] = green[x] * 2 - 1;
2669 blue[x] = blue[x] * 2 - 1;
2670 white[x] = white[x] * 2 - 1;
2671 }
2672 break;
2673
2674 case GL_FLOAT:
2675 for (x = 0; x < 4; x++) {
2676 red[x] = red[x] * 10 - 5;
2677 green[x] = green[x] * 10 - 5;
2678 blue[x] = blue[x] * 10 - 5;
2679 white[x] = white[x] * 10 - 5;
2680 }
2681 break;
2682
2683 default:
2684 assert(0);
2685 }
2686
2687 data = malloc(w * h * 4 * sizeof(GLfloat));
2688
2689 for (y = 0; y < h; y++) {
2690 for (x = 0; x < w; x++) {
2691 const int size = w > h ? w : h;
2692 const float *color;
2693
2694 if (x < w / 2 && y < h / 2)
2695 color = red;
2696 else if (y < h / 2)
2697 color = green;
2698 else if (x < w / 2)
2699 color = blue;
2700 else
2701 color = white;
2702
2703 switch (internalFormat) {
2704 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
2705 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
2706 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
2707 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
2708 case GL_COMPRESSED_RGB_FXT1_3DFX:
2709 case GL_COMPRESSED_RGBA_FXT1_3DFX:
2710 case GL_COMPRESSED_RED_RGTC1:
2711 case GL_COMPRESSED_SIGNED_RED_RGTC1:
2712 case GL_COMPRESSED_RG_RGTC2:
2713 case GL_COMPRESSED_SIGNED_RG_RGTC2:
2714 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
2715 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
2716 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
2717 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
2718 case GL_COMPRESSED_RGBA_BPTC_UNORM:
2719 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
2720 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
2721 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
2722 if (size == 4)
2723 color = red;
2724 else if (size == 2)
2725 color = green;
2726 else if (size == 1)
2727 color = blue;
2728 break;
2729 default:
2730 break;
2731 }
2732
2733 memcpy(data + (y * w + x) * 4, color,
2734 4 * sizeof(float));
2735 }
2736 }
2737
2738 return data;
2739 }
2740
2741 GLubyte *
piglit_rgbw_image_ubyte(int w,int h,GLboolean alpha)2742 piglit_rgbw_image_ubyte(int w, int h, GLboolean alpha)
2743 {
2744 GLubyte red[4] = {255, 0, 0, 0};
2745 GLubyte green[4] = {0, 255, 0, 64};
2746 GLubyte blue[4] = {0, 0, 255, 128};
2747 GLubyte white[4] = {255, 255, 255, 255};
2748 GLubyte *data;
2749 int x, y;
2750
2751 if (!alpha) {
2752 red[3] = 255;
2753 green[3] = 255;
2754 blue[3] = 255;
2755 white[3] = 255;
2756 }
2757
2758 data = malloc(w * h * 4 * sizeof(GLubyte));
2759
2760 for (y = 0; y < h; y++) {
2761 for (x = 0; x < w; x++) {
2762 const GLubyte *color;
2763
2764 if (x < w / 2 && y < h / 2)
2765 color = red;
2766 else if (y < h / 2)
2767 color = green;
2768 else if (x < w / 2)
2769 color = blue;
2770 else
2771 color = white;
2772
2773 memcpy(data + (y * w + x) * 4, color,
2774 4 * sizeof(GLubyte));
2775 }
2776 }
2777
2778 return data;
2779 }
2780
2781 /**
2782 * Generates a texture with the given internalFormat, w, h with a
2783 * teximage of r, g, b, w quadrants.
2784 *
2785 * Note that for compressed teximages, where the blocking would be
2786 * problematic, we assign the whole layers at w == 4 to red, w == 2 to
2787 * green, and w == 1 to blue.
2788 */
2789 GLuint
piglit_rgbw_texture(GLenum internalFormat,int w,int h,GLboolean mip,GLboolean alpha,GLenum basetype)2790 piglit_rgbw_texture(GLenum internalFormat, int w, int h, GLboolean mip,
2791 GLboolean alpha, GLenum basetype)
2792 {
2793 int size, level;
2794 GLuint tex;
2795 GLenum teximage_type;
2796
2797 switch (basetype) {
2798 case GL_UNSIGNED_NORMALIZED:
2799 case GL_SIGNED_NORMALIZED:
2800 case GL_FLOAT:
2801 teximage_type = GL_FLOAT;
2802 break;
2803 case GL_UNSIGNED_BYTE:
2804 teximage_type = GL_UNSIGNED_BYTE;
2805 break;
2806 default:
2807 assert(0);
2808 return 0;
2809 }
2810
2811 glGenTextures(1, &tex);
2812 glBindTexture(GL_TEXTURE_2D, tex);
2813 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2814 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2815 if (mip) {
2816 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2817 GL_LINEAR);
2818 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2819 GL_LINEAR_MIPMAP_NEAREST);
2820 } else {
2821 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2822 GL_NEAREST);
2823 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2824 GL_NEAREST);
2825 }
2826
2827 for (level = 0, size = w > h ? w : h; size > 0; level++, size >>= 1) {
2828 void *data;
2829
2830 if (teximage_type == GL_UNSIGNED_BYTE)
2831 data = piglit_rgbw_image_ubyte(w, h, alpha);
2832 else
2833 data = piglit_rgbw_image(internalFormat, w, h,
2834 alpha, basetype);
2835
2836 glTexImage2D(GL_TEXTURE_2D, level,
2837 internalFormat,
2838 w, h, 0,
2839 GL_RGBA, teximage_type, data);
2840 free(data);
2841
2842 if (!mip)
2843 break;
2844
2845 if (w > 1)
2846 w >>= 1;
2847 if (h > 1)
2848 h >>= 1;
2849 }
2850
2851 return tex;
2852 }
2853
2854 /**
2855 * Generate a 4 texel RGBA 1D texture with texels red, green, blue, white,
2856 * edge clamping and NEAREST filtering.
2857 */
2858 GLuint
piglit_rgbw_texture_1d(void)2859 piglit_rgbw_texture_1d(void)
2860 {
2861 GLuint tex;
2862 glGenTextures(1, &tex);
2863 glBindTexture(GL_TEXTURE_1D, tex);
2864 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2865 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2866 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2867 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2868
2869 static const float img[] = {1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1};
2870 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 4, 0, GL_RGBA, GL_FLOAT, img);
2871
2872 return tex;
2873 }
2874
2875 /**
2876 * Generate a 2 by 2 by 2 texel RGBA 3D texture with texels red, green, blue,
2877 * white, yellow, magenta, cyan, black, edge clamping and NEAREST filtering.
2878 */
2879 GLuint
piglit_rgbw_texture_3d(void)2880 piglit_rgbw_texture_3d(void)
2881 {
2882 GLuint tex;
2883 glGenTextures(1, &tex);
2884 glBindTexture(GL_TEXTURE_3D, tex);
2885 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2886 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2887 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
2888 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2889 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2890
2891 static const float img[] = {1, 0, 0, 1, 0, 1, 0, 1,
2892 0, 0, 1, 1, 1, 1, 1, 1,
2893 1, 1, 0, 1, 1, 0, 1, 1,
2894 0, 1, 1, 1, 0, 0, 0, 1};
2895 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_FLOAT, img);
2896
2897 return tex;
2898 }
2899
2900 /*
2901 * Maps a given integer internalformat to a valid format, including
2902 * the num_components info.
2903 */
2904 static void
map_integer_internalformat(GLenum internalformat,GLenum * format,int * num_components)2905 map_integer_internalformat(GLenum internalformat, GLenum *format, int *num_components)
2906 {
2907 switch(internalformat) {
2908 case GL_R32I:
2909 *format = GL_RED_INTEGER;
2910 *num_components = 1;
2911 break;
2912 case GL_RG32I:
2913 *format = GL_RG_INTEGER;
2914 *num_components = 2;
2915 break;
2916 case GL_RGB32I:
2917 *format = GL_RGB_INTEGER;
2918 *num_components = 3;
2919 break;
2920 case GL_RGBA32I:
2921 *format = GL_RGBA_INTEGER;
2922 *num_components = 4;
2923 break;
2924 default:
2925 printf("piglit_integer_texture only supports 32-bit integer"
2926 " internalformats\n");
2927 piglit_report_result(PIGLIT_FAIL);
2928 }
2929 }
2930
2931 /**
2932 * Generates a texture with the given integer internal format.
2933 * It tries to use all the 4 data references (x, y, b, a) to fill the data. So:
2934 * * For 4 components: R = x, G = y, B = b, A = a.
2935 * * For 3 components: R = x, G = y, B = b + a
2936 * * For 2 components: R = x + b, G = y + a
2937 * * For 1 components: R = x + y * b + a
2938 * Note that it assumes internalformats using 32 bit integer, so we would use GL_INT.
2939 */
piglit_integer_texture(GLenum internalFormat,int w,int h,int b,int a)2940 GLuint piglit_integer_texture(GLenum internalFormat, int w, int h, int b, int a)
2941 {
2942 int *img;
2943 int *p;
2944 GLuint tex;
2945 GLenum format;
2946 int num_components;
2947 int x, y;
2948
2949 map_integer_internalformat(internalFormat, &format, &num_components);
2950
2951 img = malloc(w * h * num_components * sizeof(int));
2952
2953 for (y = 0, p = img; y < h; ++y) {
2954 for (x = 0; x < w; ++x) {
2955 switch(num_components) {
2956 case 4:
2957 p[0] = x;
2958 p[1] = y;
2959 p[2] = b;
2960 p[3] = a;
2961 break;
2962 case 3:
2963 p[0] = x;
2964 p[1] = y;
2965 p[2] = b + a;
2966 break;
2967 case 2:
2968 p[0] = x + b;
2969 p[1] = y + a;
2970 break;
2971 case 1:
2972 p[0] = x + y * b + a;
2973 break;
2974 }
2975
2976 p += num_components;
2977 }
2978 }
2979
2980 glGenTextures(1, &tex);
2981 glBindTexture(GL_TEXTURE_2D, tex);
2982 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2983 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2984 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2985 GL_NEAREST);
2986 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2987 GL_NEAREST);
2988
2989 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, w, h);
2990 glTexSubImage2D(GL_TEXTURE_2D,
2991 0, 0, 0, w, h, format, GL_INT, img);
2992 free(img);
2993
2994 return tex;
2995 }
2996
2997 /**
2998 * Create a depth texture. The depth texture will be a gradient which varies
2999 * from 0.0 at the left side to 1.0 at the right side. For a 2D array texture,
3000 * all the texture layers will have the same gradient.
3001 *
3002 * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_1D_ARRAY,
3003 * GL_TEXTURE_2D_ARRAY or GL_TEXTURE_RECTANGLE.
3004 * \param internalformat either GL_DEPTH_STENCIL, GL_DEPTH_COMPONENT,
3005 * GL_DEPTH24_STENCIL8_EXT or GL_DEPTH32F_STENCIL8.
3006 * \param w, h, d level 0 image width, height and depth
3007 * \param mip if true, create a full mipmap. Else, create single-level texture.
3008 * \return the new texture object id
3009 */
3010 GLuint
piglit_depth_texture(GLenum target,GLenum internalformat,int w,int h,int d,GLboolean mip)3011 piglit_depth_texture(GLenum target, GLenum internalformat, int w, int h, int d, GLboolean mip)
3012 {
3013 void *data;
3014 float *f = NULL, *f2 = NULL;
3015 unsigned int *i = NULL;
3016 int size, x, y, level, layer;
3017 GLuint tex;
3018 GLenum type, format;
3019
3020 glGenTextures(1, &tex);
3021 glBindTexture(target, tex);
3022 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3023 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3024 if (mip) {
3025 glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
3026 GL_LINEAR);
3027 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
3028 GL_LINEAR_MIPMAP_NEAREST);
3029 } else {
3030 glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
3031 GL_NEAREST);
3032 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
3033 GL_NEAREST);
3034 }
3035 data = malloc(w * h * 4 * sizeof(GLfloat));
3036
3037 if (internalformat == GL_DEPTH_STENCIL_EXT ||
3038 internalformat == GL_DEPTH24_STENCIL8_EXT) {
3039 format = GL_DEPTH_STENCIL_EXT;
3040 type = GL_UNSIGNED_INT_24_8_EXT;
3041 i = data;
3042 } else if (internalformat == GL_DEPTH32F_STENCIL8) {
3043 format = GL_DEPTH_STENCIL;
3044 type = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
3045 f2 = data;
3046 } else {
3047 format = GL_DEPTH_COMPONENT;
3048 type = GL_FLOAT;
3049 f = data;
3050 }
3051
3052 for (level = 0, size = w > h ? w : h; size > 0; level++, size >>= 1) {
3053 for (y = 0; y < h; y++) {
3054 for (x = 0; x < w; x++) {
3055 float val = (float)(x) / (w - 1);
3056 if (f)
3057 f[y * w + x] = val;
3058 else if (f2)
3059 f2[(y * w + x)*2] = val;
3060 else if (i)
3061 i[y * w + x] = 0xffffff00 * val;
3062 }
3063 }
3064
3065 switch (target) {
3066 case GL_TEXTURE_1D:
3067 glTexImage1D(target, level,
3068 internalformat,
3069 w, 0,
3070 format, type, data);
3071 break;
3072
3073 case GL_TEXTURE_1D_ARRAY:
3074 case GL_TEXTURE_2D:
3075 case GL_TEXTURE_RECTANGLE:
3076 glTexImage2D(target, level,
3077 internalformat,
3078 w, h, 0,
3079 format, type, data);
3080 break;
3081
3082 case GL_TEXTURE_2D_ARRAY:
3083 glTexImage3D(target, level,
3084 internalformat,
3085 w, h, d, 0,
3086 format, type, NULL);
3087 for (layer = 0; layer < d; layer++) {
3088 glTexSubImage3D(target, level,
3089 0, 0, layer, w, h, 1,
3090 format, type, data);
3091 }
3092 break;
3093
3094 default:
3095 assert(0);
3096 }
3097
3098 if (!mip)
3099 break;
3100
3101 if (w > 1)
3102 w >>= 1;
3103 if (target != GL_TEXTURE_1D &&
3104 target != GL_TEXTURE_1D_ARRAY &&
3105 h > 1)
3106 h >>= 1;
3107 }
3108 free(data);
3109 return tex;
3110 }
3111
3112 /**
3113 * Create 1D or 2D array texture in which each slice is a different color.
3114 * the color pattern is red, green, blue, white, red, green, ...
3115 */
3116 GLuint
piglit_array_texture(GLenum target,GLenum internalformat,int w,int h,int d,GLboolean mip)3117 piglit_array_texture(GLenum target, GLenum internalformat,
3118 int w, int h, int d, GLboolean mip)
3119 {
3120 float *data;
3121 int size, i, level, layer;
3122 GLuint tex;
3123 GLenum type = GL_FLOAT, format = GL_RGBA;
3124
3125 if (target == GL_TEXTURE_1D_ARRAY) {
3126 assert(h == 1);
3127 }
3128 else {
3129 assert(target == GL_TEXTURE_2D_ARRAY);
3130 }
3131
3132 glGenTextures(1, &tex);
3133 glBindTexture(target, tex);
3134 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3135 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3136 if (mip) {
3137 glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
3138 GL_LINEAR);
3139 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
3140 GL_LINEAR_MIPMAP_NEAREST);
3141 } else {
3142 glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
3143 GL_NEAREST);
3144 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
3145 GL_NEAREST);
3146 }
3147 data = malloc(w * h * 4 * sizeof(GLfloat));
3148
3149 size = w > h ? w : h;
3150
3151 for (level = 0; size > 0; level++, size >>= 1) {
3152
3153 /* Create mipmap level */
3154 if (target == GL_TEXTURE_1D_ARRAY) {
3155 glTexImage2D(target, level, internalformat,
3156 w, d, 0, format, type, NULL);
3157 }
3158 else {
3159 glTexImage3D(target, level, internalformat,
3160 w, h, d, 0, format, type, NULL);
3161 }
3162
3163 for (layer = 0; layer < d; layer++) {
3164 /* Set whole layer to one color */
3165 for (i = 0; i < w * h; i++) {
3166 memcpy(data + 4 * i,
3167 color_wheel[layer %
3168 ARRAY_SIZE(color_wheel)],
3169 sizeof(color_wheel[0]));
3170 }
3171
3172 if (target == GL_TEXTURE_1D_ARRAY) {
3173 glTexSubImage2D(target, level,
3174 0, layer, w, 1,
3175 format, type, data);
3176 }
3177 else {
3178 glTexSubImage3D(target, level,
3179 0, 0, layer, w, h, 1,
3180 format, type, data);
3181 }
3182 }
3183
3184 if (!mip)
3185 break;
3186
3187 if (w > 1)
3188 w >>= 1;
3189 if (h > 1)
3190 h >>= 1;
3191 }
3192 free(data);
3193 return tex;
3194 }
3195
3196 static const char multisample_texture_vs_source[] =
3197 "#version 130\n"
3198 "in vec2 vertex;\n"
3199 "out vec2 tex_coords;\n"
3200 "void main()\n"
3201 "{\n"
3202 " tex_coords = vertex;\n"
3203 " vec2 pos = (vertex.xy * 2) - vec2(1, 1);\n"
3204 " gl_Position = vec4(pos, 0, 1);\n"
3205 "}\n";
3206
3207 static const char multisample_texture_fs_source[] =
3208 "#version 130\n"
3209 "#extension GL_ARB_sample_shading : enable\n"
3210 "in vec2 tex_coords;\n"
3211 "uniform sampler2DArray tex;\n"
3212 "uniform int tex_depth;\n"
3213 "uniform int z;\n"
3214 "void main()\n"
3215 "{\n"
3216 " int layer = (gl_SampleID * tex_depth) + z;\n"
3217 " gl_FragColor = texture(tex, vec3(tex_coords, layer));\n"
3218 "}\n";
3219
3220 /**
3221 * Uploads an arbitrary multisample texture.
3222 *
3223 * This function acts like glTexImage for multisample textures. If the
3224 * input texture is zero, it will create one. Otherwise, it will use the
3225 * texture given and assumes that glTexImage[23]DMultisample has already
3226 * been called to establish the storage.
3227 *
3228 * When this function returns, multisample texture will be bound to the
3229 * currently active texture.
3230 *
3231 * \param target either GL_TEXTURE_2D_MULTISAMPLE or
3232 * GL_TEXTURE2D_MULTISAMPLE_ARRAY
3233 * \param tex texture ID for existing texture, or zero
3234 * \param internalformat a renderable color format accepted by
3235 * glTexImage2DMultisample
3236 * \param width texture width
3237 * \param height texture height
3238 * \param depth texture depth. If target is
3239 * GL_TEXTURE_2D_MULTISAMPLE, this must be 1.
3240 * \param samples the number of samples
3241 * \param format format of the pixel data
3242 * \param type type of the pixel data
3243 * \param data pixel data with whitch to fill the texture
3244 *
3245 * \return the new texture object id
3246 */
3247 GLuint
piglit_multisample_texture(GLenum target,GLuint tex,GLenum internalFormat,unsigned width,unsigned height,unsigned depth,unsigned samples,GLenum format,GLenum type,const void * data)3248 piglit_multisample_texture(GLenum target, GLuint tex, GLenum internalFormat,
3249 unsigned width, unsigned height,
3250 unsigned depth, unsigned samples,
3251 GLenum format, GLenum type, const void *data)
3252 {
3253 static GLuint prog = 0;
3254 static GLint tex_loc, tex_depth_loc, z_loc;
3255 static GLuint fbo, array_tex, ms_tex;
3256 static const float verts[] = {
3257 0.0, 0.0,
3258 0.0, 1.0,
3259 1.0, 1.0,
3260 1.0, 1.0,
3261 1.0, 0.0,
3262 0.0, 0.0
3263 };
3264 unsigned z;
3265
3266 struct {
3267 GLint active_tex;
3268 GLint draw_fbo;
3269 GLint prog;
3270 GLint viewport[4];
3271 GLboolean arb_sample_shading;
3272 GLfloat min_sample_shading;
3273 GLint clamp_fragment_color;
3274 } backup;
3275
3276 piglit_require_extension("GL_ARB_texture_multisample");
3277 piglit_require_extension("GL_ARB_sample_shading");
3278
3279 if (target == GL_TEXTURE_2D_MULTISAMPLE) {
3280 assert(depth == 1);
3281 } else if (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
3282 } else {
3283 assert(!"Invalid texture target");
3284 return 0;
3285 }
3286
3287 if (prog == 0) {
3288 /* First-run setup */
3289 prog = piglit_build_simple_program_unlinked(
3290 multisample_texture_vs_source,
3291 multisample_texture_fs_source);
3292 glBindAttribLocation(prog, 0, "vertex");
3293 glLinkProgram(prog);
3294 if (!piglit_link_check_status(prog)) {
3295 prog = 0;
3296 return 0;
3297 }
3298
3299 tex_loc = glGetUniformLocation(prog, "tex");
3300 tex_depth_loc = glGetUniformLocation(prog, "tex_depth");
3301 z_loc = glGetUniformLocation(prog, "z");
3302
3303 glGenFramebuffers(1, &fbo);
3304 glGenTextures(1, &array_tex);
3305 }
3306
3307 /* Backup client values so we can restore them later */
3308 glGetIntegerv(GL_ACTIVE_TEXTURE, &backup.active_tex);
3309 glGetIntegerv(GL_CURRENT_PROGRAM, &backup.prog);
3310 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &backup.draw_fbo);
3311 glGetIntegerv(GL_CLAMP_FRAGMENT_COLOR, &backup.clamp_fragment_color);
3312 glGetIntegerv(GL_VIEWPORT, backup.viewport);
3313 glGetBooleanv(GL_SAMPLE_SHADING_ARB, &backup.arb_sample_shading);
3314 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_ARB, &backup.min_sample_shading);
3315
3316 glEnable(GL_SAMPLE_SHADING_ARB);
3317 glMinSampleShadingARB(1.0f);
3318
3319 if (tex) {
3320 ms_tex = tex;
3321 } else {
3322 glGenTextures(1, &ms_tex);
3323 glBindTexture(target, ms_tex);
3324 if (target == GL_TEXTURE_2D_MULTISAMPLE) {
3325 assert(depth == 1);
3326 glTexImage2DMultisample(target, samples, internalFormat,
3327 width, height, GL_TRUE);
3328 } else {
3329 glTexImage3DMultisample(target, samples, internalFormat,
3330 width, height, depth, GL_TRUE);
3331 }
3332 }
3333
3334 glBindTexture(GL_TEXTURE_2D_ARRAY, array_tex);
3335 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3336 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3337 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalFormat, width, height,
3338 depth * samples, 0, format, type, data);
3339
3340 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
3341 glViewport(0, 0, width, height);
3342
3343 glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
3344
3345 glUseProgram(prog);
3346 glUniform1i(tex_loc, backup.active_tex - GL_TEXTURE0);
3347 glUniform1i(tex_depth_loc, depth);
3348
3349 glEnableVertexAttribArray(0);
3350 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
3351
3352 if (target == GL_TEXTURE_2D_MULTISAMPLE) {
3353 glUniform1i(z_loc, 0);
3354 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
3355 GL_COLOR_ATTACHMENT0,
3356 target, ms_tex, 0);
3357 if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) !=
3358 GL_FRAMEBUFFER_COMPLETE)
3359 goto error;
3360
3361 glDrawArrays(GL_TRIANGLES, 0, 6);
3362 } else {
3363 for (z = 0; z < depth; ++z) {
3364 glUniform1i(z_loc, z);
3365 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER,
3366 GL_COLOR_ATTACHMENT0,
3367 ms_tex, 0, z);
3368 if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) !=
3369 GL_FRAMEBUFFER_COMPLETE)
3370 goto error;
3371
3372 glDrawArrays(GL_TRIANGLES, 0, 6);
3373 }
3374 }
3375
3376 glDisableVertexAttribArray(0);
3377
3378 /* Restore values for the client */
3379 if (!backup.arb_sample_shading)
3380 glDisable(GL_SAMPLE_SHADING_ARB);
3381 glMinSampleShadingARB(backup.min_sample_shading);
3382
3383 glUseProgram(backup.prog);
3384 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, backup.draw_fbo);
3385 glViewport(backup.viewport[0], backup.viewport[1],
3386 backup.viewport[2], backup.viewport[3]);
3387 glBindTexture(target, ms_tex);
3388 glClampColor(GL_CLAMP_FRAGMENT_COLOR, backup.clamp_fragment_color);
3389
3390 return ms_tex;
3391
3392 error:
3393 if (tex == 0) /* We created it, clean it up */
3394 glDeleteTextures(1, &ms_tex);
3395
3396 return 0;
3397 }
3398
3399 /**
3400 * Require transform feedback.
3401 *
3402 * Transform feedback may either be provided by GL 3.0 or
3403 * EXT_transform_feedback.
3404 */
3405 void
piglit_require_transform_feedback(void)3406 piglit_require_transform_feedback(void)
3407 {
3408 if (!(piglit_get_gl_version() >= 30 ||
3409 piglit_is_extension_supported("GL_EXT_transform_feedback"))) {
3410 printf("Transform feedback not supported.\n");
3411 piglit_report_result(PIGLIT_SKIP);
3412 }
3413 }
3414
3415 /**
3416 * Convert the image into a format that can be easily understood by
3417 * visual inspection, and display it on the screen.
3418 *
3419 * Luminance and intensity values are converted to a grayscale value.
3420 * Alpha values are visualized by blending the image with a grayscale
3421 * checkerboard.
3422 *
3423 * Pass image_count = 0 to disable drawing multiple images to window
3424 * system framebuffer.
3425 */
3426 void
piglit_visualize_image(float * img,GLenum base_internal_format,int image_width,int image_height,int image_count,bool rhs)3427 piglit_visualize_image(float *img, GLenum base_internal_format,
3428 int image_width, int image_height,
3429 int image_count, bool rhs)
3430 {
3431 int x, y;
3432 float checker;
3433 unsigned components = piglit_num_components(base_internal_format);
3434 float *visualization =
3435 (float *) malloc(sizeof(float)*3*image_width*image_height);
3436 for (y = 0; y < image_height; ++y) {
3437 for ( x = 0; x < image_width; ++x) {
3438 float r = 0, g = 0, b = 0, a = 1;
3439 float *pixel =
3440 &img[(y * image_width + x) * components];
3441 switch (base_internal_format) {
3442 case GL_ALPHA:
3443 a = pixel[0];
3444 break;
3445 case GL_RGBA:
3446 a = pixel[3];
3447 /* Fall through */
3448 case GL_RGB:
3449 b = pixel[2];
3450 /* Fall through */
3451 case GL_RG:
3452 g = pixel[1];
3453 /* Fall through */
3454 case GL_RED:
3455 r = pixel[0];
3456 break;
3457 case GL_LUMINANCE_ALPHA:
3458 a = pixel[1];
3459 /* Fall through */
3460 case GL_INTENSITY:
3461 case GL_LUMINANCE:
3462 r = pixel[0];
3463 g = pixel[0];
3464 b = pixel[0];
3465 break;
3466 }
3467 checker = ((x ^ y) & 0x10) ? 0.75 : 0.25;
3468 r = r * a + checker * (1 - a);
3469 g = g * a + checker * (1 - a);
3470 b = b * a + checker * (1 - a);
3471 visualization[(y * image_width + x) * 3] = r;
3472 visualization[(y * image_width + x) * 3 + 1] = g;
3473 visualization[(y * image_width + x) * 3 + 2] = b;
3474 }
3475 }
3476 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
3477 glUseProgram(0);
3478
3479 /* To simultaneously display multiple images on window system
3480 * framebuffer.
3481 */
3482 if(image_count) {
3483 /* Use glWindowPos to directly update x, y coordinates of
3484 * current raster position without getting transformed by
3485 * modelview projection matrix and viewport-to-window
3486 * transform.
3487 */
3488 glWindowPos2f(rhs ? image_width : 0,
3489 (image_count - 1) * image_height);
3490 }
3491 else {
3492 glRasterPos2f(rhs ? 0 : -1, -1);
3493 }
3494 glDrawPixels(image_width, image_height, GL_RGB, GL_FLOAT,
3495 visualization);
3496 free(visualization);
3497 }
3498
3499 /**
3500 * Convert from sRGB color space to linear color space, using the
3501 * formula from the GL 3.0 spec, section 4.1.8 (sRGB Texture Color
3502 * Conversion).
3503 */
3504 float
piglit_srgb_to_linear(float x)3505 piglit_srgb_to_linear(float x)
3506 {
3507 if (x <= 0.0405)
3508 return x / 12.92;
3509 else
3510 return pow((x + 0.055) / 1.055, 2.4);
3511 }
3512
3513 /* Convert from linear color space to sRGB color space. */
3514 float
piglit_linear_to_srgb(float x)3515 piglit_linear_to_srgb(float x)
3516 {
3517 if (x < 0.0f)
3518 return 0.0f;
3519 else if (x < 0.0031308f)
3520 return 12.92f * x;
3521 else if (x < 1.0f)
3522 return 1.055f * powf(x, 0.41666f) - 0.055f;
3523 else
3524 return 1.0f;
3525 }
3526