progs/egl: Add eglut.
authorChia-I Wu <olv@lunarg.com>
Thu, 1 Apr 2010 04:19:47 +0000 (12:19 +0800)
committerChia-I Wu <olv@lunarg.com>
Thu, 1 Apr 2010 14:25:48 +0000 (22:25 +0800)
eglut is a simple library with GLUT-like API.  It is intended to be used
by simple EGL demos.

progs/egl/eglut/Makefile [new file with mode: 0644]
progs/egl/eglut/eglut.c [new file with mode: 0644]
progs/egl/eglut/eglut.h [new file with mode: 0644]
progs/egl/eglut/eglut_screen.c [new file with mode: 0644]
progs/egl/eglut/eglut_x11.c [new file with mode: 0644]
progs/egl/eglut/eglutint.h [new file with mode: 0644]

diff --git a/progs/egl/eglut/Makefile b/progs/egl/eglut/Makefile
new file mode 100644 (file)
index 0000000..f5cafa7
--- /dev/null
@@ -0,0 +1,35 @@
+# progs/egl/eglut
+
+TOP = ../../..
+include $(TOP)/configs/current
+
+INCLUDES = \
+       -I$(TOP)/include
+
+SOURCES = $(wildcard *.c)
+
+EGLUT_X11_OBJECTS = eglut.o eglut_x11.o
+EGLUT_SCREEN_OBJECTS = eglut.o eglut_screen.o
+
+default: depend libeglut-x11.a libeglut-screen.a
+
+libeglut-x11.a: $(EGLUT_X11_OBJECTS)
+       $(MKLIB) -o eglut-x11 -static $(EGLUT_X11_OBJECTS)
+
+libeglut-screen.a: $(EGLUT_SCREEN_OBJECTS)
+       $(MKLIB) -o eglut-screen -static $(EGLUT_SCREEN_OBJECTS)
+
+.c.o:
+       $(CC) -c -o $@ $< $(INCLUDES) $(DEFINES) $(CFLAGS)
+
+depend: $(SOURCES)
+       @rm -f depend
+       @touch depend
+       @$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES) \
+               > /dev/null 2>/dev/null
+
+clean:
+       rm -f *.o *.a
+       rm -f depend depend.bak
+
+sinclude depend
diff --git a/progs/egl/eglut/eglut.c b/progs/egl/eglut/eglut.c
new file mode 100644 (file)
index 0000000..0bfd5d5
--- /dev/null
@@ -0,0 +1,326 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/time.h>
+
+#include "EGL/egl.h"
+#include "EGL/eglext.h"
+
+#include "eglutint.h"
+
+static struct eglut_state _eglut_state = {
+   .api_mask = EGLUT_OPENGL_ES1_BIT,
+   .window_width = 300,
+   .window_height = 300,
+   .verbose = 0,
+   .num_windows = 0,
+};
+
+struct eglut_state *_eglut = &_eglut_state;
+
+void
+_eglutFatal(char *format, ...)
+{
+  va_list args;
+
+  va_start(args, format);
+
+  fprintf(stderr, "EGLUT: ");
+  vfprintf(stderr, format, args);
+  va_end(args);
+  putc('\n', stderr);
+
+  exit(1);
+}
+
+/* return current time (in milliseconds) */
+int
+_eglutNow(void)
+{
+   struct timeval tv;
+#ifdef __VMS
+   (void) gettimeofday(&tv, NULL );
+#else
+   struct timezone tz;
+   (void) gettimeofday(&tv, &tz);
+#endif
+   return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+static void
+_eglutDestroyWindow(struct eglut_window *win)
+{
+   if (_eglut->surface_type != EGL_PBUFFER_BIT &&
+       _eglut->surface_type != EGL_SCREEN_BIT_MESA)
+      eglDestroySurface(_eglut->dpy, win->surface);
+
+   _eglutNativeFiniWindow(win);
+
+   eglDestroyContext(_eglut->dpy, win->context);
+}
+
+static EGLConfig
+_eglutChooseConfig(void)
+{
+   EGLConfig config;
+   EGLint config_attribs[32];
+   EGLint renderable_type, num_configs, i;
+
+   i = 0;
+   config_attribs[i++] = EGL_RED_SIZE;
+   config_attribs[i++] = 1;
+   config_attribs[i++] = EGL_GREEN_SIZE;
+   config_attribs[i++] = 1;
+   config_attribs[i++] = EGL_BLUE_SIZE;
+   config_attribs[i++] = 1;
+   config_attribs[i++] = EGL_DEPTH_SIZE;
+   config_attribs[i++] = 1;
+
+   config_attribs[i++] = EGL_SURFACE_TYPE;
+   config_attribs[i++] = _eglut->surface_type;
+
+   config_attribs[i++] = EGL_RENDERABLE_TYPE;
+   renderable_type = 0x0;
+   if (_eglut->api_mask & EGLUT_OPENGL_BIT)
+      renderable_type |= EGL_OPENGL_BIT;
+   if (_eglut->api_mask & (EGLUT_OPENGL_ES1_BIT | EGLUT_OPENGL_ES2_BIT))
+      renderable_type |= EGL_OPENGL_ES_BIT;
+   if (_eglut->api_mask & EGLUT_OPENVG_BIT)
+      renderable_type |= EGL_OPENVG_BIT;
+   config_attribs[i++] = renderable_type;
+
+   config_attribs[i] = EGL_NONE;
+
+   if (!eglChooseConfig(_eglut->dpy,
+            config_attribs, &config, 1, &num_configs) || !num_configs)
+      _eglutFatal("failed to choose a config");
+
+   return config;
+}
+
+static struct eglut_window *
+_eglutCreateWindow(const char *title, int x, int y, int w, int h)
+{
+   struct eglut_window *win;
+   EGLint context_attribs[4];
+   EGLint api, i;
+
+   win = calloc(1, sizeof(*win));
+   if (!win)
+      _eglutFatal("failed to allocate window");
+
+   win->config = _eglutChooseConfig();
+
+   i = 0;
+   context_attribs[i] = EGL_NONE;
+
+   /* multiple APIs? */
+
+   api = EGL_OPENGL_ES_API;
+   if (_eglut->api_mask & EGLUT_OPENGL_BIT) {
+      api = EGL_OPENGL_API;
+   }
+   else if (_eglut->api_mask & EGLUT_OPENVG_BIT) {
+      api = EGL_OPENVG_API;
+   }
+   else if (_eglut->api_mask & EGLUT_OPENGL_ES2_BIT) {
+      context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
+      context_attribs[i++] = 2;
+   }
+
+   context_attribs[i] = EGL_NONE;
+
+   eglBindAPI(api);
+   win->context = eglCreateContext(_eglut->dpy,
+         win->config, EGL_NO_CONTEXT, context_attribs);
+   if (!win->context)
+      _eglutFatal("failed to create context");
+
+   _eglutNativeInitWindow(win, title, x, y, w, h);
+   switch (_eglut->surface_type) {
+   case EGL_WINDOW_BIT:
+      win->surface = eglCreateWindowSurface(_eglut->dpy,
+            win->config, win->native.u.window, NULL);
+      break;
+   case EGL_PIXMAP_BIT:
+      win->surface = eglCreatePixmapSurface(_eglut->dpy,
+            win->config, win->native.u.pixmap, NULL);
+      break;
+   case EGL_PBUFFER_BIT:
+   case EGL_SCREEN_BIT_MESA:
+      win->surface = win->native.u.surface;
+      break;
+   default:
+      break;
+   }
+   if (win->surface == EGL_NO_SURFACE)
+      _eglutFatal("failed to create surface");
+
+   return win;
+}
+
+void
+eglutInitAPIMask(int mask)
+{
+   _eglut->api_mask = mask;
+}
+
+void
+eglutInitWindowSize(int width, int height)
+{
+   _eglut->window_width = width;
+   _eglut->window_height = height;
+}
+
+void
+eglutInit(int argc, char **argv)
+{
+   int i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0)
+         _eglut->display_name = argv[++i];
+      else if (strcmp(argv[i], "-info") == 0) {
+         _eglut->verbose = 1;
+      }
+   }
+
+   _eglutNativeInitDisplay();
+   _eglut->dpy = eglGetDisplay(_eglut->native_dpy);
+
+   if (!eglInitialize(_eglut->dpy, &_eglut->major, &_eglut->minor))
+      _eglutFatal("failed to initialize EGL display");
+
+   _eglut->init_time = _eglutNow();
+
+   printf("EGL_VERSION = %s\n", eglQueryString(_eglut->dpy, EGL_VERSION));
+}
+
+int
+eglutGet(int state)
+{
+   int val;
+
+   switch (state) {
+   case EGLUT_ELAPSED_TIME:
+      val = _eglutNow() - _eglut->init_time;
+      break;
+   default:
+      val = -1;
+      break;
+   }
+
+   return val;
+}
+
+void
+eglutIdleFunc(EGLUTidleCB func)
+{
+   _eglut->idle_cb = func;
+}
+
+void
+eglutPostRedisplay(void)
+{
+   _eglut->redisplay = 1;
+}
+
+void
+eglutMainLoop(void)
+{
+   struct eglut_window *win = _eglut->current;
+
+   if (!win)
+      _eglutFatal("no window is created\n");
+
+   if (win->reshape_cb)
+      win->reshape_cb(win->native.width, win->native.height);
+
+   _eglutNativeEventLoop();
+}
+
+static void
+_eglutFini(void)
+{
+   eglTerminate(_eglut->dpy);
+   _eglutNativeFiniDisplay();
+}
+
+static void
+_eglutDefaultKeyboard(unsigned char key)
+{
+   if (key == 27) {
+      /* XXX it causes some bug in st/egl KMS backend */
+      if ( _eglut->surface_type != EGL_SCREEN_BIT_MESA)
+         eglMakeCurrent(_eglut->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+      _eglutDestroyWindow(_eglut->current);
+      _eglutFini();
+
+      exit(0);
+   }
+}
+
+int
+eglutCreateWindow(const char *title)
+{
+   struct eglut_window *win;
+
+   win = _eglutCreateWindow(title, 0, 0,
+         _eglut->window_width, _eglut->window_height);
+
+   win->index = _eglut->num_windows++;
+   win->reshape_cb = NULL;
+   win->display_cb = NULL;
+   win->keyboard_cb = _eglutDefaultKeyboard;
+   win->special_cb = NULL;
+
+   if (!eglMakeCurrent(_eglut->dpy, win->surface, win->surface, win->context))
+      _eglutFatal("failed to make window current");
+   _eglut->current = win;
+
+   return win->index;
+}
+
+int
+eglutGetWindowWidth(void)
+{
+   struct eglut_window *win = _eglut->current;
+   return win->native.width;
+}
+
+int
+eglutGetWindowHeight(void)
+{
+   struct eglut_window *win = _eglut->current;
+   return win->native.height;
+}
+
+void
+eglutDisplayFunc(EGLUTdisplayCB func)
+{
+   struct eglut_window *win = _eglut->current;
+   win->display_cb = func;
+
+}
+
+void
+eglutReshapeFunc(EGLUTreshapeCB func)
+{
+   struct eglut_window *win = _eglut->current;
+   win->reshape_cb = func;
+}
+
+void
+eglutKeyboardFunc(EGLUTkeyboardCB func)
+{
+   struct eglut_window *win = _eglut->current;
+   win->keyboard_cb = func;
+}
+
+void
+eglutSpecialFunc(EGLUTspecialCB func)
+{
+   struct eglut_window *win = _eglut->current;
+   win->special_cb = func;
+}
diff --git a/progs/egl/eglut/eglut.h b/progs/egl/eglut/eglut.h
new file mode 100644 (file)
index 0000000..521cc12
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef EGLUT_H
+#define EGLUT_H
+
+/* used by eglutInitAPIMask */
+enum {
+   EGLUT_OPENGL_BIT     = 0x1,
+   EGLUT_OPENGL_ES1_BIT = 0x2,
+   EGLUT_OPENGL_ES2_BIT = 0x4,
+   EGLUT_OPENVG_BIT     = 0x8
+};
+
+/* used by EGLUTspecialCB */
+enum {
+   /* function keys */
+   EGLUT_KEY_F1,
+   EGLUT_KEY_F2,
+   EGLUT_KEY_F3,
+   EGLUT_KEY_F4,
+   EGLUT_KEY_F5,
+   EGLUT_KEY_F6,
+   EGLUT_KEY_F7,
+   EGLUT_KEY_F8,
+   EGLUT_KEY_F9,
+   EGLUT_KEY_F10,
+   EGLUT_KEY_F11,
+   EGLUT_KEY_F12,
+
+   /* directional keys */
+   EGLUT_KEY_LEFT,
+   EGLUT_KEY_UP,
+   EGLUT_KEY_RIGHT,
+   EGLUT_KEY_DOWN,
+};
+
+/* used by eglutGet */
+enum {
+   EGLUT_ELAPSED_TIME
+};
+
+typedef void (*EGLUTidleCB)(void);
+typedef void (*EGLUTreshapeCB)(int, int);
+typedef void (*EGLUTdisplayCB)(void);
+typedef void (*EGLUTkeyboardCB)(unsigned char);
+typedef void (*EGLUTspecialCB)(int);
+
+void eglutInitAPIMask(int mask);
+void eglutInitWindowSize(int width, int height);
+void eglutInit(int argc, char **argv);
+
+int eglutGet(int state);
+
+void eglutIdleFunc(EGLUTidleCB func);
+void eglutPostRedisplay(void);
+
+void eglutMainLoop(void);
+
+int eglutCreateWindow(const char *title);
+
+int eglutGetWindowWidth(void);
+int eglutGetWindowHeight(void);
+
+void eglutDisplayFunc(EGLUTdisplayCB func);
+void eglutReshapeFunc(EGLUTreshapeCB func);
+void eglutKeyboardFunc(EGLUTkeyboardCB func);
+void eglutSpecialFunc(EGLUTspecialCB func);
+
+#endif /* EGLUT_H */
diff --git a/progs/egl/eglut/eglut_screen.c b/progs/egl/eglut/eglut_screen.c
new file mode 100644 (file)
index 0000000..50549e4
--- /dev/null
@@ -0,0 +1,154 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+#define EGL_EGLEXT_PROTOTYPES
+#include "EGL/egl.h"
+#include "EGL/eglext.h"
+
+#include "eglutint.h"
+
+#define MAX_MODES 100
+
+static EGLScreenMESA kms_screen;
+static EGLModeMESA kms_mode;
+static EGLint kms_width, kms_height;
+
+void
+_eglutNativeInitDisplay(void)
+{
+   _eglut->native_dpy = EGL_DEFAULT_DISPLAY;
+   _eglut->surface_type = EGL_SCREEN_BIT_MESA;
+}
+
+void
+_eglutNativeFiniDisplay(void)
+{
+   kms_screen = 0;
+   kms_mode = 0;
+   kms_width = 0;
+   kms_height = 0;
+}
+
+static void
+init_kms(void)
+{
+   EGLModeMESA modes[MAX_MODES];
+   EGLint num_screens, num_modes;
+   EGLint width, height, best_mode;
+   EGLint i;
+
+   if (!eglGetScreensMESA(_eglut->dpy, &kms_screen, 1, &num_screens) ||
+         !num_screens)
+      _eglutFatal("eglGetScreensMESA failed\n");
+
+   if (!eglGetModesMESA(_eglut->dpy, kms_screen,
+            modes, MAX_MODES, &num_modes) || !num_modes)
+      _eglutFatal("eglGetModesMESA failed!\n");
+
+   printf("Found %d modes:\n", num_modes);
+
+   best_mode = 0;
+   width = 0;
+   height = 0;
+   for (i = 0; i < num_modes; i++) {
+      EGLint w, h;
+      eglGetModeAttribMESA(_eglut->dpy, modes[i], EGL_WIDTH, &w);
+      eglGetModeAttribMESA(_eglut->dpy, modes[i], EGL_HEIGHT, &h);
+      printf("%3d: %d x %d\n", i, w, h);
+      if (w > width && h > height) {
+         width = w;
+         height = h;
+         best_mode = i;
+      }
+   }
+
+   printf("Will use screen size: %d x %d\n", width, height);
+
+   kms_mode = modes[best_mode];
+   kms_width = width;
+   kms_height = height;
+}
+
+void
+_eglutNativeInitWindow(struct eglut_window *win, const char *title,
+                       int x, int y, int w, int h)
+{
+   EGLint surf_attribs[16];
+   EGLint i;
+   const char *exts;
+
+   exts = eglQueryString(_eglut->dpy, EGL_EXTENSIONS);
+   if (!exts || !strstr(exts, "EGL_MESA_screen_surface"))
+      _eglutFatal("EGL_MESA_screen_surface is not supported\n");
+
+   init_kms();
+
+   i = 0;
+   surf_attribs[i++] = EGL_WIDTH;
+   surf_attribs[i++] = kms_width;
+   surf_attribs[i++] = EGL_HEIGHT;
+   surf_attribs[i++] = kms_height;
+   surf_attribs[i++] = EGL_NONE;
+
+   /* create surface */
+   win->native.u.surface = eglCreateScreenSurfaceMESA(_eglut->dpy,
+         win->config, surf_attribs);
+   if (win->native.u.surface == EGL_NO_SURFACE)
+      _eglutFatal("eglCreateScreenSurfaceMESA failed\n");
+
+   if (!eglShowScreenSurfaceMESA(_eglut->dpy, kms_screen,
+            win->native.u.surface, kms_mode))
+      _eglutFatal("eglShowScreenSurfaceMESA failed\n");
+
+   win->native.width = kms_width;
+   win->native.height = kms_height;
+}
+
+void
+_eglutNativeFiniWindow(struct eglut_window *win)
+{
+   eglShowScreenSurfaceMESA(_eglut->dpy,
+         kms_screen, EGL_NO_SURFACE, 0);
+   eglDestroySurface(_eglut->dpy, win->native.u.surface);
+}
+
+void
+_eglutNativeEventLoop(void)
+{
+   int start = _eglutNow();
+   int frames = 0;
+
+   _eglut->redisplay = 1;
+
+   while (1) {
+      struct eglut_window *win = _eglut->current;
+      int now = _eglutNow();
+
+      if (now - start > 5000) {
+         double elapsed = (double) (now - start) / 1000.0;
+
+         printf("%d frames in %3.1f seconds = %6.3f FPS\n",
+               frames, elapsed, frames / elapsed);
+
+         start = now;
+         frames = 0;
+
+         /* send escape */
+         if (win->keyboard_cb)
+            win->keyboard_cb(27);
+      }
+
+      if (_eglut->idle_cb)
+         _eglut->idle_cb();
+
+      if (_eglut->redisplay) {
+         _eglut->redisplay = 0;
+
+         if (win->display_cb)
+            win->display_cb();
+         eglSwapBuffers(_eglut->dpy, win->surface);
+         frames++;
+      }
+   }
+}
diff --git a/progs/egl/eglut/eglut_x11.c b/progs/egl/eglut/eglut_x11.c
new file mode 100644 (file)
index 0000000..f3b2280
--- /dev/null
@@ -0,0 +1,220 @@
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+
+#include "eglutint.h"
+
+void
+_eglutNativeInitDisplay(void)
+{
+   _eglut->native_dpy = XOpenDisplay(_eglut->display_name);
+   if (!_eglut->native_dpy)
+      _eglutFatal("failed to initialize native display");
+
+   _eglut->surface_type = EGL_WINDOW_BIT;
+}
+
+void
+_eglutNativeFiniDisplay(void)
+{
+   XCloseDisplay(_eglut->native_dpy);
+}
+
+void
+_eglutNativeInitWindow(struct eglut_window *win, const char *title,
+                       int x, int y, int w, int h)
+{
+   XVisualInfo *visInfo, visTemplate;
+   int num_visuals;
+   Window root, xwin;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   EGLint vid;
+
+   if (!eglGetConfigAttrib(_eglut->dpy,
+            win->config, EGL_NATIVE_VISUAL_ID, &vid))
+      _eglutFatal("failed to get visual id");
+
+   /* The X window visual must match the EGL config */
+   visTemplate.visualid = vid;
+   visInfo = XGetVisualInfo(_eglut->native_dpy,
+         VisualIDMask, &visTemplate, &num_visuals);
+   if (!visInfo)
+      _eglutFatal("failed to get an visual of id 0x%x", vid);
+
+   root = RootWindow(_eglut->native_dpy, DefaultScreen(_eglut->native_dpy));
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(_eglut->native_dpy,
+         root, visInfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   xwin = XCreateWindow(_eglut->native_dpy, root, x, y, w, h,
+         0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr);
+   if (!xwin)
+      _eglutFatal("failed to create a window");
+
+   XFree(visInfo);
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = w;
+      sizehints.height = h;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(_eglut->native_dpy, xwin, &sizehints);
+      XSetStandardProperties(_eglut->native_dpy, xwin,
+            title, title, None, (char **) NULL, 0, &sizehints);
+   }
+
+   XMapWindow(_eglut->native_dpy, xwin);
+
+   win->native.u.window = xwin;
+   win->native.width = w;
+   win->native.height = h;
+}
+
+void
+_eglutNativeFiniWindow(struct eglut_window *win)
+{
+   XDestroyWindow(_eglut->native_dpy, win->native.u.window);
+}
+
+static int
+lookup_keysym(KeySym sym)
+{
+   int special;
+
+   switch (sym) {
+   case XK_F1:
+      special = EGLUT_KEY_F1;
+      break;
+   case XK_F2:
+      special = EGLUT_KEY_F2;
+      break;
+   case XK_F3:
+      special = EGLUT_KEY_F3;
+      break;
+   case XK_F4:
+      special = EGLUT_KEY_F4;
+      break;
+   case XK_F5:
+      special = EGLUT_KEY_F5;
+      break;
+   case XK_F6:
+      special = EGLUT_KEY_F6;
+      break;
+   case XK_F7:
+      special = EGLUT_KEY_F7;
+      break;
+   case XK_F8:
+      special = EGLUT_KEY_F8;
+      break;
+   case XK_F9:
+      special = EGLUT_KEY_F9;
+      break;
+   case XK_F10:
+      special = EGLUT_KEY_F10;
+      break;
+   case XK_F11:
+      special = EGLUT_KEY_F11;
+      break;
+   case XK_F12:
+      special = EGLUT_KEY_F12;
+      break;
+   case XK_KP_Left:
+   case XK_Left:
+      special = EGLUT_KEY_LEFT;
+      break;
+   case XK_KP_Up:
+   case XK_Up:
+      special = EGLUT_KEY_UP;
+      break;
+   case XK_KP_Right:
+   case XK_Right:
+      special = EGLUT_KEY_RIGHT;
+      break;
+   case XK_KP_Down:
+   case XK_Down:
+      special = EGLUT_KEY_DOWN;
+      break;
+   default:
+      special = -1;
+      break;
+   }
+
+   return special;
+}
+
+static void
+next_event(struct eglut_window *win)
+{
+   int redraw = 0;
+   XEvent event;
+
+   if (!XPending(_eglut->native_dpy)) {
+      if (_eglut->idle_cb)
+         _eglut->idle_cb();
+      return;
+   }
+
+   XNextEvent(_eglut->native_dpy, &event);
+
+   switch (event.type) {
+   case Expose:
+      redraw = 1;
+      break;
+   case ConfigureNotify:
+      win->native.width = event.xconfigure.width;
+      win->native.height = event.xconfigure.height;
+      if (win->reshape_cb)
+         win->reshape_cb(win->native.width, win->native.height);
+      break;
+   case KeyPress:
+      {
+         char buffer[1];
+         KeySym sym;
+         int r;
+
+         r = XLookupString(&event.xkey,
+               buffer, sizeof(buffer), &sym, NULL);
+         if (r && win->keyboard_cb) {
+            win->keyboard_cb(buffer[0]);
+         }
+         else if (!r && win->special_cb) {
+            r = lookup_keysym(sym);
+            if (r >= 0)
+               win->special_cb(r);
+         }
+      }
+      redraw = 1;
+      break;
+   default:
+      ; /*no-op*/
+   }
+
+   _eglut->redisplay = redraw;
+}
+
+void
+_eglutNativeEventLoop(void)
+{
+   while (1) {
+      struct eglut_window *win = _eglut->current;
+
+      next_event(win);
+
+      if (_eglut->redisplay) {
+         _eglut->redisplay = 0;
+
+         if (win->display_cb)
+            win->display_cb();
+         eglSwapBuffers(_eglut->dpy, win->surface);
+      }
+   }
+}
diff --git a/progs/egl/eglut/eglutint.h b/progs/egl/eglut/eglutint.h
new file mode 100644 (file)
index 0000000..54d329f
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _EGLUTINT_H_
+#define _EGLUTINT_H_
+
+#include "EGL/egl.h"
+#include "eglut.h"
+
+struct eglut_window {
+   EGLConfig config;
+   EGLContext context;
+
+   /* initialized by native display */
+   struct {
+      union {
+         EGLNativeWindowType window;
+         EGLNativePixmapType pixmap;
+         EGLSurface surface; /* pbuffer or screen surface */
+      } u;
+      int width, height;
+   } native;
+
+   EGLSurface surface;
+
+   int index;
+
+   EGLUTreshapeCB reshape_cb;
+   EGLUTdisplayCB display_cb;
+   EGLUTkeyboardCB keyboard_cb;
+   EGLUTspecialCB special_cb;
+};
+
+struct eglut_state {
+   int api_mask;
+   int window_width, window_height;
+   const char *display_name;
+   int verbose;
+   int init_time;
+
+   EGLUTidleCB idle_cb;
+
+   int num_windows;
+
+   /* initialized by native display */
+   EGLNativeDisplayType native_dpy;
+   EGLint surface_type;
+
+   EGLDisplay dpy;
+   EGLint major, minor;
+
+   struct eglut_window *current;
+
+   int redisplay;
+};
+
+extern struct eglut_state *_eglut;
+
+void
+_eglutFatal(char *format, ...);
+
+int
+_eglutNow(void);
+
+void
+_eglutNativeInitDisplay(void);
+
+void
+_eglutNativeFiniDisplay(void);
+
+void
+_eglutNativeInitWindow(struct eglut_window *win, const char *title,
+                       int x, int y, int w, int h);
+
+void
+_eglutNativeFiniWindow(struct eglut_window *win);
+
+void
+_eglutNativeEventLoop(void);
+
+#endif /* _EGLUTINT_H_ */