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, &current_texture);
1942 	glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &current_read_fbo);
1943 	glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &current_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