[Cogl] [PATCH] Adds Emscripten support to Cogl

Robert Bragg robert at sixbynine.org
Fri May 10 14:03:44 PDT 2013


From: Robert Bragg <robert at linux.intel.com>

This enables Emscripten support in Cogl via the SDL winsys. Assuming you
have setup an emscripten toolchain you can configure Cogl like this:

 emconfigure ./configure --enable-debug --enable-emscripten

Building the examples will build .html files that can be loaded directly
by a WebGL enabled browser.
---
 cogl/cogl-debug.c                |   2 +
 cogl/cogl.c                      |   4 +
 cogl/winsys/cogl-winsys-sdl.c    |  22 +++-
 configure.ac                     | 272 ++++++++++++++++++++++++++-------------
 examples/Makefile.am             |  20 +++
 examples/cogl-emscripten-hello.c | 144 +++++++++++++++++++++
 examples/cogl-info.c             |   4 +
 tests/conform/Makefile.am        |   8 +-
 8 files changed, 379 insertions(+), 97 deletions(-)
 create mode 100644 examples/cogl-emscripten-hello.c

diff --git a/cogl/cogl-debug.c b/cogl/cogl-debug.c
index 01af450..eea6157 100644
--- a/cogl/cogl-debug.c
+++ b/cogl/cogl-debug.c
@@ -26,7 +26,9 @@
 #endif
 
 #include <stdlib.h>
+#ifdef ENABLE_NLS
 #include <glib/gi18n-lib.h>
+#endif
 
 #include "cogl-private.h"
 #include "cogl-debug.h"
diff --git a/cogl/cogl.c b/cogl/cogl.c
index 578f0b4..a0ba821 100644
--- a/cogl/cogl.c
+++ b/cogl/cogl.c
@@ -28,7 +28,9 @@
 #include <string.h>
 #include <math.h>
 #include <stdlib.h>
+#ifdef ENABLE_NLS
 #include <glib/gi18n-lib.h>
+#endif
 
 #include "cogl-debug.h"
 #include "cogl-util.h"
@@ -161,8 +163,10 @@ _cogl_init (void)
 
   if (initialized == FALSE)
     {
+#ifdef ENABLE_NLS
       bindtextdomain (GETTEXT_PACKAGE, COGL_LOCALEDIR);
       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#endif
 
 #ifdef COGL_HAS_GTYPE_SUPPORT
       g_type_init ();
diff --git a/cogl/winsys/cogl-winsys-sdl.c b/cogl/winsys/cogl-winsys-sdl.c
index ed8212e..8af11ac 100644
--- a/cogl/winsys/cogl-winsys-sdl.c
+++ b/cogl/winsys/cogl-winsys-sdl.c
@@ -57,6 +57,8 @@ _cogl_winsys_renderer_get_proc_address (CoglRenderer *renderer,
                                         const char *name,
                                         CoglBool in_core)
 {
+  CoglFuncPtr ptr;
+
   /* XXX: It's not totally clear whether it's safe to call this for
    * core functions. From the code it looks like the implementations
    * will fall back to using some form of dlsym if the winsys
@@ -87,7 +89,16 @@ static CoglBool
 _cogl_winsys_renderer_connect (CoglRenderer *renderer,
                                CoglError **error)
 {
-#ifndef COGL_HAS_SDL_GLES_SUPPORT
+#ifdef USING_EMSCRIPTEN
+  if (renderer->driver != COGL_DRIVER_GLES2)
+    {
+      _cogl_set_error (error, COGL_WINSYS_ERROR,
+                       COGL_WINSYS_ERROR_INIT,
+                       "The SDL winsys with emscripten only supports "
+                       "the GLES2 driver");
+      return FALSE;
+    }
+#elif !defined (COGL_HAS_SDL_GLES_SUPPORT)
   if (renderer->driver != COGL_DRIVER_GL)
     {
       _cogl_set_error (error, COGL_WINSYS_ERROR,
@@ -95,7 +106,7 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
                    "The SDL winsys only supports the GL driver");
       return FALSE;
     }
-#endif /* COGL_HAS_SDL_GLES_SUPPORT */
+#endif
 
   if (SDL_Init (SDL_INIT_VIDEO) == -1)
     {
@@ -180,7 +191,12 @@ _cogl_winsys_display_setup (CoglDisplay *display,
       SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 1);
       SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 1);
       break;
-#endif /* COGL_HAS_SDL_GLES_SUPPORT */
+
+#elif defined (USING_EMSCRIPTEN)
+    case COGL_DRIVER_GLES2:
+      sdl_display->video_mode_flags = SDL_OPENGL;
+      break;
+#endif
 
     default:
       g_assert_not_reached ();
diff --git a/configure.ac b/configure.ac
index f0bb096..a4184b7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -197,6 +197,30 @@ dnl ================================================================
 dnl Handle extra configure options
 dnl ================================================================
 
+
+dnl     ============================================================
+dnl     Emscripten support
+dnl     ============================================================
+
+AC_ARG_ENABLE(
+  [emscripten],
+  [AC_HELP_STRING([--enable-emscripten=@<:@no/yes@:>@], [Support building for emscripten])],
+  [],
+  enable_emscripten=no
+)
+AS_IF([test "x$enable_emscripten" = "xyes"],
+      [
+        enable_standalone=yes
+        enable_sdl=yes
+        enable_gles2=yes
+        enable_gl=no
+        AC_DEFINE([USING_EMSCRIPTEN], 1, [Cogl is being compiled with emscripten])
+        COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EMSCRIPTEN_SUPPORT"
+      ]
+)
+AM_CONDITIONAL(USING_EMSCRIPTEN, [test "$enable_emscripten" = "yes"])
+
+
 dnl     ============================================================
 dnl     Standalone cogl
 dnl     ============================================================
@@ -376,19 +400,24 @@ dnl ================================================================
 dnl     ============================================================
 dnl     Should glib be used?
 dnl     ============================================================
-AM_PATH_GLIB_2_0([glib_req_version],
-                 [have_glib=yes], [have_glib=no],
-                 [gobject gthread gmodule-no-export])
-AC_ARG_ENABLE(
-  [glib],
-  [AC_HELP_STRING([--enable-glib=@<:@no/yes@:>@], [Enable glib support @<:@default=yes@:>@])],
-  [],
-  enable_glib=yes
+AS_IF([test "x$enable_standalone" = "xno"],
+      [
+        AM_PATH_GLIB_2_0([glib_req_version],
+                         [have_glib=yes], [have_glib=no],
+                         [gobject gthread gmodule-no-export])
+        AC_ARG_ENABLE(
+                      [glib],
+                      [AC_HELP_STRING([--enable-glib=@<:@no/yes@:>@], [Enable glib support @<:@default=yes@:>@])],
+                      [],
+                      enable_glib=yes
+                      )
+
+        AS_IF([test "x$have_glib" = "xno" && test "x$enable_glib" = "xyes"],
+              [AC_MSG_ERROR([gobject-2.0 is required])])
+      ],
+      [enable_glib=no]
 )
 
-AS_IF([test "x$have_glib" = "xno" && test "x$enable_glib" = "xyes"],
-      [AC_MSG_ERROR([gobject-2.0 is required])])
-
 AM_CONDITIONAL([USE_GLIB], [test "x$enable_glib" = "xyes"])
 
 AS_IF([test "x$enable_glib" = "xyes"],
@@ -648,24 +677,32 @@ AS_IF([test "x$enable_gles2" = "xyes"],
         COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES2"
         HAVE_GLES2=1
 
-        PKG_CHECK_EXISTS([glesv2],
-          [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL glesv2"
-           COGL_GLES2_LIBNAME="libGLESv2.so"
-          ],
-          [
-            # We have to check the two headers independently as GLES2/gl2ext.h
-            # needs to include GLES2/gl2.h to have the GL types defined (eg.
-            # GLenum).
-            AC_CHECK_HEADER([GLES2/gl2.h],
-                            [],
-                            [AC_MSG_ERROR([Unable to locate GLES2/gl2.h])])
-            AC_CHECK_HEADER([GLES2/gl2ext.h],
-                            [],
-                            [AC_MSG_ERROR([Unable to locate GLES2/gl2ext.h])],
-                            [#include <GLES2/gl2.h>])
+        AS_IF([test "x$enable_emscripten" = "xyes"],
+              [
+                GL_LIBRARY_DIRECTLY_LINKED=yes
+                COGL_GLES2_LIBNAME=""
+              ],
 
-            COGL_GLES2_LIBNAME="libGLESv2.so"
-          ])
+              [
+                PKG_CHECK_EXISTS([glesv2],
+                  [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL glesv2"
+                   COGL_GLES2_LIBNAME="libGLESv2.so"
+                  ],
+                  [
+                    # We have to check the two headers independently as GLES2/gl2ext.h
+                    # needs to include GLES2/gl2.h to have the GL types defined (eg.
+                    # GLenum).
+                    AC_CHECK_HEADER([GLES2/gl2.h],
+                                    [],
+                                    [AC_MSG_ERROR([Unable to locate GLES2/gl2.h])])
+                    AC_CHECK_HEADER([GLES2/gl2ext.h],
+                                    [],
+                                    [AC_MSG_ERROR([Unable to locate GLES2/gl2ext.h])],
+                                    [#include <GLES2/gl2.h>])
+
+                    COGL_GLES2_LIBNAME="libGLESv2.so"
+                  ])
+              ])
       ])
 
 HAVE_GL=0
@@ -833,35 +870,58 @@ AC_ARG_ENABLE(
   [enable_sdl=no])
 AS_IF([test "x$enable_sdl" = "xyes"],
       [
-        PKG_CHECK_MODULES([SDL],
-                          [sdl],
-                          [],
-                          [AC_MSG_ERROR([SDL support requested but SDL not found])])
+        AS_IF([test "x$enable_emscripten" = "xno"],
+              [
+                PKG_CHECK_MODULES([SDL],
+                                  [sdl],
+                                  [
+                                   COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES sdl"
+                                  ],
+                                  [
+                                   AC_CHECK_HEADER([SDL/SDL.h],
+                                                   [],
+                                                   [AC_MSG_ERROR([SDL support requested but SDL not found])])
+                                  ])
+              ])
 
         SUPPORT_SDL=yes
         GL_WINSYS_APIS="$GL_WINSYS_APIS sdl"
-        COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES sdl"
 
         COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_SDL_SUPPORT"
 
-        dnl WebOS has a specially patched version of SDL to add
-        dnl support for creating a GLES1/2 context. This tries to
-        dnl detect that patch so we can use it if the GLES2 driver is
-        dnl selected.
-        cogl_save_CPPFLAGS="$CPPFLAGS"
-        CPPFLAGS="$CPPFLAGS $SDL_CFLAGS"
-        AC_CHECK_DECL([SDL_OPENGLES],
-                      [SUPPORT_SDL_GLES=yes],
-                      [SUPPORT_SDL_GLES=no],
-                      [#include <SDL.h>])
-        AC_CHECK_DECL([SDL_GL_CONTEXT_MAJOR_VERSION], [], [SUPPORT_SDL_GLES=no],
-                      [#include <SDL.h>])
-        AC_CHECK_DECL([SDL_GL_CONTEXT_MINOR_VERSION], [], [SUPPORT_SDL_GLES=no],
-                      [#include <SDL.h>])
-        CPPFLAGS="$cogl_save_CPPFLAGS"
-
-        AS_IF([test "x$SUPPORT_SDL_GLES" = "xyes"],
-              COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_SDL_GLES_SUPPORT")
+        dnl If we are building with emscripten then that simply implies we are
+        dnl using SDL in conjunction with WebGL (GLES2)
+        AS_IF([test "x$enable_emscripten" = "xyes"],
+              [
+                SUPPORTED_SDL_GL_APIS="webgl"
+                SUPPORT_SDL_WEBGL=yes
+                SUPPORT_SDL_GLES=no
+                COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_SDL_WEBGL_SUPPORT"
+              ],
+              [
+                dnl WebOS has a specially patched version of SDL to add
+                dnl support for creating a GLES1/2 context. This tries to
+                dnl detect that patch so we can use it if the GLES2 driver is
+                dnl selected.
+                cogl_save_CPPFLAGS="$CPPFLAGS"
+                CPPFLAGS="$CPPFLAGS $SDL_CFLAGS"
+                AC_CHECK_DECL([SDL_OPENGLES],
+                              [SUPPORT_SDL_GLES=yes],
+                              [SUPPORT_SDL_GLES=no],
+                              [#include <SDL.h>])
+                AC_CHECK_DECL([SDL_GL_CONTEXT_MAJOR_VERSION], [], [SUPPORT_SDL_GLES=no],
+                              [#include <SDL.h>])
+                AC_CHECK_DECL([SDL_GL_CONTEXT_MINOR_VERSION], [], [SUPPORT_SDL_GLES=no],
+                              [#include <SDL.h>])
+                CPPFLAGS="$cogl_save_CPPFLAGS"
+
+                AS_IF([test "x$SUPPORT_SDL_GLES" = "xyes"],
+                      [
+                       SUPPORTED_SDL_GL_APIS="gles1 gles2"
+                       COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_SDL_GLES_SUPPORT"
+                      ],
+                      [ SUPPORTED_SDL_GL_APIS="gl" ])
+              ])
       ],
       [SUPPORT_SDL=no])
 AM_CONDITIONAL(SUPPORT_SDL, [test "x$SUPPORT_SDL" = "xyes"])
@@ -1043,7 +1103,12 @@ AC_ARG_ENABLE(
   [xlib-egl-platform],
   [AC_HELP_STRING([--enable-xlib-egl-platform=@<:@no/yes@:>@], [Enable support for the Xlib egl platform @<:@default=auto@:>@])],
   [],
-  AS_IF([test "x$enable_gles1" = "xyes" -o "x$enable_gles2" = "xyes" && test "x$SUPPORT_SDL_GLES" != "xyes" && test "x$SUPPORT_SDL2" != "xyes" && test $EGL_PLATFORM_COUNT -eq 0],
+  AS_IF([test "x$enable_gles1" = "xyes" -o \
+         "x$enable_gles2" = "xyes" && \
+         test "x$SUPPORT_SDL_GLES" != "xyes" && \
+         test "x$SUPPORT_SDL_WEBGL" != "xyes" && \
+         test "x$SUPPORT_SDL2" != "xyes" && \
+         test $EGL_PLATFORM_COUNT -eq 0],
         [enable_xlib_egl_platform=yes], [enable_xlib_egl_platform=no])
 )
 AS_IF([test "x$enable_xlib_egl_platform" = "xyes"],
@@ -1146,22 +1211,25 @@ AS_ALL_LINGUAS
 
 
 AC_SUBST(COGL_PKG_REQUIRES)
-PKG_CHECK_MODULES(COGL_DEP, [$COGL_PKG_REQUIRES])
-if test -n "$COGL_PKG_REQUIRES_GL"; then
-  PKG_CHECK_MODULES(COGL_DEP_GL, [$COGL_PKG_REQUIRES_GL])
-
-  dnl Strip out the GL libraries from the GL pkg-config files so we can
-  dnl dynamically load them instead
-  gl_libs=""
-  for x in $COGL_DEP_GL_LIBS; do
-    AS_CASE([$x],
-            [-lGL], [],
-            [-lGLESv2], [],
-            [-lGLESv1_CM], [],
-            [*], [gl_libs="$gl_libs $x"])
-  done
-  COGL_DEP_CFLAGS="$COGL_DEP_CFLAGS $COGL_DEP_CFLAGS_GL"
-  COGL_DEP_LIBS="$COGL_DEP_LIBS $gl_libs"
+if test -n "$COGL_PKG_REQUIRES"; then
+  PKG_CHECK_MODULES(COGL_DEP, [$COGL_PKG_REQUIRES])
+
+  if test -n "$COGL_PKG_REQUIRES_GL"; then
+    PKG_CHECK_MODULES(COGL_DEP_GL, [$COGL_PKG_REQUIRES_GL])
+
+    dnl Strip out the GL libraries from the GL pkg-config files so we can
+    dnl dynamically load them instead
+    gl_libs=""
+    for x in $COGL_DEP_GL_LIBS; do
+      AS_CASE([$x],
+              [-lGL], [],
+              [-lGLESv2], [],
+              [-lGLESv1_CM], [],
+              [*], [gl_libs="$gl_libs $x"])
+    done
+    COGL_DEP_CFLAGS="$COGL_DEP_CFLAGS $COGL_DEP_CFLAGS_GL"
+    COGL_DEP_LIBS="$COGL_DEP_LIBS $gl_libs"
+  fi
 fi
 AC_SUBST(COGL_PANGO_PKG_REQUIRES)
 
@@ -1211,7 +1279,11 @@ dnl ================================================================
 
 dnl The 'ffs' function is part of C99 so it isn't always
 dnl available. Cogl has a fallback if needed.
-AC_CHECK_FUNCS([ffs])
+dnl
+dnl XXX: ffs isnt available with the emscripten toolchain currently
+dnl but the check passes so we manually skip the check in this case
+AS_IF([test "x$enable_emscripten" = "xno"],
+      [AC_CHECK_FUNCS([ffs])])
 
 dnl 'memmem' is a GNU extension but we have a simple fallback
 AC_CHECK_FUNCS([memmem])
@@ -1228,29 +1300,42 @@ dnl ================================================================
 
 dnl These are values from system headers that we want to copy into the
 dnl public Cogl headers without having to include the system header
-AC_CHECK_HEADER(poll.h,
-        [
-         AC_COMPUTE_INT(COGL_SYSDEF_POLLIN, POLLIN, [#include <poll.h>],
-                        AC_MSG_ERROR([Unable to get value of POLLIN]))
-         AC_COMPUTE_INT(COGL_SYSDEF_POLLPRI, POLLPRI, [#include <poll.h>],
-                        AC_MSG_ERROR([Unable to get value of POLLPRI]))
-         AC_COMPUTE_INT(COGL_SYSDEF_POLLOUT, POLLOUT, [#include <poll.h>],
-                        AC_MSG_ERROR([Unable to get value of POLLOUT]))
-         AC_COMPUTE_INT(COGL_SYSDEF_POLLERR, POLLERR, [#include <poll.h>],
-                        AC_MSG_ERROR([Unable to get value of POLLERR]))
-         AC_COMPUTE_INT(COGL_SYSDEF_POLLHUP, POLLHUP, [#include <poll.h>],
-                        AC_MSG_ERROR([Unable to get value of POLLHUP]))
-         AC_COMPUTE_INT(COGL_SYSDEF_POLLNVAL, POLLNVAL, [#include <poll.h>],
-                        AC_MSG_ERROR([Unable to get value of POLLNVAL]))
-        ],
-        [
-         COGL_SYSDEF_POLLIN=1
-         COGL_SYSDEF_POLLPRI=2
-         COGL_SYSDEF_POLLOUT=4
-         COGL_SYSDEF_POLLERR=8
-         COGL_SYSDEF_POLLHUP=16
-         COGL_SYSDEF_POLLNVAL=32
-        ])
+dnl
+dnl XXX: poll(2) can't currently be used with emscripten even though
+dnl poll.h is in the toolchain headers so we manually skip the check
+dnl in this case
+have_poll_h=no
+AS_IF([test "x$enable_emscripten" = "xno"],
+      [
+       AC_CHECK_HEADER(poll.h,
+                       [
+                        AC_COMPUTE_INT(COGL_SYSDEF_POLLIN, POLLIN, [#include <poll.h>],
+                                       AC_MSG_ERROR([Unable to get value of POLLIN]))
+                        AC_COMPUTE_INT(COGL_SYSDEF_POLLPRI, POLLPRI, [#include <poll.h>],
+                                       AC_MSG_ERROR([Unable to get value of POLLPRI]))
+                        AC_COMPUTE_INT(COGL_SYSDEF_POLLOUT, POLLOUT, [#include <poll.h>],
+                                       AC_MSG_ERROR([Unable to get value of POLLOUT]))
+                        AC_COMPUTE_INT(COGL_SYSDEF_POLLERR, POLLERR, [#include <poll.h>],
+                                       AC_MSG_ERROR([Unable to get value of POLLERR]))
+                        AC_COMPUTE_INT(COGL_SYSDEF_POLLHUP, POLLHUP, [#include <poll.h>],
+                                       AC_MSG_ERROR([Unable to get value of POLLHUP]))
+                        AC_COMPUTE_INT(COGL_SYSDEF_POLLNVAL, POLLNVAL, [#include <poll.h>],
+                                       AC_MSG_ERROR([Unable to get value of POLLNVAL]))
+                        COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_POLL_SUPPORT"
+                        have_poll_h=yes
+                       ])
+      ])
+
+AS_IF([test "x$have_poll_h" = "xno"],
+      [
+       COGL_SYSDEF_POLLIN=1
+       COGL_SYSDEF_POLLPRI=2
+       COGL_SYSDEF_POLLOUT=4
+       COGL_SYSDEF_POLLERR=8
+       COGL_SYSDEF_POLLHUP=16
+       COGL_SYSDEF_POLLNVAL=32
+      ])
+
 COGL_DEFINES_EXTRA="$COGL_DEFINES_EXTRA
 #define COGL_SYSDEF_POLLIN $COGL_SYSDEF_POLLIN
 #define COGL_SYSDEF_POLLPRI $COGL_SYSDEF_POLLPRI
@@ -1375,8 +1460,9 @@ echo "        EGL Platforms:${EGL_PLATFORMS}"
 echo "        Wayland compositor support: ${enable_wayland_egl_server}"
 fi
 if test "x$SUPPORT_SDL" = "xyes"; then
-echo "        Support GLES under SDL: ${SUPPORT_SDL_GLES}"
+echo "        Supported SDL GL APIs: ${SUPPORTED_SDL_GL_APIS}"
 fi
+echo "        Building for emscripten environment: $enable_emscripten"
 echo "        Build libcogl-gles2 GLES 2.0 frontend api: ${enable_cogl_gles2}"
 echo "        Image backend: ${COGL_IMAGE_BACKEND}"
 echo "        Cogl Pango: ${enable_cogl_pango}"
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 87deb28..cd772fe 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -82,18 +82,38 @@ endif
 
 endif #USE_GLIB
 
+# XXX although emscripten "supports sdl" we can't build cogl-sdl-hello
+# un-modified for emscripten since emscripten doesn't support
+# SDL_WaitEvent() and we need to use some special emscripten apis
+# to create a mainloop....
+if USING_EMSCRIPTEN
+
+programs += cogl-emscripten-hello
+cogl_emscripten_hello_SOURCES = cogl-emscripten-hello.c
+cogl_emscripten_hello_LDADD = $(common_ldadd)
+
+else # USING_EMSCRIPTEN
+
 if SUPPORT_SDL
 programs += cogl-sdl-hello
 cogl_sdl_hello_SOURCES = cogl-sdl-hello.c
 cogl_sdl_hello_LDADD = $(common_ldadd)
 endif
 
+endif # USING_EMSCRIPTEN
+
 if SUPPORT_SDL2
 programs += cogl-sdl2-hello
 cogl_sdl2_hello_SOURCES = cogl-sdl2-hello.c
 cogl_sdl2_hello_LDADD = $(common_ldadd)
 endif
 
+if USING_EMSCRIPTEN
+%.html: %.o $(top_builddir)/cogl/.libs/libcogl2.so $(top_builddir)/deps/glib/.libs/libglib.a
+	emcc --minify 0 -o $@ $^
+
+all-local: $(addsuffix .html, $(programs))
+endif
 
 if INSTALL_EXAMPLES
 bin_PROGRAMS = $(programs)
diff --git a/examples/cogl-emscripten-hello.c b/examples/cogl-emscripten-hello.c
new file mode 100644
index 0000000..3932091
--- /dev/null
+++ b/examples/cogl-emscripten-hello.c
@@ -0,0 +1,144 @@
+#include <cogl/cogl.h>
+#include <stdio.h>
+#include <SDL.h>
+#include <emscripten.h>
+
+/* This short example is just to demonstrate mixing SDL with Cogl as a
+   simple way to get portable support for events */
+
+typedef struct Data
+{
+  CoglPrimitive *triangle;
+  CoglPipeline *pipeline;
+  float center_x, center_y;
+  CoglFramebuffer *fb;
+  CoglBool quit;
+  CoglBool redraw_queued;
+  CoglBool ready_to_draw;
+} Data;
+
+static Data data;
+static CoglContext *ctx;
+
+static void
+redraw (Data *data)
+{
+  CoglFramebuffer *fb = data->fb;
+
+  cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
+
+  cogl_framebuffer_push_matrix (fb);
+  cogl_framebuffer_translate (fb, data->center_x, -data->center_y, 0.0f);
+
+  cogl_framebuffer_draw_primitive (fb, data->pipeline, data->triangle);
+  cogl_framebuffer_pop_matrix (fb);
+
+  cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
+}
+
+static void
+handle_event (Data *data, SDL_Event *event)
+{
+  switch (event->type)
+    {
+    case SDL_VIDEOEXPOSE:
+      data->redraw_queued = TRUE;
+      break;
+
+    case SDL_MOUSEMOTION:
+      {
+        int width =
+          cogl_framebuffer_get_width (COGL_FRAMEBUFFER (data->fb));
+        int height =
+          cogl_framebuffer_get_height (COGL_FRAMEBUFFER (data->fb));
+
+        data->center_x = event->motion.x * 2.0f / width - 1.0f;
+        data->center_y = event->motion.y * 2.0f / height - 1.0f;
+
+        data->redraw_queued = TRUE;
+      }
+      break;
+
+    case SDL_QUIT:
+      data->quit = TRUE;
+      break;
+    }
+}
+
+static void
+frame_cb (CoglOnscreen *onscreen,
+          CoglFrameEvent event,
+          CoglFrameInfo *info,
+          void *user_data)
+{
+  Data *data = user_data;
+
+  if (event == COGL_FRAME_EVENT_SYNC)
+    data->ready_to_draw = TRUE;
+}
+
+static void
+mainloop (void)
+{
+  SDL_Event event;
+  while (SDL_PollEvent (&event) && !data.quit)
+    {
+      handle_event (&data, &event);
+      cogl_sdl_handle_event (ctx, &event);
+    }
+
+  if (data.quit)
+    emscripten_cancel_main_loop ();
+
+  redraw (&data);
+  data.redraw_queued = FALSE;
+  data.ready_to_draw = FALSE;
+
+  cogl_sdl_idle (ctx);
+}
+
+int
+main (int argc, char **argv)
+{
+  CoglOnscreen *onscreen;
+  CoglError *error = NULL;
+  CoglVertexP2C4 triangle_vertices[] = {
+    {0, 0.7, 0xff, 0x00, 0x00, 0xff},
+    {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff},
+    {0.7, -0.7, 0x00, 0x00, 0xff, 0xff}
+  };
+
+  ctx = cogl_sdl_context_new (SDL_USEREVENT, &error);
+  if (!ctx)
+    {
+      fprintf (stderr, "Failed to create context: %s\n", error->message);
+      return 1;
+    }
+
+  onscreen = cogl_onscreen_new (ctx, 800, 600);
+  data.fb = COGL_FRAMEBUFFER (onscreen);
+
+  cogl_onscreen_add_frame_callback (onscreen,
+                                    frame_cb,
+                                    &data,
+                                    NULL /* destroy callback */);
+
+  data.center_x = 0.0f;
+  data.center_y = 0.0f;
+  data.quit = FALSE;
+
+  cogl_onscreen_show (onscreen);
+
+  data.triangle = cogl_primitive_new_p2c4 (ctx, COGL_VERTICES_MODE_TRIANGLES,
+                                           3, triangle_vertices);
+  data.pipeline = cogl_pipeline_new (ctx);
+
+  data.redraw_queued = TRUE;
+  data.ready_to_draw = TRUE;
+
+  emscripten_set_main_loop (mainloop, -1, TRUE);
+
+  cogl_object_unref (ctx);
+
+  return 0;
+}
diff --git a/examples/cogl-info.c b/examples/cogl-info.c
index 1680f7d..0a29d99 100644
--- a/examples/cogl-info.c
+++ b/examples/cogl-info.c
@@ -222,7 +222,11 @@ main (int argc, char **argv)
   const char *winsys_name;
   OutputState output_state;
 
+#ifdef COGL_HAS_EMSCRIPTEN_SUPPORT
+  ctx = cogl_sdl_context_new (SDL_USEREVENT, &error);
+#else
   ctx = cogl_context_new (NULL, &error);
+#endif
   if (!ctx) {
       fprintf (stderr, "Failed to create context: %s\n", error->message);
       return 1;
diff --git a/tests/conform/Makefile.am b/tests/conform/Makefile.am
index d5c25db..e07f117 100644
--- a/tests/conform/Makefile.am
+++ b/tests/conform/Makefile.am
@@ -27,7 +27,6 @@ unported_test_sources = \
 
 test_sources = \
 	test-atlas-migration.c \
-	test-bitmask.c \
 	test-blend-strings.c \
 	test-depth-test.c \
 	test-color-mask.c \
@@ -67,6 +66,13 @@ test_sources = \
 	test-pipeline-cache-unrefs-texture.c \
 	$(NULL)
 
+# XXX: the emscripten toolchain gets upset about multiple definitions
+# of symbols due to the tricks we play in test-bitmask.c with
+# including cogl-util.c
+if !USING_EMSCRIPTEN
+test_sources += test-bitmask.c
+endif
+
 test_conformance_SOURCES = $(common_sources) $(test_sources)
 
 if OS_WIN32
-- 
1.8.2.1



More information about the Cogl mailing list