Demos (master): eglfbdev: add a demo for EGL on fbdev

Chia-I Wu olv at kemper.freedesktop.org
Tue Jun 28 06:13:39 UTC 2011


Module: Demos
Branch: master
Commit: a05e5db67134086e4f2fc8480890a2b315c8c704
URL:    http://cgit.freedesktop.org/mesa/demos/commit/?id=a05e5db67134086e4f2fc8480890a2b315c8c704

Author: Chia-I Wu <olvaffe at gmail.com>
Date:   Mon Jun 27 15:20:40 2011 +0900

eglfbdev: add a demo for EGL on fbdev

---

 src/egl/opengles1/Makefile.am |    1 +
 src/egl/opengles1/eglfbdev.c  |  338 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 339 insertions(+), 0 deletions(-)

diff --git a/src/egl/opengles1/Makefile.am b/src/egl/opengles1/Makefile.am
index 752c3d1..7a9828d 100644
--- a/src/egl/opengles1/Makefile.am
+++ b/src/egl/opengles1/Makefile.am
@@ -43,6 +43,7 @@ noinst_PROGRAMS = \
 	clear \
 	drawtex_screen \
 	drawtex_x11 \
+	eglfbdev \
 	es1_info \
 	gears_screen \
 	gears_x11 \
diff --git a/src/egl/opengles1/eglfbdev.c b/src/egl/opengles1/eglfbdev.c
new file mode 100644
index 0000000..bbc268e
--- /dev/null
+++ b/src/egl/opengles1/eglfbdev.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2011 LunarG Inc.
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors:
+ *    Chia-I Wu <olv at lunarg.com>
+ */
+
+/*
+ * This is a demonstration of EGL on fbdev:
+ *
+ *   The native display is the fd of the device;
+ *   There is only one native window, NULL;
+ *   There is no native pixmaps.
+ *
+ * It is the app's responsibility to set up the tty, open the fb device, and
+ * initialize EGL.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+/* for tty */
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
+#include <signal.h>
+
+/* for fbdev */
+#include <linux/fb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* for EGL */
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+
+static int tty_fd = -1;
+static int tty_saved_vtno;
+
+static int tty_open_vt(int vtno)
+{
+   const char tty[] = "/dev/tty%d";
+   char name[64];
+   int size, flags;
+
+   size = snprintf(name, sizeof(name), tty, vtno);
+   if (size >= sizeof(name))
+      return -1;
+
+   flags = (vtno) ? O_RDWR | O_NDELAY : O_WRONLY;
+
+   return open(name, flags);
+}
+
+static int tty_switch_vt(int fd, int vtno)
+{
+   int ret;
+
+   ret = ioctl(fd, VT_ACTIVATE, vtno);
+   if (ret >= 0)
+      ret = ioctl(fd, VT_WAITACTIVE, vtno);
+
+   return ret;
+}
+
+
+static int tty_init_vt(void)
+{
+   struct vt_stat vts;
+   int fd, vtno;
+
+   /* get the next available tty number */
+   fd = tty_open_vt(0);
+   if (fd < 0)
+      return -1;
+   if (ioctl(fd, VT_OPENQRY, &vtno) < 0)
+      goto fail;
+   close(fd);
+
+   fd = tty_open_vt(vtno);
+   if (fd < 0)
+      return -1;
+
+   /* save the current VT */
+   if (ioctl(fd, VT_GETSTATE, &vts) < 0)
+      goto fail;
+   tty_saved_vtno = vts.v_active;
+
+   if (tty_switch_vt(fd, vtno))
+      goto fail;
+
+   return fd;
+
+fail:
+   close(fd);
+   return -1;
+}
+
+static void
+tty_close(void)
+{
+   /* restore */
+   ioctl(tty_fd, KDSETMODE, KD_TEXT);
+   tty_switch_vt(tty_fd, tty_saved_vtno);
+
+   close(tty_fd);
+}
+
+static void
+signal_handler(int sig)
+{
+   if (tty_fd >= 0)
+      tty_close();
+}
+
+static int tty_open(void)
+{
+   struct sigaction sa;
+
+   tty_fd = tty_init_vt();
+   if (tty_fd < 0)
+      return -1;
+
+   /* install the signal handler */
+   memset(&sa, 0, sizeof(sa));
+   sigemptyset(&sa.sa_mask);
+   sa.sa_handler = signal_handler;
+   if (sigaction(SIGINT, &sa, NULL))
+      goto fail;
+   if (sigaction(SIGTERM, &sa, NULL))
+      goto fail;
+   if (sigaction(SIGABRT, &sa, NULL))
+      goto fail;
+
+   if (ioctl(tty_fd, KDSETMODE, KD_GRAPHICS) < 0)
+      goto fail;
+
+   tcflush(tty_fd, TCIOFLUSH);
+
+   return 0;
+
+fail:
+   tty_close();
+   tty_fd = -1;
+   return -1;
+}
+
+static EGLDisplay egl_dpy;
+static EGLContext egl_ctx;
+static EGLSurface egl_surf;
+static EGLBoolean egl_verbose;
+
+static void
+egl_fatal(char *format, ...)
+{
+   va_list args;
+
+   va_start(args, format);
+   vfprintf(stderr, format, args);
+   va_end(args);
+   putc('\n', stderr);
+
+   abort();
+}
+
+static void
+egl_init_for_fbdev(int fd, EGLBoolean verbose)
+{
+   const EGLNativeWindowType native_win = (EGLNativeWindowType) NULL;
+   EGLint major, minor, num_configs;
+   EGLConfig conf;
+
+   egl_verbose = verbose;
+
+   /* make Mesa/EGL happy */
+   setenv("EGL_PLATFORM", "fbdev", 0);
+
+   egl_dpy = eglGetDisplay((EGLNativeDisplayType) fd);
+   if (egl_dpy == EGL_NO_DISPLAY)
+      egl_fatal("failed to get a display");
+   if (!eglInitialize(egl_dpy, &major, &minor))
+      egl_fatal("failed to initialize EGL");
+
+   if (egl_verbose) {
+      printf("EGL %d.%d\n", major, minor);
+      printf("EGL_VENDOR: %s\n", eglQueryString(egl_dpy, EGL_VENDOR));
+      printf("EGL_VERSION: %s\n", eglQueryString(egl_dpy, EGL_VERSION));
+      printf("EGL_EXTENSIONS: %s\n", eglQueryString(egl_dpy, EGL_EXTENSIONS));
+      printf("EGL_CLIENT_APIS: %s\n",
+            eglQueryString(egl_dpy, EGL_CLIENT_APIS));
+   }
+
+   if (!eglChooseConfig(egl_dpy, NULL, &conf, 1, &num_configs) ||
+       !num_configs)
+      egl_fatal("failed to choose a config");
+
+   egl_ctx = eglCreateContext(egl_dpy, conf, EGL_NO_CONTEXT, NULL);
+   if (egl_ctx == EGL_NO_CONTEXT)
+      egl_fatal("failed to create a context");
+
+   egl_surf = eglCreateWindowSurface(egl_dpy, conf, native_win, NULL);
+   if (egl_surf == EGL_NO_SURFACE)
+      egl_fatal("failed to create a surface");
+
+   if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx))
+      egl_fatal("failed to make context/surface current");
+}
+
+static void
+egl_present(void)
+{
+   if (!eglSwapBuffers(egl_dpy, egl_surf))
+      egl_fatal("failed to swap buffers");
+}
+
+static void
+egl_destroy(void)
+{
+   eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+   eglDestroyContext(egl_dpy, egl_surf);
+   eglDestroyContext(egl_dpy, egl_ctx);
+   eglTerminate(egl_dpy);
+
+   egl_surf = EGL_NO_SURFACE;
+   egl_ctx = EGL_NO_CONTEXT;
+   egl_dpy = EGL_NO_DISPLAY;
+}
+
+/* stolen from tri.c */
+static void
+draw(int frame)
+{
+   static const GLfloat verts[3][2] = {
+      { -1, -1 },
+      {  1, -1 },
+      {  0,  1 }
+   };
+   static const GLfloat colors[3][4] = {
+      { 1, 0, 0, 1 },
+      { 0, 1, 0, 1 },
+      { 0, 0, 1, 1 }
+   };
+   GLfloat view_rotz = (GLfloat) frame;
+
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glPushMatrix();
+   glRotatef(view_rotz, 0, 0, 1);
+
+   glVertexPointer(2, GL_FLOAT, 0, verts);
+   glColorPointer(4, GL_FLOAT, 0, colors);
+
+   glEnableClientState(GL_VERTEX_ARRAY);
+   glEnableClientState(GL_COLOR_ARRAY);
+
+   /* draw triangle */
+   glDrawArrays(GL_TRIANGLES, 0, 3);
+
+   glDisableClientState(GL_VERTEX_ARRAY);
+   glDisableClientState(GL_COLOR_ARRAY);
+
+   glPopMatrix();
+}
+
+static void
+init(int width, int height)
+{
+   GLfloat ar = (GLfloat) width / height;
+
+   glViewport(0, 0, width, height);
+
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
+
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0.0, 0.0, -10.0);
+}
+
+int
+main(int argc, char **argv)
+{
+   const char fbdev[] = "/dev/fb0";
+   struct fb_var_screeninfo vinfo;
+   int fd, tty_err, frame;
+
+   fd = open(fbdev, O_RDWR);
+   if (fd < 0)
+      egl_fatal("failed to open %s", fbdev);
+
+   memset(&vinfo, 0, sizeof(vinfo));
+   if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo))
+      egl_fatal("failed to get fb info");
+
+   /* initialize EGL */
+   egl_init_for_fbdev(fd, EGL_TRUE);
+
+   /* try to open a new tty */
+   tty_err = tty_open();
+
+   init(vinfo.xres, vinfo.yres);
+   for (frame = 0; frame <= 180; frame++) {
+      draw(frame);
+      egl_present();
+   }
+
+   if (!tty_err)
+      tty_close();
+
+   egl_destroy();
+   close(fd);
+
+   return 0;
+}




More information about the mesa-commit mailing list