]> git.cworth.org Git - apitrace-tests/commitdiff
Add egl apps.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Fri, 25 Nov 2011 08:58:20 +0000 (08:58 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Fri, 25 Nov 2011 08:59:10 +0000 (08:59 +0000)
20 files changed:
.gitignore
CMakeLists.txt
apps/CMakeLists.txt
apps/egl/CMakeLists.txt [new file with mode: 0644]
apps/egl/eglut/CMakeLists.txt [new file with mode: 0644]
apps/egl/eglut/eglut.c [new file with mode: 0644]
apps/egl/eglut/eglut.h [new file with mode: 0644]
apps/egl/eglut/eglut_screen.c [new file with mode: 0644]
apps/egl/eglut/eglut_x11.c [new file with mode: 0644]
apps/egl/eglut/eglutint.h [new file with mode: 0644]
apps/egl/gl/.gitignore [new file with mode: 0644]
apps/egl/gl/CMakeLists.txt [new file with mode: 0644]
apps/egl/gl/tri.c [new file with mode: 0644]
apps/egl/gles1/.gitignore [new file with mode: 0644]
apps/egl/gles1/CMakeLists.txt [new file with mode: 0644]
apps/egl/gles1/clear.c [new file with mode: 0644]
apps/egl/gles1/tri.c [new file with mode: 0644]
apps/egl/gles2/.gitignore [new file with mode: 0644]
apps/egl/gles2/CMakeLists.txt [new file with mode: 0644]
apps/egl/gles2/tri.c [new file with mode: 0644]

index 6a7a17719cbe1db7218ccc75e82a8ff720518b9f..353306b8a8878105068b9e7e7e9af7f19830ea77 100644 (file)
@@ -1,5 +1,8 @@
 .*.sw?
+*.a
+*.o
 *.pyc
+*.so
 CMakeCache.txt
 CMakeFiles
 CTestTestfile.cmake
index e8820c23936f5b67ccb400819e15b2bb3613c11b..d45e557b6fc090b88c45b0664ad011f249833200 100644 (file)
@@ -2,6 +2,8 @@ cmake_minimum_required (VERSION 2.8)
 
 project (apitrace-tests)
 
+include (FindPkgConfig)
+
 # Set default built type
 if (NOT CMAKE_BUILD_TYPE)
    set (CMAKE_BUILD_TYPE Debug
@@ -18,6 +20,13 @@ find_package (GLUT)
 find_path (GLEW_INCLUDE_DIR GL/glew.h /usr/include/GL)
 find_library (GLEW_glew_LIBRARY GLEW /usr/lib)
 
+if (NOT WIN32)
+       pkg_check_modules (EGL egl)
+       pkg_check_modules (GLESV1 glesv1_cm)
+       pkg_check_modules (GLESV2 glesv2)
+       pkg_check_modules (VG vg)
+endif ()
+
 if (UNIX)
        link_libraries(m)
 endif (UNIX)
index 895ace9c637b3632b864d7d1682be5ba1a17fed5..12981b36672807306f585ec9cc4ab1c95fad7fdc 100644 (file)
@@ -1,3 +1,7 @@
 if (OPENGL_FOUND)
     add_subdirectory (gl)
 endif ()
+
+if (EGL_FOUND)
+    add_subdirectory (egl)
+endif ()
diff --git a/apps/egl/CMakeLists.txt b/apps/egl/CMakeLists.txt
new file mode 100644 (file)
index 0000000..395acb1
--- /dev/null
@@ -0,0 +1,13 @@
+add_subdirectory(eglut)
+
+if (OPENGL_FOUND)
+       add_subdirectory(gl)
+endif ()
+
+if (GLESV1_FOUND)
+       add_subdirectory(gles1)
+endif ()
+
+if (GLESV2_FOUND)
+       add_subdirectory(gles2)
+endif ()
diff --git a/apps/egl/eglut/CMakeLists.txt b/apps/egl/eglut/CMakeLists.txt
new file mode 100644 (file)
index 0000000..08b2257
--- /dev/null
@@ -0,0 +1,12 @@
+include_directories (
+       ${EGL_INCLUDE_DIRS}
+)
+
+if (X11_FOUND)
+       add_library (eglut eglut.c eglut_x11.c)
+       target_link_libraries (eglut ${EGL_LIBRARIES} ${X11_X11_LIB})
+else ()
+       add_library (eglut eglut.c eglut_screen.c)
+       target_link_libraries (eglut ${EGL_LIBRARIES})
+endif ()
+
diff --git a/apps/egl/eglut/eglut.c b/apps/egl/eglut/eglut.c
new file mode 100644 (file)
index 0000000..2ee6f15
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2010 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@lunarg.com>
+ */
+
+#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)
+      renderable_type |= EGL_OPENGL_ES_BIT;
+   if (_eglut->api_mask & EGLUT_OPENGL_ES2_BIT)
+      renderable_type |= EGL_OPENGL_ES2_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));
+   if (_eglut->verbose) {
+      printf("EGL_VENDOR = %s\n", eglQueryString(_eglut->dpy, EGL_VENDOR));
+      printf("EGL_EXTENSIONS = %s\n",
+            eglQueryString(_eglut->dpy, EGL_EXTENSIONS));
+      printf("EGL_CLIENT_APIS = %s\n",
+            eglQueryString(_eglut->dpy, EGL_CLIENT_APIS));
+   }
+}
+
+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();
+}
+
+void
+eglutDestroyWindow(int win)
+{
+   struct eglut_window *window = _eglut->current;
+
+   if (window->index != win)
+      return;
+
+   /* 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);
+}
+
+static void
+_eglutDefaultKeyboard(unsigned char key)
+{
+   if (key == 27) {
+      if (_eglut->current)
+         eglutDestroyWindow(_eglut->current->index);
+      _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/apps/egl/eglut/eglut.h b/apps/egl/eglut/eglut.h
new file mode 100644 (file)
index 0000000..7c07b6d
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 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@lunarg.com>
+ */
+
+#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);
+void eglutDestroyWindow(int win);
+
+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/apps/egl/eglut/eglut_screen.c b/apps/egl/eglut/eglut_screen.c
new file mode 100644 (file)
index 0000000..021a8f1
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2010 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@lunarg.com>
+ */
+
+#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);
+         fflush(stdout);
+
+         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/apps/egl/eglut/eglut_x11.c b/apps/egl/eglut/eglut_x11.c
new file mode 100644 (file)
index 0000000..ff8ab33
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2010 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@lunarg.com>
+ */
+
+#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)) {
+      /* there is an idle callback */
+      if (_eglut->idle_cb) {
+         _eglut->idle_cb();
+         return;
+      }
+
+      /* the app requests re-display */
+      if (_eglut->redisplay)
+         return;
+   }
+
+   /* block for next event */
+   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/apps/egl/eglut/eglutint.h b/apps/egl/eglut/eglutint.h
new file mode 100644 (file)
index 0000000..a4520b0
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2010 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@lunarg.com>
+ */
+
+#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_ */
diff --git a/apps/egl/gl/.gitignore b/apps/egl/gl/.gitignore
new file mode 100644 (file)
index 0000000..0c42c31
--- /dev/null
@@ -0,0 +1 @@
+tri
diff --git a/apps/egl/gl/CMakeLists.txt b/apps/egl/gl/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1f4c606
--- /dev/null
@@ -0,0 +1,17 @@
+include_directories(
+    ${CMAKE_CURRENT_SOURCE_DIR}/../eglut
+    ${EGL_INCLUDE_DIRS}
+    ${OPENGL_INCLUDE_PATH}
+)
+
+set (api egl)
+
+set (targets
+    tri
+)
+
+foreach (target ${targets})
+    add_executable (${api}_${target} ${target}.c)
+    set_target_properties (${api}_${target} PROPERTIES OUTPUT_NAME ${target})
+    target_link_libraries (${api}_${target} eglut ${OPENGL_gl_LIBRARY})
+endforeach (target)
diff --git a/apps/egl/gl/tri.c b/apps/egl/gl/tri.c
new file mode 100644 (file)
index 0000000..fb1dde3
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2008  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.
+ */
+
+/*
+ * Draw a triangle with X/EGL.
+ * Brian Paul
+ * 3 June 2008
+ */
+
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <GL/gl.h>
+
+#include "eglut.h"
+
+
+static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
+
+
+static void
+draw(void)
+{
+   static const GLfloat verts[3][2] = {
+      { -1, -1 },
+      {  1, -1 },
+      {  0,  1 }
+   };
+   static const GLfloat colors[3][3] = {
+      { 1, 0, 0 },
+      { 0, 1, 0 },
+      { 0, 0, 1 }
+   };
+
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glPushMatrix();
+   glRotatef(view_rotx, 1, 0, 0);
+   glRotatef(view_roty, 0, 1, 0);
+   glRotatef(view_rotz, 0, 0, 1);
+
+   {
+      glVertexPointer(2, GL_FLOAT, 0, verts);
+      glColorPointer(3, GL_FLOAT, 0, colors);
+      glEnableClientState(GL_VERTEX_ARRAY);
+      glEnableClientState(GL_COLOR_ARRAY);
+
+      glDrawArrays(GL_TRIANGLES, 0, 3);
+
+      glDisableClientState(GL_VERTEX_ARRAY);
+      glDisableClientState(GL_COLOR_ARRAY);
+   }
+
+   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, -10.0);
+}
+
+
+static void
+init(void)
+{
+   glClearColor(0.4, 0.4, 0.4, 0.0);
+}
+
+
+static void
+special_key(int special)
+{
+   switch (special) {
+   case EGLUT_KEY_LEFT:
+      view_roty += 5.0;
+      break;
+   case EGLUT_KEY_RIGHT:
+      view_roty -= 5.0;
+      break;
+   case EGLUT_KEY_UP:
+      view_rotx += 5.0;
+      break;
+   case EGLUT_KEY_DOWN:
+      view_rotx -= 5.0;
+      break;
+   default:
+      break;
+   }
+}
+
+int
+main(int argc, char *argv[])
+{
+   eglutInitWindowSize(300, 300);
+   eglutInitAPIMask(EGLUT_OPENGL_BIT);
+   eglutInit(argc, argv);
+
+   eglutCreateWindow("egltri");
+
+   eglutReshapeFunc(reshape);
+   eglutDisplayFunc(draw);
+   eglutSpecialFunc(special_key);
+
+   init();
+
+   eglutMainLoop();
+
+   return 0;
+}
diff --git a/apps/egl/gles1/.gitignore b/apps/egl/gles1/.gitignore
new file mode 100644 (file)
index 0000000..a775a31
--- /dev/null
@@ -0,0 +1,2 @@
+clear
+tri
diff --git a/apps/egl/gles1/CMakeLists.txt b/apps/egl/gles1/CMakeLists.txt
new file mode 100644 (file)
index 0000000..96e300d
--- /dev/null
@@ -0,0 +1,18 @@
+include_directories(
+    ${CMAKE_CURRENT_SOURCE_DIR}/../eglut
+    ${EGL_INCLUDE_DIRS}
+    ${GLESV1_INCLUDE_DIRS}
+)
+
+set (api gles1)
+
+set (targets
+    clear
+    tri
+)
+
+foreach (target ${targets})
+    add_executable (${api}_${target} ${target}.c)
+    set_target_properties (${api}_${target} PROPERTIES OUTPUT_NAME ${target})
+    target_link_libraries (${api}_${target} eglut ${GLESV1_LIBRARIES})
+endforeach (target)
diff --git a/apps/egl/gles1/clear.c b/apps/egl/gles1/clear.c
new file mode 100644 (file)
index 0000000..9fe1b52
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 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@lunarg.com>
+ */
+
+/*
+ * This demo tests eglGetProcAddress and glClear.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+
+#include "eglut.h"
+
+typedef void (GL_APIENTRY *type_ClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (GL_APIENTRY *type_Clear)(GLbitfield mask);
+
+static type_ClearColor fn_ClearColor;
+static type_Clear fn_Clear;
+
+static void
+draw(void)
+{
+   fn_Clear(GL_COLOR_BUFFER_BIT);
+}
+
+static void *
+get_proc(const char *name)
+{
+   void *proc;
+
+   proc = (void *) eglGetProcAddress(name);
+   if (!proc) {
+      /*
+       * note that eglGetProcAddress is not required to support non-extension
+       * functions
+       */
+      printf("failed to find %s (not necessarily a bug)\n", name);
+      exit(1);
+   }
+
+   return proc;
+}
+
+static void
+init(void)
+{
+   fn_ClearColor = (type_ClearColor) get_proc("glClearColor");
+   fn_Clear = (type_Clear) get_proc("glClear");
+
+   fn_ClearColor(1.0, 0.4, 0.4, 0.0);
+}
+
+int
+main(int argc, char *argv[])
+{
+   eglutInitWindowSize(300, 300);
+   eglutInitAPIMask(EGLUT_OPENGL_ES1_BIT);
+   eglutInit(argc, argv);
+
+   eglutCreateWindow("clear");
+
+   eglutDisplayFunc(draw);
+
+   init();
+
+   eglutMainLoop();
+
+   return 0;
+}
diff --git a/apps/egl/gles1/tri.c b/apps/egl/gles1/tri.c
new file mode 100644 (file)
index 0000000..01ad9bd
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2008  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.
+ */
+
+/*
+ * Draw a triangle with X/EGL and OpenGL ES 1.x
+ * Brian Paul
+ * 5 June 2008
+ */
+
+#define USE_FIXED_POINT 0
+
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <GLES/gl.h>  /* use OpenGL ES 1.x */
+#include <GLES/glext.h>
+#include <EGL/egl.h>
+
+#include "eglut.h"
+
+
+#define FLOAT_TO_FIXED(X)   ((X) * 65535.0)
+
+
+
+static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
+
+
+static void
+draw(void)
+{
+#if USE_FIXED_POINT
+   static const GLfixed verts[3][2] = {
+      { -65536, -65536 },
+      {  65536, -65536 },
+      {      0,  65536 }
+   };
+   static const GLfixed colors[3][4] = {
+      { 65536,     0,     0,    65536 },
+      {     0, 65536,     0 ,   65536},
+      {     0,     0, 65536 ,   65536}
+   };
+#else
+   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 }
+   };
+#endif
+
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glPushMatrix();
+   glRotatef(view_rotx, 1, 0, 0);
+   glRotatef(view_roty, 0, 1, 0);
+   glRotatef(view_rotz, 0, 0, 1);
+
+   {
+#if USE_FIXED_POINT
+      glVertexPointer(2, GL_FIXED, 0, verts);
+      glColorPointer(4, GL_FIXED, 0, colors);
+#else
+      glVertexPointer(2, GL_FLOAT, 0, verts);
+      glColorPointer(4, GL_FLOAT, 0, colors);
+#endif
+      glEnableClientState(GL_VERTEX_ARRAY);
+      glEnableClientState(GL_COLOR_ARRAY);
+
+      /* draw triangle */
+      glDrawArrays(GL_TRIANGLES, 0, 3);
+
+      /* draw some points */
+      glPointSizex(FLOAT_TO_FIXED(15.5));
+      glDrawArrays(GL_POINTS, 0, 3);
+
+      glDisableClientState(GL_VERTEX_ARRAY);
+      glDisableClientState(GL_COLOR_ARRAY);
+   }
+
+   if (0) {
+      /* test code */
+      GLfixed size;
+      glGetFixedv(GL_POINT_SIZE, &size);
+      printf("GL_POINT_SIZE = 0x%x %f\n", size, size / 65536.0);
+   }
+
+   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();
+#ifdef GL_VERSION_ES_CM_1_0
+   glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
+#else
+   glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
+#endif
+   
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0.0, 0.0, -10.0);
+}
+
+
+static void
+test_query_matrix(void)
+{
+   PFNGLQUERYMATRIXXOESPROC procQueryMatrixx;
+   typedef void (*voidproc)();
+   GLfixed mantissa[16];
+   GLint exponent[16];
+   GLbitfield rv;
+   int i;
+
+   procQueryMatrixx = (PFNGLQUERYMATRIXXOESPROC) eglGetProcAddress("glQueryMatrixxOES");
+   assert(procQueryMatrixx);
+   /* Actually try out this one */
+   rv = (*procQueryMatrixx)(mantissa, exponent);
+   for (i = 0; i < 16; i++) {
+      if (rv & (1<<i)) {
+        printf("matrix[%d] invalid\n", i);
+      }
+      else {
+         printf("matrix[%d] = %f * 2^(%d)\n", i, mantissa[i]/65536.0, exponent[i]);
+      }
+   }
+   assert(!eglGetProcAddress("glFoo"));
+}
+
+
+static void
+init(void)
+{
+   glClearColor(0.4, 0.4, 0.4, 0.0);
+
+   if (0)
+      test_query_matrix();
+}
+
+static void
+special_key(int special)
+{
+   switch (special) {
+   case EGLUT_KEY_LEFT:
+      view_roty += 5.0;
+      break;
+   case EGLUT_KEY_RIGHT:
+      view_roty -= 5.0;
+      break;
+   case EGLUT_KEY_UP:
+      view_rotx += 5.0;
+      break;
+   case EGLUT_KEY_DOWN:
+      view_rotx -= 5.0;
+      break;
+   default:
+      break;
+   }
+}
+
+int
+main(int argc, char *argv[])
+{
+   eglutInitWindowSize(300, 300);
+   eglutInitAPIMask(EGLUT_OPENGL_ES1_BIT);
+   eglutInit(argc, argv);
+
+   eglutCreateWindow("tri");
+
+   eglutReshapeFunc(reshape);
+   eglutDisplayFunc(draw);
+   eglutSpecialFunc(special_key);
+
+   init();
+
+   eglutMainLoop();
+
+   return 0;
+}
diff --git a/apps/egl/gles2/.gitignore b/apps/egl/gles2/.gitignore
new file mode 100644 (file)
index 0000000..0c42c31
--- /dev/null
@@ -0,0 +1 @@
+tri
diff --git a/apps/egl/gles2/CMakeLists.txt b/apps/egl/gles2/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a45efdc
--- /dev/null
@@ -0,0 +1,19 @@
+include_directories(
+    ${CMAKE_CURRENT_SOURCE_DIR}/../eglut
+    ${EGL_INCLUDE_DIRS}
+    ${GLESV2_INCLUDE_DIRS}
+)
+
+set (api gles2)
+
+set (targets
+    tri
+)
+
+if (X11_FOUND)
+    foreach (target ${targets})
+       add_executable (${api}_${target} ${target}.c)
+       set_target_properties (${api}_${target} PROPERTIES OUTPUT_NAME ${target})
+       target_link_libraries (${api}_${target} ${EGL_LIBRARIES} ${GLESV2_LIBRARIES})
+    endforeach (target)
+endif ()
diff --git a/apps/egl/gles2/tri.c b/apps/egl/gles2/tri.c
new file mode 100644 (file)
index 0000000..8a2bf3e
--- /dev/null
@@ -0,0 +1,525 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+/*
+ * Draw a triangle with X/EGL and OpenGL ES 2.x
+ */
+
+#define USE_FULL_GL 0
+
+
+
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#if USE_FULL_GL
+#include <GL/gl.h>  /* use full OpenGL */
+#else
+#include <GLES2/gl2.h>  /* use OpenGL ES 2.x */
+#endif
+#include <EGL/egl.h>
+
+
+#define FLOAT_TO_FIXED(X)   ((X) * 65535.0)
+
+
+
+static GLfloat view_rotx = 0.0, view_roty = 0.0;
+
+static GLint u_matrix = -1;
+static GLint attr_pos = 0, attr_color = 1;
+
+
+static void
+make_z_rot_matrix(GLfloat angle, GLfloat *m)
+{
+   float c = cos(angle * M_PI / 180.0);
+   float s = sin(angle * M_PI / 180.0);
+   int i;
+   for (i = 0; i < 16; i++)
+      m[i] = 0.0;
+   m[0] = m[5] = m[10] = m[15] = 1.0;
+
+   m[0] = c;
+   m[1] = s;
+   m[4] = -s;
+   m[5] = c;
+}
+
+static void
+make_scale_matrix(GLfloat xs, GLfloat ys, GLfloat zs, GLfloat *m)
+{
+   int i;
+   for (i = 0; i < 16; i++)
+      m[i] = 0.0;
+   m[0] = xs;
+   m[5] = ys;
+   m[10] = zs;
+   m[15] = 1.0;
+}
+
+
+static void
+mul_matrix(GLfloat *prod, const GLfloat *a, const GLfloat *b)
+{
+#define A(row,col)  a[(col<<2)+row]
+#define B(row,col)  b[(col<<2)+row]
+#define P(row,col)  p[(col<<2)+row]
+   GLfloat p[16];
+   GLint i;
+   for (i = 0; i < 4; i++) {
+      const GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
+      P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
+      P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
+      P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
+      P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
+   }
+   memcpy(prod, p, sizeof(p));
+#undef A
+#undef B
+#undef PROD
+}
+
+
+static void
+draw(void)
+{
+   static const GLfloat verts[3][2] = {
+      { -1, -1 },
+      {  1, -1 },
+      {  0,  1 }
+   };
+   static const GLfloat colors[3][3] = {
+      { 1, 0, 0 },
+      { 0, 1, 0 },
+      { 0, 0, 1 }
+   };
+   GLfloat mat[16], rot[16], scale[16];
+
+   /* Set modelview/projection matrix */
+   make_z_rot_matrix(view_rotx, rot);
+   make_scale_matrix(0.5, 0.5, 0.5, scale);
+   mul_matrix(mat, rot, scale);
+   glUniformMatrix4fv(u_matrix, 1, GL_FALSE, mat);
+
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   {
+      glVertexAttribPointer(attr_pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
+      glVertexAttribPointer(attr_color, 3, GL_FLOAT, GL_FALSE, 0, colors);
+      glEnableVertexAttribArray(attr_pos);
+      glEnableVertexAttribArray(attr_color);
+
+      glDrawArrays(GL_TRIANGLES, 0, 3);
+
+      glDisableVertexAttribArray(attr_pos);
+      glDisableVertexAttribArray(attr_color);
+   }
+}
+
+
+/* new window size or exposure */
+static void
+reshape(int width, int height)
+{
+   glViewport(0, 0, (GLint) width, (GLint) height);
+}
+
+
+static void
+create_shaders(void)
+{
+   static const char *fragShaderText =
+      "varying vec4 v_color;\n"
+      "void main() {\n"
+      "   gl_FragColor = v_color;\n"
+      "}\n";
+   static const char *vertShaderText =
+      "uniform mat4 modelviewProjection;\n"
+      "attribute vec4 pos;\n"
+      "attribute vec4 color;\n"
+      "varying vec4 v_color;\n"
+      "void main() {\n"
+      "   gl_Position = modelviewProjection * pos;\n"
+      "   v_color = color;\n"
+      "}\n";
+
+   GLuint fragShader, vertShader, program;
+   GLint stat;
+
+   fragShader = glCreateShader(GL_FRAGMENT_SHADER);
+   glShaderSource(fragShader, 1, (const char **) &fragShaderText, NULL);
+   glCompileShader(fragShader);
+   glGetShaderiv(fragShader, GL_COMPILE_STATUS, &stat);
+   if (!stat) {
+      printf("Error: fragment shader did not compile!\n");
+      exit(1);
+   }
+
+   vertShader = glCreateShader(GL_VERTEX_SHADER);
+   glShaderSource(vertShader, 1, (const char **) &vertShaderText, NULL);
+   glCompileShader(vertShader);
+   glGetShaderiv(vertShader, GL_COMPILE_STATUS, &stat);
+   if (!stat) {
+      printf("Error: vertex shader did not compile!\n");
+      exit(1);
+   }
+
+   program = glCreateProgram();
+   glAttachShader(program, fragShader);
+   glAttachShader(program, vertShader);
+   glLinkProgram(program);
+
+   glGetProgramiv(program, GL_LINK_STATUS, &stat);
+   if (!stat) {
+      char log[1000];
+      GLsizei len;
+      glGetProgramInfoLog(program, 1000, &len, log);
+      printf("Error: linking:\n%s\n", log);
+      exit(1);
+   }
+
+   glUseProgram(program);
+
+   if (1) {
+      /* test setting attrib locations */
+      glBindAttribLocation(program, attr_pos, "pos");
+      glBindAttribLocation(program, attr_color, "color");
+      glLinkProgram(program);  /* needed to put attribs into effect */
+   }
+   else {
+      /* test automatic attrib locations */
+      attr_pos = glGetAttribLocation(program, "pos");
+      attr_color = glGetAttribLocation(program, "color");
+   }
+
+   u_matrix = glGetUniformLocation(program, "modelviewProjection");
+   printf("Uniform modelviewProjection at %d\n", u_matrix);
+   printf("Attrib pos at %d\n", attr_pos);
+   printf("Attrib color at %d\n", attr_color);
+}
+
+
+static void
+init(void)
+{
+   typedef void (*proc)();
+
+#if 1 /* test code */
+   proc p = eglGetProcAddress("glMapBufferOES");
+   assert(p);
+#endif
+
+   glClearColor(0.4, 0.4, 0.4, 0.0);
+
+   create_shaders();
+}
+
+
+/*
+ * 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_DEPTH_SIZE, 1,
+      EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+      EGL_NONE
+   };
+#if USE_FULL_GL
+   static const EGLint ctx_attribs[] = {
+       EGL_NONE
+   };
+#else
+   static const EGLint ctx_attribs[] = {
+      EGL_CONTEXT_CLIENT_VERSION, 2,
+      EGL_NONE
+   };
+#endif
+
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   XVisualInfo *visInfo, visTemplate;
+   int num_visuals;
+   EGLContext ctx;
+   EGLConfig config;
+   EGLint num_configs;
+   EGLint vid;
+
+   scrnum = DefaultScreen( x_dpy );
+   root = RootWindow( x_dpy, scrnum );
+
+   if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
+      printf("Error: couldn't get an EGL visual config\n");
+      exit(1);
+   }
+
+   assert(config);
+   assert(num_configs > 0);
+
+   if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
+      printf("Error: eglGetConfigAttrib() failed\n");
+      exit(1);
+   }
+
+   /* The X window visual must match the EGL config */
+   visTemplate.visualid = vid;
+   visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &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;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   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);
+   }
+
+#if USE_FULL_GL /* XXX fix this when eglBindAPI() works */
+   eglBindAPI(EGL_OPENGL_API);
+#else
+   eglBindAPI(EGL_OPENGL_ES_API);
+#endif
+
+   ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs );
+   if (!ctx) {
+      printf("Error: eglCreateContext failed\n");
+      exit(1);
+   }
+
+#if !USE_FULL_GL
+   /* test eglQueryContext() */
+   {
+      EGLint val;
+      eglQueryContext(egl_dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &val);
+      assert(val == 2);
+   }
+#endif
+
+   *surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
+   if (!*surfRet) {
+      printf("Error: eglCreateWindowSurface failed\n");
+      exit(1);
+   }
+
+   /* sanity checks */
+   {
+      EGLint val;
+      eglQuerySurface(egl_dpy, *surfRet, EGL_WIDTH, &val);
+      assert(val == width);
+      eglQuerySurface(egl_dpy, *surfRet, EGL_HEIGHT, &val);
+      assert(val == height);
+      assert(eglGetConfigAttrib(egl_dpy, config, EGL_SURFACE_TYPE, &val));
+      assert(val & EGL_WINDOW_BIT);
+   }
+
+   XFree(visInfo);
+
+   *winRet = win;
+   *ctxRet = ctx;
+}
+
+
+static void
+event_loop(Display *dpy, Window win,
+           EGLDisplay egl_dpy, EGLSurface egl_surf)
+{
+   while (1) {
+      int redraw = 0;
+      XEvent event;
+
+      XNextEvent(dpy, &event);
+
+      switch (event.type) {
+      case Expose:
+         redraw = 1;
+         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;
+               }
+            }
+         }
+         redraw = 1;
+         break;
+      default:
+         ; /*no-op*/
+      }
+
+      if (redraw) {
+         draw();
+         eglSwapBuffers(egl_dpy, egl_surf);
+      }
+   }
+}
+
+
+static void
+usage(void)
+{
+   printf("Usage:\n");
+   printf("  -display <displayname>  set the display to run on\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 {
+         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);
+
+   s = eglQueryString(egl_dpy, EGL_VENDOR);
+   printf("EGL_VENDOR = %s\n", s);
+
+   s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
+   printf("EGL_EXTENSIONS = %s\n", s);
+
+   s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
+   printf("EGL_CLIENT_APIS = %s\n", s);
+
+   make_x_window(x_dpy, egl_dpy,
+                 "OpenGL ES 2.x tri", 0, 0, winWidth, winHeight,
+                 &win, &egl_ctx, &egl_surf);
+
+   XMapWindow(x_dpy, win);
+   if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
+      printf("Error: eglMakeCurrent() failed\n");
+      return -1;
+   }
+
+   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));
+      printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
+   }
+
+   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);
+
+   eglDestroyContext(egl_dpy, egl_ctx);
+   eglDestroySurface(egl_dpy, egl_surf);
+   eglTerminate(egl_dpy);
+
+
+   XDestroyWindow(x_dpy, win);
+   XCloseDisplay(x_dpy);
+
+   return 0;
+}