1 // SPDX-FileCopyrightText: Copyright 2012 Intel Corporation
2 // SPDX-License-Identifier: BSD-2-Clause
5 /// @brief Test basic OpenGL rendering with all platform/gl_api combinations.
7 /// Each test does the following:
8 /// 1. Initialize waffle with a platform and gl_api.
9 /// 2. Create a context and window.
10 /// 3. On the window call waffle_make_current, glClear,
11 /// and waffle_swap_buffers.
12 /// 4. Verify the window contents with glReadPixels.
13 /// 5. Tear down all waffle state.
17 #include <setjmp.h> // for cmocka.h
18 #include <stdarg.h> // for va_start, va_end
23 #include <sys/types.h>
32 #include "gl_basic_cocoa.h"
38 // Choosing a smaller window would shorten the execution time of pixel
39 // validation, but Windows 7 enforces a minimum size.
44 static const float RED_F
= 1.00;
45 static const float GREEN_F
= 0.00;
46 static const float BLUE_F
= 1.00;
47 static const float ALPHA_F
= 1.00;
49 static const uint8_t RED_UB
= 0xff;
50 static const uint8_t GREEN_UB
= 0x00;
51 static const uint8_t BLUE_UB
= 0xff;
52 static const uint8_t ALPHA_UB
= 0xff;
54 struct test_state_gl_basic
{
56 struct waffle_display
*dpy
;
57 struct waffle_config
*config
;
58 struct waffle_window
*window
;
59 struct waffle_context
*ctx
;
61 uint8_t actual_pixels
[4 * WINDOW_WIDTH
* WINDOW_HEIGHT
];
62 uint8_t expect_pixels
[4 * WINDOW_WIDTH
* WINDOW_HEIGHT
];
65 #define ASSERT_GL(statement) \
68 assert_false(glGetError()); \
71 typedef unsigned int GLenum
;
72 typedef unsigned char GLboolean
;
73 typedef unsigned int GLbitfield
;
75 typedef signed char GLbyte
; /* 1-byte signed */
76 typedef short GLshort
; /* 2-byte signed */
77 typedef int GLint
; /* 4-byte signed */
78 typedef unsigned char GLubyte
; /* 1-byte unsigned */
79 typedef unsigned short GLushort
; /* 2-byte unsigned */
80 typedef unsigned int GLuint
; /* 4-byte unsigned */
81 typedef int GLsizei
; /* 4-byte signed */
82 typedef float GLfloat
; /* single precision float */
83 typedef float GLclampf
; /* single precision float in [0,1] */
84 typedef double GLdouble
; /* double precision float */
85 typedef double GLclampd
; /* double precision float in [0,1] */
87 #define GL_NO_ERROR 0x0000
88 #define GL_VERSION 0x1F02
89 #define GL_UNSIGNED_BYTE 0x1401
90 #define GL_UNSIGNED_INT 0x1405
91 #define GL_FLOAT 0x1406
93 #define GL_RGBA 0x1908
94 #define GL_COLOR_BUFFER_BIT 0x00004000
95 #define GL_CONTEXT_FLAGS 0x821e
96 #define GL_CONTEXT_ROBUST_ACCESS 0x90F3
98 #define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
99 #define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
101 #define GL_CONTEXT_PROFILE_MASK 0x9126
102 #define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
103 #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
109 #define APIENTRY __stdcall
113 static GLenum(APIENTRY
*glGetError
)(void);
114 static const GLubyte
*(APIENTRY
*glGetString
)(GLenum name
);
115 static void(APIENTRY
*glGetIntegerv
)(GLenum pname
, GLint
*params
);
116 static void(APIENTRY
*glClearColor
)(GLclampf red
,
120 static void(APIENTRY
*glClear
)(GLbitfield mask
);
121 static void(APIENTRY
*glReadPixels
)(GLint x
,
132 struct test_state_gl_basic
*ts
;
134 ts
= calloc(1, sizeof(*ts
));
138 for (int y
= 0; y
< WINDOW_HEIGHT
; ++y
) {
139 for (int x
= 0; x
< WINDOW_WIDTH
; ++x
) {
140 uint8_t *p
= &ts
->expect_pixels
[4 * (y
* WINDOW_WIDTH
+ x
)];
147 // Fill actual_pixels with canaries.
148 memset(&ts
->actual_pixels
, 0x99, sizeof(ts
->actual_pixels
));
155 teardown(void **state
)
161 // The rules that dictate how to properly query a GL symbol are complex. The
162 // rules depend on the OS, on the winsys API, and even on the particular driver
163 // being used. The rules differ between EGL 1.4 and EGL 1.5; differ between
164 // Linux, Windows, and Mac; and differ between Mesa and Mali.
166 // This function hides that complexity with a naive heuristic: try, then try
169 get_gl_symbol(enum waffle_enum context_api
, const char *name
)
172 enum waffle_enum dl
= 0;
175 switch (context_api
) {
176 case WAFFLE_CONTEXT_OPENGL
: dl
= WAFFLE_DL_OPENGL
; break;
177 case WAFFLE_CONTEXT_OPENGL_ES1
: dl
= WAFFLE_DL_OPENGL_ES1
; break;
178 case WAFFLE_CONTEXT_OPENGL_ES2
: dl
= WAFFLE_DL_OPENGL_ES2
; break;
179 case WAFFLE_CONTEXT_OPENGL_ES3
: dl
= WAFFLE_DL_OPENGL_ES3
; break;
180 default: assert_true(0); break;
184 if (waffle_dl_can_open(dl
)) {
185 sym
= waffle_dl_sym(dl
, name
);
189 sym
= waffle_get_proc_address(name
);
195 static int32_t waffle_platform
;
196 static const char *platform
;
202 gl_basic_init(void **state
)
204 struct test_state_gl_basic
*ts
;
207 ret
= setup((void **)&ts
);
211 const int32_t init_attrib_list
[] = {
213 WAFFLE_PLATFORM
, waffle_platform
,
218 ts
->initialized
= waffle_init(init_attrib_list
);
219 if (!ts
->initialized
) {
230 gl_basic_fini(void **state
)
232 struct test_state_gl_basic
*ts
= *state
;
235 // XXX: return immediately on error or attempt to finish the teardown ?
236 if (ts
->dpy
) // XXX: keep track if we've had current ctx ?
237 ret
= waffle_make_current(ts
->dpy
, NULL
, NULL
);
239 ret
= waffle_window_destroy(ts
->window
);
241 ret
= waffle_context_destroy(ts
->ctx
);
243 ret
= waffle_config_destroy(ts
->config
);
245 ret
= waffle_display_disconnect(ts
->dpy
);
248 ret
= waffle_teardown();
255 TEST_CTX_FWDCOMPAT
= 1 << 0,
256 TEST_CTX_DEBUG
= 1 << 1,
257 TEST_CTX_ROBUST
= 1 << 2,
258 TEST_CTX_LOSE_CONTEXT
= 1 << 3,
261 #define gl_basic_draw(state, ...) \
264 state, (struct gl_basic_draw_args__){ .api = 0, \
265 .version = WAFFLE_DONT_CARE, \
266 .profile = WAFFLE_DONT_CARE, \
267 .expect_error = WAFFLE_NO_ERROR, \
268 .context_flags = 0, \
272 struct gl_basic_draw_args__
{
276 int32_t expect_error
;
277 uint32_t context_flags
;
281 #define assert_int_equal_print(_a, _b) \
283 fprintf(stderr, #_a " (%d) != " #_b "(%d)\n", _a, _b); \
284 assert_true(0 && "Integer comparison failed"); \
287 #define assert_int_ge(_a, _b) \
289 fprintf(stderr, #_a " (%d) < " #_b "(%d)\n", _a, _b); \
290 assert_true(0 && "Integer comparison failed"); \
293 #define assert_in_range_print(_a, _min, _max) \
294 if (_a < _min || _a > _max) { \
296 #_a " (%d) outside range " #_min "(%d) - " #_max "(%d)\n", _a, \
298 assert_true(0 && "Integer comparison failed"); \
301 #define assert_string_len_equal(_actual, _expected, _len) \
302 if (strncmp(_actual, _expected, _len) != 0) { \
303 fprintf(stderr, "Expected (" #_expected "): \"%.*s\"\n", (int)_len, \
305 fprintf(stderr, "Received (" #_actual "): \"%.*s\"\n", (int)_len, \
307 assert_true(0 && "String comparison failed"); \
313 const struct waffle_error_info
*info
= waffle_error_get_info();
314 const char *code
= waffle_error_to_string(info
->code
);
316 if (info
->message_length
> 0)
317 fprintf(stderr
, "Waffle error: 0x%x %s: %s\n", info
->code
, code
,
320 fprintf(stderr
, "Waffle error: 0x%x %s\n", info
->code
, code
);
323 #define assert_true_with_wfl_error(_arg) \
330 gl_basic_draw__(void **state
, struct gl_basic_draw_args__ args
)
332 struct test_state_gl_basic
*ts
= *state
;
333 int32_t waffle_context_api
= args
.api
;
334 int32_t context_version
= args
.version
;
335 int32_t context_profile
= args
.profile
;
336 int32_t expect_error
= args
.expect_error
;
337 bool context_forward_compatible
= args
.context_flags
& TEST_CTX_FWDCOMPAT
;
338 bool context_debug
= args
.context_flags
& TEST_CTX_DEBUG
;
339 bool context_robust
= args
.context_flags
& TEST_CTX_ROBUST
;
340 bool lose_context_on_reset
= args
.context_flags
& TEST_CTX_LOSE_CONTEXT
;
341 bool alpha
= args
.alpha
;
344 int32_t config_attrib_list
[64];
347 const intptr_t window_attrib_list
[] = {
349 WAFFLE_WINDOW_WIDTH
, WINDOW_WIDTH
,
350 WAFFLE_WINDOW_HEIGHT
, WINDOW_HEIGHT
,
356 config_attrib_list
[i
++] = WAFFLE_CONTEXT_API
;
357 config_attrib_list
[i
++] = waffle_context_api
;
358 if (context_version
!= WAFFLE_DONT_CARE
) {
359 config_attrib_list
[i
++] = WAFFLE_CONTEXT_MAJOR_VERSION
;
360 config_attrib_list
[i
++] = context_version
/ 10;
361 config_attrib_list
[i
++] = WAFFLE_CONTEXT_MINOR_VERSION
;
362 config_attrib_list
[i
++] = context_version
% 10;
364 if (context_profile
!= WAFFLE_DONT_CARE
) {
365 config_attrib_list
[i
++] = WAFFLE_CONTEXT_PROFILE
;
366 config_attrib_list
[i
++] = context_profile
;
368 if (context_forward_compatible
) {
369 config_attrib_list
[i
++] = WAFFLE_CONTEXT_FORWARD_COMPATIBLE
;
370 config_attrib_list
[i
++] = true;
373 config_attrib_list
[i
++] = WAFFLE_CONTEXT_DEBUG
;
374 config_attrib_list
[i
++] = true;
376 if (context_robust
) {
377 config_attrib_list
[i
++] = WAFFLE_CONTEXT_ROBUST_ACCESS
;
378 config_attrib_list
[i
++] = true;
380 if (lose_context_on_reset
) {
381 config_attrib_list
[i
++] = WAFFLE_CONTEXT_LOSE_CONTEXT_ON_RESET
;
382 config_attrib_list
[i
++] = true;
384 config_attrib_list
[i
++] = WAFFLE_RED_SIZE
;
385 config_attrib_list
[i
++] = 8;
386 config_attrib_list
[i
++] = WAFFLE_GREEN_SIZE
;
387 config_attrib_list
[i
++] = 8;
388 config_attrib_list
[i
++] = WAFFLE_BLUE_SIZE
;
389 config_attrib_list
[i
++] = 8;
390 config_attrib_list
[i
++] = WAFFLE_ALPHA_SIZE
;
391 config_attrib_list
[i
++] = alpha
;
392 config_attrib_list
[i
++] = 0;
395 ts
->dpy
= waffle_display_connect(NULL
);
396 assert_true_with_wfl_error(ts
->dpy
);
398 ts
->config
= waffle_config_choose(ts
->dpy
, config_attrib_list
);
400 assert_true(ts
->config
== NULL
);
401 assert_true((int32_t)waffle_error_get_code() == expect_error
);
403 } else if (ts
->config
== NULL
) {
404 switch (waffle_error_get_code()) {
405 case WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM
:
407 case WAFFLE_ERROR_UNKNOWN
:
408 // Assume that the native platform rejected the requested
411 // XXX: skip() is not annotated as noreturn, leading to compiler
412 // warning about implicit fallthrough
415 assert_true_with_wfl_error(ts
->config
);
419 ts
->window
= waffle_window_create2(ts
->config
, window_attrib_list
);
420 assert_true_with_wfl_error(ts
->window
);
422 ret
= waffle_window_show(ts
->window
);
423 assert_true_with_wfl_error(ret
);
425 ts
->ctx
= waffle_context_create(ts
->config
, NULL
);
426 if (ts
->ctx
== NULL
) {
427 switch (waffle_error_get_code()) {
428 case WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM
:
430 case WAFFLE_ERROR_UNKNOWN
:
431 // Assume that the native platform rejected the requested
434 // XXX: skip() is not annotated as noreturn, leading to compiler
435 // warning about implicit fallthrough
438 assert_true_with_wfl_error(ts
->ctx
);
442 // Get OpenGL functions.
444 assert_true(glClear
= get_gl_symbol(waffle_context_api
, "glClear"));
445 assert_true(glClearColor
= get_gl_symbol(waffle_context_api
, "glClearColor"));
446 assert_true(glGetError
= get_gl_symbol(waffle_context_api
, "glGetError"));
447 assert_true(glGetIntegerv
= get_gl_symbol(waffle_context_api
, "glGetIntegerv"));
448 assert_true(glReadPixels
= get_gl_symbol(waffle_context_api
, "glReadPixels"));
449 assert_true(glGetString
= get_gl_symbol(waffle_context_api
, "glGetString"));
452 ret
= waffle_make_current(ts
->dpy
, ts
->window
, ts
->ctx
);
453 assert_true_with_wfl_error(ret
);
455 assert_true(waffle_get_current_display() == ts
->dpy
);
456 assert_true(waffle_get_current_window() == ts
->window
);
457 assert_true(waffle_get_current_context() == ts
->ctx
);
459 const char *version_str
, *expected_version_str
;
460 int major
, minor
, count
;
462 ASSERT_GL(version_str
= (const char *)glGetString(GL_VERSION
));
463 assert_true(version_str
!= NULL
);
466 switch (waffle_context_api
) {
467 case WAFFLE_CONTEXT_OPENGL
: expected_version_str
= ""; break;
468 case WAFFLE_CONTEXT_OPENGL_ES1
: expected_version_str
= "OpenGL ES-CM "; break;
469 case WAFFLE_CONTEXT_OPENGL_ES2
:
470 case WAFFLE_CONTEXT_OPENGL_ES3
: expected_version_str
= "OpenGL ES "; break;
471 // Explicitly initialize, to appease GCC
472 default: expected_version_str
= ""; assert_true(0); break;
476 const size_t version_str_len
= strlen(expected_version_str
);
477 assert_string_len_equal(version_str
, expected_version_str
, version_str_len
);
478 version_str
+= version_str_len
;
480 count
= sscanf(version_str
, "%d.%d", &major
, &minor
);
481 assert_int_equal_print(count
, 2);
482 assert_int_ge(major
, 0);
483 assert_in_range_print(minor
, 0, 10);
485 if (context_version
!= WAFFLE_DONT_CARE
) {
486 int expected_major
= context_version
/ 10;
487 int expected_minor
= context_version
% 10;
489 assert_int_ge(major
, expected_major
);
490 if (major
== expected_major
)
491 assert_int_ge(minor
, expected_minor
);
494 const char *profile_suffix
= "";
496 if (waffle_context_api
== WAFFLE_CONTEXT_OPENGL
) {
497 switch (context_profile
) {
498 case WAFFLE_CONTEXT_CORE_PROFILE
:
499 profile_suffix
= " (Core Profile)";
502 "MacOS Core contexts, omit the \"%s\" suffix in "
503 "glGetString(GL_VERSION)."
504 "Applying workaround.\n",
509 case WAFFLE_CONTEXT_COMPATIBILITY_PROFILE
:
510 // HACK: seems like Mesa 19.3.3 at least will report
511 if (context_forward_compatible
)
512 profile_suffix
= " (Core Profile)";
514 profile_suffix
= " (Compatibility Profile)";
516 case WAFFLE_DONT_CARE
:
524 char profile_str
[30]; // 30 should be enough ;-)
525 sprintf(profile_str
, "%d.%d%s", major
, minor
, profile_suffix
);
527 const size_t profile_str_len
= strlen(profile_str
);
528 assert_string_len_equal(version_str
, profile_str
, profile_str_len
);
530 int version_10x
= 10 * major
+ minor
;
532 // Another profile check
533 if (waffle_context_api
== WAFFLE_CONTEXT_OPENGL
&& version_10x
>= 32) {
534 GLint profile_mask
= 0;
535 glGetIntegerv(GL_CONTEXT_PROFILE_MASK
, &profile_mask
);
537 switch (context_profile
) {
538 case WAFFLE_CONTEXT_CORE_PROFILE
:
539 assert_true(profile_mask
& GL_CONTEXT_CORE_PROFILE_BIT
);
541 case WAFFLE_CONTEXT_COMPATIBILITY_PROFILE
:
542 // HACK: seems like Mesa 19.3.3 at least will report
543 if (context_forward_compatible
)
544 assert_true(profile_mask
& GL_CONTEXT_CORE_PROFILE_BIT
);
546 assert_true(profile_mask
&
547 GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
);
549 case WAFFLE_DONT_CARE
:
557 if ((waffle_context_api
== WAFFLE_CONTEXT_OPENGL
&& version_10x
>= 30) ||
558 (waffle_context_api
!= WAFFLE_CONTEXT_OPENGL
&& version_10x
>= 32)) {
559 GLint context_flags
= 0;
560 if (context_forward_compatible
|| context_debug
) {
561 glGetIntegerv(GL_CONTEXT_FLAGS
, &context_flags
);
564 if (context_forward_compatible
) {
565 assert_true(context_flags
& GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
);
569 assert_true(context_flags
& GL_CONTEXT_FLAG_DEBUG_BIT
);
573 // GL_ROBUST_ACCESS comes with the following extensions
578 // To keep it simple, assume the correct extension is there if
579 // glGetError is happy ;-)
580 if (context_robust
) {
581 GLint robust_flag
= 0;
582 glGetIntegerv(GL_CONTEXT_ROBUST_ACCESS
, &robust_flag
);
584 if (glGetError() == GL_NO_ERROR
)
585 assert_true(robust_flag
);
589 ASSERT_GL(glClearColor(RED_F
, GREEN_F
, BLUE_F
, ALPHA_F
));
590 ASSERT_GL(glClear(GL_COLOR_BUFFER_BIT
));
591 ASSERT_GL(glReadPixels(0, 0, WINDOW_WIDTH
, WINDOW_HEIGHT
, GL_RGBA
,
592 GL_UNSIGNED_BYTE
, ts
->actual_pixels
));
593 ret
= waffle_window_swap_buffers(ts
->window
);
594 assert_true_with_wfl_error(ret
);
596 assert_memory_equal(&ts
->actual_pixels
, &ts
->expect_pixels
,
597 sizeof(ts
->expect_pixels
));
601 // List of tests common to all platforms.
606 #define test_rgb(waffle_api) \
607 static void waffle_api##_rgb(void **state) \
609 gl_basic_draw(state, \
610 .api=WAFFLE_CONTEXT_##waffle_api); \
613 #define test_rgba(waffle_api) \
614 static void waffle_api##_rgba(void **state) \
616 gl_basic_draw(state, \
617 .api=WAFFLE_CONTEXT_##waffle_api, \
621 #define test_context_flags(waffle_api, waffle_flags) \
622 static void waffle_api##_##waffle_flags(void **state) \
624 int32_t expect_error = TEST_##waffle_flags & TEST_CTX_FWDCOMPAT ? \
625 WAFFLE_ERROR_BAD_ATTRIBUTE : WAFFLE_NO_ERROR; \
626 gl_basic_draw(state, \
627 .api=WAFFLE_CONTEXT_##waffle_api, \
628 .context_flags=TEST_##waffle_flags, \
629 .expect_error=expect_error); \
632 #define test_version(waffle_api, waffle_version) \
633 static void waffle_api##_##waffle_version(void **state) \
635 gl_basic_draw(state, \
636 .api=WAFFLE_CONTEXT_##waffle_api, \
637 .version=waffle_version); \
640 #define test_version_fwdcompat(waffle_api, waffle_version) \
641 static void waffle_api##_fwdcompat_##waffle_version(void **state) \
643 gl_basic_draw(state, \
644 .api=WAFFLE_CONTEXT_##waffle_api, \
645 .version=waffle_version, \
646 .context_flags=TEST_CTX_FWDCOMPAT); \
649 #define test_profile_version(waffle_profile, waffle_version) \
650 static void waffle_profile##_##waffle_version(void **state) \
652 gl_basic_draw(state, \
653 .api=WAFFLE_CONTEXT_OPENGL, \
654 .version=waffle_version, \
655 .profile=WAFFLE_CONTEXT_##waffle_profile##_PROFILE); \
658 #define test_profile_context_flags(waffle_profile, waffle_flags) \
659 static void waffle_profile##_##waffle_flags(void **state) \
661 gl_basic_draw(state, \
662 .api=WAFFLE_CONTEXT_OPENGL, \
664 .profile=WAFFLE_CONTEXT_##waffle_profile##_PROFILE, \
665 .context_flags=TEST_##waffle_flags); \
670 // Most of the following tests will return ERROR_UNSUPPORTED_ON_PLATFORM
671 // on Apple/CGL, where NO_ERROR is expected.
672 // This is safe, as the test is skipped when the said error occurs.
674 // As BAD_ATTRIBUTE (core validation) takes greater precedence over
675 // UNSUPPORTED_ON_PLATFORM (platform specific one).
676 // Thus we're safe to use the former here, eventhough CGL has support
677 // for neither GLES* nor fwdcompa "CGL and everyone else".
681 // Quick notes which combinations we test and why
682 // - w/o version, for each API/profile combination check variations of
683 // - visual - make sure we can draw fine, duh
684 // - flags - flags selection machinery is funky
685 // - fwdcompat was introduced with OpenGL 3.0, check it and 3.1
686 // - specific version
687 // - all known versions
692 // OPENGL, no profile
697 test_context_flags(OPENGL
, CTX_FWDCOMPAT
)
698 test_context_flags(OPENGL
, CTX_DEBUG
)
699 test_context_flags(OPENGL
, CTX_ROBUST
)
700 test_context_flags(OPENGL
, CTX_LOSE_CONTEXT
)
702 test_version_fwdcompat(OPENGL
, 30)
703 test_version_fwdcompat(OPENGL
, 31)
705 test_version(OPENGL
, 10)
706 test_version(OPENGL
, 11)
707 test_version(OPENGL
, 12)
708 test_version(OPENGL
, 13)
709 test_version(OPENGL
, 14)
710 test_version(OPENGL
, 15)
711 test_version(OPENGL
, 20)
712 test_version(OPENGL
, 21)
713 test_version(OPENGL
, 30)
714 test_version(OPENGL
, 31)
716 // OPENGL, CORE profile
718 test_profile_context_flags(CORE
, CTX_FWDCOMPAT
)
719 test_profile_context_flags(CORE
, CTX_DEBUG
)
720 test_profile_context_flags(CORE
, CTX_ROBUST
)
721 test_profile_context_flags(CORE
, CTX_LOSE_CONTEXT
)
723 test_profile_version(CORE
, 32)
724 test_profile_version(CORE
, 33)
725 test_profile_version(CORE
, 40)
726 test_profile_version(CORE
, 41)
727 test_profile_version(CORE
, 42)
728 test_profile_version(CORE
, 43)
729 test_profile_version(CORE
, 44)
730 test_profile_version(CORE
, 45)
731 test_profile_version(CORE
, 46)
733 // OPENGL, COMPATIBILITY profile
735 test_profile_context_flags(COMPATIBILITY
, CTX_FWDCOMPAT
)
736 test_profile_context_flags(COMPATIBILITY
, CTX_DEBUG
)
737 test_profile_context_flags(COMPATIBILITY
, CTX_ROBUST
)
738 test_profile_context_flags(COMPATIBILITY
, CTX_LOSE_CONTEXT
)
740 test_profile_version(COMPATIBILITY
, 32)
741 test_profile_version(COMPATIBILITY
, 33)
742 test_profile_version(COMPATIBILITY
, 40)
743 test_profile_version(COMPATIBILITY
, 41)
744 test_profile_version(COMPATIBILITY
, 42)
745 test_profile_version(COMPATIBILITY
, 43)
746 test_profile_version(COMPATIBILITY
, 44)
747 test_profile_version(COMPATIBILITY
, 45)
748 test_profile_version(COMPATIBILITY
, 46)
753 test_rgba(OPENGL_ES1
)
755 test_context_flags(OPENGL_ES1
, CTX_FWDCOMPAT
)
756 test_context_flags(OPENGL_ES1
, CTX_DEBUG
)
757 test_context_flags(OPENGL_ES1
, CTX_ROBUST
)
758 test_context_flags(OPENGL_ES1
, CTX_LOSE_CONTEXT
)
760 test_version(OPENGL_ES1
, 10)
761 test_version(OPENGL_ES1
, 11)
766 test_rgba(OPENGL_ES2
)
768 test_context_flags(OPENGL_ES2
, CTX_FWDCOMPAT
)
769 test_context_flags(OPENGL_ES2
, CTX_DEBUG
)
770 test_context_flags(OPENGL_ES2
, CTX_ROBUST
)
771 test_context_flags(OPENGL_ES2
, CTX_LOSE_CONTEXT
)
773 test_version(OPENGL_ES2
, 20)
778 test_rgba(OPENGL_ES3
)
780 test_context_flags(OPENGL_ES3
, CTX_FWDCOMPAT
)
781 test_context_flags(OPENGL_ES3
, CTX_DEBUG
)
782 test_context_flags(OPENGL_ES3
, CTX_ROBUST
)
783 test_context_flags(OPENGL_ES3
, CTX_LOSE_CONTEXT
)
785 test_version(OPENGL_ES3
, 30)
786 test_version(OPENGL_ES3
, 31)
787 test_version(OPENGL_ES3
, 32)
793 removeArg(int index
, int *argc
, char **argv
)
797 for (; index
< *argc
; ++index
)
798 argv
[index
] = argv
[index
+ 1];
802 removeXcodeArgs(int *argc
, char **argv
)
804 // Xcode sometimes adds additional arguments.
805 for (int i
= 1; i
< *argc
;) {
806 if (strcmp(argv
[i
], "-NSDocumentRevisionsDebugMode") == 0 ||
807 strcmp(argv
[i
], "-ApplePersistenceIgnoreState") == 0) {
808 removeArg(i
, argc
, argv
);
809 removeArg(i
, argc
, argv
);
817 static const char *usage_message
=
819 " gl_basic_test <Required Parameter> [Options]\n"
822 " Run the basic functionality tests.\n"
824 "Required Parameter:\n"
826 " One of: cgl, gbm, glx, wayland, wgl or x11_egl\n"
830 " Print gl_basic_test usage information.\n";
832 #if defined(__GNUC__)
833 #define NORETURN __attribute__((noreturn))
834 #elif defined(_MSC_VER)
835 #define NORETURN __declspec(noreturn)
840 #if defined(__clang__)
841 #define PRINTFLIKE(f, a) __attribute__((format(printf, f, a)))
842 #elif defined(__GNUC__)
843 #define PRINTFLIKE(f, a) __attribute__((format(gnu_printf, f, a)))
845 #define PRINTFLIKE(f, a)
849 write_usage_and_exit(FILE *f
, int exit_code
)
851 fprintf(f
, "%s", usage_message
);
860 static const struct option get_opts
[] = {
861 { .name
= "platform", .has_arg
= required_argument
, .val
= OPT_PLATFORM
},
862 { .name
= "help", .has_arg
= no_argument
, .val
= OPT_HELP
},
865 static void NORETURN
PRINTFLIKE(1, 2)
866 usage_error_printf(const char *fmt
, ...)
868 fprintf(stderr
, "gl_basic_test usage error: ");
873 vfprintf(stderr
, fmt
, ap
);
875 fprintf(stderr
, " ");
878 fprintf(stderr
, "(see gl_basic_test --help)\n");
887 static const struct enum_map platform_map
[] = {
888 { WAFFLE_PLATFORM_CGL
, "cgl" },
889 { WAFFLE_PLATFORM_GBM
, "gbm" },
890 { WAFFLE_PLATFORM_GLX
, "glx" },
891 { WAFFLE_PLATFORM_WAYLAND
, "wayland" },
892 { WAFFLE_PLATFORM_WGL
, "wgl" },
893 { WAFFLE_PLATFORM_X11_EGL
, "x11_egl" },
894 { WAFFLE_PLATFORM_SURFACELESS_EGL
, "surfaceless_egl" },
895 { WAFFLE_PLATFORM_SURFACELESS_EGL
, "sl" },
899 /// @brief Translate string to `enum waffle_enum`.
901 /// @param self is a list of map items. The last item must be zero-filled.
902 /// @param result is altered only if @a s if found.
903 /// @return true if @a s was found in @a map.
905 enum_map_translate_str(const struct enum_map
*self
, const char *s
, int *result
)
907 for (const struct enum_map
*i
= self
; i
->i
!= 0; ++i
) {
908 if (!strncmp(s
, i
->s
, strlen(i
->s
) + 1)) {
917 /// @return true on success.
919 parse_args(int argc
, char *argv
[])
921 bool loop_get_opt
= true;
924 removeXcodeArgs(&argc
, argv
);
927 // prevent getopt_long from printing an error message
930 while (loop_get_opt
) {
931 int opt
= getopt_long(argc
, argv
, "hp:", get_opts
, NULL
);
934 loop_get_opt
= false;
937 goto error_unrecognized_arg
;
939 if (!enum_map_translate_str(platform_map
, optarg
,
941 usage_error_printf("'%s' is not a valid platform", optarg
);
946 write_usage_and_exit(stdout
, EXIT_SUCCESS
);
949 loop_get_opt
= false;
955 goto error_unrecognized_arg
;
958 if (!waffle_platform
) {
959 usage_error_printf("--platform is required");
964 error_unrecognized_arg
:
966 usage_error_printf("unrecognized option '%s'", optarg
);
968 usage_error_printf("unrecognized option '-%c'", optopt
);
970 usage_error_printf("unrecognized option");
974 main(int argc
, char *argv
[])
976 parse_args(argc
, argv
);
978 #define unit_test_make(name) \
979 cmocka_unit_test_setup_teardown(name, gl_basic_init, gl_basic_fini)
981 const struct CMUnitTest tests
[] = {
983 // OPENGL, no profile
985 unit_test_make(OPENGL_rgb
),
986 unit_test_make(OPENGL_rgba
),
988 unit_test_make(OPENGL_CTX_FWDCOMPAT
),
989 unit_test_make(OPENGL_CTX_DEBUG
),
990 unit_test_make(OPENGL_CTX_ROBUST
),
991 unit_test_make(OPENGL_CTX_LOSE_CONTEXT
),
993 unit_test_make(OPENGL_fwdcompat_30
),
994 unit_test_make(OPENGL_fwdcompat_31
),
996 unit_test_make(OPENGL_10
),
997 unit_test_make(OPENGL_11
),
998 unit_test_make(OPENGL_12
),
999 unit_test_make(OPENGL_13
),
1000 unit_test_make(OPENGL_14
),
1001 unit_test_make(OPENGL_15
),
1002 unit_test_make(OPENGL_20
),
1003 unit_test_make(OPENGL_21
),
1004 unit_test_make(OPENGL_30
),
1005 unit_test_make(OPENGL_31
),
1007 // OPENGL, CORE profile
1009 unit_test_make(CORE_CTX_FWDCOMPAT
),
1010 unit_test_make(CORE_CTX_DEBUG
),
1011 unit_test_make(CORE_CTX_ROBUST
),
1012 unit_test_make(CORE_CTX_LOSE_CONTEXT
),
1014 unit_test_make(CORE_32
),
1015 unit_test_make(CORE_33
),
1016 unit_test_make(CORE_40
),
1017 unit_test_make(CORE_41
),
1018 unit_test_make(CORE_42
),
1019 unit_test_make(CORE_43
),
1020 unit_test_make(CORE_44
),
1021 unit_test_make(CORE_45
),
1022 unit_test_make(CORE_46
),
1024 // OPENGL, COMPATIBILITY profile
1026 unit_test_make(COMPATIBILITY_CTX_FWDCOMPAT
),
1027 unit_test_make(COMPATIBILITY_CTX_DEBUG
),
1028 unit_test_make(COMPATIBILITY_CTX_ROBUST
),
1029 unit_test_make(COMPATIBILITY_CTX_LOSE_CONTEXT
),
1031 unit_test_make(COMPATIBILITY_32
),
1032 unit_test_make(COMPATIBILITY_33
),
1033 unit_test_make(COMPATIBILITY_40
),
1034 unit_test_make(COMPATIBILITY_41
),
1035 unit_test_make(COMPATIBILITY_42
),
1036 unit_test_make(COMPATIBILITY_43
),
1037 unit_test_make(COMPATIBILITY_44
),
1038 unit_test_make(COMPATIBILITY_45
),
1039 unit_test_make(COMPATIBILITY_46
),
1043 unit_test_make(OPENGL_ES1_rgb
),
1044 unit_test_make(OPENGL_ES1_rgba
),
1046 unit_test_make(OPENGL_ES1_CTX_FWDCOMPAT
),
1047 unit_test_make(OPENGL_ES1_CTX_DEBUG
),
1048 unit_test_make(OPENGL_ES1_CTX_ROBUST
),
1049 unit_test_make(OPENGL_ES1_CTX_LOSE_CONTEXT
),
1051 unit_test_make(OPENGL_ES1_10
),
1052 unit_test_make(OPENGL_ES1_11
),
1056 unit_test_make(OPENGL_ES2_rgb
),
1057 unit_test_make(OPENGL_ES2_rgba
),
1059 unit_test_make(OPENGL_ES2_CTX_FWDCOMPAT
),
1060 unit_test_make(OPENGL_ES2_CTX_DEBUG
),
1061 unit_test_make(OPENGL_ES2_CTX_ROBUST
),
1062 unit_test_make(OPENGL_ES2_CTX_LOSE_CONTEXT
),
1064 unit_test_make(OPENGL_ES2_20
),
1068 unit_test_make(OPENGL_ES3_rgb
),
1069 unit_test_make(OPENGL_ES3_rgba
),
1071 unit_test_make(OPENGL_ES3_CTX_FWDCOMPAT
),
1072 unit_test_make(OPENGL_ES3_CTX_DEBUG
),
1073 unit_test_make(OPENGL_ES3_CTX_ROBUST
),
1074 unit_test_make(OPENGL_ES3_CTX_LOSE_CONTEXT
),
1076 unit_test_make(OPENGL_ES3_30
),
1077 unit_test_make(OPENGL_ES3_31
),
1078 unit_test_make(OPENGL_ES3_32
),
1081 return cmocka_run_group_tests_name(platform
, tests
, NULL
, NULL
);