2 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
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:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
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.
23 * Ported to X/EGL/GLES. XXX Actually, uses full OpenGL ATM.
29 * Command line options:
30 * -info print GL implementation information
35 #define GL_GLEXT_PROTOTYPES
36 #define EGL_EGLEXT_PROTOTYPES
43 #include <X11/Xutil.h>
44 #include <X11/keysym.h>
48 #include <EGL/eglext.h>
55 /* XXX this probably isn't very portable */
60 /* return current time (in seconds) */
66 (void) gettimeofday(&tv
, NULL
);
69 (void) gettimeofday(&tv
, &tz
);
71 return (double) tv
.tv_sec
+ tv
.tv_usec
/ 1000000.0;
80 /* update this function for other platforms! */
81 static double t
= 0.0;
84 fprintf(stderr
, "Warning: current_time() not implemented!!\n");
95 #define M_PI 3.14159265
99 static GLfloat view_rotx
= 20.0, view_roty
= 30.0, view_rotz
= 0.0;
100 static GLint gear1
, gear2
, gear3
;
101 static GLfloat angle
= 0.0;
105 * Draw a gear wheel. You'll probably want to call this function when
106 * building a display list since we do a lot of trig here.
108 * Input: inner_radius - radius of hole at center
109 * outer_radius - radius at center of teeth
110 * width - width of gear
111 * teeth - number of teeth
112 * tooth_depth - depth of tooth
115 gear(GLfloat inner_radius
, GLfloat outer_radius
, GLfloat width
,
116 GLint teeth
, GLfloat tooth_depth
)
124 r1
= outer_radius
- tooth_depth
/ 2.0;
125 r2
= outer_radius
+ tooth_depth
/ 2.0;
127 da
= 2.0 * M_PI
/ teeth
/ 4.0;
129 glShadeModel(GL_FLAT
);
131 glNormal3f(0.0, 0.0, 1.0);
133 /* draw front face */
134 glBegin(GL_QUAD_STRIP
);
135 for (i
= 0; i
<= teeth
; i
++) {
136 angle
= i
* 2.0 * M_PI
/ teeth
;
137 glVertex3f(r0
* cos(angle
), r0
* sin(angle
), width
* 0.5);
138 glVertex3f(r1
* cos(angle
), r1
* sin(angle
), width
* 0.5);
140 glVertex3f(r0
* cos(angle
), r0
* sin(angle
), width
* 0.5);
141 glVertex3f(r1
* cos(angle
+ 3 * da
), r1
* sin(angle
+ 3 * da
),
147 /* draw front sides of teeth */
149 da
= 2.0 * M_PI
/ teeth
/ 4.0;
150 for (i
= 0; i
< teeth
; i
++) {
151 angle
= i
* 2.0 * M_PI
/ teeth
;
153 glVertex3f(r1
* cos(angle
), r1
* sin(angle
), width
* 0.5);
154 glVertex3f(r2
* cos(angle
+ da
), r2
* sin(angle
+ da
), width
* 0.5);
155 glVertex3f(r2
* cos(angle
+ 2 * da
), r2
* sin(angle
+ 2 * da
),
157 glVertex3f(r1
* cos(angle
+ 3 * da
), r1
* sin(angle
+ 3 * da
),
162 glNormal3f(0.0, 0.0, -1.0);
165 glBegin(GL_QUAD_STRIP
);
166 for (i
= 0; i
<= teeth
; i
++) {
167 angle
= i
* 2.0 * M_PI
/ teeth
;
168 glVertex3f(r1
* cos(angle
), r1
* sin(angle
), -width
* 0.5);
169 glVertex3f(r0
* cos(angle
), r0
* sin(angle
), -width
* 0.5);
171 glVertex3f(r1
* cos(angle
+ 3 * da
), r1
* sin(angle
+ 3 * da
),
173 glVertex3f(r0
* cos(angle
), r0
* sin(angle
), -width
* 0.5);
178 /* draw back sides of teeth */
180 da
= 2.0 * M_PI
/ teeth
/ 4.0;
181 for (i
= 0; i
< teeth
; i
++) {
182 angle
= i
* 2.0 * M_PI
/ teeth
;
184 glVertex3f(r1
* cos(angle
+ 3 * da
), r1
* sin(angle
+ 3 * da
),
186 glVertex3f(r2
* cos(angle
+ 2 * da
), r2
* sin(angle
+ 2 * da
),
188 glVertex3f(r2
* cos(angle
+ da
), r2
* sin(angle
+ da
), -width
* 0.5);
189 glVertex3f(r1
* cos(angle
), r1
* sin(angle
), -width
* 0.5);
193 /* draw outward faces of teeth */
194 glBegin(GL_QUAD_STRIP
);
195 for (i
= 0; i
< teeth
; i
++) {
196 angle
= i
* 2.0 * M_PI
/ teeth
;
198 glVertex3f(r1
* cos(angle
), r1
* sin(angle
), width
* 0.5);
199 glVertex3f(r1
* cos(angle
), r1
* sin(angle
), -width
* 0.5);
200 u
= r2
* cos(angle
+ da
) - r1
* cos(angle
);
201 v
= r2
* sin(angle
+ da
) - r1
* sin(angle
);
202 len
= sqrt(u
* u
+ v
* v
);
205 glNormal3f(v
, -u
, 0.0);
206 glVertex3f(r2
* cos(angle
+ da
), r2
* sin(angle
+ da
), width
* 0.5);
207 glVertex3f(r2
* cos(angle
+ da
), r2
* sin(angle
+ da
), -width
* 0.5);
208 glNormal3f(cos(angle
), sin(angle
), 0.0);
209 glVertex3f(r2
* cos(angle
+ 2 * da
), r2
* sin(angle
+ 2 * da
),
211 glVertex3f(r2
* cos(angle
+ 2 * da
), r2
* sin(angle
+ 2 * da
),
213 u
= r1
* cos(angle
+ 3 * da
) - r2
* cos(angle
+ 2 * da
);
214 v
= r1
* sin(angle
+ 3 * da
) - r2
* sin(angle
+ 2 * da
);
215 glNormal3f(v
, -u
, 0.0);
216 glVertex3f(r1
* cos(angle
+ 3 * da
), r1
* sin(angle
+ 3 * da
),
218 glVertex3f(r1
* cos(angle
+ 3 * da
), r1
* sin(angle
+ 3 * da
),
220 glNormal3f(cos(angle
), sin(angle
), 0.0);
223 glVertex3f(r1
* cos(0), r1
* sin(0), width
* 0.5);
224 glVertex3f(r1
* cos(0), r1
* sin(0), -width
* 0.5);
228 glShadeModel(GL_SMOOTH
);
230 /* draw inside radius cylinder */
231 glBegin(GL_QUAD_STRIP
);
232 for (i
= 0; i
<= teeth
; i
++) {
233 angle
= i
* 2.0 * M_PI
/ teeth
;
234 glNormal3f(-cos(angle
), -sin(angle
), 0.0);
235 glVertex3f(r0
* cos(angle
), r0
* sin(angle
), -width
* 0.5);
236 glVertex3f(r0
* cos(angle
), r0
* sin(angle
), width
* 0.5);
245 glClearColor(0.2, 0.2, 0.2, 0.2);
246 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
249 glRotatef(view_rotx
, 1.0, 0.0, 0.0);
250 glRotatef(view_roty
, 0.0, 1.0, 0.0);
251 glRotatef(view_rotz
, 0.0, 0.0, 1.0);
254 glTranslatef(-3.0, -2.0, 0.0);
255 glRotatef(angle
, 0.0, 0.0, 1.0);
260 glTranslatef(3.1, -2.0, 0.0);
261 glRotatef(-2.0 * angle
- 9.0, 0.0, 0.0, 1.0);
266 glTranslatef(-3.1, 4.2, 0.0);
267 glRotatef(-2.0 * angle
- 25.0, 0.0, 0.0, 1.0);
275 /* new window size or exposure */
277 reshape(int width
, int height
)
279 GLfloat ar
= (GLfloat
) width
/ (GLfloat
) height
;
281 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
283 glMatrixMode(GL_PROJECTION
);
285 glFrustum(-ar
, ar
, -1, 1, 5.0, 60.0);
287 glMatrixMode(GL_MODELVIEW
);
289 glTranslatef(0.0, 0.0, -40.0);
297 static GLfloat pos
[4] = { 5.0, 5.0, 10.0, 0.0 };
298 static GLfloat red
[4] = { 0.8, 0.1, 0.0, 1.0 };
299 static GLfloat green
[4] = { 0.0, 0.8, 0.2, 1.0 };
300 static GLfloat blue
[4] = { 0.2, 0.2, 1.0, 1.0 };
302 glLightfv(GL_LIGHT0
, GL_POSITION
, pos
);
303 glEnable(GL_CULL_FACE
);
304 glEnable(GL_LIGHTING
);
306 glEnable(GL_DEPTH_TEST
);
309 gear1
= glGenLists(1);
310 glNewList(gear1
, GL_COMPILE
);
311 glMaterialfv(GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, red
);
312 gear(1.0, 4.0, 1.0, 20, 0.7);
315 gear2
= glGenLists(1);
316 glNewList(gear2
, GL_COMPILE
);
317 glMaterialfv(GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, green
);
318 gear(0.5, 2.0, 2.0, 10, 0.7);
321 gear3
= glGenLists(1);
322 glNewList(gear3
, GL_COMPILE
);
323 glMaterialfv(GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, blue
);
324 gear(1.3, 2.0, 0.5, 10, 0.7);
327 glEnable(GL_NORMALIZE
);
332 EGLNativeDisplayType xdpy
;
333 EGLNativeWindowType xwin
;
334 EGLNativePixmapType xpix
;
352 static struct egl_manager
*
353 egl_manager_new(EGLNativeDisplayType xdpy
, const EGLint
*attrib_list
,
356 struct egl_manager
*eman
;
360 eman
= calloc(1, sizeof(*eman
));
364 eman
->verbose
= verbose
;
367 eman
->dpy
= eglGetDisplay(eman
->xdpy
);
368 if (eman
->dpy
== EGL_NO_DISPLAY
) {
369 printf("eglGetDisplay() failed\n");
374 if (!eglInitialize(eman
->dpy
, &eman
->major
, &eman
->minor
)) {
375 printf("eglInitialize() failed\n");
380 ver
= eglQueryString(eman
->dpy
, EGL_VERSION
);
381 printf("EGL_VERSION = %s\n", ver
);
383 if (!eglChooseConfig(eman
->dpy
, attrib_list
, &eman
->conf
, 1, &num_conf
) ||
385 printf("eglChooseConfig() failed\n");
386 eglTerminate(eman
->dpy
);
391 eman
->ctx
= eglCreateContext(eman
->dpy
, eman
->conf
, EGL_NO_CONTEXT
, NULL
);
392 if (eman
->ctx
== EGL_NO_CONTEXT
) {
393 printf("eglCreateContext() failed\n");
394 eglTerminate(eman
->dpy
);
403 egl_manager_create_window(struct egl_manager
*eman
, const char *name
,
404 EGLint w
, EGLint h
, EGLBoolean need_surface
,
405 EGLBoolean fullscreen
, const EGLint
*attrib_list
)
407 XVisualInfo vinfo_template
, *vinfo
= NULL
;
408 EGLint val
, num_vinfo
;
410 XSetWindowAttributes attrs
;
414 if (!eglGetConfigAttrib(eman
->dpy
, eman
->conf
,
415 EGL_NATIVE_VISUAL_ID
, &val
)) {
416 printf("eglGetConfigAttrib() failed\n");
420 vinfo_template
.visualid
= (VisualID
) val
;
421 vinfo
= XGetVisualInfo(eman
->xdpy
, VisualIDMask
, &vinfo_template
, &num_vinfo
);
423 /* try harder if window surface is not needed */
424 if (!vinfo
&& !need_surface
&&
425 eglGetConfigAttrib(eman
->dpy
, eman
->conf
, EGL_BUFFER_SIZE
, &val
)) {
428 vinfo_template
.depth
= val
;
429 vinfo
= XGetVisualInfo(eman
->xdpy
, VisualDepthMask
, &vinfo_template
, &num_vinfo
);
433 printf("XGetVisualInfo() failed\n");
437 root
= DefaultRootWindow(eman
->xdpy
);
440 w
= DisplayWidth(eman
->xdpy
, DefaultScreen(eman
->xdpy
));
441 h
= DisplayHeight(eman
->xdpy
, DefaultScreen(eman
->xdpy
));
444 /* window attributes */
445 attrs
.background_pixel
= 0;
446 attrs
.border_pixel
= 0;
447 attrs
.colormap
= XCreateColormap(eman
->xdpy
, root
, vinfo
->visual
, AllocNone
);
448 attrs
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
449 attrs
.override_redirect
= fullscreen
;
450 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
| CWOverrideRedirect
;
452 eman
->xwin
= XCreateWindow(eman
->xdpy
, root
, x
, y
, w
, h
,
453 0, vinfo
->depth
, InputOutput
,
454 vinfo
->visual
, mask
, &attrs
);
457 /* set hints and properties */
459 XSizeHints sizehints
;
463 sizehints
.height
= h
;
464 sizehints
.flags
= USSize
| USPosition
;
465 XSetNormalHints(eman
->xdpy
, eman
->xwin
, &sizehints
);
466 XSetStandardProperties(eman
->xdpy
, eman
->xwin
, name
, name
,
467 None
, (char **)NULL
, 0, &sizehints
);
471 eman
->win
= eglCreateWindowSurface(eman
->dpy
, eman
->conf
,
472 eman
->xwin
, attrib_list
);
473 if (eman
->win
== EGL_NO_SURFACE
) {
474 printf("eglCreateWindowSurface() failed\n");
475 XDestroyWindow(eman
->xdpy
, eman
->xwin
);
481 eman
->gc
= XCreateGC(eman
->xdpy
, eman
->xwin
, 0, NULL
);
483 XMapWindow(eman
->xdpy
, eman
->xwin
);
489 egl_manager_create_pixmap(struct egl_manager
*eman
, EGLNativeWindowType xwin
,
490 EGLBoolean need_surface
, const EGLint
*attrib_list
)
492 XWindowAttributes attrs
;
494 if (!XGetWindowAttributes(eman
->xdpy
, xwin
, &attrs
)) {
495 printf("XGetWindowAttributes() failed\n");
499 eman
->xpix
= XCreatePixmap(eman
->xdpy
, xwin
,
500 attrs
.width
, attrs
.height
, attrs
.depth
);
503 eman
->pix
= eglCreatePixmapSurface(eman
->dpy
, eman
->conf
,
504 eman
->xpix
, attrib_list
);
505 if (eman
->pix
== EGL_NO_SURFACE
) {
506 printf("eglCreatePixmapSurface() failed\n");
507 XFreePixmap(eman
->xdpy
, eman
->xpix
);
517 egl_manager_create_pbuffer(struct egl_manager
*eman
, const EGLint
*attrib_list
)
519 eman
->pbuf
= eglCreatePbufferSurface(eman
->dpy
, eman
->conf
, attrib_list
);
520 if (eman
->pbuf
== EGL_NO_SURFACE
) {
521 printf("eglCreatePbufferSurface() failed\n");
529 egl_manager_destroy(struct egl_manager
*eman
)
531 eglMakeCurrent(eman
->dpy
, EGL_NO_SURFACE
, EGL_NO_SURFACE
, EGL_NO_CONTEXT
);
532 eglTerminate(eman
->dpy
);
534 if (eman
->xwin
!= None
)
535 XDestroyWindow(eman
->xdpy
, eman
->xwin
);
536 if (eman
->xpix
!= None
)
537 XFreePixmap(eman
->xdpy
, eman
->xpix
);
539 XFreeGC(eman
->xdpy
, eman
->gc
);
547 GEARS_PIXMAP_TEXTURE
,
549 GEARS_PBUFFER_TEXTURE
,
554 texture_gears(struct egl_manager
*eman
, int surface_type
)
556 static const GLint verts
[12] =
557 { -5, -6, -10, 5, -6, -10, -5, 4, 10, 5, 4, 10 };
558 static const GLint tex_coords
[8] = { 0, 0, 1, 0, 0, 1, 1, 1 };
560 eglMakeCurrent(eman
->dpy
, eman
->win
, eman
->win
, eman
->ctx
);
562 glClearColor(0, 0, 0, 0);
563 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
565 glEnable(GL_TEXTURE_2D
);
566 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
567 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_R
, GL_REPEAT
);
568 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
569 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
571 glEnableClientState(GL_VERTEX_ARRAY
);
572 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
573 glVertexPointer(3, GL_INT
, 0, verts
);
574 glTexCoordPointer(2, GL_INT
, 0, tex_coords
);
576 if (surface_type
== GEARS_PBUFFER_TEXTURE
)
577 eglBindTexImage(eman
->dpy
, eman
->pbuf
, EGL_BACK_BUFFER
);
579 glDrawArrays(GL_TRIANGLE_STRIP
, 0, 4);
581 glDisableClientState(GL_VERTEX_ARRAY
);
582 glDisableClientState(GL_COLOR_ARRAY
);
583 glDisable(GL_TEXTURE_2D
);
585 if (surface_type
== GEARS_PBUFFER_TEXTURE
)
586 eglReleaseTexImage(eman
->dpy
, eman
->pbuf
, EGL_BACK_BUFFER
);
588 eglSwapBuffers(eman
->dpy
, eman
->win
);
592 copy_gears(struct egl_manager
*eman
,
593 EGLint tile_w
, EGLint tile_h
, EGLint w
, EGLint h
)
599 for (x
= 0; x
< w
; x
+= tile_w
) {
600 for (y
= 0; y
< h
; y
+= tile_h
) {
602 XCopyArea(eman
->xdpy
, eman
->xpix
, eman
->xwin
, eman
->gc
,
603 0, 0, tile_w
, tile_h
, x
, y
);
609 event_loop(struct egl_manager
*eman
, EGLint surface_type
, EGLint w
, EGLint h
)
611 int window_w
= w
, window_h
= h
;
613 if (surface_type
== EGL_PBUFFER_BIT
)
614 printf("there will be no screen update if "
615 "eglCopyBuffers() is not implemented\n");
618 while (XPending(eman
->xdpy
) > 0) {
620 XNextEvent(eman
->xdpy
, &event
);
621 switch (event
.type
) {
623 /* we'll redraw below */
625 case ConfigureNotify
:
626 window_w
= event
.xconfigure
.width
;
627 window_h
= event
.xconfigure
.height
;
628 if (surface_type
== EGL_WINDOW_BIT
)
629 reshape(window_w
, window_h
);
635 code
= XLookupKeysym(&event
.xkey
, 0);
636 if (code
== XK_Left
) {
639 else if (code
== XK_Right
) {
642 else if (code
== XK_Up
) {
645 else if (code
== XK_Down
) {
649 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
651 if (buffer
[0] == 27) {
661 static int frames
= 0;
662 static double tRot0
= -1.0, tRate0
= -1.0;
663 double dt
, t
= current_time();
669 /* advance rotation for next frame */
670 angle
+= 70.0 * dt
; /* 70 degrees per second */
674 switch (surface_type
) {
677 eglSwapBuffers(eman
->dpy
, eman
->win
);
682 if (!eglCopyBuffers(eman
->dpy
, eman
->pbuf
, eman
->xpix
))
684 copy_gears(eman
, w
, h
, window_w
, window_h
);
687 case GEARS_PBUFFER_TEXTURE
:
688 eglMakeCurrent(eman
->dpy
, eman
->pbuf
, eman
->pbuf
, eman
->ctx
);
690 texture_gears(eman
, surface_type
);
695 copy_gears(eman
, w
, h
, window_w
, window_h
);
698 case GEARS_PIXMAP_TEXTURE
:
699 eglMakeCurrent(eman
->dpy
, eman
->pix
, eman
->pix
, eman
->ctx
);
701 texture_gears(eman
, surface_type
);
704 case GEARS_RENDERBUFFER
:
705 glBindFramebuffer(GL_FRAMEBUFFER_EXT
, eman
->fbo
);
707 glBindFramebuffer(GL_FRAMEBUFFER_EXT
, 0);
708 texture_gears(eman
, surface_type
);
716 if (t
- tRate0
>= 5.0) {
717 GLfloat seconds
= t
- tRate0
;
718 GLfloat fps
= frames
/ seconds
;
719 printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames
, seconds
,
733 printf(" -display <displayname> set the display to run on\n");
734 printf(" -fullscreen run in fullscreen mode\n");
735 printf(" -info display OpenGL renderer info\n");
736 printf(" -pixmap use pixmap surface\n");
737 printf(" -pixmap-texture use pixmap surface and texture using EGLImage\n");
738 printf(" -pbuffer use pbuffer surface and eglCopyBuffers\n");
739 printf(" -pbuffer-texture use pbuffer surface and eglBindTexImage\n");
740 printf(" -renderbuffer renderbuffer as EGLImage and bind as texture from\n");
743 static const char *names
[] = {
753 main(int argc
, char *argv
[])
755 const int winWidth
= 300, winHeight
= 300;
757 char *dpyName
= NULL
;
758 struct egl_manager
*eman
;
760 EGL_SURFACE_TYPE
, EGL_WINDOW_BIT
, /* may be changed later */
765 EGL_RENDERABLE_TYPE
, EGL_OPENGL_BIT
,
768 char win_title
[] = "xeglgears (window/pixmap/pbuffer)";
769 EGLint surface_type
= GEARS_WINDOW
;
770 GLboolean printInfo
= GL_FALSE
;
771 GLboolean fullscreen
= GL_FALSE
;
773 GLuint texture
, color_rb
, depth_rb
;
776 for (i
= 1; i
< argc
; i
++) {
777 if (strcmp(argv
[i
], "-display") == 0) {
781 else if (strcmp(argv
[i
], "-info") == 0) {
784 else if (strcmp(argv
[i
], "-fullscreen") == 0) {
785 fullscreen
= GL_TRUE
;
787 else if (strcmp(argv
[i
], "-pixmap") == 0) {
788 surface_type
= GEARS_PIXMAP
;
789 attribs
[1] = EGL_PIXMAP_BIT
;
791 else if (strcmp(argv
[i
], "-pixmap-texture") == 0) {
792 surface_type
= GEARS_PIXMAP_TEXTURE
;
793 attribs
[1] = EGL_PIXMAP_BIT
;
795 else if (strcmp(argv
[i
], "-pbuffer") == 0) {
796 surface_type
= GEARS_PBUFFER
;
797 attribs
[1] = EGL_PBUFFER_BIT
;
799 else if (strcmp(argv
[i
], "-pbuffer-texture") == 0) {
800 surface_type
= GEARS_PBUFFER_TEXTURE
;
801 attribs
[1] = EGL_PBUFFER_BIT
;
803 else if (strcmp(argv
[i
], "-renderbuffer") == 0) {
804 surface_type
= GEARS_RENDERBUFFER
;
812 x_dpy
= XOpenDisplay(dpyName
);
814 printf("Error: couldn't open display %s\n",
815 dpyName
? dpyName
: getenv("DISPLAY"));
819 eglBindAPI(EGL_OPENGL_API
);
821 eman
= egl_manager_new(x_dpy
, attribs
, printInfo
);
823 XCloseDisplay(x_dpy
);
827 snprintf(win_title
, sizeof(win_title
),
828 "xeglgears (%s)", names
[surface_type
]);
830 ret
= egl_manager_create_window(eman
, win_title
, winWidth
, winHeight
,
831 EGL_TRUE
, fullscreen
, NULL
);
835 /* create surface(s) */
836 switch (surface_type
) {
839 ret
= eglMakeCurrent(eman
->dpy
, eman
->win
, eman
->win
, eman
->ctx
);
842 case GEARS_PIXMAP_TEXTURE
:
843 ret
= egl_manager_create_pixmap(eman
, eman
->xwin
, EGL_TRUE
, NULL
);
844 if (surface_type
== GEARS_PIXMAP_TEXTURE
)
845 eman
->image
= eglCreateImageKHR (eman
->dpy
, eman
->ctx
,
846 EGL_NATIVE_PIXMAP_KHR
,
847 (EGLClientBuffer
) eman
->xpix
, NULL
);
849 ret
= eglMakeCurrent(eman
->dpy
, eman
->pix
, eman
->pix
, eman
->ctx
);
852 case GEARS_PBUFFER_TEXTURE
:
854 EGLint pbuf_attribs
[] = {
856 EGL_HEIGHT
, winHeight
,
857 EGL_TEXTURE_FORMAT
, EGL_TEXTURE_RGB
,
858 EGL_TEXTURE_TARGET
, EGL_TEXTURE_2D
,
861 ret
= (egl_manager_create_pixmap(eman
, eman
->xwin
,
863 egl_manager_create_pbuffer(eman
, pbuf_attribs
));
865 ret
= eglMakeCurrent(eman
->dpy
, eman
->pbuf
, eman
->pbuf
, eman
->ctx
);
870 case GEARS_RENDERBUFFER
:
871 ret
= eglMakeCurrent(eman
->dpy
, eman
->win
, eman
->win
, eman
->ctx
);
872 if (ret
== EGL_FALSE
)
873 printf("failed to make context current\n");
875 glGenFramebuffers(1, &eman
->fbo
);
876 glBindFramebuffer(GL_FRAMEBUFFER_EXT
, eman
->fbo
);
878 glGenRenderbuffers(1, &color_rb
);
879 glBindRenderbuffer(GL_RENDERBUFFER_EXT
, color_rb
);
880 glRenderbufferStorage(GL_RENDERBUFFER_EXT
, GL_RGBA
, winWidth
, winHeight
);
881 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
,
882 GL_COLOR_ATTACHMENT0_EXT
,
886 eman
->image
= eglCreateImageKHR(eman
->dpy
, eman
->ctx
,
887 EGL_GL_RENDERBUFFER_KHR
,
888 (EGLClientBuffer
) color_rb
, NULL
);
890 glGenRenderbuffers(1, &depth_rb
);
891 glBindRenderbuffer(GL_RENDERBUFFER_EXT
, depth_rb
);
892 glRenderbufferStorage(GL_RENDERBUFFER_EXT
,
893 GL_DEPTH_COMPONENT
, winWidth
, winHeight
);
894 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
,
895 GL_DEPTH_ATTACHMENT_EXT
,
899 if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
) != GL_FRAMEBUFFER_COMPLETE
) {
900 printf("framebuffer not complete\n");
911 switch (surface_type
) {
912 case GEARS_PIXMAP_TEXTURE
:
913 case GEARS_RENDERBUFFER
:
914 glGenTextures(1, &texture
);
915 glBindTexture(GL_TEXTURE_2D
, texture
);
916 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D
, eman
->image
);
918 case GEARS_PBUFFER_TEXTURE
:
919 glGenTextures(1, &texture
);
920 glBindTexture(GL_TEXTURE_2D
, texture
);
925 egl_manager_destroy(eman
);
926 XCloseDisplay(x_dpy
);
931 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
932 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
933 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
938 /* Set initial projection/viewing transformation.
939 * We can't be sure we'll get a ConfigureNotify event when the window
942 reshape(winWidth
, winHeight
);
944 event_loop(eman
, surface_type
, winWidth
, winHeight
);
946 glDeleteLists(gear1
, 1);
947 glDeleteLists(gear2
, 1);
948 glDeleteLists(gear3
, 1);
950 egl_manager_destroy(eman
);
951 XCloseDisplay(x_dpy
);