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