From 0e7a632e139611b63b188d9a4a3a49e296d93ea3 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Sun, 28 Apr 2013 02:42:24 +0100 Subject: [PATCH] Adds initial Emscripten support to Cogl This enables basic 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. Note: at this point the emscripten support has just barely been smoke tested so it's expected that as we continue to build on this we will learn about more things we need to change in Cogl to full support this environment. Reviewed-by: Neil Roberts (cherry picked from commit a3bc2e7539391b074e697839dfae60b69c37cf10) --- cogl/Makefile.am | 1 + cogl/cogl-debug.c | 2 +- cogl/cogl-i18n-private.h | 35 ++++ cogl/cogl-profile.c | 2 +- cogl/cogl.c | 4 +- cogl/winsys/cogl-winsys-egl.c | 3 +- cogl/winsys/cogl-winsys-glx.c | 3 +- cogl/winsys/cogl-winsys-sdl.c | 22 ++- configure.ac | 268 ++++++++++++++++++++----------- examples/Makefile.am | 20 +++ examples/cogl-emscripten-hello.c | 135 ++++++++++++++++ examples/cogl-info.c | 4 + tests/conform/Makefile.am | 12 +- 13 files changed, 408 insertions(+), 103 deletions(-) create mode 100644 cogl/cogl-i18n-private.h create mode 100644 examples/cogl-emscripten-hello.c diff --git a/cogl/Makefile.am b/cogl/Makefile.am index 4a65ce285..9622c1c4f 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -258,6 +258,7 @@ cogl_sources_c = \ $(cogl_winsys_common_sources) \ $(cogl_tesselator_sources) \ $(srcdir)/cogl-private.h \ + $(srcdir)/cogl-i18n-private.h \ $(srcdir)/cogl-debug.h \ $(srcdir)/cogl-debug-options.h \ $(srcdir)/cogl-gpu-info.c \ diff --git a/cogl/cogl-debug.c b/cogl/cogl-debug.c index 4498d418c..ccb33e697 100644 --- a/cogl/cogl-debug.c +++ b/cogl/cogl-debug.c @@ -26,8 +26,8 @@ #endif #include -#include +#include "cogl-i18n-private.h" #include "cogl-private.h" #include "cogl-debug.h" #include "cogl1-context.h" diff --git a/cogl/cogl-i18n-private.h b/cogl/cogl-i18n-private.h new file mode 100644 index 000000000..bd66a2cec --- /dev/null +++ b/cogl/cogl-i18n-private.h @@ -0,0 +1,35 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2013 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * + */ + +#ifndef _COGL_I18N_PRIVATE_H_ +#define _COGL_I18N_PRIVATE_H_ + +#ifdef ENABLE_NLS +#include +#else +#define _(X) X +#define N_(X) X +#endif + +#endif /* _COGL_I18N_PRIVATE_H_ */ diff --git a/cogl/cogl-profile.c b/cogl/cogl-profile.c index 042fb7882..ce687a204 100644 --- a/cogl/cogl-profile.c +++ b/cogl/cogl-profile.c @@ -6,8 +6,8 @@ #include "cogl-profile.h" #include "cogl-debug.h" +#include "cogl-i18n-private.h" -#include #include UProfContext *_cogl_uprof_context; diff --git a/cogl/cogl.c b/cogl/cogl.c index 7ed7480a4..36421a541 100644 --- a/cogl/cogl.c +++ b/cogl/cogl.c @@ -26,10 +26,10 @@ #include #include #include -#include #define COGL_VERSION_MIN_REQUIRED COGL_VERSION_1_4 +#include "cogl-i18n-private.h" #include "cogl-debug.h" #include "cogl-util.h" #include "cogl-context-private.h" @@ -746,8 +746,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-egl.c b/cogl/winsys/cogl-winsys-egl.c index 84d735dc4..1810615e3 100644 --- a/cogl/winsys/cogl-winsys-egl.c +++ b/cogl/winsys/cogl-winsys-egl.c @@ -28,6 +28,7 @@ #include "config.h" #endif +#include "cogl-i18n-private.h" #include "cogl-util.h" #include "cogl-winsys-egl-private.h" #include "cogl-winsys-private.h" @@ -49,8 +50,6 @@ #include #include -#include - #ifndef EGL_KHR_create_context #define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c index e0e2b0c88..849844a8f 100644 --- a/cogl/winsys/cogl-winsys-glx.c +++ b/cogl/winsys/cogl-winsys-glx.c @@ -28,6 +28,7 @@ #include "config.h" #endif +#include "cogl-i18n-private.h" #include "cogl-util.h" #include "cogl-winsys-private.h" #include "cogl-feature-private.h" @@ -59,8 +60,6 @@ #include #include -#include - #include #include diff --git a/cogl/winsys/cogl-winsys-sdl.c b/cogl/winsys/cogl-winsys-sdl.c index ed8212e3a..8af11ac3c 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 0f2c70acf..daadfc74c 100644 --- a/configure.ac +++ b/configure.ac @@ -207,6 +207,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 ============================================================ @@ -386,18 +410,23 @@ 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])]) + AS_IF([test "x$have_glib" = "xno" && test "x$enable_glib" = "xyes"], + [AC_MSG_ERROR([gobject-2.0 is required])]) + ], + [enable_glib=no] +) AM_CONDITIONAL([USE_GLIB], [test "x$enable_glib" = "xyes"]) @@ -620,24 +649,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 ]) + 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 ]) + + COGL_GLES2_LIBNAME="libGLESv2.so" + ]) + ]) ]) HAVE_GL=0 @@ -805,35 +842,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 ]) - AC_CHECK_DECL([SDL_GL_CONTEXT_MAJOR_VERSION], [], [SUPPORT_SDL_GLES=no], - [#include ]) - AC_CHECK_DECL([SDL_GL_CONTEXT_MINOR_VERSION], [], [SUPPORT_SDL_GLES=no], - [#include ]) - CPPFLAGS="$cogl_save_CPPFLAGS" + 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 ]) + AC_CHECK_DECL([SDL_GL_CONTEXT_MAJOR_VERSION], [], [SUPPORT_SDL_GLES=no], + [#include ]) + AC_CHECK_DECL([SDL_GL_CONTEXT_MINOR_VERSION], [], [SUPPORT_SDL_GLES=no], + [#include ]) + CPPFLAGS="$cogl_save_CPPFLAGS" - AS_IF([test "x$SUPPORT_SDL_GLES" = "xyes"], - COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_SDL_GLES_SUPPORT") + 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"]) @@ -1015,7 +1075,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"], @@ -1118,22 +1183,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]) +if test -n "$COGL_PKG_REQUIRES"; then + PKG_CHECK_MODULES(COGL_DEP, [$COGL_PKG_REQUIRES]) - 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_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) @@ -1175,7 +1243,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]) @@ -1192,29 +1264,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 ], - AC_MSG_ERROR([Unable to get value of POLLIN])) - AC_COMPUTE_INT(COGL_SYSDEF_POLLPRI, POLLPRI, [#include ], - AC_MSG_ERROR([Unable to get value of POLLPRI])) - AC_COMPUTE_INT(COGL_SYSDEF_POLLOUT, POLLOUT, [#include ], - AC_MSG_ERROR([Unable to get value of POLLOUT])) - AC_COMPUTE_INT(COGL_SYSDEF_POLLERR, POLLERR, [#include ], - AC_MSG_ERROR([Unable to get value of POLLERR])) - AC_COMPUTE_INT(COGL_SYSDEF_POLLHUP, POLLHUP, [#include ], - AC_MSG_ERROR([Unable to get value of POLLHUP])) - AC_COMPUTE_INT(COGL_SYSDEF_POLLNVAL, POLLNVAL, [#include ], - 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 ], + AC_MSG_ERROR([Unable to get value of POLLIN])) + AC_COMPUTE_INT(COGL_SYSDEF_POLLPRI, POLLPRI, [#include ], + AC_MSG_ERROR([Unable to get value of POLLPRI])) + AC_COMPUTE_INT(COGL_SYSDEF_POLLOUT, POLLOUT, [#include ], + AC_MSG_ERROR([Unable to get value of POLLOUT])) + AC_COMPUTE_INT(COGL_SYSDEF_POLLERR, POLLERR, [#include ], + AC_MSG_ERROR([Unable to get value of POLLERR])) + AC_COMPUTE_INT(COGL_SYSDEF_POLLHUP, POLLHUP, [#include ], + AC_MSG_ERROR([Unable to get value of POLLHUP])) + AC_COMPUTE_INT(COGL_SYSDEF_POLLNVAL, POLLNVAL, [#include ], + 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 @@ -1337,8 +1422,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 ae3e5f743..404920af3 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -77,18 +77,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 + $(CC) $(AM_CFLAGS) $(CFLAGS) -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 000000000..de3821f8e --- /dev/null +++ b/examples/cogl-emscripten-hello.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include + +/* 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 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; + } +} + +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)) + { + handle_event (&data, &event); + cogl_sdl_handle_event (ctx, &event); + } + + 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; + + 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 736f42e50..37c964bd7 100644 --- a/examples/cogl-info.c +++ b/examples/cogl-info.c @@ -227,7 +227,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 aa4a5706a..263e761fb 100644 --- a/tests/conform/Makefile.am +++ b/tests/conform/Makefile.am @@ -28,7 +28,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 \ @@ -66,9 +65,18 @@ test_sources = \ test-primitive-and-journal.c \ test-copy-replace-texture.c \ test-pipeline-cache-unrefs-texture.c \ - test-fence.c \ $(NULL) +if !USING_EMSCRIPTEN +# 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 +test_sources += test-bitmask.c +# test-fence depends on the glib mainloop so it won't compile if using +# emscripten which builds in standalone mode. +test_sources += test-fence.c +endif + test_conformance_SOURCES = $(common_sources) $(test_sources) if OS_WIN32