tests: enable all the tests
[mesa-waffle.git] / examples / gl_basic.c
blob170888fa70696b2863e523db607d9bc6dc62c680
1 // Copyright 2012 - 2014 Intel Corporation
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // - Redistributions of source code must retain the above copyright notice, this
9 // list of conditions and the following disclaimer.
11 // - Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 /// @file
27 /// @brief Do some basic OpenGL rendering using Waffle.
28 ///
29 /// This example does the following:
30 /// 1. Dynamically choose the platform and OpenGL API according to
31 /// command line arguments.
32 /// 2. Create a window and OpenGL context.
33 /// 3. Fill the window with red, then green, then blue, sleeping between
34 /// each buffer swap.
36 #define _POSIX_C_SOURCE 199309L // glibc feature macro for nanosleep.
37 #define WAFFLE_API_VERSION 0x0106
38 #define WAFFLE_API_EXPERIMENTAL
40 #include <assert.h>
41 #include <getopt.h>
42 #include <stdarg.h>
43 #include <stdbool.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #if !defined(_WIN32)
48 #include <time.h>
49 #else
50 #include <windows.h>
51 #endif
53 #ifdef __APPLE__
54 # import <Foundation/NSAutoreleasePool.h>
55 # import <Appkit/NSApplication.h>
57 static void
58 removeXcodeArgs(int *argc, char **argv);
59 #endif
61 #include "waffle.h"
63 static const char *usage_message =
64 "usage:\n"
65 " gl_basic --platform=android|cgl|gbm|glx|wayland|wgl|x11_egl\n"
66 " --api=gl|gles1|gles2|gles3\n"
67 " [--version=MAJOR.MINOR]\n"
68 " [--profile=core|compat|none]\n"
69 " [--forward-compatible]\n"
70 " [--debug]\n"
71 " [--robust]\n"
72 " [--resize-window]\n"
73 " [--window-size=WIDTHxHEIGHT | --fullscreen]\n"
74 "\n"
75 "examples:\n"
76 " gl_basic --platform=glx --api=gl\n"
77 " gl_basic --platform=x11_egl --api=gl --version=3.2 --profile=core\n"
78 " gl_basic --platform=wayland --api=gles3\n"
79 "\n"
80 "description:\n"
81 " Create a window. Fill it with red, green, then blue.\n"
82 "\n"
83 "options:\n"
84 " --forward-compatible\n"
85 " Create a forward-compatible context.\n"
86 "\n"
87 " --debug\n"
88 " Create a debug context.\n"
89 "\n"
90 " --robust\n"
91 " Create a robust context.\n"
92 "\n"
93 " --resize-window\n"
94 " Resize the window between each draw call.\n"
95 "\n"
96 " --fullscreen\n"
97 " Create a fullscreen window.\n"
100 enum {
101 OPT_PLATFORM = 1,
102 OPT_API,
103 OPT_VERSION,
104 OPT_PROFILE,
105 OPT_DEBUG,
106 OPT_FORWARD_COMPATIBLE,
107 OPT_ROBUST,
108 OPT_RESIZE_WINDOW,
109 OPT_WINDOW_SIZE,
110 OPT_FULLSCREEN,
113 static const struct option get_opts[] = {
114 { .name = "platform", .has_arg = required_argument, .val = OPT_PLATFORM },
115 { .name = "api", .has_arg = required_argument, .val = OPT_API },
116 { .name = "version", .has_arg = required_argument, .val = OPT_VERSION },
117 { .name = "profile", .has_arg = required_argument, .val = OPT_PROFILE },
118 { .name = "debug", .has_arg = no_argument, .val = OPT_DEBUG },
119 { .name = "forward-compatible", .has_arg = no_argument, .val = OPT_FORWARD_COMPATIBLE },
120 { .name = "robust", .has_arg = no_argument, .val = OPT_ROBUST },
121 { .name = "resize-window", .has_arg = no_argument, .val = OPT_RESIZE_WINDOW },
122 { .name = "window-size", .has_arg = required_argument, .val = OPT_WINDOW_SIZE },
123 { .name = "fullscreen", .has_arg = no_argument, .val = OPT_FULLSCREEN },
124 { 0 },
127 #if defined(__GNUC__)
128 #define NORETURN __attribute__((noreturn))
129 #elif defined(_MSC_VER)
130 #define NORETURN __declspec(noreturn)
131 #else
132 #define NORETURN
133 #endif
135 static void NORETURN
136 error_printf(const char *fmt, ...)
138 va_list ap;
140 fflush(stdout);
142 va_start(ap, fmt);
143 fprintf(stderr, "gl_basic: error: ");
144 vfprintf(stderr, fmt, ap);
145 fprintf(stderr, "\n");
146 va_end(ap);
148 exit(EXIT_FAILURE);
151 static void NORETURN
152 usage_error_printf(const char *fmt, ...)
154 fflush(stdout);
155 fprintf(stderr, "gl_basic: usage error");
157 if (fmt) {
158 va_list ap;
159 va_start(ap, fmt);
160 fprintf(stderr, ": ");
161 vfprintf(stderr, fmt, ap);
162 va_end(ap);
165 fprintf(stderr, "\n");
166 fprintf(stderr, "\n");
167 fprintf(stderr, "%s", usage_message);
169 exit(EXIT_FAILURE);
172 static void
173 error_waffle(void)
175 const struct waffle_error_info *info = waffle_error_get_info();
176 const char *code = waffle_error_to_string(info->code);
178 if (info->message_length > 0)
179 error_printf("%s: %s", code, info->message);
180 else
181 error_printf("%s", code);
184 static void
185 error_get_gl_symbol(const char *name)
187 error_printf("failed to get function pointer for %s", name);
190 typedef float GLclampf;
191 typedef unsigned int GLbitfield;
192 typedef unsigned int GLint;
193 typedef int GLsizei;
194 typedef unsigned int GLenum;
195 typedef void GLvoid;
197 enum {
198 // Copied from <GL/gl*.h>.
199 GL_UNSIGNED_BYTE = 0x00001401,
200 GL_RGBA = 0x00001908,
201 GL_COLOR_BUFFER_BIT = 0x00004000,
203 GL_CONTEXT_FLAGS = 0x821e,
204 GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT = 0x00000001,
205 GL_CONTEXT_FLAG_DEBUG_BIT = 0x00000002,
206 GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT = 0x00000004 ,
209 static int window_width = 320;
210 static int window_height = 240;
212 #ifndef _WIN32
213 #define APIENTRY
214 #else
215 #ifndef APIENTRY
216 #define APIENTRY __stdcall
217 #endif
218 #endif
220 static void (APIENTRY *glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
221 static void (APIENTRY *glClear)(GLbitfield mask);
222 static GLenum (APIENTRY *glGetError)(void);
223 static void (APIENTRY *glGetIntegerv)(GLenum pname, GLint *params);
224 static void (APIENTRY *glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height,
225 GLenum format, GLenum type, GLvoid* data);
226 static void (APIENTRY *glViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
228 /// @brief Command line options.
229 struct options {
230 /// @brief One of `WAFFLE_PLATFORM_*`.
231 int platform;
233 /// @brief One of `WAFFLE_CONTEXT_OPENGL_*`.
234 int context_api;
236 /// @brief One of `WAFFLE_CONTEXT_PROFILE_*` or `WAFFLE_NONE`.
237 int context_profile;
239 int context_version;
241 bool context_forward_compatible;
242 bool context_debug;
243 bool context_robust;
245 bool resize_window;
247 bool fullscreen;
249 /// @brief One of `WAFFLE_DL_*`.
250 int dl;
253 struct enum_map {
254 int i;
255 const char *s;
258 static const struct enum_map platform_map[] = {
259 {WAFFLE_PLATFORM_ANDROID, "android" },
260 {WAFFLE_PLATFORM_CGL, "cgl", },
261 {WAFFLE_PLATFORM_GBM, "gbm" },
262 {WAFFLE_PLATFORM_GLX, "glx" },
263 {WAFFLE_PLATFORM_WAYLAND, "wayland" },
264 {WAFFLE_PLATFORM_WGL, "wgl" },
265 {WAFFLE_PLATFORM_X11_EGL, "x11_egl" },
266 {0, 0 },
269 static const struct enum_map context_api_map[] = {
270 {WAFFLE_CONTEXT_OPENGL, "gl" },
271 {WAFFLE_CONTEXT_OPENGL_ES1, "gles1" },
272 {WAFFLE_CONTEXT_OPENGL_ES2, "gles2" },
273 {WAFFLE_CONTEXT_OPENGL_ES3, "gles3" },
274 {0, 0 },
277 /// @brief Translate string to `enum waffle_enum`.
279 /// @param self is a list of map items. The last item must be zero-filled.
280 /// @param result is altered only if @a s if found.
281 /// @return true if @a s was found in @a map.
282 static bool
283 enum_map_translate_str(
284 const struct enum_map *self,
285 const char *s,
286 int *result)
288 for (const struct enum_map *i = self; i->i != 0; ++i) {
289 if (!strncmp(s, i->s, strlen(i->s) + 1)) {
290 *result = i->i;
291 return true;
295 return false;
298 /// @return true on success.
299 static bool
300 parse_args(int argc, char *argv[], struct options *opts)
302 bool ok;
303 bool loop_get_opt = true;
304 bool found_window_size = false;
306 #ifdef __APPLE__
307 removeXcodeArgs(&argc, argv);
308 #endif
310 // Set some context attrs to invalid values.
311 opts->context_profile = -1;
312 opts->context_version = -1;
314 while (loop_get_opt) {
315 int opt = getopt_long(argc, argv, "", get_opts, NULL);
316 switch (opt) {
317 case -1:
318 loop_get_opt = false;
319 break;
320 case '?':
321 goto error_unrecognized_arg;
322 case OPT_PLATFORM:
323 ok = enum_map_translate_str(platform_map, optarg,
324 &opts->platform);
325 if (!ok) {
326 usage_error_printf("'%s' is not a valid platform",
327 optarg);
329 break;
330 case OPT_API:
331 ok = enum_map_translate_str(context_api_map, optarg,
332 &opts->context_api);
333 if (!ok) {
334 usage_error_printf("'%s' is not a valid API for an OpenGL "
335 "context", optarg);
337 break;
338 case OPT_VERSION: {
339 int major;
340 int minor;
341 int match_count;
343 match_count = sscanf(optarg, "%d.%d", &major, &minor);
344 if (match_count != 2) {
345 usage_error_printf("'%s' is not a valid OpenGL version",
346 optarg);
348 opts->context_version = 10 * major + minor;
349 break;
351 case OPT_PROFILE:
352 if (strcmp(optarg, "none") == 0) {
353 opts->context_profile = WAFFLE_NONE;
354 } else if (strcmp(optarg, "core") == 0) {
355 opts->context_profile = WAFFLE_CONTEXT_CORE_PROFILE;
356 } else if (strcmp(optarg, "compat") == 0) {
357 opts->context_profile = WAFFLE_CONTEXT_COMPATIBILITY_PROFILE;
358 } else {
359 usage_error_printf("'%s' is not a valid OpenGL profile",
360 optarg);
362 break;
363 case OPT_FORWARD_COMPATIBLE:
364 opts->context_forward_compatible = true;
365 break;
366 case OPT_DEBUG:
367 opts->context_debug = true;
368 break;
369 case OPT_ROBUST:
370 opts->context_robust = true;
371 break;
372 case OPT_RESIZE_WINDOW:
373 opts->resize_window = true;
374 break;
375 case OPT_WINDOW_SIZE: {
376 int match_count;
377 match_count = sscanf(optarg, "%dx%d", &window_width, &window_height);
378 if (match_count != 2) {
379 usage_error_printf("'%s' is not a valid window geometry",
380 optarg);
382 found_window_size = true;
383 break;
385 case OPT_FULLSCREEN:
386 opts->fullscreen = true;
387 break;
388 default:
389 abort();
390 loop_get_opt = false;
391 break;
395 if (optind < argc) {
396 goto error_unrecognized_arg;
399 if (!opts->platform) {
400 usage_error_printf("--platform is required");
403 if (!opts->context_api) {
404 usage_error_printf("--api is required");
407 if (opts->fullscreen && found_window_size) {
408 usage_error_printf("--fullscreen and --window-size are mutually "
409 "exclusive options");
412 // Set dl.
413 switch (opts->context_api) {
414 case WAFFLE_CONTEXT_OPENGL: opts->dl = WAFFLE_DL_OPENGL; break;
415 case WAFFLE_CONTEXT_OPENGL_ES1: opts->dl = WAFFLE_DL_OPENGL_ES1; break;
416 case WAFFLE_CONTEXT_OPENGL_ES2: opts->dl = WAFFLE_DL_OPENGL_ES2; break;
417 case WAFFLE_CONTEXT_OPENGL_ES3: opts->dl = WAFFLE_DL_OPENGL_ES3; break;
418 default:
419 abort();
420 break;
423 return true;
425 error_unrecognized_arg:
426 usage_error_printf("unrecognized option '%s'", optarg);
429 // The rules that dictate how to properly query a GL symbol are complex. The
430 // rules depend on the OS, on the winsys API, and even on the particular driver
431 // being used. The rules differ between EGL 1.4 and EGL 1.5; differ between
432 // Linux, Windows, and Mac; and differ between Mesa and Mali.
434 // This function hides that complexity with a naive heuristic: try, then try
435 // again.
436 static void *
437 get_gl_symbol(const struct options *opts, const char *name)
439 void *sym = NULL;
441 if (waffle_dl_can_open(opts->dl)) {
442 sym = waffle_dl_sym(opts->dl, name);
445 if (!sym) {
446 sym = waffle_get_proc_address(name);
449 return sym;
452 static bool
453 draw(struct waffle_window *window, bool resize)
455 bool ok;
456 unsigned char *colors;
457 int width = window_width;
458 int height = window_height;
460 #if !defined(_WIN32)
461 static const struct timespec sleep_time = {
462 // 0.5 sec
463 .tv_sec = 0,
464 .tv_nsec = 500000000,
466 #endif
468 for (int i = 0; i < 3; ++i) {
469 switch (i) {
470 case 0: glClearColor(1, 0, 0, 1); break;
471 case 1: glClearColor(0, 1, 0, 1); break;
472 case 2: glClearColor(0, 0, 1, 1); break;
473 case 3: abort(); break;
476 if (resize) {
477 width = (i + 2) * 40;
478 height = width;
479 waffle_window_resize(window, width, height);
480 glViewport(0, 0, width, height);
483 glClear(GL_COLOR_BUFFER_BIT);
485 colors = calloc(width * height * 4, sizeof(*colors));
486 glReadPixels(0, 0,
487 width, height,
488 GL_RGBA, GL_UNSIGNED_BYTE,
489 colors);
490 for (int j = 0; j < width * height * 4; j += 4) {
491 if ((colors[j] != (i == 0 ? 0xff : 0)) ||
492 (colors[j+1] != (i == 1 ? 0xff : 0)) ||
493 (colors[j+2] != (i == 2 ? 0xff : 0)) ||
494 (colors[j+3] != 0xff)) {
495 fprintf(stderr, "glReadPixels returned unexpected result\n");
496 break;
499 free(colors);
501 if (i == 0) {
502 ok = waffle_window_show(window);
503 if (!ok)
504 return false;
507 ok = waffle_window_swap_buffers(window);
508 if (!ok)
509 return false;
511 #if !defined(_WIN32)
512 nanosleep(&sleep_time, NULL);
513 #else
514 Sleep(500);
515 #endif
518 return true;
521 #ifdef __APPLE__
523 static NSAutoreleasePool *pool;
525 static void
526 cocoa_init(void)
528 // From the NSApplication Class Reference:
529 // [...] if you do need to use Cocoa classes within the main()
530 // function itself (other than to load nib files or to instantiate
531 // NSApplication), you should create an autorelease pool before using
532 // the classes and then release the pool when you’re done.
533 pool = [[NSAutoreleasePool alloc] init];
535 // From the NSApplication Class Reference:
536 // The sharedApplication class method initializes the display
537 // environment and connects your program to the window server and the
538 // display server.
540 // It also creates the singleton NSApp if it does not yet exist.
541 [NSApplication sharedApplication];
544 static void
545 cocoa_finish(void)
547 [pool drain];
550 static void
551 removeArg(int index, int *argc, char **argv)
553 --*argc;
554 for (; index < *argc; ++index)
555 argv[index] = argv[index + 1];
558 static void
559 removeXcodeArgs(int *argc, char **argv)
561 // Xcode sometimes adds additional arguments.
562 for (int i = 1; i < *argc; )
564 if (strcmp(argv[i], "-NSDocumentRevisionsDebugMode") == 0 ||
565 strcmp(argv[i], "-ApplePersistenceIgnoreState" ) == 0)
567 removeArg(i, argc, argv);
568 removeArg(i, argc, argv);
569 } else
570 ++i;
574 #endif // __APPLE__
576 #ifdef __native_client__
577 #include "ppapi_simple/ps_main.h"
579 // We need to rename main() for native client
580 // because ppapi_simple already defines main().
582 int basic_test_main(int argc, char **argv);
583 PPAPI_SIMPLE_REGISTER_MAIN(basic_test_main)
585 basic_test_main(int argc, char **argv)
586 #else
588 main(int argc, char **argv)
589 #endif
591 bool ok;
592 int i;
594 struct options opts = {0};
596 int32_t init_attrib_list[3];
597 int32_t config_attrib_list[64];
598 intptr_t window_attrib_list[5];
600 struct waffle_display *dpy;
601 struct waffle_config *config;
602 struct waffle_context *ctx;
603 struct waffle_window *window;
605 GLint context_flags = 0;
607 #ifdef __APPLE__
608 cocoa_init();
609 #endif
611 #ifdef __native_client__
612 // Fixed arguments for native client.
613 opts.context_api = WAFFLE_CONTEXT_OPENGL_ES2;
614 opts.platform = WAFFLE_PLATFORM_NACL;
615 opts.dl = WAFFLE_DL_OPENGL_ES2;
616 opts.context_profile = WAFFLE_NONE;
617 opts.context_version = -1;
618 #else
619 ok = parse_args(argc, argv, &opts);
620 if (!ok)
621 exit(EXIT_FAILURE);
622 #endif
624 i = 0;
625 init_attrib_list[i++] = WAFFLE_PLATFORM;
626 init_attrib_list[i++] = opts.platform;
627 init_attrib_list[i++] = WAFFLE_NONE;
629 ok = waffle_init(init_attrib_list);
630 if (!ok)
631 error_waffle();
633 dpy = waffle_display_connect(NULL);
634 if (!dpy)
635 error_waffle();
637 if (!waffle_display_supports_context_api(dpy, opts.context_api)) {
638 error_printf("Display does not support %s",
639 waffle_enum_to_string(opts.context_api));
642 glClear = get_gl_symbol(&opts, "glClear");
643 if (!glClear)
644 error_get_gl_symbol("glClear");
646 glClearColor = get_gl_symbol(&opts, "glClearColor");
647 if (!glClearColor)
648 error_get_gl_symbol("glClearColor");
650 glGetError = get_gl_symbol(&opts, "glGetError");
651 if (!glGetError)
652 error_get_gl_symbol("glGetError");
654 glGetIntegerv = get_gl_symbol(&opts, "glGetIntegerv");
655 if (!glGetIntegerv)
656 error_get_gl_symbol("glGetIntegerv");
658 glReadPixels = get_gl_symbol(&opts, "glReadPixels");
659 if (!glReadPixels)
660 error_get_gl_symbol("glReadPixels");
662 glViewport = get_gl_symbol(&opts, "glViewport");
663 if (!glViewport)
664 error_get_gl_symbol("glViewport");
666 i = 0;
667 config_attrib_list[i++] = WAFFLE_CONTEXT_API;
668 config_attrib_list[i++] = opts.context_api;
670 if (opts.context_profile != -1) {
671 config_attrib_list[i++] = WAFFLE_CONTEXT_PROFILE;
672 config_attrib_list[i++] = opts.context_profile;
675 if (opts.context_version != -1) {
676 config_attrib_list[i++] = WAFFLE_CONTEXT_MAJOR_VERSION;
677 config_attrib_list[i++] = opts.context_version / 10;
678 config_attrib_list[i++] = WAFFLE_CONTEXT_MINOR_VERSION;
679 config_attrib_list[i++] = opts.context_version % 10;
682 if (opts.context_forward_compatible) {
683 config_attrib_list[i++] = WAFFLE_CONTEXT_FORWARD_COMPATIBLE;
684 config_attrib_list[i++] = true;
687 if (opts.context_debug) {
688 config_attrib_list[i++] = WAFFLE_CONTEXT_DEBUG;
689 config_attrib_list[i++] = true;
692 if (opts.context_robust) {
693 config_attrib_list[i++] = WAFFLE_CONTEXT_ROBUST_ACCESS,
694 config_attrib_list[i++] = true;
697 config_attrib_list[i++] = WAFFLE_RED_SIZE;
698 config_attrib_list[i++] = 8;
699 config_attrib_list[i++] = WAFFLE_GREEN_SIZE;
700 config_attrib_list[i++] = 8;
701 config_attrib_list[i++] = WAFFLE_BLUE_SIZE;
702 config_attrib_list[i++] = 8;
703 config_attrib_list[i++] = WAFFLE_ALPHA_SIZE;
704 config_attrib_list[i++] = 8;
705 config_attrib_list[i++] = WAFFLE_DOUBLE_BUFFERED;
706 config_attrib_list[i++] = true;
707 config_attrib_list[i++] = 0;
709 config = waffle_config_choose(dpy, config_attrib_list);
710 if (!config)
711 error_waffle();
713 ctx = waffle_context_create(config, NULL);
714 if (!ctx)
715 error_waffle();
718 i = 0;
719 if (opts.fullscreen) {
720 window_attrib_list[i++] = WAFFLE_WINDOW_FULLSCREEN;
721 window_attrib_list[i++] = true;
722 window_attrib_list[i++] = 0;
723 } else {
724 window_attrib_list[i++] = WAFFLE_WINDOW_WIDTH;
725 window_attrib_list[i++] = window_width;
726 window_attrib_list[i++] = WAFFLE_WINDOW_HEIGHT;
727 window_attrib_list[i++] = window_height;
728 window_attrib_list[i++] = 0;
731 window = waffle_window_create2(config, window_attrib_list);
732 if (!window)
733 error_waffle();
735 ok = waffle_make_current(dpy, window, ctx);
736 if (!ok)
737 error_waffle();
739 if (opts.context_forward_compatible || opts.context_debug) {
740 glGetIntegerv(GL_CONTEXT_FLAGS, &context_flags);
743 if (glGetError())
744 error_printf("glGetIntegerv(GL_CONTEXT_FLAGS) failed");
746 if (opts.context_forward_compatible
747 && !(context_flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)) {
748 error_printf("context is not forward-compatible");
751 if (opts.context_debug
752 && !(context_flags & GL_CONTEXT_FLAG_DEBUG_BIT)) {
753 error_printf("context is not a debug context");
756 // Don't verify if the context is robust because that pollutes this simple
757 // example program with hairy GL logic. The method of verifying if
758 // a context is robust varies on the combination of context profile,
759 // context version, and supported extensions.
761 ok = draw(window, opts.resize_window);
762 if (!ok)
763 error_waffle();
765 ok = waffle_make_current(dpy, NULL, NULL);
766 if (!ok)
767 error_waffle();
769 ok = waffle_window_destroy(window);
770 if (!ok)
771 error_waffle();
773 ok = waffle_context_destroy(ctx);
774 if (!ok)
775 error_waffle();
777 ok = waffle_config_destroy(config);
778 if (!ok)
779 error_waffle();
781 ok = waffle_display_disconnect(dpy);
782 if (!ok)
783 error_waffle();
785 ok = waffle_teardown();
786 if (!ok)
787 error_waffle();
789 #ifdef __APPLE__
790 cocoa_finish();
791 #endif
793 printf("gl_basic: run was successful\n");
794 return EXIT_SUCCESS;