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