1 /* Copyright © 2011-2012 Intel Corporation
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a
4  * copy of this software and associated documentation files (the "Software"),
5  * to deal in the Software without restriction, including without limitation
6  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7  * and/or sell copies of the Software, and to permit persons to whom the
8  * Software is furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice (including the next
11  * paragraph) shall be included in all copies or substantial portions of the
12  * Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 
23 /** @file minmax-test.c
24  *
25  * Helpers for performing minimuTest for the minimum maximum values in section 6.2 "State Tables"
26  * of the GL 3.0 spec.
27  */
28 
29 #include <inttypes.h>
30 #include <string.h>
31 
32 #include "piglit-util-gl.h"
33 #include "minmax-test.h"
34 
35 bool piglit_minmax_pass = true;
36 
piglit_print_minmax_header(void)37 void piglit_print_minmax_header(void)
38 {
39 	printf("%-50s %8s %8s\n", "token", "minimum", "value");
40 }
41 
42 static void
piglit_report_int(const char * name,GLint limit,GLint val,bool pass)43 piglit_report_int(const char *name, GLint limit, GLint val, bool pass)
44 {
45 	if (pass) {
46 		printf("%-50s %8d %8d\n", name, limit, val);
47 	} else {
48 		fprintf(stderr, "%-50s %8d %8d (ERROR)\n",
49 			name, limit, val);
50 		piglit_minmax_pass = false;
51 	}
52 }
53 
54 static void
piglit_report_uint(const char * name,GLuint limit,GLuint val,bool pass)55 piglit_report_uint(const char *name, GLuint limit, GLuint val, bool pass)
56 {
57 
58 	printf("%-50s %8u %8u", name, limit, val);
59 	if (!pass) {
60 		printf(" (ERROR)");
61 		piglit_minmax_pass = false;
62 	}
63 	printf("\n");
64 }
65 
66 static void
piglit_report_int64(const char * name,GLint64 limit,GLint64 val,bool pass)67 piglit_report_int64(const char *name, GLint64 limit, GLint64 val, bool pass)
68 {
69 	printf("%-50s %8"PRId64" %8"PRId64 , name, limit, val);
70 	if (!pass) {
71 		printf(" (ERROR)");
72 		piglit_minmax_pass = false;
73 	}
74 	printf("\n");
75 }
76 
77 static void
piglit_report_uint64(const char * name,GLuint64 limit,GLuint64 val,bool pass)78 piglit_report_uint64(const char *name, GLuint64 limit, GLuint64 val, bool pass)
79 {
80 	printf("%-50s %8"PRIu64" %8"PRIu64 , name, limit, val);
81 	if (!pass) {
82 		printf(" (ERROR)");
83 		piglit_minmax_pass = false;
84 	}
85 	printf("\n");
86 }
87 
88 static void
piglit_report_float(const char * name,GLfloat limit,GLfloat val,bool pass)89 piglit_report_float(const char *name, GLfloat limit, GLfloat val, bool pass)
90 {
91 	if (pass) {
92 		printf("%-50s %8.1f %8.1f\n", name, limit, val);
93 	} else {
94 		fprintf(stderr, "%-50s %8f %8f (ERROR)\n",
95 			name, limit, val);
96 		piglit_minmax_pass = false;
97 	}
98 }
99 
100 #define SENTINEL  0xDEADBEEF
101 
102 static void
piglit_test_int(GLenum token,GLint limit,bool max)103 piglit_test_int(GLenum token, GLint limit, bool max)
104 {
105 	const char *name = piglit_get_gl_enum_name(token);
106 	GLint val = SENTINEL;
107 	bool pass;
108 
109 	glGetIntegerv(token, &val);
110 
111 	pass = piglit_check_gl_error(GL_NO_ERROR);
112 
113 	piglit_report_int(name, limit, val,
114 			  pass &&
115 			  val != (GLint)SENTINEL &&
116 			  ((max && val <= limit) ||
117 			   (!max && val >= limit)));
118 }
119 
120 static void
piglit_test_int_v(GLenum token,GLuint index,GLint limit,bool max)121 piglit_test_int_v(GLenum token, GLuint index, GLint limit, bool max)
122 {
123 	char *name;
124 	GLint val = 9999;
125 	(void)!asprintf(&name, "%s[%d]", piglit_get_gl_enum_name(token), index);
126 
127 	glGetIntegeri_v(token, index, &val);
128 
129 	piglit_report_int(name, limit, val,
130 			  (max && val <= limit) ||
131 			  (!max && val >= limit));
132 
133 	free(name);
134 }
135 
136 static void
piglit_test_uint(GLenum token,GLuint limit,bool max)137 piglit_test_uint(GLenum token, GLuint limit, bool max)
138 {
139 	const char *name = piglit_get_gl_enum_name(token);
140 	GLuint val = SENTINEL;
141 	bool pass;
142 
143 	glGetIntegerv(token, (GLint*) &val);
144 
145 	pass = piglit_check_gl_error(GL_NO_ERROR);
146 
147 	piglit_report_uint(name, limit, val,
148 			   pass &&
149 			   val != SENTINEL &&
150 			   ((max && val <= limit) ||
151 			    (!max && val >= limit)));
152 }
153 
154 static void
piglit_test_int64(GLenum token,GLint64 limit,bool max)155 piglit_test_int64(GLenum token, GLint64 limit, bool max)
156 {
157 	const char *name = piglit_get_gl_enum_name(token);
158 	GLint64 val = SENTINEL;
159 	bool pass;
160 
161 	glGetInteger64v(token, &val);
162 
163 	pass = piglit_check_gl_error(GL_NO_ERROR);
164 
165 	piglit_report_int64(name, limit, val,
166 			    pass &&
167 			    val != SENTINEL &&
168 			    ((max && val <= limit) ||
169 			     (!max && val >= limit)));
170 }
171 
172 static void
piglit_test_uint64(GLenum token,GLuint64 limit,bool max)173 piglit_test_uint64(GLenum token, GLuint64 limit, bool max)
174 {
175 	const char *name = piglit_get_gl_enum_name(token);
176 	GLuint64 val = SENTINEL;
177 	bool pass;
178 
179 	/* To obtain GLuint64 values, we must use glGetInteger64v.
180 	 * Justification is found in the GL_ARB_sync spec:
181 	 *
182 	 *   30) What is the type of the timeout interval?
183 	 *
184 	 *       RESOLVED: GLuint64. [...] Consequently the type of <timeout>
185 	 *       has been changed to 'GLuint64' and a corresponding
186 	 *       'GetInteger64v' query taking 'GLint64' added (by symmetry
187 	 *       with GetInteger, where unsigned quantities are queries with
188 	 *       a function taking a pointer to a signed integer - the pointer
189 	 *       conversion is harmless).
190 	 */
191 
192 	glGetInteger64v(token, (GLint64*) &val);
193 
194 	pass = piglit_check_gl_error(GL_NO_ERROR);
195 
196 	piglit_report_uint64(name, limit, val,
197 			     pass &&
198 			     val != SENTINEL &&
199 			     ((max && val <= limit) ||
200 			      (!max && val >= limit)));
201 }
202 
piglit_test_min_int_v(GLenum token,GLuint index,GLint min)203 void piglit_test_min_int_v(GLenum token, GLuint index, GLint min)
204 {
205 	piglit_test_int_v(token, index, min, false);
206 }
207 
piglit_test_max_int_v(GLenum token,GLuint index,GLint max)208 void piglit_test_max_int_v(GLenum token, GLuint index, GLint max)
209 {
210 	piglit_test_int_v(token, index, max, true);
211 }
212 
piglit_test_min_int(GLenum token,GLint min)213 void piglit_test_min_int(GLenum token, GLint min)
214 {
215 	piglit_test_int(token, min, false);
216 }
217 
piglit_test_max_int(GLenum token,GLint max)218 void piglit_test_max_int(GLenum token, GLint max)
219 {
220 	piglit_test_int(token, max, true);
221 }
222 
piglit_test_min_uint(GLenum token,GLuint min)223 void piglit_test_min_uint(GLenum token, GLuint min)
224 {
225 	piglit_test_uint(token, min, false);
226 }
227 
piglit_test_max_uint(GLenum token,GLuint max)228 void piglit_test_max_uint(GLenum token, GLuint max)
229 {
230 	piglit_test_uint(token, max, true);
231 }
232 
piglit_test_min_int64(GLenum token,GLint64 min)233 void piglit_test_min_int64(GLenum token, GLint64 min)
234 {
235 	piglit_test_int64(token, min, false);
236 }
237 
piglit_test_max_int64(GLenum token,GLint64 max)238 void piglit_test_max_int64(GLenum token, GLint64 max)
239 {
240 	piglit_test_int64(token, max, true);
241 }
242 
piglit_test_min_uint64(GLenum token,GLuint64 min)243 void piglit_test_min_uint64(GLenum token, GLuint64 min)
244 {
245 	piglit_test_uint64(token, min, false);
246 }
247 
piglit_test_max_uint64(GLenum token,GLuint64 max)248 void piglit_test_max_uint64(GLenum token, GLuint64 max)
249 {
250 	piglit_test_uint64(token, max, true);
251 }
252 
253 static void
piglit_test_float(GLenum token,GLfloat limit,bool max)254 piglit_test_float(GLenum token, GLfloat limit, bool max)
255 {
256 	const char *name = piglit_get_gl_enum_name(token);
257 	GLfloat val = SENTINEL;
258 	bool pass;
259 
260 	glGetFloatv(token, &val);
261 
262 	pass = piglit_check_gl_error(GL_NO_ERROR);
263 
264 	piglit_report_float(name, limit, val,
265 			    pass &&
266 			    val != (GLfloat)SENTINEL &&
267 			    ((max && val <= limit) ||
268 			     (!max && val >= limit)));
269 }
270 
piglit_test_min_float(GLenum token,GLfloat min)271 void piglit_test_min_float(GLenum token, GLfloat min)
272 {
273 	piglit_test_float(token, min, false);
274 }
275 
piglit_test_max_float(GLenum token,GLfloat max)276 void piglit_test_max_float(GLenum token, GLfloat max)
277 {
278 	piglit_test_float(token, max, true);
279 }
280 
281 /** Tests tha the range referneced by the token covers at least low-high. */
piglit_test_range_float(GLenum token,GLfloat low,GLfloat high)282 void piglit_test_range_float(GLenum token, GLfloat low, GLfloat high)
283 {
284 	const char *name = piglit_get_gl_enum_name(token);
285 	char *temp;
286 	GLfloat vals[2] = {SENTINEL, SENTINEL};
287 	bool pass;
288 
289 	glGetFloatv(token, vals);
290 
291 	pass = piglit_check_gl_error(GL_NO_ERROR);
292 
293 	(void)!asprintf(&temp, "%s[0]", name);
294 	piglit_report_float(temp, low, vals[0], pass && vals[0] <= low);
295 	free(temp);
296 
297 	(void)!asprintf(&temp, "%s[1]", name);
298 	piglit_report_float(temp, high, vals[1], pass && vals[1] >= high);
299 	free(temp);
300 }
301 
piglit_test_min_viewport_dimensions(void)302 void piglit_test_min_viewport_dimensions(void)
303 {
304 	int min_w, min_h;
305 	GLint dims[2] = {9999, 9999};
306 
307 	if (piglit_get_gl_version() < 30) {
308 		/* FINISHME:
309 		 *
310 		 *     "The maximum viewport dimensions must be
311 		 *      greater than or equal to the larger of the
312 		 *      visible dimensions of the display being
313 		 *      rendered to (if a display exists), and the
314 		 *      largest renderbuffer image which can be
315 		 *      successfully created and attached to a
316 		 *      framebuffer object (see chapter 4).  INVALID
317 		 *      VALUE is generated if either w or h is
318 		 *      negative."
319 		 *
320 		 * We're only looking at RB limits here.
321 		 */
322 		int rb_size = 9999;
323 		glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &rb_size);
324 
325 		min_w = rb_size;
326 		min_h = rb_size;
327 	} else {
328 		/* FINISHME:
329 		 *
330 		 *     "The maximum viewport dimensions must be
331 		 *      greater than or equal to the visible
332 		 *      dimensions of the display being rendered to."
333 		 *
334 		 * Surely the screen is at least 1024x768, right?
335 		 */
336 		min_w = 1024;
337 		min_h = 768;
338 	}
339 
340 	glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
341 
342 	piglit_report_int("GL_MAX_VIEWPORT_DIMS[0]", min_w, dims[0],
343 			  dims[0] >= min_w);
344 	piglit_report_int("GL_MAX_VIEWPORT_DIMS[1]", min_h, dims[1],
345 			  dims[1] >= min_h);
346 }
347 
348 void
piglit_test_oq_bits()349 piglit_test_oq_bits()
350 {
351 	GLint dims[2] = {9999, 9999};
352 	GLint minbits, oqbits = 9999;
353 
354 	/* From the GL 2.1 specification:
355 	 *
356 	 *     "The number of query counter bits may be zero, in which
357 	 *      case the counter contains no useful
358 	 *      information. Otherwise, the minimum number of bits
359 	 *      allowed is a function of the implementation’s maximum
360 	 *      viewport dimensions (MAX_VIEWPORT_DIMS). In this case,
361 	 *      the counter must be able to represent at least two
362 	 *      overdraws for every pixel in the viewport The formula
363 	 *      to compute the allowable minimum value (where n is the
364 	 *      minimum number of bits) is:
365 	 *
366 	 *      n = min{32, log2(maxViewportWidth ∗ maxViewportHeight * 2}"
367 	 */
368 
369 	glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
370 	minbits = log2((float)dims[0] * dims[1] * 2);
371 	if (minbits > 32)
372 		minbits = 32;
373 
374 	glGetQueryiv(GL_SAMPLES_PASSED, GL_QUERY_COUNTER_BITS, &oqbits);
375 	if (oqbits == 0 || oqbits >= minbits) {
376 		printf("%-50s   0 / %2d %8d\n",
377 		       "GL_QUERY_COUNTER_BITS(GL_SAMPLES_PASSED)",
378 		       minbits, oqbits);
379 	} else {
380 		fprintf(stderr,
381 			"%-50s   0 / %2d %8d\n",
382 			"GL_QUERY_COUNTER_BITS(GL_SAMPLES_PASSED)",
383 			minbits, oqbits);
384 		piglit_minmax_pass = false;
385 	}
386 }
387 
388 void
piglit_test_tf_bits(GLenum target)389 piglit_test_tf_bits(GLenum target)
390 {
391 	GLint bits = 9999;
392 	const char *name;
393 
394 	if (target == GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)
395 		name = "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN bits";
396 	else
397 		name = "GL_PRIMITIVES_GENERATED bits";
398 
399 	/* From the GL 3.0 specification, page 329:
400 	 *
401 	 *     "If pname is QUERY_COUNTER_BITS, the
402 	 *      implementation-dependent number of query counter bits
403 	 *      may be zero, in which case the counter contains no
404 	 *      useful information.
405 	 *
406 	 *      For primitive queries (PRIMITIVES GENERATED and
407 	 *      TRANSFORM FEEDBACK PRIMITIVES WRITTEN) if the number
408 	 *      of bits is non-zero, the minimum number of bits
409 	 *      allowed is 32."
410 	 */
411 
412 	glGetQueryiv(target, GL_QUERY_COUNTER_BITS, &bits);
413 	if (bits == 0 || bits >= 32) {
414 		printf("%-50s %8s %8d\n", name, "0 / 32", bits);
415 	} else {
416 		fprintf(stderr, "%-50s %8s %8d (ERROR)\n",
417 			name, "0 / 32", bits);
418 		piglit_minmax_pass = false;
419 	}
420 }
421