Merge branch 'mesa_7_7_branch'
[mesa.git] / progs / egl / xeglgears.c
1 /*
2 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
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
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22 /*
23 * Ported to X/EGL/GLES. XXX Actually, uses full OpenGL ATM.
24 * Brian Paul
25 * 30 May 2008
26 */
27
28 /*
29 * Command line options:
30 * -info print GL implementation information
31 *
32 */
33
34
35 #include <math.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <X11/Xlib.h>
40 #include <X11/Xutil.h>
41 #include <X11/keysym.h>
42 #include <GL/gl.h>
43 #include <EGL/egl.h>
44
45
46 #define BENCHMARK
47
48 #ifdef BENCHMARK
49
50 /* XXX this probably isn't very portable */
51
52 #include <sys/time.h>
53 #include <unistd.h>
54
55 /* return current time (in seconds) */
56 static double
57 current_time(void)
58 {
59 struct timeval tv;
60 #ifdef __VMS
61 (void) gettimeofday(&tv, NULL );
62 #else
63 struct timezone tz;
64 (void) gettimeofday(&tv, &tz);
65 #endif
66 return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
67 }
68
69 #else /*BENCHMARK*/
70
71 /* dummy */
72 static double
73 current_time(void)
74 {
75 /* update this function for other platforms! */
76 static double t = 0.0;
77 static int warn = 1;
78 if (warn) {
79 fprintf(stderr, "Warning: current_time() not implemented!!\n");
80 warn = 0;
81 }
82 return t += 1.0;
83 }
84
85 #endif /*BENCHMARK*/
86
87
88
89 #ifndef M_PI
90 #define M_PI 3.14159265
91 #endif
92
93
94 static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
95 static GLint gear1, gear2, gear3;
96 static GLfloat angle = 0.0;
97
98 /*
99 *
100 * Draw a gear wheel. You'll probably want to call this function when
101 * building a display list since we do a lot of trig here.
102 *
103 * Input: inner_radius - radius of hole at center
104 * outer_radius - radius at center of teeth
105 * width - width of gear
106 * teeth - number of teeth
107 * tooth_depth - depth of tooth
108 */
109 static void
110 gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
111 GLint teeth, GLfloat tooth_depth)
112 {
113 GLint i;
114 GLfloat r0, r1, r2;
115 GLfloat angle, da;
116 GLfloat u, v, len;
117
118 r0 = inner_radius;
119 r1 = outer_radius - tooth_depth / 2.0;
120 r2 = outer_radius + tooth_depth / 2.0;
121
122 da = 2.0 * M_PI / teeth / 4.0;
123
124 glShadeModel(GL_FLAT);
125
126 glNormal3f(0.0, 0.0, 1.0);
127
128 /* draw front face */
129 glBegin(GL_QUAD_STRIP);
130 for (i = 0; i <= teeth; i++) {
131 angle = i * 2.0 * M_PI / teeth;
132 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
133 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
134 if (i < teeth) {
135 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
136 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
137 width * 0.5);
138 }
139 }
140 glEnd();
141
142 /* draw front sides of teeth */
143 glBegin(GL_QUADS);
144 da = 2.0 * M_PI / teeth / 4.0;
145 for (i = 0; i < teeth; i++) {
146 angle = i * 2.0 * M_PI / teeth;
147
148 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
149 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
150 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
151 width * 0.5);
152 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
153 width * 0.5);
154 }
155 glEnd();
156
157 glNormal3f(0.0, 0.0, -1.0);
158
159 /* draw back face */
160 glBegin(GL_QUAD_STRIP);
161 for (i = 0; i <= teeth; i++) {
162 angle = i * 2.0 * M_PI / teeth;
163 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
164 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
165 if (i < teeth) {
166 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
167 -width * 0.5);
168 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
169 }
170 }
171 glEnd();
172
173 /* draw back sides of teeth */
174 glBegin(GL_QUADS);
175 da = 2.0 * M_PI / teeth / 4.0;
176 for (i = 0; i < teeth; i++) {
177 angle = i * 2.0 * M_PI / teeth;
178
179 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
180 -width * 0.5);
181 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
182 -width * 0.5);
183 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
184 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
185 }
186 glEnd();
187
188 /* draw outward faces of teeth */
189 glBegin(GL_QUAD_STRIP);
190 for (i = 0; i < teeth; i++) {
191 angle = i * 2.0 * M_PI / teeth;
192
193 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
194 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
195 u = r2 * cos(angle + da) - r1 * cos(angle);
196 v = r2 * sin(angle + da) - r1 * sin(angle);
197 len = sqrt(u * u + v * v);
198 u /= len;
199 v /= len;
200 glNormal3f(v, -u, 0.0);
201 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
202 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
203 glNormal3f(cos(angle), sin(angle), 0.0);
204 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
205 width * 0.5);
206 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
207 -width * 0.5);
208 u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
209 v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
210 glNormal3f(v, -u, 0.0);
211 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
212 width * 0.5);
213 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
214 -width * 0.5);
215 glNormal3f(cos(angle), sin(angle), 0.0);
216 }
217
218 glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
219 glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
220
221 glEnd();
222
223 glShadeModel(GL_SMOOTH);
224
225 /* draw inside radius cylinder */
226 glBegin(GL_QUAD_STRIP);
227 for (i = 0; i <= teeth; i++) {
228 angle = i * 2.0 * M_PI / teeth;
229 glNormal3f(-cos(angle), -sin(angle), 0.0);
230 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
231 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
232 }
233 glEnd();
234 }
235
236
237 static void
238 draw(void)
239 {
240 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
241
242 glPushMatrix();
243 glRotatef(view_rotx, 1.0, 0.0, 0.0);
244 glRotatef(view_roty, 0.0, 1.0, 0.0);
245 glRotatef(view_rotz, 0.0, 0.0, 1.0);
246
247 glPushMatrix();
248 glTranslatef(-3.0, -2.0, 0.0);
249 glRotatef(angle, 0.0, 0.0, 1.0);
250 glCallList(gear1);
251 glPopMatrix();
252
253 glPushMatrix();
254 glTranslatef(3.1, -2.0, 0.0);
255 glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
256 glCallList(gear2);
257 glPopMatrix();
258
259 glPushMatrix();
260 glTranslatef(-3.1, 4.2, 0.0);
261 glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
262 glCallList(gear3);
263 glPopMatrix();
264
265 glPopMatrix();
266 }
267
268
269 /* new window size or exposure */
270 static void
271 reshape(int width, int height)
272 {
273 GLfloat ar = (GLfloat) width / (GLfloat) height;
274
275 glViewport(0, 0, (GLint) width, (GLint) height);
276
277 glMatrixMode(GL_PROJECTION);
278 glLoadIdentity();
279 glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
280
281 glMatrixMode(GL_MODELVIEW);
282 glLoadIdentity();
283 glTranslatef(0.0, 0.0, -40.0);
284 }
285
286
287
288 static void
289 init(void)
290 {
291 static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
292 static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
293 static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
294 static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
295
296 glLightfv(GL_LIGHT0, GL_POSITION, pos);
297 glEnable(GL_CULL_FACE);
298 glEnable(GL_LIGHTING);
299 glEnable(GL_LIGHT0);
300 glEnable(GL_DEPTH_TEST);
301
302 /* make the gears */
303 gear1 = glGenLists(1);
304 glNewList(gear1, GL_COMPILE);
305 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
306 gear(1.0, 4.0, 1.0, 20, 0.7);
307 glEndList();
308
309 gear2 = glGenLists(1);
310 glNewList(gear2, GL_COMPILE);
311 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
312 gear(0.5, 2.0, 2.0, 10, 0.7);
313 glEndList();
314
315 gear3 = glGenLists(1);
316 glNewList(gear3, GL_COMPILE);
317 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
318 gear(1.3, 2.0, 0.5, 10, 0.7);
319 glEndList();
320
321 glEnable(GL_NORMALIZE);
322
323 glClearColor(0.2, 0.2, 0.2, 0.0);
324 }
325
326
327 struct egl_manager {
328 EGLNativeDisplayType xdpy;
329 EGLNativeWindowType xwin;
330 EGLNativePixmapType xpix;
331
332 EGLDisplay dpy;
333 EGLConfig conf;
334 EGLContext ctx;
335
336 EGLSurface win;
337 EGLSurface pix;
338 EGLSurface pbuf;
339
340 EGLBoolean verbose;
341 EGLint major, minor;
342 };
343
344 static struct egl_manager *
345 egl_manager_new(EGLNativeDisplayType xdpy, const EGLint *attrib_list,
346 EGLBoolean verbose)
347 {
348 struct egl_manager *eman;
349 const char *ver;
350 EGLint num_conf;
351
352 eman = calloc(1, sizeof(*eman));
353 if (!eman)
354 return NULL;
355
356 eman->verbose = verbose;
357 eman->xdpy = xdpy;
358
359 eman->dpy = eglGetDisplay(eman->xdpy);
360 if (eman->dpy == EGL_NO_DISPLAY) {
361 printf("eglGetDisplay() failed\n");
362 free(eman);
363 return NULL;
364 }
365
366 if (!eglInitialize(eman->dpy, &eman->major, &eman->minor)) {
367 printf("eglInitialize() failed\n");
368 free(eman);
369 return NULL;
370 }
371
372 ver = eglQueryString(eman->dpy, EGL_VERSION);
373 printf("EGL_VERSION = %s\n", ver);
374
375 if (!eglChooseConfig(eman->dpy, attrib_list, &eman->conf, 1, &num_conf) ||
376 !num_conf) {
377 printf("eglChooseConfig() failed\n");
378 eglTerminate(eman->dpy);
379 free(eman);
380 return NULL;
381 }
382
383 eman->ctx = eglCreateContext(eman->dpy, eman->conf, EGL_NO_CONTEXT, NULL);
384 if (eman->ctx == EGL_NO_CONTEXT) {
385 printf("eglCreateContext() failed\n");
386 eglTerminate(eman->dpy);
387 free(eman);
388 return NULL;
389 }
390
391 return eman;
392 }
393
394 static EGLBoolean
395 egl_manager_create_window(struct egl_manager *eman, const char *name,
396 EGLint w, EGLint h, EGLBoolean need_surface,
397 EGLBoolean fullscreen, const EGLint *attrib_list)
398 {
399 XVisualInfo vinfo_template, *vinfo = NULL;
400 EGLint val, num_vinfo;
401 Window root;
402 XSetWindowAttributes attrs;
403 unsigned long mask;
404 EGLint x = 0, y = 0;
405
406 if (!eglGetConfigAttrib(eman->dpy, eman->conf,
407 EGL_NATIVE_VISUAL_ID, &val)) {
408 printf("eglGetConfigAttrib() failed\n");
409 return EGL_FALSE;
410 }
411 if (val) {
412 vinfo_template.visualid = (VisualID) val;
413 vinfo = XGetVisualInfo(eman->xdpy, VisualIDMask, &vinfo_template, &num_vinfo);
414 }
415 /* try harder if window surface is not needed */
416 if (!vinfo && !need_surface &&
417 eglGetConfigAttrib(eman->dpy, eman->conf, EGL_BUFFER_SIZE, &val)) {
418 if (val == 32)
419 val = 24;
420 vinfo_template.depth = val;
421 vinfo = XGetVisualInfo(eman->xdpy, VisualDepthMask, &vinfo_template, &num_vinfo);
422 }
423
424 if (!vinfo) {
425 printf("XGetVisualInfo() failed\n");
426 return EGL_FALSE;
427 }
428
429 root = DefaultRootWindow(eman->xdpy);
430 if (fullscreen) {
431 x = y = 0;
432 w = DisplayWidth(eman->xdpy, DefaultScreen(eman->xdpy));
433 h = DisplayHeight(eman->xdpy, DefaultScreen(eman->xdpy));
434 }
435
436 /* window attributes */
437 attrs.background_pixel = 0;
438 attrs.border_pixel = 0;
439 attrs.colormap = XCreateColormap(eman->xdpy, root, vinfo->visual, AllocNone);
440 attrs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
441 attrs.override_redirect = fullscreen;
442 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
443
444 eman->xwin = XCreateWindow(eman->xdpy, root, x, y, w, h,
445 0, vinfo->depth, InputOutput,
446 vinfo->visual, mask, &attrs);
447 XFree(vinfo);
448
449 /* set hints and properties */
450 {
451 XSizeHints sizehints;
452 sizehints.x = x;
453 sizehints.y = y;
454 sizehints.width = w;
455 sizehints.height = h;
456 sizehints.flags = USSize | USPosition;
457 XSetNormalHints(eman->xdpy, eman->xwin, &sizehints);
458 XSetStandardProperties(eman->xdpy, eman->xwin, name, name,
459 None, (char **)NULL, 0, &sizehints);
460 }
461
462 if (need_surface) {
463 eman->win = eglCreateWindowSurface(eman->dpy, eman->conf,
464 eman->xwin, attrib_list);
465 if (eman->win == EGL_NO_SURFACE) {
466 printf("eglCreateWindowSurface() failed\n");
467 XDestroyWindow(eman->xdpy, eman->xwin);
468 eman->xwin = None;
469 return EGL_FALSE;
470 }
471 }
472
473 XMapWindow(eman->xdpy, eman->xwin);
474
475 return EGL_TRUE;
476 }
477
478 static EGLBoolean
479 egl_manager_create_pixmap(struct egl_manager *eman, EGLNativeWindowType xwin,
480 EGLBoolean need_surface, const EGLint *attrib_list)
481 {
482 XWindowAttributes attrs;
483
484 if (!XGetWindowAttributes(eman->xdpy, xwin, &attrs)) {
485 printf("XGetWindowAttributes() failed\n");
486 return EGL_FALSE;
487 }
488
489 eman->xpix = XCreatePixmap(eman->xdpy, xwin,
490 attrs.width, attrs.height, attrs.depth);
491
492 if (need_surface) {
493 eman->pix = eglCreatePixmapSurface(eman->dpy, eman->conf,
494 eman->xpix, attrib_list);
495 if (eman->pix == EGL_NO_SURFACE) {
496 printf("eglCreatePixmapSurface() failed\n");
497 XFreePixmap(eman->xdpy, eman->xpix);
498 eman->xpix = None;
499 return EGL_FALSE;
500 }
501 }
502
503 return EGL_TRUE;
504 }
505
506 static EGLBoolean
507 egl_manager_create_pbuffer(struct egl_manager *eman, const EGLint *attrib_list)
508 {
509 eman->pbuf = eglCreatePbufferSurface(eman->dpy, eman->conf, attrib_list);
510 if (eman->pbuf == EGL_NO_SURFACE) {
511 printf("eglCreatePbufferSurface() failed\n");
512 return EGL_FALSE;
513 }
514
515 return EGL_TRUE;
516 }
517
518 static void
519 egl_manager_destroy(struct egl_manager *eman)
520 {
521 eglMakeCurrent(eman->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
522 eglTerminate(eman->dpy);
523
524 if (eman->xwin != None)
525 XDestroyWindow(eman->xdpy, eman->xwin);
526 if (eman->xpix != None)
527 XFreePixmap(eman->xdpy, eman->xpix);
528
529 free(eman);
530 }
531
532 static void
533 event_loop(struct egl_manager *eman, EGLint surface_type, EGLint w, EGLint h)
534 {
535 GC gc = XCreateGC(eman->xdpy, eman->xwin, 0, NULL);
536 EGLint orig_w = w, orig_h = h;
537
538 if (surface_type == EGL_PBUFFER_BIT)
539 printf("there will be no screen update if "
540 "eglCopyBuffers() is not implemented\n");
541
542 while (1) {
543 while (XPending(eman->xdpy) > 0) {
544 XEvent event;
545 XNextEvent(eman->xdpy, &event);
546 switch (event.type) {
547 case Expose:
548 /* we'll redraw below */
549 break;
550 case ConfigureNotify:
551 w = event.xconfigure.width;
552 h = event.xconfigure.height;
553 if (surface_type == EGL_WINDOW_BIT)
554 reshape(w, h);
555 break;
556 case KeyPress:
557 {
558 char buffer[10];
559 int r, code;
560 code = XLookupKeysym(&event.xkey, 0);
561 if (code == XK_Left) {
562 view_roty += 5.0;
563 }
564 else if (code == XK_Right) {
565 view_roty -= 5.0;
566 }
567 else if (code == XK_Up) {
568 view_rotx += 5.0;
569 }
570 else if (code == XK_Down) {
571 view_rotx -= 5.0;
572 }
573 else {
574 r = XLookupString(&event.xkey, buffer, sizeof(buffer),
575 NULL, NULL);
576 if (buffer[0] == 27) {
577 /* escape */
578 return;
579 }
580 }
581 }
582 }
583 }
584
585 {
586 static int frames = 0;
587 static double tRot0 = -1.0, tRate0 = -1.0;
588 double dt, t = current_time();
589 int x, y;
590 if (tRot0 < 0.0)
591 tRot0 = t;
592 dt = t - tRot0;
593 tRot0 = t;
594
595 /* advance rotation for next frame */
596 angle += 70.0 * dt; /* 70 degrees per second */
597 if (angle > 3600.0)
598 angle -= 3600.0;
599
600 draw();
601 switch (surface_type) {
602 case EGL_WINDOW_BIT:
603 eglSwapBuffers(eman->dpy, eman->win);
604 break;
605 case EGL_PBUFFER_BIT:
606 eglWaitClient();
607 if (!eglCopyBuffers(eman->dpy, eman->pbuf, eman->xpix))
608 break;
609 /* fall through */
610 case EGL_PIXMAP_BIT:
611 eglWaitClient();
612 for (x = 0; x < w; x += orig_w) {
613 for (y = 0; y < h; y += orig_h) {
614 XCopyArea(eman->xdpy, eman->xpix, eman->xwin, gc,
615 0, 0, orig_w, orig_h, x, y);
616 }
617 }
618 break;
619 }
620
621 frames++;
622
623 if (tRate0 < 0.0)
624 tRate0 = t;
625 if (t - tRate0 >= 5.0) {
626 GLfloat seconds = t - tRate0;
627 GLfloat fps = frames / seconds;
628 printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
629 fps);
630 tRate0 = t;
631 frames = 0;
632 }
633 }
634 }
635
636 XFreeGC(eman->xdpy, gc);
637 }
638
639
640 static void
641 usage(void)
642 {
643 printf("Usage:\n");
644 printf(" -display <displayname> set the display to run on\n");
645 printf(" -fullscreen run in fullscreen mode\n");
646 printf(" -info display OpenGL renderer info\n");
647 printf(" -pixmap use pixmap surface\n");
648 printf(" -pbuffer use pbuffer surface\n");
649 }
650
651
652 int
653 main(int argc, char *argv[])
654 {
655 const int winWidth = 300, winHeight = 300;
656 Display *x_dpy;
657 char *dpyName = NULL;
658 struct egl_manager *eman;
659 EGLint attribs[] = {
660 EGL_SURFACE_TYPE, 0, /* filled later */
661 EGL_RED_SIZE, 1,
662 EGL_GREEN_SIZE, 1,
663 EGL_BLUE_SIZE, 1,
664 EGL_DEPTH_SIZE, 1,
665 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
666 EGL_NONE
667 };
668 char win_title[] = "xeglgears (window/pixmap/pbuffer)";
669 EGLint surface_type = EGL_WINDOW_BIT;
670 GLboolean printInfo = GL_FALSE;
671 GLboolean fullscreen = GL_FALSE;
672 EGLBoolean ret;
673 int i;
674
675 for (i = 1; i < argc; i++) {
676 if (strcmp(argv[i], "-display") == 0) {
677 dpyName = argv[i+1];
678 i++;
679 }
680 else if (strcmp(argv[i], "-info") == 0) {
681 printInfo = GL_TRUE;
682 }
683 else if (strcmp(argv[i], "-fullscreen") == 0) {
684 fullscreen = GL_TRUE;
685 }
686 else if (strcmp(argv[i], "-pixmap") == 0) {
687 surface_type = EGL_PIXMAP_BIT;
688 }
689 else if (strcmp(argv[i], "-pbuffer") == 0) {
690 surface_type = EGL_PBUFFER_BIT;
691 }
692 else {
693 usage();
694 return -1;
695 }
696 }
697
698 /* set surface type */
699 attribs[1] = surface_type;
700
701 x_dpy = XOpenDisplay(dpyName);
702 if (!x_dpy) {
703 printf("Error: couldn't open display %s\n",
704 dpyName ? dpyName : getenv("DISPLAY"));
705 return -1;
706 }
707
708 eglBindAPI(EGL_OPENGL_API);
709
710 eman = egl_manager_new(x_dpy, attribs, printInfo);
711 if (!eman) {
712 XCloseDisplay(x_dpy);
713 return -1;
714 }
715
716 snprintf(win_title, sizeof(win_title), "xeglgears (%s)",
717 (surface_type == EGL_WINDOW_BIT) ? "window" :
718 (surface_type == EGL_PIXMAP_BIT) ? "pixmap" : "pbuffer");
719
720 /* create surface(s) */
721 switch (surface_type) {
722 case EGL_WINDOW_BIT:
723 ret = egl_manager_create_window(eman, win_title, winWidth, winHeight,
724 EGL_TRUE, fullscreen, NULL);
725 if (ret)
726 ret = eglMakeCurrent(eman->dpy, eman->win, eman->win, eman->ctx);
727 break;
728 case EGL_PIXMAP_BIT:
729 ret = (egl_manager_create_window(eman, win_title, winWidth, winHeight,
730 EGL_FALSE, fullscreen, NULL) &&
731 egl_manager_create_pixmap(eman, eman->xwin,
732 EGL_TRUE, NULL));
733 if (ret)
734 ret = eglMakeCurrent(eman->dpy, eman->pix, eman->pix, eman->ctx);
735 break;
736 case EGL_PBUFFER_BIT:
737 {
738 EGLint pbuf_attribs[] = {
739 EGL_WIDTH, winWidth,
740 EGL_HEIGHT, winHeight,
741 EGL_NONE
742 };
743 ret = (egl_manager_create_window(eman, win_title, winWidth, winHeight,
744 EGL_FALSE, fullscreen, NULL) &&
745 egl_manager_create_pixmap(eman, eman->xwin,
746 EGL_FALSE, NULL) &&
747 egl_manager_create_pbuffer(eman, pbuf_attribs));
748 if (ret)
749 ret = eglMakeCurrent(eman->dpy, eman->pbuf, eman->pbuf, eman->ctx);
750 }
751 break;
752 default:
753 ret = EGL_FALSE;
754 break;
755 }
756
757 if (!ret) {
758 egl_manager_destroy(eman);
759 XCloseDisplay(x_dpy);
760 return -1;
761 }
762
763 if (printInfo) {
764 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
765 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
766 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
767 }
768
769 init();
770
771 /* Set initial projection/viewing transformation.
772 * We can't be sure we'll get a ConfigureNotify event when the window
773 * first appears.
774 */
775 reshape(winWidth, winHeight);
776
777 event_loop(eman, surface_type, winWidth, winHeight);
778
779 glDeleteLists(gear1, 1);
780 glDeleteLists(gear2, 1);
781 glDeleteLists(gear3, 1);
782
783 egl_manager_destroy(eman);
784 XCloseDisplay(x_dpy);
785
786 return 0;
787 }