]> git.cworth.org Git - apitrace-tests/blob - apps/egl/eglut/eglut.c
Add egl apps.
[apitrace-tests] / apps / egl / eglut / eglut.c
1 /*
2  * Copyright (C) 2010 LunarG Inc.
3  *
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:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the 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
20  * DEALINGS IN THE SOFTWARE.
21  *
22  * Authors:
23  *    Chia-I Wu <olv@lunarg.com>
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <sys/time.h>
31
32 #include "EGL/egl.h"
33 #include "EGL/eglext.h"
34
35 #include "eglutint.h"
36
37 static struct eglut_state _eglut_state = {
38    .api_mask = EGLUT_OPENGL_ES1_BIT,
39    .window_width = 300,
40    .window_height = 300,
41    .verbose = 0,
42    .num_windows = 0,
43 };
44
45 struct eglut_state *_eglut = &_eglut_state;
46
47 void
48 _eglutFatal(char *format, ...)
49 {
50   va_list args;
51
52   va_start(args, format);
53
54   fprintf(stderr, "EGLUT: ");
55   vfprintf(stderr, format, args);
56   va_end(args);
57   putc('\n', stderr);
58
59   exit(1);
60 }
61
62 /* return current time (in milliseconds) */
63 int
64 _eglutNow(void)
65 {
66    struct timeval tv;
67 #ifdef __VMS
68    (void) gettimeofday(&tv, NULL );
69 #else
70    struct timezone tz;
71    (void) gettimeofday(&tv, &tz);
72 #endif
73    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
74 }
75
76 static void
77 _eglutDestroyWindow(struct eglut_window *win)
78 {
79    if (_eglut->surface_type != EGL_PBUFFER_BIT &&
80        _eglut->surface_type != EGL_SCREEN_BIT_MESA)
81       eglDestroySurface(_eglut->dpy, win->surface);
82
83    _eglutNativeFiniWindow(win);
84
85    eglDestroyContext(_eglut->dpy, win->context);
86 }
87
88 static EGLConfig
89 _eglutChooseConfig(void)
90 {
91    EGLConfig config;
92    EGLint config_attribs[32];
93    EGLint renderable_type, num_configs, i;
94
95    i = 0;
96    config_attribs[i++] = EGL_RED_SIZE;
97    config_attribs[i++] = 1;
98    config_attribs[i++] = EGL_GREEN_SIZE;
99    config_attribs[i++] = 1;
100    config_attribs[i++] = EGL_BLUE_SIZE;
101    config_attribs[i++] = 1;
102    config_attribs[i++] = EGL_DEPTH_SIZE;
103    config_attribs[i++] = 1;
104
105    config_attribs[i++] = EGL_SURFACE_TYPE;
106    config_attribs[i++] = _eglut->surface_type;
107
108    config_attribs[i++] = EGL_RENDERABLE_TYPE;
109    renderable_type = 0x0;
110    if (_eglut->api_mask & EGLUT_OPENGL_BIT)
111       renderable_type |= EGL_OPENGL_BIT;
112    if (_eglut->api_mask & EGLUT_OPENGL_ES1_BIT)
113       renderable_type |= EGL_OPENGL_ES_BIT;
114    if (_eglut->api_mask & EGLUT_OPENGL_ES2_BIT)
115       renderable_type |= EGL_OPENGL_ES2_BIT;
116    if (_eglut->api_mask & EGLUT_OPENVG_BIT)
117       renderable_type |= EGL_OPENVG_BIT;
118    config_attribs[i++] = renderable_type;
119
120    config_attribs[i] = EGL_NONE;
121
122    if (!eglChooseConfig(_eglut->dpy,
123             config_attribs, &config, 1, &num_configs) || !num_configs)
124       _eglutFatal("failed to choose a config");
125
126    return config;
127 }
128
129 static struct eglut_window *
130 _eglutCreateWindow(const char *title, int x, int y, int w, int h)
131 {
132    struct eglut_window *win;
133    EGLint context_attribs[4];
134    EGLint api, i;
135
136    win = calloc(1, sizeof(*win));
137    if (!win)
138       _eglutFatal("failed to allocate window");
139
140    win->config = _eglutChooseConfig();
141
142    i = 0;
143    context_attribs[i] = EGL_NONE;
144
145    /* multiple APIs? */
146
147    api = EGL_OPENGL_ES_API;
148    if (_eglut->api_mask & EGLUT_OPENGL_BIT) {
149       api = EGL_OPENGL_API;
150    }
151    else if (_eglut->api_mask & EGLUT_OPENVG_BIT) {
152       api = EGL_OPENVG_API;
153    }
154    else if (_eglut->api_mask & EGLUT_OPENGL_ES2_BIT) {
155       context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
156       context_attribs[i++] = 2;
157    }
158
159    context_attribs[i] = EGL_NONE;
160
161    eglBindAPI(api);
162    win->context = eglCreateContext(_eglut->dpy,
163          win->config, EGL_NO_CONTEXT, context_attribs);
164    if (!win->context)
165       _eglutFatal("failed to create context");
166
167    _eglutNativeInitWindow(win, title, x, y, w, h);
168    switch (_eglut->surface_type) {
169    case EGL_WINDOW_BIT:
170       win->surface = eglCreateWindowSurface(_eglut->dpy,
171             win->config, win->native.u.window, NULL);
172       break;
173    case EGL_PIXMAP_BIT:
174       win->surface = eglCreatePixmapSurface(_eglut->dpy,
175             win->config, win->native.u.pixmap, NULL);
176       break;
177    case EGL_PBUFFER_BIT:
178    case EGL_SCREEN_BIT_MESA:
179       win->surface = win->native.u.surface;
180       break;
181    default:
182       break;
183    }
184    if (win->surface == EGL_NO_SURFACE)
185       _eglutFatal("failed to create surface");
186
187    return win;
188 }
189
190 void
191 eglutInitAPIMask(int mask)
192 {
193    _eglut->api_mask = mask;
194 }
195
196 void
197 eglutInitWindowSize(int width, int height)
198 {
199    _eglut->window_width = width;
200    _eglut->window_height = height;
201 }
202
203 void
204 eglutInit(int argc, char **argv)
205 {
206    int i;
207
208    for (i = 1; i < argc; i++) {
209       if (strcmp(argv[i], "-display") == 0)
210          _eglut->display_name = argv[++i];
211       else if (strcmp(argv[i], "-info") == 0) {
212          _eglut->verbose = 1;
213       }
214    }
215
216    _eglutNativeInitDisplay();
217    _eglut->dpy = eglGetDisplay(_eglut->native_dpy);
218
219    if (!eglInitialize(_eglut->dpy, &_eglut->major, &_eglut->minor))
220       _eglutFatal("failed to initialize EGL display");
221
222    _eglut->init_time = _eglutNow();
223
224    printf("EGL_VERSION = %s\n", eglQueryString(_eglut->dpy, EGL_VERSION));
225    if (_eglut->verbose) {
226       printf("EGL_VENDOR = %s\n", eglQueryString(_eglut->dpy, EGL_VENDOR));
227       printf("EGL_EXTENSIONS = %s\n",
228             eglQueryString(_eglut->dpy, EGL_EXTENSIONS));
229       printf("EGL_CLIENT_APIS = %s\n",
230             eglQueryString(_eglut->dpy, EGL_CLIENT_APIS));
231    }
232 }
233
234 int
235 eglutGet(int state)
236 {
237    int val;
238
239    switch (state) {
240    case EGLUT_ELAPSED_TIME:
241       val = _eglutNow() - _eglut->init_time;
242       break;
243    default:
244       val = -1;
245       break;
246    }
247
248    return val;
249 }
250
251 void
252 eglutIdleFunc(EGLUTidleCB func)
253 {
254    _eglut->idle_cb = func;
255 }
256
257 void
258 eglutPostRedisplay(void)
259 {
260    _eglut->redisplay = 1;
261 }
262
263 void
264 eglutMainLoop(void)
265 {
266    struct eglut_window *win = _eglut->current;
267
268    if (!win)
269       _eglutFatal("no window is created\n");
270
271    if (win->reshape_cb)
272       win->reshape_cb(win->native.width, win->native.height);
273
274    _eglutNativeEventLoop();
275 }
276
277 static void
278 _eglutFini(void)
279 {
280    eglTerminate(_eglut->dpy);
281    _eglutNativeFiniDisplay();
282 }
283
284 void
285 eglutDestroyWindow(int win)
286 {
287    struct eglut_window *window = _eglut->current;
288
289    if (window->index != win)
290       return;
291
292    /* XXX it causes some bug in st/egl KMS backend */
293    if ( _eglut->surface_type != EGL_SCREEN_BIT_MESA)
294       eglMakeCurrent(_eglut->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
295
296    _eglutDestroyWindow(_eglut->current);
297 }
298
299 static void
300 _eglutDefaultKeyboard(unsigned char key)
301 {
302    if (key == 27) {
303       if (_eglut->current)
304          eglutDestroyWindow(_eglut->current->index);
305       _eglutFini();
306
307       exit(0);
308    }
309 }
310
311 int
312 eglutCreateWindow(const char *title)
313 {
314    struct eglut_window *win;
315
316    win = _eglutCreateWindow(title, 0, 0,
317          _eglut->window_width, _eglut->window_height);
318
319    win->index = _eglut->num_windows++;
320    win->reshape_cb = NULL;
321    win->display_cb = NULL;
322    win->keyboard_cb = _eglutDefaultKeyboard;
323    win->special_cb = NULL;
324
325    if (!eglMakeCurrent(_eglut->dpy, win->surface, win->surface, win->context))
326       _eglutFatal("failed to make window current");
327    _eglut->current = win;
328
329    return win->index;
330 }
331
332 int
333 eglutGetWindowWidth(void)
334 {
335    struct eglut_window *win = _eglut->current;
336    return win->native.width;
337 }
338
339 int
340 eglutGetWindowHeight(void)
341 {
342    struct eglut_window *win = _eglut->current;
343    return win->native.height;
344 }
345
346 void
347 eglutDisplayFunc(EGLUTdisplayCB func)
348 {
349    struct eglut_window *win = _eglut->current;
350    win->display_cb = func;
351
352 }
353
354 void
355 eglutReshapeFunc(EGLUTreshapeCB func)
356 {
357    struct eglut_window *win = _eglut->current;
358    win->reshape_cb = func;
359 }
360
361 void
362 eglutKeyboardFunc(EGLUTkeyboardCB func)
363 {
364    struct eglut_window *win = _eglut->current;
365    win->keyboard_cb = func;
366 }
367
368 void
369 eglutSpecialFunc(EGLUTspecialCB func)
370 {
371    struct eglut_window *win = _eglut->current;
372    win->special_cb = func;
373 }