diff options
| -rw-r--r-- | progs/egl/Makefile | 10 | ||||
| -rw-r--r-- | progs/egl/xeglgears.c | 604 | 
2 files changed, 613 insertions, 1 deletions
| diff --git a/progs/egl/Makefile b/progs/egl/Makefile index da710cbbbf..ae2267f38f 100644 --- a/progs/egl/Makefile +++ b/progs/egl/Makefile @@ -13,7 +13,8 @@ PROGRAMS = \  	demo2 \  	demo3 \  	eglinfo \ -	eglgears +	eglgears \ +	xeglgears  .c.o: @@ -59,6 +60,13 @@ eglgears.o: eglgears.c $(HEADERS)  	$(CC) -c $(CFLAGS) -I$(TOP)/include eglgears.c +xeglgears: xeglgears.o $(TOP)/$(LIB_DIR)/libEGL.so +	$(CC) $(CFLAGS) xeglgears.o -L$(TOP)/$(LIB_DIR) -lEGL $(LIBDRM_LIB) $(APP_LIB_DEPS) -o $@ + +xeglgears.o: xeglgears.c $(HEADERS) +	$(CC) -c $(CFLAGS) -I$(TOP)/include xeglgears.c + +  clean:  	rm -f *.o *~  	rm -f *.so diff --git a/progs/egl/xeglgears.c b/progs/egl/xeglgears.c new file mode 100644 index 0000000000..503958cf8c --- /dev/null +++ b/progs/egl/xeglgears.c @@ -0,0 +1,604 @@ +/* + * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved. + *  + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + *  + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Ported to X/EGL/GLES.   XXX Actually, uses full OpenGL ATM. + * Brian Paul + * 30 May 2008 + */ + +/* + * Command line options: + *    -info      print GL implementation information + * + */ + + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <GL/gl.h> +#include <GLES/egl.h> + + +#define BENCHMARK + +#ifdef BENCHMARK + +/* XXX this probably isn't very portable */ + +#include <sys/time.h> +#include <unistd.h> + +/* return current time (in seconds) */ +static double +current_time(void) +{ +   struct timeval tv; +#ifdef __VMS +   (void) gettimeofday(&tv, NULL ); +#else +   struct timezone tz; +   (void) gettimeofday(&tv, &tz); +#endif +   return (double) tv.tv_sec + tv.tv_usec / 1000000.0; +} + +#else /*BENCHMARK*/ + +/* dummy */ +static double +current_time(void) +{ +   /* update this function for other platforms! */ +   static double t = 0.0; +   static int warn = 1; +   if (warn) { +      fprintf(stderr, "Warning: current_time() not implemented!!\n"); +      warn = 0; +   } +   return t += 1.0; +} + +#endif /*BENCHMARK*/ + + + +#ifndef M_PI +#define M_PI 3.14159265 +#endif + + +static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; +static GLint gear1, gear2, gear3; +static GLfloat angle = 0.0; + +static GLboolean fullscreen = GL_FALSE;	/* Create a single fullscreen window */ + + +/* + * + *  Draw a gear wheel.  You'll probably want to call this function when + *  building a display list since we do a lot of trig here. + *  + *  Input:  inner_radius - radius of hole at center + *          outer_radius - radius at center of teeth + *          width - width of gear + *          teeth - number of teeth + *          tooth_depth - depth of tooth + */ +static void +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, +     GLint teeth, GLfloat tooth_depth) +{ +   GLint i; +   GLfloat r0, r1, r2; +   GLfloat angle, da; +   GLfloat u, v, len; + +   r0 = inner_radius; +   r1 = outer_radius - tooth_depth / 2.0; +   r2 = outer_radius + tooth_depth / 2.0; + +   da = 2.0 * M_PI / teeth / 4.0; + +   glShadeModel(GL_FLAT); + +   glNormal3f(0.0, 0.0, 1.0); + +   /* draw front face */ +   glBegin(GL_QUAD_STRIP); +   for (i = 0; i <= teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; +      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); +      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); +      if (i < teeth) { +	 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); +	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		    width * 0.5); +      } +   } +   glEnd(); + +   /* draw front sides of teeth */ +   glBegin(GL_QUADS); +   da = 2.0 * M_PI / teeth / 4.0; +   for (i = 0; i < teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; + +      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); +      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); +      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), +		 width * 0.5); +      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		 width * 0.5); +   } +   glEnd(); + +   glNormal3f(0.0, 0.0, -1.0); + +   /* draw back face */ +   glBegin(GL_QUAD_STRIP); +   for (i = 0; i <= teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; +      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); +      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); +      if (i < teeth) { +	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		    -width * 0.5); +	 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); +      } +   } +   glEnd(); + +   /* draw back sides of teeth */ +   glBegin(GL_QUADS); +   da = 2.0 * M_PI / teeth / 4.0; +   for (i = 0; i < teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; + +      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		 -width * 0.5); +      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), +		 -width * 0.5); +      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); +      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); +   } +   glEnd(); + +   /* draw outward faces of teeth */ +   glBegin(GL_QUAD_STRIP); +   for (i = 0; i < teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; + +      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); +      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); +      u = r2 * cos(angle + da) - r1 * cos(angle); +      v = r2 * sin(angle + da) - r1 * sin(angle); +      len = sqrt(u * u + v * v); +      u /= len; +      v /= len; +      glNormal3f(v, -u, 0.0); +      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); +      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); +      glNormal3f(cos(angle), sin(angle), 0.0); +      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), +		 width * 0.5); +      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), +		 -width * 0.5); +      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); +      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); +      glNormal3f(v, -u, 0.0); +      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		 width * 0.5); +      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		 -width * 0.5); +      glNormal3f(cos(angle), sin(angle), 0.0); +   } + +   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); +   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); + +   glEnd(); + +   glShadeModel(GL_SMOOTH); + +   /* draw inside radius cylinder */ +   glBegin(GL_QUAD_STRIP); +   for (i = 0; i <= teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; +      glNormal3f(-cos(angle), -sin(angle), 0.0); +      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); +      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); +   } +   glEnd(); +} + + +static void +draw(void) +{ +   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + +   glPushMatrix(); +   glRotatef(view_rotx, 1.0, 0.0, 0.0); +   glRotatef(view_roty, 0.0, 1.0, 0.0); +   glRotatef(view_rotz, 0.0, 0.0, 1.0); + +   glPushMatrix(); +   glTranslatef(-3.0, -2.0, 0.0); +   glRotatef(angle, 0.0, 0.0, 1.0); +   glCallList(gear1); +   glPopMatrix(); + +   glPushMatrix(); +   glTranslatef(3.1, -2.0, 0.0); +   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); +   glCallList(gear2); +   glPopMatrix(); + +   glPushMatrix(); +   glTranslatef(-3.1, 4.2, 0.0); +   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); +   glCallList(gear3); +   glPopMatrix(); + +   glPopMatrix(); +} + + +/* new window size or exposure */ +static void +reshape(int width, int height) +{ +   GLfloat ar = (GLfloat) width / (GLfloat) height; + +   glViewport(0, 0, (GLint) width, (GLint) height); + +   glMatrixMode(GL_PROJECTION); +   glLoadIdentity(); +   glFrustum(-ar, ar, -1, 1, 5.0, 60.0); +    +   glMatrixMode(GL_MODELVIEW); +   glLoadIdentity(); +   glTranslatef(0.0, 0.0, -40.0); +} +    + + +static void +init(void) +{ +   static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; +   static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; +   static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; +   static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; + +   glLightfv(GL_LIGHT0, GL_POSITION, pos); +   glEnable(GL_CULL_FACE); +   glEnable(GL_LIGHTING); +   glEnable(GL_LIGHT0); +   glEnable(GL_DEPTH_TEST); + +   /* make the gears */ +   gear1 = glGenLists(1); +   glNewList(gear1, GL_COMPILE); +   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); +   gear(1.0, 4.0, 1.0, 20, 0.7); +   glEndList(); + +   gear2 = glGenLists(1); +   glNewList(gear2, GL_COMPILE); +   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); +   gear(0.5, 2.0, 2.0, 10, 0.7); +   glEndList(); + +   gear3 = glGenLists(1); +   glNewList(gear3, GL_COMPILE); +   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); +   gear(1.3, 2.0, 0.5, 10, 0.7); +   glEndList(); + +   glEnable(GL_NORMALIZE); + +   glClearColor(0.2, 0.2, 0.2, 0.0); +} + + +/* + * Create an RGB, double-buffered X window. + * Return the window and context handles. + */ +static void +make_x_window(Display *x_dpy, EGLDisplay egl_dpy, +              const char *name, +              int x, int y, int width, int height, +              Window *winRet, +              EGLContext *ctxRet, +              EGLSurface *surfRet) +{ +   static const EGLint attribs[] = { +      EGL_RED_SIZE, 1, +      EGL_GREEN_SIZE, 1, +      EGL_BLUE_SIZE, 1, +      /*EGL_DOUBLEBUFFER,*/ +      EGL_DEPTH_SIZE, 1, +      EGL_NONE +   }; + +   int scrnum; +   XSetWindowAttributes attr; +   unsigned long mask; +   Window root; +   Window win; +   XVisualInfo *visInfo, visTemplate; +   int num_visuals; +   EGLContext ctx; +   EGLConfig config; +   EGLint num_configs; + +   scrnum = DefaultScreen( x_dpy ); +   root = RootWindow( x_dpy, scrnum ); + +   if (fullscreen) { +      x = 0; y = 0; +      width = DisplayWidth( x_dpy, scrnum ); +      height = DisplayHeight( x_dpy, scrnum ); +   } + +   if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) { +      printf("Error: couldn't get an EGL visual config\n"); +      exit(1); +   } + +   /* choose X window visual similar to EGL config */ +   visTemplate.screen = DefaultScreen(x_dpy); +   visTemplate.depth = 32; /* 24? */ +   visInfo = XGetVisualInfo(x_dpy, +                            (VisualDepthMask | VisualScreenMask), +                            &visTemplate, &num_visuals); +   if (!visInfo) { +      printf("Error: couldn't get X visual\n"); +      exit(1); +   } + +   /* window attributes */ +   attr.background_pixel = 0; +   attr.border_pixel = 0; +   attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone); +   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; +   attr.override_redirect = fullscreen; +   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; + +   win = XCreateWindow( x_dpy, root, 0, 0, width, height, +		        0, visInfo->depth, InputOutput, +		        visInfo->visual, mask, &attr ); + +   /* set hints and properties */ +   { +      XSizeHints sizehints; +      sizehints.x = x; +      sizehints.y = y; +      sizehints.width  = width; +      sizehints.height = height; +      sizehints.flags = USSize | USPosition; +      XSetNormalHints(x_dpy, win, &sizehints); +      XSetStandardProperties(x_dpy, win, name, name, +                              None, (char **)NULL, 0, &sizehints); +   } + +   ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL ); +   if (!ctx) { +      printf("Error: glXCreateContext failed\n"); +      exit(1); +   } + +   *surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL); + +   XFree(visInfo); + +   *winRet = win; +   *ctxRet = ctx; +} + + +static void +event_loop(Display *dpy, Window win, +           EGLDisplay egl_dpy, EGLSurface egl_surf) +{ +   while (1) { +      while (XPending(dpy) > 0) { +         XEvent event; +         XNextEvent(dpy, &event); +         switch (event.type) { +	 case Expose: +            /* we'll redraw below */ +	    break; +	 case ConfigureNotify: +	    reshape(event.xconfigure.width, event.xconfigure.height); +	    break; +         case KeyPress: +            { +               char buffer[10]; +               int r, code; +               code = XLookupKeysym(&event.xkey, 0); +               if (code == XK_Left) { +                  view_roty += 5.0; +               } +               else if (code == XK_Right) { +                  view_roty -= 5.0; +               } +               else if (code == XK_Up) { +                  view_rotx += 5.0; +               } +               else if (code == XK_Down) { +                  view_rotx -= 5.0; +               } +               else { +                  r = XLookupString(&event.xkey, buffer, sizeof(buffer), +                                    NULL, NULL); +                  if (buffer[0] == 27) { +                     /* escape */ +                     return; +                  } +               } +            } +         } +      } + +      { +         static int frames = 0; +         static double tRot0 = -1.0, tRate0 = -1.0; +         double dt, t = current_time(); +         if (tRot0 < 0.0) +            tRot0 = t; +         dt = t - tRot0; +         tRot0 = t; + +         /* advance rotation for next frame */ +         angle += 70.0 * dt;  /* 70 degrees per second */ +         if (angle > 3600.0) +             angle -= 3600.0; + +         draw(); +         eglSwapBuffers(egl_dpy, egl_surf); + +         frames++; + +         if (tRate0 < 0.0) +            tRate0 = t; +         if (t - tRate0 >= 5.0) { +            GLfloat seconds = t - tRate0; +            GLfloat fps = frames / seconds; +            printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, +                   fps); +            tRate0 = t; +            frames = 0; +         } +      } +   } +} + + +static void +usage(void) +{ +   printf("Usage:\n"); +   printf("  -display <displayname>  set the display to run on\n"); +   printf("  -fullscreen             run in fullscreen mode\n"); +   printf("  -info                   display OpenGL renderer info\n"); +} +  + +int +main(int argc, char *argv[]) +{ +   const int winWidth = 300, winHeight = 300; +   Display *x_dpy; +   Window win; +   EGLSurface egl_surf; +   EGLContext egl_ctx; +   EGLDisplay egl_dpy; +   char *dpyName = NULL; +   GLboolean printInfo = GL_FALSE; +   EGLint egl_major, egl_minor; +   int i; +   const char *s; + +   for (i = 1; i < argc; i++) { +      if (strcmp(argv[i], "-display") == 0) { +         dpyName = argv[i+1]; +         i++; +      } +      else if (strcmp(argv[i], "-info") == 0) { +         printInfo = GL_TRUE; +      } +      else if (strcmp(argv[i], "-fullscreen") == 0) { +         fullscreen = GL_TRUE; +      } +      else { +         usage(); +         return -1; +      } +   } + +   x_dpy = XOpenDisplay(dpyName); +   if (!x_dpy) { +      printf("Error: couldn't open display %s\n", +	     dpyName ? dpyName : getenv("DISPLAY")); +      return -1; +   } + +   egl_dpy = eglGetDisplay(x_dpy); +   if (!egl_dpy) { +      printf("Error: eglGetDisplay() failed\n"); +      return -1; +   } + +   if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) { +      printf("Error: eglInitialize() failed\n"); +      return -1; +   } + +   s = eglQueryString(egl_dpy, EGL_VERSION); +   printf("EGL_VERSION = %s\n", s); + +   make_x_window(x_dpy, egl_dpy, +                 "glxgears", 0, 0, winWidth, winHeight, +                 &win, &egl_ctx, &egl_surf); + +   XMapWindow(x_dpy, win); +   eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx); + +   if (printInfo) { +      printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER)); +      printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION)); +      printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR)); +   } + +   init(); + +   /* Set initial projection/viewing transformation. +    * We can't be sure we'll get a ConfigureNotify event when the window +    * first appears. +    */ +   reshape(winWidth, winHeight); + +   event_loop(x_dpy, win, egl_dpy, egl_surf); + +   glDeleteLists(gear1, 1); +   glDeleteLists(gear2, 1); +   glDeleteLists(gear3, 1); + +   eglDestroyContext(egl_dpy, egl_ctx); +   eglDestroySurface(egl_dpy, egl_surf); +   eglTerminate(egl_dpy); + + +   XDestroyWindow(x_dpy, win); +   XCloseDisplay(x_dpy); + +   return 0; +} | 
