2 * Copyright © 2012, 2014 Intel Corporation
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
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 NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 #include "piglit-util-gl.h"
27 #include "piglit-util-waffle.h"
29 #include "piglit_wfl_framework.h"
38 make_context_current_singlepass(struct piglit_wfl_framework
*wfl_fw
,
39 const struct piglit_gl_test_config
*test_config
,
40 enum context_flavor flavor
,
41 const int32_t partial_config_attrib_list
[]);
43 struct piglit_wfl_framework
*
44 piglit_wfl_framework(struct piglit_gl_framework
*gl_fw
)
46 return (struct piglit_wfl_framework
*) gl_fw
;
50 piglit_wfl_framework_choose_platform(const struct piglit_gl_test_config
*test_config
)
52 const char *env
= getenv("PIGLIT_PLATFORM");
54 if (env
== NULL
|| streq(env
, "mixed_glx_egl")) {
55 #if defined(PIGLIT_HAS_X11) && defined(PIGLIT_HAS_EGL)
56 if (test_config
->supports_gl_es_version
) {
57 /* Some GLX implementations don't support creation of
58 * ES1 and ES2 contexts, so use XEGL instead.
60 return WAFFLE_PLATFORM_X11_EGL
;
63 #if defined(PIGLIT_HAS_GLX)
64 return WAFFLE_PLATFORM_GLX
;
65 #elif defined(PIGLIT_HAS_WGL)
66 return WAFFLE_PLATFORM_WGL
;
68 fprintf(stderr
, "environment var PIGLIT_PLATFORM must be set "
69 "when piglit is built without GLX support\n");
70 piglit_report_result(PIGLIT_FAIL
);
74 else if (streq(env
, "gbm")) {
76 return WAFFLE_PLATFORM_GBM
;
78 fprintf(stderr
, "environment var PIGLIT_PLATFORM=gbm, but "
79 "piglit was built without GBM support\n");
80 piglit_report_result(PIGLIT_FAIL
);
84 else if (streq(env
, "glx")) {
86 return WAFFLE_PLATFORM_GLX
;
88 fprintf(stderr
, "environment var PIGLIT_PLATFORM=glx, but "
89 "piglit was built without GLX support\n");
90 piglit_report_result(PIGLIT_FAIL
);
94 else if (streq(env
, "x11_egl")) {
95 #if defined(PIGLIT_HAS_X11) && defined(PIGLIT_HAS_EGL)
96 return WAFFLE_PLATFORM_X11_EGL
;
98 fprintf(stderr
, "environment var PIGLIT_PLATFORM=x11_egl, "
99 "but piglit was built without X11/EGL support\n");
100 piglit_report_result(PIGLIT_FAIL
);
104 else if (streq(env
, "wayland")) {
105 #ifdef PIGLIT_HAS_WAYLAND
106 return WAFFLE_PLATFORM_WAYLAND
;
108 fprintf(stderr
, "environment var PIGLIT_PLATFORM=wayland, "
109 "but piglit was built without Wayland support\n");
110 piglit_report_result(PIGLIT_FAIL
);
114 else if (strcmp(env
, "wgl") == 0) {
115 #ifdef PIGLIT_HAS_WGL
116 return WAFFLE_PLATFORM_WGL
;
118 fprintf(stderr
, "environment var PIGLIT_PLATFORM=wgl, "
119 "but piglit was built without WGL support\n");
120 piglit_report_result(PIGLIT_FAIL
);
124 else if (streq(env
, "surfaceless_egl")) {
125 #if WAFFLE_MAJOR_VERSION > 1 || (WAFFLE_MAJOR_VERSION == 1 && WAFFLE_MINOR_VERSION >= 6)
126 #if defined(PIGLIT_HAS_EGL)
127 return WAFFLE_PLATFORM_SURFACELESS_EGL
;
129 fprintf(stderr
, "environment var PIGLIT_PLATFORM=surfaceless_egl, "
130 "but piglit was built without EGL support\n");
131 piglit_report_result(PIGLIT_FAIL
);
134 fprintf(stderr
, "environment var PIGLIT_PLATFORM=surfaceless_egl, "
135 "but piglit was built with a too old libwaffle (< 1.6.0)\n");
136 piglit_report_result(PIGLIT_FAIL
);
141 fprintf(stderr
, "environment var PIGLIT_PLATFORM has bad "
142 "value \"%s\"\n", env
);
143 piglit_report_result(PIGLIT_FAIL
);
151 * \brief Concatenate two zero-terminated attribute lists.
153 * This function interprets null pointers as empty lists, just as Waffle does.
156 concat_attrib_lists(const int32_t a
[], const int32_t b
[])
158 int a_length
= waffle_attrib_list_length(a
);
159 int b_length
= waffle_attrib_list_length(b
);
160 int r_length
= a_length
+ b_length
;
162 /* +1 for the terminal 0. */
163 int r_size
= (2 * r_length
+ 1) * sizeof(int32_t);
165 /* Don't copy the terminal 0.
167 * If a list is null, then the copy size is conveniently zero.
169 int a_copy_size
= 2 * a_length
* sizeof(int32_t);
170 int b_copy_size
= 2 * b_length
* sizeof(int32_t);
172 int32_t *r
= calloc(1, r_size
);
174 memcpy(r
, a
, a_copy_size
);
175 memcpy(r
+ 2 * a_length
, b
, b_copy_size
);
182 * \brief Construct human-readable description of the context and an
183 * attribute list suitable for waffle_config_choose().
185 * The function deduces the values of WAFFLE_CONTEXT_API,
186 * WAFFLE_CONTEXT_PROFILE, WAFFLE_CONTEXT_MAJOR_VERSION,
187 * WAFFLE_CONTEXT_MINOR_VERSION, WAFFLE_CONTEXT_FORWARD_COMPATIBLE and
188 * WAFFLE_CONTEXT_DEBUG from the given context \a flavor and \a
189 * test_config. At the same time, it produces human-readable description
190 * of the context. At most \a bufsize bytes, including the terminal null,
191 * are written to \a buf.
193 * The \a partial_attrib_list must not contain any of those
194 * attributes. Any attributes in \a partial_attrib_list are added to the
195 * returned attribute list \a attrib_list.
198 parse_test_config(const struct piglit_gl_test_config
*test_config
,
199 enum context_flavor flavor
,
200 char buf
[], size_t bufsize
,
201 const int32_t partial_attrib_list
[],
202 int32_t *attrib_list
[])
204 const char *api_str
, *profile_str
= "", *fwd_compat_str
= "",
206 int32_t major_version
, minor_version
;
207 int32_t head_attrib_list
[64];
211 /* Derived class must not provide any context attributes. */
213 assert(waffle_attrib_list_get(partial_attrib_list
, WAFFLE_CONTEXT_API
, &junk
) == false);
214 assert(waffle_attrib_list_get(partial_attrib_list
, WAFFLE_CONTEXT_PROFILE
, &junk
) == false);
215 assert(waffle_attrib_list_get(partial_attrib_list
, WAFFLE_CONTEXT_MAJOR_VERSION
, &junk
) == false);
216 assert(waffle_attrib_list_get(partial_attrib_list
, WAFFLE_CONTEXT_MINOR_VERSION
, &junk
) == false);
217 assert(waffle_attrib_list_get(partial_attrib_list
, WAFFLE_CONTEXT_FORWARD_COMPATIBLE
, &junk
) == false);
218 assert(waffle_attrib_list_get(partial_attrib_list
, WAFFLE_CONTEXT_DEBUG
, &junk
) == false);
221 case CONTEXT_GL_CORE
:
222 assert(test_config
->supports_gl_core_version
);
226 head_attrib_list
[i
++] = WAFFLE_CONTEXT_API
;
227 head_attrib_list
[i
++] = WAFFLE_CONTEXT_OPENGL
;
229 profile_str
= "Core ";
230 if (test_config
->supports_gl_core_version
>= 32) {
231 head_attrib_list
[i
++] = WAFFLE_CONTEXT_PROFILE
;
232 head_attrib_list
[i
++] = WAFFLE_CONTEXT_CORE_PROFILE
;
235 major_version
= test_config
->supports_gl_core_version
/ 10;
236 head_attrib_list
[i
++] = WAFFLE_CONTEXT_MAJOR_VERSION
;
237 head_attrib_list
[i
++] = major_version
;
239 minor_version
= test_config
->supports_gl_core_version
% 10;
240 head_attrib_list
[i
++] = WAFFLE_CONTEXT_MINOR_VERSION
;
241 head_attrib_list
[i
++] = minor_version
;
244 case CONTEXT_GL_COMPAT
:
245 assert(test_config
->supports_gl_compat_version
);
249 head_attrib_list
[i
++] = WAFFLE_CONTEXT_API
;
250 head_attrib_list
[i
++] = WAFFLE_CONTEXT_OPENGL
;
252 profile_str
= "Compatibility ";
253 if (test_config
->supports_gl_compat_version
>= 32) {
254 head_attrib_list
[i
++] = WAFFLE_CONTEXT_PROFILE
;
255 head_attrib_list
[i
++] = WAFFLE_CONTEXT_COMPATIBILITY_PROFILE
;
258 major_version
= test_config
->supports_gl_compat_version
/ 10;
259 head_attrib_list
[i
++] = WAFFLE_CONTEXT_MAJOR_VERSION
;
260 head_attrib_list
[i
++] = major_version
;
262 minor_version
= test_config
->supports_gl_compat_version
% 10;
263 head_attrib_list
[i
++] = WAFFLE_CONTEXT_MINOR_VERSION
;
264 head_attrib_list
[i
++] = minor_version
;
267 case CONTEXT_GL_ES
: {
268 int32_t waffle_context_api
;
269 assert(test_config
->supports_gl_es_version
);
271 if (test_config
->supports_gl_es_version
< 40 &&
272 test_config
->supports_gl_es_version
>= 30) {
273 waffle_context_api
= WAFFLE_CONTEXT_OPENGL_ES3
;
274 } else if (test_config
->supports_gl_es_version
>= 20) {
275 waffle_context_api
= WAFFLE_CONTEXT_OPENGL_ES2
;
276 } else if (test_config
->supports_gl_es_version
>= 10) {
277 waffle_context_api
= WAFFLE_CONTEXT_OPENGL_ES1
;
279 printf("piglit: error: config attribute "
280 "'supports_gl_es_version' has "
282 test_config
->supports_gl_es_version
);
283 piglit_report_result(PIGLIT_FAIL
);
287 api_str
= "OpenGL ES";
288 head_attrib_list
[i
++] = WAFFLE_CONTEXT_API
;
289 head_attrib_list
[i
++] = waffle_context_api
;
291 major_version
= test_config
->supports_gl_es_version
/ 10;
292 head_attrib_list
[i
++] = WAFFLE_CONTEXT_MAJOR_VERSION
;
293 head_attrib_list
[i
++] = major_version
;
295 minor_version
= test_config
->supports_gl_es_version
% 10;
296 head_attrib_list
[i
++] = WAFFLE_CONTEXT_MINOR_VERSION
;
297 head_attrib_list
[i
++] = minor_version
;
302 /* There are no 3.1 core profiles -- the closest is 3.1 context without
303 * ARB_compatibility or a 3.2 core context --, and setting
304 * forward-compatible flag should ensure we don't get a 3.1 context w/
307 if (test_config
->require_forward_compatible_context
||
308 (flavor
== CONTEXT_GL_CORE
&&
309 test_config
->supports_gl_core_version
== 31)) {
310 fwd_compat_str
= "Forward-Compatible ";
312 head_attrib_list
[i
++] = WAFFLE_CONTEXT_FORWARD_COMPATIBLE
;
313 head_attrib_list
[i
++] = true;
316 if (test_config
->require_debug_context
) {
317 debug_str
= "Debug ";
319 head_attrib_list
[i
++] = WAFFLE_CONTEXT_DEBUG
;
320 head_attrib_list
[i
++] = true;
323 head_attrib_list
[i
++] = 0;
326 snprintf(buf
, bufsize
, "%s %d.%d %s%s%sContext",
327 api_str
, major_version
, minor_version
, fwd_compat_str
,
328 profile_str
, debug_str
);
331 *attrib_list
= concat_attrib_lists(head_attrib_list
, partial_attrib_list
);
335 * Check that the context's actual version no less than the requested
336 * version for \a flavor.
339 check_gl_version(const struct piglit_gl_test_config
*test_config
,
340 enum context_flavor flavor
,
341 const char *context_description
)
344 case CONTEXT_GL_CORE
:
346 /* There is no need to check the context version here, because
347 * Piglit explicitly supplied the desired version to
348 * waffle_config_choose().
351 case CONTEXT_GL_COMPAT
: {
352 int actual_version
= piglit_get_gl_version();
353 if (actual_version
>= test_config
->supports_gl_compat_version
)
356 fprintf(stderr
, "piglit: error: Requested a %s, but actual "
357 "context version is %d.%d\n",
360 actual_version
% 10);
370 * \brief Handle requests for OpenGL 3.1 profiles.
372 * Strictly speaking, an OpenGL 3.1 context has no profile. (See the
373 * EGL_KHR_create_context spec for the ugly details [1]). If the user does
374 * request a specific OpenGL 3.1 profile, though, then let's do what the user
377 * If the user requests a OpenGL 3.1 Core Context, and the returned context is
378 * exactly an OpenGL 3.1 context but it exposes GL_ARB_compatibility, then
379 * fallback to requesting an OpenGL 3.2 Core Context because, if context
380 * creation succeeds, then Waffle guarantees that an OpenGL 3.2 Context will
381 * have the requested profile. Likewise for OpenGL 3.1 Compatibility Contexts.
383 * [1] http://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_create_context.txt
386 special_case_gl31(struct piglit_wfl_framework
*wfl_fw
,
387 const struct piglit_gl_test_config
*test_config
,
388 enum context_flavor flavor
,
389 const char *context_description
,
390 const int32_t partial_config_attrib_list
[])
392 int requested_gl_version
, actual_gl_version
;
393 bool has_core_profile
;
394 struct piglit_gl_test_config fallback_config
= *test_config
;
395 const char *error_verb
= NULL
;
398 case CONTEXT_GL_CORE
:
399 requested_gl_version
= test_config
->supports_gl_core_version
;
400 fallback_config
.supports_gl_core_version
= 32;
401 error_verb
= "exposes";
403 case CONTEXT_GL_COMPAT
:
404 requested_gl_version
= test_config
->supports_gl_compat_version
;
405 fallback_config
.supports_gl_compat_version
= 32;
406 error_verb
= "lacks";
415 if (requested_gl_version
< 31) {
416 /* For context versions < 3.1, the GLX, EGL, and CGL specs
417 * promise that the returned context will have the
418 * compatibility profile. So Piglit has no need to check the
421 assert(flavor
== CONTEXT_GL_COMPAT
);
425 actual_gl_version
= piglit_get_gl_version();
426 assert(actual_gl_version
>= 31);
428 if (actual_gl_version
>= 32) {
429 /* For context versions >= 3.2, the GLX, EGL, and CGL specs
430 * promise that the returned context will have the requested
431 * profile. So Piglit has no need to check the profile here.
433 piglit_logd("Requested an %s, and received a matching "
434 "%d.%d context\n", context_description
,
435 actual_gl_version
/ 10, actual_gl_version
% 10);
439 has_core_profile
= !piglit_is_extension_supported("GL_ARB_compatibility");
440 if (flavor
== CONTEXT_GL_CORE
&& has_core_profile
) {
442 } else if (flavor
== CONTEXT_GL_COMPAT
&& !has_core_profile
) {
446 piglit_logd("Requested an %s, and the returned context is exactly a 3.1 "
447 "context. But it has the wrong profile because it %s the "
448 "GL_ARB_compatibility extension. Fallback to requesting a "
449 "3.2 context, which is guaranteed to have the correct "
450 "profile if context creation succeeds.",
451 context_description
, error_verb
);
453 waffle_make_current(wfl_fw
->display
, NULL
, NULL
);
454 waffle_window_destroy(wfl_fw
->window
);
455 waffle_context_destroy(wfl_fw
->context
);
456 waffle_config_destroy(wfl_fw
->config
);
457 wfl_fw
->window
= NULL
;
458 wfl_fw
->context
= NULL
;
459 wfl_fw
->config
= NULL
;
461 return make_context_current_singlepass(
462 wfl_fw
, &fallback_config
, flavor
,
463 partial_config_attrib_list
);
467 make_context_current_singlepass(struct piglit_wfl_framework
*wfl_fw
,
468 const struct piglit_gl_test_config
*test_config
,
469 enum context_flavor flavor
,
470 const int32_t partial_config_attrib_list
[])
473 int32_t *attrib_list
= NULL
;
476 assert(wfl_fw
->config
== NULL
);
477 assert(wfl_fw
->context
== NULL
);
478 assert(wfl_fw
->window
== NULL
);
480 parse_test_config(test_config
, flavor
, ctx_desc
, sizeof(ctx_desc
),
481 partial_config_attrib_list
, &attrib_list
);
483 wfl_fw
->config
= waffle_config_choose(wfl_fw
->display
, attrib_list
);
485 if (!wfl_fw
->config
) {
486 wfl_log_error("waffle_config_choose");
487 fprintf(stderr
, "piglit: error: Failed to create "
488 "waffle_config for %s\n", ctx_desc
);
492 wfl_fw
->context
= waffle_context_create(wfl_fw
->config
, NULL
);
493 if (!wfl_fw
->context
) {
494 wfl_log_error("waffle_context_create");
495 fprintf(stderr
, "piglit: error: Failed to create "
496 "waffle_context for %s\n", ctx_desc
);
500 wfl_fw
->window
= wfl_checked_window_create(wfl_fw
->config
,
501 test_config
->window_width
,
502 test_config
->window_height
);
504 wfl_checked_make_current(wfl_fw
->display
,
508 #ifdef PIGLIT_USE_OPENGL
509 piglit_dispatch_default_init(PIGLIT_DISPATCH_GL
);
510 #elif defined(PIGLIT_USE_OPENGL_ES1)
511 piglit_dispatch_default_init(PIGLIT_DISPATCH_ES1
);
512 #elif defined(PIGLIT_USE_OPENGL_ES2) || defined(PIGLIT_USE_OPENGL_ES3)
513 piglit_dispatch_default_init(PIGLIT_DISPATCH_ES2
);
518 ok
= check_gl_version(test_config
, flavor
, ctx_desc
);
522 ok
= special_case_gl31(wfl_fw
, test_config
, flavor
, ctx_desc
,
523 partial_config_attrib_list
);
527 piglit_gl_invalidate_extensions();
531 waffle_make_current(wfl_fw
->display
, NULL
, NULL
);
532 waffle_window_destroy(wfl_fw
->window
);
533 waffle_context_destroy(wfl_fw
->context
);
534 waffle_config_destroy(wfl_fw
->config
);
536 wfl_fw
->window
= NULL
;
537 wfl_fw
->context
= NULL
;
538 wfl_fw
->config
= NULL
;
540 piglit_gl_invalidate_extensions();
546 make_context_current(struct piglit_wfl_framework
*wfl_fw
,
547 const struct piglit_gl_test_config
*test_config
,
548 const int32_t partial_config_attrib_list
[])
552 #if defined(PIGLIT_USE_OPENGL)
554 if (test_config
->supports_gl_core_version
) {
555 ok
= make_context_current_singlepass(wfl_fw
, test_config
,
557 partial_config_attrib_list
);
559 /* OpenGL 3.1 is special. It doesn't have
560 * a compatibility profile, but it can have
563 piglit_is_core_profile
=
564 !piglit_is_extension_supported("GL_ARB_compatibility");
569 piglit_is_core_profile
= false;
571 if (test_config
->supports_gl_core_version
&&
572 test_config
->supports_gl_compat_version
) {
573 /* The above attempt to create a core context failed. */
574 printf("piglit: info: Falling back to GL %d.%d "
575 "compatibility context\n",
576 test_config
->supports_gl_compat_version
/ 10,
577 test_config
->supports_gl_compat_version
% 10);
580 if (test_config
->supports_gl_compat_version
) {
581 ok
= make_context_current_singlepass(wfl_fw
, test_config
,
583 partial_config_attrib_list
);
585 if (test_config
->supports_gl_compat_version
== 31 &&
586 !piglit_is_extension_supported("GL_ARB_compatibility")) {
587 printf("piglit: info: Failed to create a compat profile\n");
588 piglit_report_result(PIGLIT_SKIP
);
595 #elif defined(PIGLIT_USE_OPENGL_ES1) || \
596 defined(PIGLIT_USE_OPENGL_ES2) || \
597 defined(PIGLIT_USE_OPENGL_ES3)
598 ok
= make_context_current_singlepass(wfl_fw
, test_config
,
600 partial_config_attrib_list
);
608 printf("piglit: info: Failed to create any GL context\n");
609 piglit_report_result(PIGLIT_SKIP
);
614 piglit_wfl_framework_init(struct piglit_wfl_framework
*wfl_fw
,
615 const struct piglit_gl_test_config
*test_config
,
617 const int32_t partial_config_attrib_list
[])
619 static bool is_waffle_initialized
= false;
620 static int32_t initialized_platform
= 0;
622 (void)initialized_platform
;
624 if (is_waffle_initialized
) {
625 assert(platform
== initialized_platform
);
627 const int32_t attrib_list
[] = {
628 WAFFLE_PLATFORM
, platform
,
632 wfl_checked_init(attrib_list
);
633 is_waffle_initialized
= true;
634 initialized_platform
= platform
;
637 if (!piglit_gl_framework_init(&wfl_fw
->gl_fw
, test_config
)) {
638 piglit_wfl_framework_teardown(wfl_fw
);
642 wfl_fw
->platform
= platform
;
643 wfl_fw
->display
= wfl_checked_display_connect(NULL
);
644 make_context_current(wfl_fw
, test_config
, partial_config_attrib_list
);
650 piglit_wfl_framework_teardown(struct piglit_wfl_framework
*wfl_fw
)
652 waffle_make_current(wfl_fw
->display
, NULL
, NULL
);
653 waffle_window_destroy(wfl_fw
->window
);
654 waffle_context_destroy(wfl_fw
->context
);
655 waffle_config_destroy(wfl_fw
->config
);
656 waffle_display_disconnect(wfl_fw
->display
);
658 piglit_gl_framework_teardown(&wfl_fw
->gl_fw
);