add segl
authorChia-I Wu <olvaffe@gmail.com>
Fri, 22 Jan 2010 16:11:48 +0000 (00:11 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Sat, 23 Jan 2010 02:10:47 +0000 (10:10 +0800)
progs/egl/segl/Makefile [new file with mode: 0644]
progs/egl/segl/segl.c [new file with mode: 0644]
progs/egl/segl/segl.h [new file with mode: 0644]
progs/egl/segl/segl_kms.c [new file with mode: 0644]
progs/egl/segl/segl_x11.c [new file with mode: 0644]

diff --git a/progs/egl/segl/Makefile b/progs/egl/segl/Makefile
new file mode 100644 (file)
index 0000000..c5f13f6
--- /dev/null
@@ -0,0 +1,21 @@
+# progs/egl/segl/Makefile
+
+TOP = ../../..
+include $(TOP)/configs/current
+
+SEGL_LIBS := $(foreach dpy, $(EGL_DISPLAYS), libsegl-$(dpy).a)
+
+all: $(SEGL_LIBS)
+
+x11_OBJECTS := segl.o segl_x11.o
+kms_OBJECTS := segl.o segl_kms.o
+
+libsegl-x11.a: $(x11_OBJECTS)
+       $(MKLIB) -o segl-x11 -static $(x11_OBJECTS)
+
+libsegl-kms.a: $(kms_OBJECTS)
+       $(MKLIB) -o segl-kms -static $(kms_OBJECTS)
+
+clean:
+       rm -f $(sort $(x11_OBJECTS) $(kms_OBJECTS))
+       rm -f $(SEGL_LIBS)
diff --git a/progs/egl/segl/segl.c b/progs/egl/segl/segl.c
new file mode 100644 (file)
index 0000000..b1df71a
--- /dev/null
@@ -0,0 +1,167 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <EGL/egl.h>
+
+#include "segl.h"
+
+static void
+segl_log(struct segl *segl, const char *format, ...)
+{
+   va_list ap;
+
+   va_start(ap, format);
+
+   if (segl->winsys->vlog)
+      segl->winsys->vlog(segl->winsys, format, ap);
+   else
+      vfprintf(stdout, format, ap);
+
+   va_end(ap);
+}
+
+static EGLBoolean
+segl_init_egl(struct segl *segl, const EGLint *attribs)
+{
+   EGLint num_conf;
+
+   segl->dpy = eglGetDisplay(segl->winsys->dpy);
+   if (!segl->dpy)
+      return EGL_FALSE;
+
+   if (!eglInitialize(segl->dpy, &segl->major, &segl->minor))
+      return EGL_FALSE;
+
+   if (segl->verbose) {
+      const char *ver = eglQueryString(segl->dpy, EGL_VERSION);
+      segl_log(segl, "EGL_VERSION = %s\n", ver);
+   }
+
+   if (!eglChooseConfig(segl->dpy, attribs, &segl->conf, 1, &num_conf) ||
+       !num_conf) {
+      segl_log(segl, "failed to choose a config\n");
+      eglTerminate(segl->dpy);
+      return EGL_FALSE;
+   }
+
+   return EGL_TRUE;
+}
+
+struct segl *
+segl_new(struct segl_winsys *winsys, const EGLint *attribs)
+{
+   struct segl *segl;
+
+   segl = calloc(1, sizeof(*segl));
+   if (segl) {
+      segl->verbose = EGL_TRUE;
+      segl->winsys = winsys;
+
+      if (!segl_init_egl(segl, attribs)) {
+         free(segl);
+         return NULL;
+      }
+   }
+
+   return segl;
+}
+
+void
+segl_destroy(struct segl *segl)
+{
+   free(segl);
+}
+
+EGLBoolean
+segl_create_window(struct segl *segl, const char *name,
+                   EGLint width, EGLint height, const EGLint *attribs,
+                   EGLNativeWindowType *win_ret, EGLSurface *surf_ret)
+{
+   EGLNativeWindowType win;
+   EGLSurface surf;
+   EGLint visual;
+
+   if (!win_ret) {
+      if (surf_ret)
+         *surf_ret = EGL_NO_SURFACE;
+      return EGL_TRUE;
+   }
+
+   if (!eglGetConfigAttrib(segl->dpy, segl->conf, EGL_NATIVE_VISUAL_ID, &visual))
+      return EGL_FALSE;
+
+   win = segl->winsys->create_window(segl->winsys,
+         name, width, height, visual);
+   if (surf_ret) {
+      surf = eglCreateWindowSurface(segl->dpy, segl->conf, win, attribs);
+      if (!surf) {
+         segl_log(segl, "failed to create a window surface\n");
+         segl->winsys->destroy_window(segl->winsys, win);
+         return EGL_FALSE;
+      }
+
+      *surf_ret = surf;
+   }
+
+   *win_ret = win;
+
+   return EGL_TRUE;
+}
+
+EGLBoolean
+segl_create_pixmap(struct segl *segl,
+                   EGLint width, EGLint height, const EGLint *attribs,
+                   EGLNativePixmapType *pix_ret, EGLSurface *surf_ret)
+{
+   EGLNativePixmapType pix;
+   EGLSurface surf;
+   EGLint depth;
+
+   if (!pix_ret) {
+      if (surf_ret)
+         *surf_ret = EGL_NO_SURFACE;
+      return EGL_TRUE;
+   }
+
+   if (!eglGetConfigAttrib(segl->dpy, segl->conf, EGL_BUFFER_SIZE, &depth))
+      return EGL_FALSE;
+
+   pix = segl->winsys->create_pixmap(segl->winsys, width, height, depth);
+   if (surf_ret) {
+      surf = eglCreatePixmapSurface(segl->dpy, segl->conf, pix, attribs);
+      if (!surf) {
+         segl_log(segl, "failed to create a pixmap surface\n");
+         segl->winsys->destroy_pixmap(segl->winsys, pix);
+         return EGL_FALSE;
+      }
+
+      *surf_ret = surf;
+   }
+
+   *pix_ret = pix;
+
+   return EGL_TRUE;
+}
+
+void
+segl_benchmark(struct segl *segl, double seconds,
+               void (*draw_frame)(void *), void *draw_data)
+{
+   double begin, end, last_frame, duration;
+   EGLint num_frames = 0;
+
+   begin = segl->winsys->now(segl->winsys);
+   end = begin + seconds;
+
+   last_frame = begin;
+   while (last_frame < end) {
+      draw_frame(draw_data);
+      last_frame = segl->winsys->now(segl->winsys);
+      num_frames++;
+   }
+
+   duration = last_frame - begin;
+   segl_log(segl, "%d frames in %3.1f seconds = %6.3f FPS\n",
+         num_frames, duration, (double) num_frames / duration);
+}
diff --git a/progs/egl/segl/segl.h b/progs/egl/segl/segl.h
new file mode 100644 (file)
index 0000000..20faf6e
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef _SEGL_H_
+#define _SEGL_H_
+
+#include <stdarg.h>
+#include <EGL/egl.h>
+
+struct segl_winsys {
+   EGLNativeDisplayType dpy;
+
+   EGLNativeWindowType (*create_window)(struct segl_winsys *winsys,
+                                        const char *name,
+                                        EGLint width, EGLint height,
+                                        EGLint visual);
+   void (*destroy_window)(struct segl_winsys *winsys, EGLNativeWindowType win);
+
+   EGLNativePixmapType (*create_pixmap)(struct segl_winsys *winsys,
+                                        EGLint width, EGLint height,
+                                        EGLint depth);
+   void (*destroy_pixmap)(struct segl_winsys *winsys, EGLNativePixmapType pix);
+
+   /* get current time in seconds */
+   double (*now)(struct segl_winsys *winsys);
+   /* log a message.  OPTIONAL */
+   void (*vlog)(struct segl_winsys *winsys, const char *format, va_list ap);
+};
+
+struct segl {
+   EGLBoolean verbose;
+
+   struct segl_winsys *winsys;
+
+   EGLint major, minor;
+   EGLDisplay dpy;
+   EGLConfig conf;
+};
+
+struct segl_winsys *
+segl_get_winsys(EGLNativeDisplayType dpy);
+
+struct segl *
+segl_new(struct segl_winsys *winsys, const EGLint *attribs);
+
+void
+segl_destroy(struct segl *segl);
+
+EGLBoolean
+segl_create_window(struct segl *segl, const char *name,
+                   EGLint width, EGLint height, const EGLint *attribs,
+                   EGLNativeWindowType *win_ret, EGLSurface *surf_ret);
+
+EGLBoolean
+segl_create_pixmap(struct segl *segl,
+                   EGLint width, EGLint height, const EGLint *attribs,
+                   EGLNativePixmapType *pix_ret, EGLSurface *surf_ret);
+
+void
+segl_benchmark(struct segl *segl, double seconds,
+               void (*draw_frame)(void *), void *draw_data);
+
+#endif /* _SEGL_H_ */
diff --git a/progs/egl/segl/segl_kms.c b/progs/egl/segl/segl_kms.c
new file mode 100644 (file)
index 0000000..bb4fcfc
--- /dev/null
@@ -0,0 +1,59 @@
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "segl.h"
+
+static EGLNativeWindowType
+kms_create_window(struct segl_winsys *winsys, const char *name,
+                  EGLint width, EGLint height, EGLint visual)
+{
+   return 0;
+}
+
+static void
+kms_destroy_window(struct segl_winsys *winsys, EGLNativeWindowType win)
+{
+}
+
+
+static EGLNativePixmapType 
+kms_create_pixmap(struct segl_winsys *winsys, EGLint width, EGLint height,
+                  EGLint depth)
+{
+   return 0;
+}
+
+static void
+kms_destroy_pixmap(struct segl_winsys *winsys, EGLNativePixmapType pix)
+{
+}
+
+static double
+kms_now(struct segl_winsys *winsys)
+{
+   struct timeval tv;
+
+   gettimeofday(&tv, NULL);
+
+   return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+struct segl_winsys *
+segl_get_winsys(EGLNativeDisplayType dpy)
+{
+   struct segl_winsys *winsys;
+
+   winsys = calloc(1, sizeof(*winsys));
+   if (winsys) {
+      winsys->dpy = dpy;
+
+      winsys->create_window = kms_create_window;
+      winsys->destroy_window = kms_destroy_window;
+      winsys->create_pixmap = kms_create_pixmap;
+      winsys->destroy_pixmap = kms_destroy_pixmap;
+
+      winsys->now = kms_now;
+   }
+
+   return winsys;
+}
diff --git a/progs/egl/segl/segl_x11.c b/progs/egl/segl/segl_x11.c
new file mode 100644 (file)
index 0000000..7b26917
--- /dev/null
@@ -0,0 +1,117 @@
+#include <stdlib.h>
+#include <sys/time.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "segl.h"
+
+static Window
+x11_create_window(struct segl_winsys *winsys, const char *name,
+                  EGLint width, EGLint height, EGLint visual)
+{
+   XVisualInfo vinfo_template, *vinfo = NULL;
+   EGLint val, num_vinfo;
+   Window root, win;
+   XSetWindowAttributes attrs;
+   unsigned long mask;
+   EGLint x = 0, y = 0;
+
+   vinfo_template.visualid = (VisualID) val;
+   vinfo = XGetVisualInfo(winsys->dpy, VisualIDMask, &vinfo_template, &num_vinfo);
+   if (!num_vinfo) {
+      if (vinfo)
+         XFree(vinfo);
+      return None;
+   }
+
+   root = DefaultRootWindow(winsys->dpy);
+
+   /* window attributes */
+   attrs.background_pixel = 0;
+   attrs.border_pixel = 0;
+   attrs.colormap = XCreateColormap(winsys->dpy, root, vinfo->visual, AllocNone);
+   attrs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   attrs.override_redirect = False;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
+
+   win = XCreateWindow(winsys->dpy, root, x, y, width, height, 0,
+         vinfo->depth, InputOutput, vinfo->visual, mask, &attrs);
+   XFree(vinfo);
+
+   if (!win)
+      return None;
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(winsys->dpy, win, &sizehints);
+      XSetStandardProperties(winsys->dpy, win, name, name,
+                             None, (char **)NULL, 0, &sizehints);
+   }
+
+   XMapWindow(winsys->dpy, win);
+
+   return win;
+}
+
+static void
+x11_destroy_window(struct segl_winsys *winsys, Window win)
+{
+   if (win)
+      XDestroyWindow(winsys->dpy, win);
+}
+
+
+static Pixmap 
+x11_create_pixmap(struct segl_winsys *winsys, EGLint width, EGLint height,
+                  EGLint depth)
+{
+   Window root = DefaultRootWindow(winsys->dpy);
+   Pixmap pix;
+
+   pix = XCreatePixmap(winsys->dpy, (Drawable) root, width, height, depth);
+
+   return pix;
+}
+
+static void
+x11_destroy_pixmap(struct segl_winsys *winsys, Pixmap pix)
+{
+   if (pix)
+      XFreePixmap(winsys->dpy, pix);
+}
+
+static double
+x11_now(struct segl_winsys *winsys)
+{
+   struct timeval tv;
+
+   gettimeofday(&tv, NULL);
+
+   return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+struct segl_winsys *
+segl_get_winsys(EGLNativeDisplayType dpy)
+{
+   struct segl_winsys *winsys;
+
+   winsys = calloc(1, sizeof(*winsys));
+   if (winsys) {
+      winsys->dpy = dpy;
+
+      winsys->create_window = x11_create_window;
+      winsys->destroy_window = x11_destroy_window;
+      winsys->create_pixmap = x11_create_pixmap;
+      winsys->destroy_pixmap = x11_destroy_pixmap;
+
+      winsys->now = x11_now;
+   }
+
+   return winsys;
+}