Initial merge of Emscripten port!
authorRyan C. Gordon <icculus@icculus.org>
Thu, 18 Dec 2014 00:19:52 -0500
changeset 92788900afb78a19
parent 9277 f0bd40782fc7
child 9279 e1d1b6479a14
Initial merge of Emscripten port!

With this commit, you can compile SDL2 with Emscripten
( http://emscripten.org/ ), and make your SDL-based C/C++ program
into a web app.

This port was due to the efforts of several people, including: Charlie Birks,
Sathyanarayanan Gunasekaran, Jukka Jylänki, Alon Zakai, Edward Rudd,
Bruce Mitchener, and Martin Gerhardy. (Thanks, everyone!)
CMakeLists.txt
build-scripts/config.sub
configure
configure.in
docs/README-emscripten.txt
include/SDL_atomic.h
include/SDL_config.h.cmake
include/SDL_config.h.in
include/SDL_hints.h
src/audio/SDL_audio.c
src/audio/emscripten/SDL_emscriptenaudio.c
src/audio/emscripten/SDL_emscriptenaudio.h
src/cpuinfo/SDL_cpuinfo.c
src/dynapi/SDL_dynapi.h
src/filesystem/emscripten/SDL_sysfilesystem.c
src/joystick/SDL_gamecontroller.c
src/joystick/SDL_gamecontrollerdb.h
src/joystick/emscripten/SDL_sysjoystick.c
src/joystick/emscripten/SDL_sysjoystick_c.h
src/power/SDL_power.c
src/power/emscripten/SDL_syspower.c
src/render/opengles2/SDL_gles2funcs.h
src/render/opengles2/SDL_render_gles2.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/emscripten/SDL_emscriptenevents.c
src/video/emscripten/SDL_emscriptenevents.h
src/video/emscripten/SDL_emscriptenframebuffer.c
src/video/emscripten/SDL_emscriptenframebuffer.h
src/video/emscripten/SDL_emscriptenmouse.c
src/video/emscripten/SDL_emscriptenmouse.h
src/video/emscripten/SDL_emscriptenopengles.c
src/video/emscripten/SDL_emscriptenopengles.h
src/video/emscripten/SDL_emscriptenvideo.c
src/video/emscripten/SDL_emscriptenvideo.h
test/Makefile.in
test/checkkeys.c
test/configure
test/configure.in
test/emscripten/joystick-pre.js
test/loopwave.c
test/testautomation_surface.c
test/testdraw2.c
test/testdrawchessboard.c
test/testfilesystem.c
test/testgamecontroller.c
test/testgesture.c
test/testgles2.c
test/testintersections.c
test/testjoystick.c
test/testmultiaudio.c
test/testoverlay2.c
test/testrelative.c
test/testrendercopyex.c
test/testrendertarget.c
test/testscale.c
test/testsprite2.c
test/testspriteminimal.c
test/teststreaming.c
test/testviewport.c
test/testwm2.c
     1.1 --- a/CMakeLists.txt	Sat Dec 13 02:33:52 2014 -0500
     1.2 +++ b/CMakeLists.txt	Thu Dec 18 00:19:52 2014 -0500
     1.3 @@ -117,6 +117,12 @@
     1.4    set(UNIX_OR_MAC_SYS OFF)
     1.5  endif()
     1.6  
     1.7 +if (UNIX_OR_MAC_SYS AND NOT EMSCRIPTEN) # JavaScript does not yet have threading support, so disable pthreads when building for Emscripten.
     1.8 +  set(PTHREADS_ENABLED_BY_DEFAULT ON)
     1.9 +else()
    1.10 +  set(PTHREADS_ENABLED_BY_DEFAULT OFF)
    1.11 +endif()
    1.12 +
    1.13  # Default option knobs
    1.14  if(APPLE OR ARCH_64)
    1.15    set(OPT_DEF_SSEMATH ON)
    1.16 @@ -170,13 +176,19 @@
    1.17  set(SDL_LIBS "-lSDL2")
    1.18  set(SDL_CFLAGS "")
    1.19  
    1.20 +# Emscripten toolchain has a nonempty default value for this, and the checks 
    1.21 +# in this file need to change that, so remember the original value, and 
    1.22 +# restore back to that afterwards. For check_function_exists() to work in
    1.23 +# Emscripten, this value must be at its default value.
    1.24 +set(ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
    1.25 +
    1.26  if(CYGWIN)
    1.27    # We build SDL on cygwin without the UNIX emulation layer
    1.28    include_directories("-I/usr/include/mingw")
    1.29    set(CMAKE_REQUIRED_FLAGS "-mno-cygwin")
    1.30    check_c_source_compiles("int main(int argc, char **argv) {}"
    1.31      HAVE_GCC_NO_CYGWIN)
    1.32 -  set(CMAKE_REQUIRED_FLAGS)
    1.33 +  set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
    1.34    if(HAVE_GCC_NO_CYGWIN)
    1.35      list(APPEND EXTRA_LDFLAGS "-mno-cygwin")
    1.36      list(APPEND SDL_LIBS "-mno-cygwin")
    1.37 @@ -188,12 +200,35 @@
    1.38  # General includes
    1.39  include_directories(${SDL2_BINARY_DIR}/include ${SDL2_SOURCE_DIR}/include)
    1.40  
    1.41 +if(EMSCRIPTEN)
    1.42 +  # Set up default values for the currently supported set of subsystems:
    1.43 +  # Emscripten/Javascript does not have assembly support, a dynamic library 
    1.44 +  # loading architecture, low-level CPU inspection or multithreading.
    1.45 +  set(OPT_DEF_ASM FALSE)
    1.46 +  set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
    1.47 +  set(SDL_ATOMIC_ENABLED_BY_DEFAULT OFF)
    1.48 +  set(SDL_THREADS_ENABLED_BY_DEFAULT OFF)
    1.49 +  set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF)
    1.50 +  set(SDL_CPUINFO_ENABLED_BY_DEFAULT OFF)
    1.51 +  set(DLOPEN_ENABLED_BY_DEFAULT OFF)
    1.52 +else()
    1.53 +  set(SDL_SHARED_ENABLED_BY_DEFAULT ON)
    1.54 +  set(SDL_ATOMIC_ENABLED_BY_DEFAULT ON)
    1.55 +  set(SDL_THREADS_ENABLED_BY_DEFAULT ON)
    1.56 +  set(SDL_LOADSO_ENABLED_BY_DEFAULT ON)
    1.57 +  set(SDL_CPUINFO_ENABLED_BY_DEFAULT ON)
    1.58 +  set(DLOPEN_ENABLED_BY_DEFAULT ON)
    1.59 +endif()
    1.60 +
    1.61  set(SDL_SUBSYSTEMS
    1.62      Atomic Audio Video Render Events Joystick Haptic Power Threads Timers
    1.63      File Loadso CPUinfo Filesystem)
    1.64  foreach(_SUB ${SDL_SUBSYSTEMS})
    1.65    string(TOUPPER ${_SUB} _OPT)
    1.66 -  option(SDL_${_OPT} "Enable the ${_SUB} subsystem" ON)
    1.67 +  if (NOT DEFINED SDL_${_OPT}_ENABLED_BY_DEFAULT)
    1.68 +    set(SDL_${_OPT}_ENABLED_BY_DEFAULT ON)
    1.69 +  endif()
    1.70 +  option(SDL_${_OPT} "Enable the ${_SUB} subsystem" ${SDL_${_OPT}_ENABLED_BY_DEFAULT})
    1.71  endforeach()
    1.72  
    1.73  option_string(ASSERTIONS "Enable internal sanity checks (auto/disabled/release/enabled/paranoid)" "auto")
    1.74 @@ -216,9 +251,9 @@
    1.75  set_option(VIDEO_DUMMY         "Use dummy video driver" ON)
    1.76  set_option(VIDEO_OPENGL        "Include OpenGL support" ON)
    1.77  set_option(VIDEO_OPENGLES      "Include OpenGL ES support" ON)
    1.78 -set_option(PTHREADS            "Use POSIX threads for multi-threading" ${UNIX_OR_MAC_SYS})
    1.79 +set_option(PTHREADS            "Use POSIX threads for multi-threading" ${PTHREADS_ENABLED_BY_DEFAULT})
    1.80  dep_option(PTHREADS_SEM        "Use pthread semaphores" ON "PTHREADS" OFF)
    1.81 -set_option(SDL_DLOPEN          "Use dlopen for shared object loading" ON)
    1.82 +set_option(SDL_DLOPEN          "Use dlopen for shared object loading" ${DLOPEN_ENABLED_BY_DEFAULT})
    1.83  set_option(OSS                 "Support the OSS audio API" ${UNIX_SYS})
    1.84  set_option(ALSA                "Support the ALSA audio API" ${UNIX_SYS})
    1.85  dep_option(ALSA_SHARED         "Dynamically load ALSA audio support" ON "ALSA" OFF)
    1.86 @@ -251,7 +286,7 @@
    1.87  
    1.88  # TODO: We should (should we?) respect cmake's ${BUILD_SHARED_LIBS} flag here
    1.89  # The options below are for compatibility to configure's default behaviour.
    1.90 -set(SDL_SHARED ON CACHE BOOL "Build a shared version of the library")
    1.91 +set(SDL_SHARED ${SDL_SHARED_ENABLED_BY_DEFAULT} CACHE BOOL "Build a shared version of the library")
    1.92  set(SDL_STATIC ON CACHE BOOL "Build a static version of the library")
    1.93  
    1.94  # General source files
    1.95 @@ -317,7 +352,7 @@
    1.96    set(CMAKE_REQUIRED_FLAGS "-mpreferred-stack-boundary=2")
    1.97    check_c_source_compiles("int x = 0; int main(int argc, char **argv) {}"
    1.98      HAVE_GCC_PREFERRED_STACK_BOUNDARY)
    1.99 -  set(CMAKE_REQUIRED_FLAGS)
   1.100 +  set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   1.101  
   1.102    set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden -Werror")
   1.103    check_c_source_compiles("
   1.104 @@ -328,7 +363,7 @@
   1.105    if(HAVE_GCC_FVISIBILITY)
   1.106      list(APPEND EXTRA_CFLAGS "-fvisibility=hidden")
   1.107    endif()
   1.108 -  set(CMAKE_REQUIRED_FLAGS)
   1.109 +  set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   1.110  
   1.111    check_c_compiler_flag(-Wall HAVE_GCC_WALL)
   1.112    if(HAVE_GCC_WALL)
   1.113 @@ -376,7 +411,7 @@
   1.114        if(HAVE_MMX)
   1.115          list(APPEND EXTRA_CFLAGS "-mmmx")
   1.116        endif()
   1.117 -      set(CMAKE_REQUIRED_FLAGS)
   1.118 +      set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   1.119      endif()
   1.120  
   1.121      if(3DNOW)
   1.122 @@ -393,7 +428,7 @@
   1.123        if(HAVE_3DNOW)
   1.124          list(APPEND EXTRA_CFLAGS "-m3dnow")
   1.125        endif()
   1.126 -      set(CMAKE_REQUIRED_FLAGS)
   1.127 +      set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   1.128      endif()
   1.129  
   1.130      if(SSE)
   1.131 @@ -416,7 +451,7 @@
   1.132        if(HAVE_SSE)
   1.133          list(APPEND EXTRA_CFLAGS "-msse")
   1.134        endif()
   1.135 -      set(CMAKE_REQUIRED_FLAGS)
   1.136 +      set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   1.137      endif()
   1.138  
   1.139      if(SSE2)
   1.140 @@ -439,7 +474,7 @@
   1.141        if(HAVE_SSE2)
   1.142          list(APPEND EXTRA_CFLAGS "-msse2")
   1.143        endif()
   1.144 -      set(CMAKE_REQUIRED_FLAGS)
   1.145 +      set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   1.146      endif()
   1.147  
   1.148      if(SSEMATH)
   1.149 @@ -464,7 +499,7 @@
   1.150                return vec_splat_u32(0);
   1.151            }
   1.152            int main(int argc, char **argv) { }" HAVE_ALTIVEC)
   1.153 -      set(CMAKE_REQUIRED_FLAGS)
   1.154 +      set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   1.155        if(HAVE_ALTIVEC OR HAVE_ALTIVEC_H_HDR)
   1.156          set(HAVE_ALTIVEC TRUE) # if only HAVE_ALTIVEC_H_HDR is set
   1.157          list(APPEND EXTRA_CFLAGS "-maltivec")
   1.158 @@ -642,7 +677,49 @@
   1.159  endif()
   1.160  
   1.161  # Platform-specific options and settings
   1.162 -if(UNIX AND NOT APPLE)
   1.163 +if(EMSCRIPTEN)
   1.164 +  # Hide noisy warnings that intend to aid mostly during initial stages of porting a new
   1.165 +  # project. Uncomment at will for verbose cross-compiling -I/../ path info.
   1.166 +  add_definitions(-Wno-warn-absolute-paths)
   1.167 +  if(SDL_AUDIO)
   1.168 +    set(SDL_AUDIO_DRIVER_EMSCRIPTEN 1)
   1.169 +    file(GLOB EM_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/emscripten/*.c)
   1.170 +    set(SOURCE_FILES ${SOURCE_FILES} ${EM_AUDIO_SOURCES})
   1.171 +    set(HAVE_SDL_AUDIO TRUE)
   1.172 +  endif()
   1.173 +  if(SDL_FILESYSTEM)
   1.174 +    set(SDL_FILESYSTEM_EMSCRIPTEN 1)
   1.175 +    file(GLOB EM_FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/emscripten/*.c)
   1.176 +    set(SOURCE_FILES ${SOURCE_FILES} ${EM_FILESYSTEM_SOURCES})
   1.177 +    set(HAVE_SDL_FILESYSTEM TRUE)
   1.178 +  endif()
   1.179 +  if(SDL_JOYSTICK)
   1.180 +    set(SDL_JOYSTICK_EMSCRIPTEN 1)
   1.181 +    file(GLOB EM_JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/emscripten/*.c)
   1.182 +    set(SOURCE_FILES ${SOURCE_FILES} ${EM_JOYSTICK_SOURCES})
   1.183 +    set(HAVE_SDL_JOYSTICK TRUE)
   1.184 +  endif()
   1.185 +  if(SDL_POWER)
   1.186 +    set(SDL_POWER_EMSCRIPTEN 1)
   1.187 +    file(GLOB EM_POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/emscripten/*.c)
   1.188 +    set(SOURCE_FILES ${SOURCE_FILES} ${EM_POWER_SOURCES})
   1.189 +    set(HAVE_SDL_POWER TRUE)
   1.190 +  endif()
   1.191 +  if(SDL_VIDEO)
   1.192 +    set(SDL_VIDEO_DRIVER_EMSCRIPTEN 1)
   1.193 +    file(GLOB EM_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/emscripten/*.c)
   1.194 +    set(SOURCE_FILES ${SOURCE_FILES} ${EM_VIDEO_SOURCES})
   1.195 +    set(HAVE_SDL_VIDEO TRUE)
   1.196 +
   1.197 +    #enable gles
   1.198 +    if(VIDEO_OPENGLES)
   1.199 +      set(SDL_VIDEO_OPENGL_EGL 1)
   1.200 +      set(HAVE_VIDEO_OPENGLES TRUE)
   1.201 +      set(SDL_VIDEO_OPENGL_ES2 1)
   1.202 +      set(SDL_VIDEO_RENDER_OGL_ES2 1)
   1.203 +    endif()
   1.204 +  endif()
   1.205 +elseif(UNIX AND NOT APPLE)
   1.206    if(SDL_AUDIO)
   1.207      if(SYSV5 OR SOLARIS OR HPUX)
   1.208          set(SDL_AUDIO_DRIVER_SUNAUDIO 1)
   1.209 @@ -829,7 +906,7 @@
   1.210        link_directories($ENV{DXSDK_DIR}\\lib\\${PROCESSOR_ARCH})
   1.211        include_directories($ENV{DXSDK_DIR}\\Include)
   1.212      endif()
   1.213 -    set(CMAKE_REQUIRED_FLAGS)
   1.214 +    set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   1.215    endif()
   1.216  
   1.217    if(SDL_AUDIO)
     2.1 --- a/build-scripts/config.sub	Sat Dec 13 02:33:52 2014 -0500
     2.2 +++ b/build-scripts/config.sub	Thu Dec 18 00:19:52 2014 -0500
     2.3 @@ -1534,6 +1534,8 @@
     2.4  	-pnacl*)
     2.5  		os=-pnacl
     2.6  		;;
     2.7 +	-emscripten*)
     2.8 +		;;
     2.9  	-none)
    2.10  		;;
    2.11  	*)
     3.1 --- a/configure	Sat Dec 13 02:33:52 2014 -0500
     3.2 +++ b/configure	Thu Dec 18 00:19:52 2014 -0500
     3.3 @@ -21385,6 +21385,78 @@
     3.4      fi
     3.5  }
     3.6  
     3.7 +CheckEmscriptenGLES()
     3.8 +{
     3.9 +    if test x$enable_video = xyes -a x$enable_video_opengles = xyes; then
    3.10 +        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EGL support" >&5
    3.11 +$as_echo_n "checking for EGL support... " >&6; }
    3.12 +        video_opengl_egl=no
    3.13 +        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    3.14 +/* end confdefs.h.  */
    3.15 +
    3.16 +         #include <EGL/egl.h>
    3.17 +
    3.18 +int
    3.19 +main ()
    3.20 +{
    3.21 +
    3.22 +
    3.23 +  ;
    3.24 +  return 0;
    3.25 +}
    3.26 +_ACEOF
    3.27 +if ac_fn_c_try_compile "$LINENO"; then :
    3.28 +
    3.29 +        video_opengl_egl=yes
    3.30 +
    3.31 +fi
    3.32 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    3.33 +        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_opengl_egl" >&5
    3.34 +$as_echo "$video_opengl_egl" >&6; }
    3.35 +        if test x$video_opengl_egl = xyes; then
    3.36 +
    3.37 +$as_echo "#define SDL_VIDEO_OPENGL_EGL 1" >>confdefs.h
    3.38 +
    3.39 +        fi
    3.40 +
    3.41 +        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES v2 headers" >&5
    3.42 +$as_echo_n "checking for OpenGL ES v2 headers... " >&6; }
    3.43 +        video_opengles_v2=no
    3.44 +        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    3.45 +/* end confdefs.h.  */
    3.46 +
    3.47 +         #include <GLES2/gl2.h>
    3.48 +         #include <GLES2/gl2ext.h>
    3.49 +
    3.50 +int
    3.51 +main ()
    3.52 +{
    3.53 +
    3.54 +
    3.55 +  ;
    3.56 +  return 0;
    3.57 +}
    3.58 +_ACEOF
    3.59 +if ac_fn_c_try_compile "$LINENO"; then :
    3.60 +
    3.61 +        video_opengles_v2=yes
    3.62 +
    3.63 +fi
    3.64 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    3.65 +        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_opengles_v2" >&5
    3.66 +$as_echo "$video_opengles_v2" >&6; }
    3.67 +        if test x$video_opengles_v2 = xyes; then
    3.68 +
    3.69 +$as_echo "#define SDL_VIDEO_OPENGL_ES2 1" >>confdefs.h
    3.70 +
    3.71 +
    3.72 +$as_echo "#define SDL_VIDEO_RENDER_OGL_ES2 1" >>confdefs.h
    3.73 +
    3.74 +            SUMMARY_video="${SUMMARY_video} opengl_es2"
    3.75 +        fi
    3.76 +    fi
    3.77 +}
    3.78 +
    3.79  CheckInputEvents()
    3.80  {
    3.81              { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Linux 2.4 unified input interface" >&5
    3.82 @@ -23483,7 +23555,68 @@
    3.83              SOURCES="$SOURCES $srcdir/src/filesystem/nacl/*.c"
    3.84              have_filesystem=yes
    3.85          fi
    3.86 -
    3.87 +        ;;
    3.88 +    *-*-emscripten* )
    3.89 +        if test x$enable_video = xyes; then
    3.90 +
    3.91 +$as_echo "#define SDL_VIDEO_DRIVER_EMSCRIPTEN 1" >>confdefs.h
    3.92 +
    3.93 +            SOURCES="$SOURCES $srcdir/src/video/emscripten/*.c"
    3.94 +            have_video=yes
    3.95 +            SUMMARY_video="${SUMMARY_video} emscripten"
    3.96 +        fi
    3.97 +
    3.98 +        if test x$enable_audio = xyes; then
    3.99 +
   3.100 +$as_echo "#define SDL_AUDIO_DRIVER_EMSCRIPTEN 1" >>confdefs.h
   3.101 +
   3.102 +            SOURCES="$SOURCES $srcdir/src/audio/emscripten/*.c"
   3.103 +            have_audio=yes
   3.104 +            SUMMARY_audio="${SUMMARY_audio} emscripten"
   3.105 +        fi
   3.106 +
   3.107 +        CheckVisibilityHidden
   3.108 +        CheckDummyVideo
   3.109 +        CheckDiskAudio
   3.110 +        CheckDummyAudio
   3.111 +        CheckDLOPEN
   3.112 +        CheckClockGettime
   3.113 +        CheckEmscriptenGLES
   3.114 +
   3.115 +         # Set up files for the power library
   3.116 +        if test x$enable_power = xyes; then
   3.117 +
   3.118 +$as_echo "#define SDL_POWER_EMSCRIPTEN 1" >>confdefs.h
   3.119 +
   3.120 +            SOURCES="$SOURCES $srcdir/src/power/emscripten/*.c"
   3.121 +            have_power=yes
   3.122 +        fi
   3.123 +
   3.124 +        # Set up files for the power library
   3.125 +        if test x$enable_joystick = xyes; then
   3.126 +
   3.127 +$as_echo "#define SDL_JOYSTICK_EMSCRIPTEN 1" >>confdefs.h
   3.128 +
   3.129 +            SOURCES="$SOURCES $srcdir/src/joystick/emscripten/*.c"
   3.130 +            have_joystick=yes
   3.131 +        fi
   3.132 +
   3.133 +        # Set up files for the filesystem library
   3.134 +        if test x$enable_filesystem = xyes; then
   3.135 +
   3.136 +$as_echo "#define SDL_FILESYSTEM_EMSCRIPTEN 1" >>confdefs.h
   3.137 +
   3.138 +            SOURCES="$SOURCES $srcdir/src/filesystem/emscripten/*.c"
   3.139 +            have_filesystem=yes
   3.140 +        fi
   3.141 +        # Set up files for the timer library
   3.142 +        if test x$enable_timers = xyes; then
   3.143 +
   3.144 +$as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
   3.145 +
   3.146 +            SOURCES="$SOURCES $srcdir/src/timer/unix/*.c"
   3.147 +            have_timers=yes
   3.148 +        fi
   3.149          ;;
   3.150      *)
   3.151          as_fn_error $? "
     4.1 --- a/configure.in	Sat Dec 13 02:33:52 2014 -0500
     4.2 +++ b/configure.in	Thu Dec 18 00:19:52 2014 -0500
     4.3 @@ -2130,6 +2130,40 @@
     4.4      fi
     4.5  }
     4.6  
     4.7 +CheckEmscriptenGLES()
     4.8 +{
     4.9 +    if test x$enable_video = xyes -a x$enable_video_opengles = xyes; then
    4.10 +        AC_MSG_CHECKING(for EGL support)
    4.11 +        video_opengl_egl=no
    4.12 +        AC_TRY_COMPILE([
    4.13 +         #include <EGL/egl.h>
    4.14 +        ],[
    4.15 +        ],[
    4.16 +        video_opengl_egl=yes
    4.17 +        ])
    4.18 +        AC_MSG_RESULT($video_opengl_egl)
    4.19 +        if test x$video_opengl_egl = xyes; then
    4.20 +            AC_DEFINE(SDL_VIDEO_OPENGL_EGL, 1, [ ])
    4.21 +        fi
    4.22 +
    4.23 +        AC_MSG_CHECKING(for OpenGL ES v2 headers)
    4.24 +        video_opengles_v2=no
    4.25 +        AC_TRY_COMPILE([
    4.26 +         #include <GLES2/gl2.h>
    4.27 +         #include <GLES2/gl2ext.h>
    4.28 +        ],[
    4.29 +        ],[
    4.30 +        video_opengles_v2=yes
    4.31 +        ])
    4.32 +        AC_MSG_RESULT($video_opengles_v2)
    4.33 +        if test x$video_opengles_v2 = xyes; then
    4.34 +            AC_DEFINE(SDL_VIDEO_OPENGL_ES2, 1, [ ])
    4.35 +            AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES2, 1, [ ])
    4.36 +            SUMMARY_video="${SUMMARY_video} opengl_es2"
    4.37 +        fi
    4.38 +    fi
    4.39 +}
    4.40 +
    4.41  dnl See if we can use the new unified event interface in Linux 2.4
    4.42  CheckInputEvents()
    4.43  {
    4.44 @@ -3302,7 +3336,56 @@
    4.45              SOURCES="$SOURCES $srcdir/src/filesystem/nacl/*.c"
    4.46              have_filesystem=yes
    4.47          fi
    4.48 +        ;;
    4.49 +    *-*-emscripten* )
    4.50 +        if test x$enable_video = xyes; then
    4.51 +            AC_DEFINE(SDL_VIDEO_DRIVER_EMSCRIPTEN, 1, [ ])
    4.52 +            SOURCES="$SOURCES $srcdir/src/video/emscripten/*.c"
    4.53 +            have_video=yes
    4.54 +            SUMMARY_video="${SUMMARY_video} emscripten"
    4.55 +        fi
    4.56 +
    4.57 +        if test x$enable_audio = xyes; then
    4.58 +            AC_DEFINE(SDL_AUDIO_DRIVER_EMSCRIPTEN, 1, [ ])
    4.59 +            SOURCES="$SOURCES $srcdir/src/audio/emscripten/*.c"
    4.60 +            have_audio=yes
    4.61 +            SUMMARY_audio="${SUMMARY_audio} emscripten"
    4.62 +        fi
    4.63 +
    4.64 +        CheckVisibilityHidden
    4.65 +        CheckDummyVideo
    4.66 +        CheckDiskAudio
    4.67 +        CheckDummyAudio
    4.68 +        CheckDLOPEN
    4.69 +        CheckClockGettime
    4.70 +        CheckEmscriptenGLES
    4.71 +
    4.72 +         # Set up files for the power library
    4.73 +        if test x$enable_power = xyes; then
    4.74 +            AC_DEFINE(SDL_POWER_EMSCRIPTEN, 1, [ ])
    4.75 +            SOURCES="$SOURCES $srcdir/src/power/emscripten/*.c"
    4.76 +            have_power=yes
    4.77 +        fi
    4.78          
    4.79 +        # Set up files for the power library
    4.80 +        if test x$enable_joystick = xyes; then
    4.81 +            AC_DEFINE(SDL_JOYSTICK_EMSCRIPTEN, 1, [ ])
    4.82 +            SOURCES="$SOURCES $srcdir/src/joystick/emscripten/*.c"
    4.83 +            have_joystick=yes
    4.84 +        fi
    4.85 +
    4.86 +        # Set up files for the filesystem library
    4.87 +        if test x$enable_filesystem = xyes; then
    4.88 +            AC_DEFINE(SDL_FILESYSTEM_EMSCRIPTEN, 1, [ ])
    4.89 +            SOURCES="$SOURCES $srcdir/src/filesystem/emscripten/*.c"
    4.90 +            have_filesystem=yes
    4.91 +        fi
    4.92 +        # Set up files for the timer library
    4.93 +        if test x$enable_timers = xyes; then
    4.94 +            AC_DEFINE(SDL_TIMER_UNIX, 1, [ ])
    4.95 +            SOURCES="$SOURCES $srcdir/src/timer/unix/*.c"
    4.96 +            have_timers=yes
    4.97 +        fi
    4.98          ;;
    4.99      *)
   4.100          AC_MSG_ERROR([
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/docs/README-emscripten.txt	Thu Dec 18 00:19:52 2014 -0500
     5.3 @@ -0,0 +1,26 @@
     5.4 +Build:
     5.5 +$ emconfigure ./configure --host=asmjs-unknown-emscripten --disable-assembly --disable-threads --enable-cpuinfo=false CFLAGS="-O2"
     5.6 +$ emmake make
     5.7 +
     5.8 +Or with cmake:
     5.9 +$ emconfigure cmake ..
    5.10 +$ make
    5.11 +
    5.12 +To build one of the tests -
    5.13 +$ cd test/
    5.14 +$ emcc -O2 --js-opts 0 -g4 testdraw2.c -I../include ../build/.libs/libSDL2.a ../build/libSDL2_test.a -o a.html
    5.15 +
    5.16 +Uses GLES2 renderer or software
    5.17 +
    5.18 +tests: https://dl.dropboxusercontent.com/u/17360362/SDL2-em/index.html
    5.19 +
    5.20 +Some other SDL2 libraries can be easily built (assuming SDL2 is installed somwhere):
    5.21 +
    5.22 +SDL_mixer (http://www.libsdl.org/projects/SDL_mixer/)
    5.23 +    $ EMCONFIGURE_JS=1 emconfigure ../configure
    5.24 +    build as usual...
    5.25 +
    5.26 +SDL_gfx (http://cms.ferzkopp.net/index.php/software/13-sdl-gfx):
    5.27 +    $ EMCONFIGURE_JS=1 emconfigure ../configure --disable-mmx
    5.28 +    build as usual...
    5.29 +
     6.1 --- a/include/SDL_atomic.h	Sat Dec 13 02:33:52 2014 -0500
     6.2 +++ b/include/SDL_atomic.h	Thu Dec 18 00:19:52 2014 -0500
     6.3 @@ -122,7 +122,7 @@
     6.4  void _ReadWriteBarrier(void);
     6.5  #pragma intrinsic(_ReadWriteBarrier)
     6.6  #define SDL_CompilerBarrier()   _ReadWriteBarrier()
     6.7 -#elif defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
     6.8 +#elif (defined(__GNUC__) && !defined(__EMSCRIPTEN__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
     6.9  /* This is correct for all CPUs when using GCC or Solaris Studio 12.1+. */
    6.10  #define SDL_CompilerBarrier()   __asm__ __volatile__ ("" : : : "memory")
    6.11  #else
     7.1 --- a/include/SDL_config.h.cmake	Sat Dec 13 02:33:52 2014 -0500
     7.2 +++ b/include/SDL_config.h.cmake	Thu Dec 18 00:19:52 2014 -0500
     7.3 @@ -217,6 +217,7 @@
     7.4  #cmakedefine SDL_AUDIO_DRIVER_WINMM @SDL_AUDIO_DRIVER_WINMM@
     7.5  #cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND @SDL_AUDIO_DRIVER_FUSIONSOUND@
     7.6  #cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC @SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC@
     7.7 +#cmakedefine SDL_AUDIO_DRIVER_EMSCRIPTEN @SDL_AUDIO_DRIVER_EMSCRIPTEN@
     7.8  
     7.9  /* Enable various input drivers */
    7.10  #cmakedefine SDL_INPUT_LINUXEV @SDL_INPUT_LINUXEV@
    7.11 @@ -230,6 +231,7 @@
    7.12  #cmakedefine SDL_JOYSTICK_WINMM @SDL_JOYSTICK_WINMM@
    7.13  #cmakedefine SDL_JOYSTICK_USBHID @SDL_JOYSTICK_USBHID@
    7.14  #cmakedefine SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H @SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H@
    7.15 +#cmakedefine SDL_JOYSTICK_EMSCRIPTEN @SDL_JOYSTICK_EMSCRIPTEN@
    7.16  #cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@
    7.17  #cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@
    7.18  #cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@
    7.19 @@ -279,6 +281,7 @@
    7.20  #cmakedefine SDL_VIDEO_DRIVER_MIR @SDL_VIDEO_DRIVER_MIR@
    7.21  #cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC @SDL_VIDEO_DRIVER_MIR_DYNAMIC@
    7.22  #cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON@
    7.23 +#cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@
    7.24  #cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@
    7.25  #cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@
    7.26  #cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT @SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT@
    7.27 @@ -325,6 +328,7 @@
    7.28  #cmakedefine SDL_POWER_WINDOWS @SDL_POWER_WINDOWS@
    7.29  #cmakedefine SDL_POWER_MACOSX @SDL_POWER_MACOSX@
    7.30  #cmakedefine SDL_POWER_HAIKU @SDL_POWER_HAIKU@
    7.31 +#cmakedefine SDL_POWER_EMSCRIPTEN @SDL_POWER_EMSCRIPTEN@
    7.32  #cmakedefine SDL_POWER_HARDWIRED @SDL_POWER_HARDWIRED@
    7.33  
    7.34  /* Enable system filesystem support */
    7.35 @@ -333,6 +337,7 @@
    7.36  #cmakedefine SDL_FILESYSTEM_DUMMY @SDL_FILESYSTEM_DUMMY@
    7.37  #cmakedefine SDL_FILESYSTEM_UNIX @SDL_FILESYSTEM_UNIX@
    7.38  #cmakedefine SDL_FILESYSTEM_WINDOWS @SDL_FILESYSTEM_WINDOWS@
    7.39 +#cmakedefine SDL_FILESYSTEM_EMSCRIPTEN @SDL_FILESYSTEM_EMSCRIPTEN@
    7.40  
    7.41  /* Enable assembly routines */
    7.42  #cmakedefine SDL_ASSEMBLY_ROUTINES @SDL_ASSEMBLY_ROUTINES@
     8.1 --- a/include/SDL_config.h.in	Sat Dec 13 02:33:52 2014 -0500
     8.2 +++ b/include/SDL_config.h.in	Thu Dec 18 00:19:52 2014 -0500
     8.3 @@ -228,6 +228,7 @@
     8.4  #undef SDL_AUDIO_DRIVER_WINMM
     8.5  #undef SDL_AUDIO_DRIVER_FUSIONSOUND
     8.6  #undef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
     8.7 +#undef SDL_AUDIO_DRIVER_EMSCRIPTEN
     8.8  
     8.9  /* Enable various input drivers */
    8.10  #undef SDL_INPUT_LINUXEV
    8.11 @@ -243,6 +244,7 @@
    8.12  #undef SDL_JOYSTICK_WINMM
    8.13  #undef SDL_JOYSTICK_USBHID
    8.14  #undef SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
    8.15 +#undef SDL_JOYSTICK_EMSCRIPTEN
    8.16  #undef SDL_HAPTIC_DUMMY
    8.17  #undef SDL_HAPTIC_LINUX
    8.18  #undef SDL_HAPTIC_IOKIT
    8.19 @@ -287,6 +289,7 @@
    8.20  #undef SDL_VIDEO_DRIVER_X11
    8.21  #undef SDL_VIDEO_DRIVER_RPI
    8.22  #undef SDL_VIDEO_DRIVER_ANDROID
    8.23 +#undef SDL_VIDEO_DRIVER_EMSCRIPTEN
    8.24  #undef SDL_VIDEO_DRIVER_X11_DYNAMIC
    8.25  #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT
    8.26  #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR
    8.27 @@ -336,6 +339,7 @@
    8.28  #undef SDL_POWER_MACOSX
    8.29  #undef SDL_POWER_HAIKU
    8.30  #undef SDL_POWER_ANDROID
    8.31 +#undef SDL_POWER_EMSCRIPTEN
    8.32  #undef SDL_POWER_HARDWIRED
    8.33  
    8.34  /* Enable system filesystem support */
    8.35 @@ -345,6 +349,7 @@
    8.36  #undef SDL_FILESYSTEM_UNIX
    8.37  #undef SDL_FILESYSTEM_WINDOWS
    8.38  #undef SDL_FILESYSTEM_NACL
    8.39 +#undef SDL_FILESYSTEM_EMSCRIPTEN
    8.40  
    8.41  /* Enable assembly routines */
    8.42  #undef SDL_ASSEMBLY_ROUTINES
     9.1 --- a/include/SDL_hints.h	Sat Dec 13 02:33:52 2014 -0500
     9.2 +++ b/include/SDL_hints.h	Thu Dec 18 00:19:52 2014 -0500
     9.3 @@ -533,6 +533,20 @@
     9.4  #define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING"
     9.5  
     9.6  /**
     9.7 + *  \brief override the binding element for keyboard inputs for Emscripten builds
     9.8 + *
     9.9 + * This hint only applies to the emscripten platform
    9.10 + *
    9.11 + * The variable can be one of
    9.12 + *    "#window"      - The javascript window object (this is the default)
    9.13 + *    "#document"    - The javascript document object
    9.14 + *    "#screen"      - the javascript window.screen object
    9.15 + *    "#canvas"      - the WebGL canvas element
    9.16 + *    any other string without a leading # sign apples to the element on the page with that ID.
    9.17 + */
    9.18 +#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT   "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"
    9.19 +
    9.20 +/**
    9.21   *  \brief  An enumeration of hint priorities
    9.22   */
    9.23  typedef enum
    10.1 --- a/src/audio/SDL_audio.c	Sat Dec 13 02:33:52 2014 -0500
    10.2 +++ b/src/audio/SDL_audio.c	Thu Dec 18 00:19:52 2014 -0500
    10.3 @@ -71,6 +71,7 @@
    10.4  extern AudioBootStrap ANDROIDAUD_bootstrap;
    10.5  extern AudioBootStrap PSPAUD_bootstrap;
    10.6  extern AudioBootStrap SNDIO_bootstrap;
    10.7 +extern AudioBootStrap EmscriptenAudio_bootstrap;
    10.8  
    10.9  
   10.10  /* Available audio drivers */
   10.11 @@ -141,6 +142,9 @@
   10.12  #if SDL_AUDIO_DRIVER_PSP
   10.13      &PSPAUD_bootstrap,
   10.14  #endif
   10.15 +#if SDL_AUDIO_DRIVER_EMSCRIPTEN
   10.16 +    &EmscriptenAudio_bootstrap,
   10.17 +#endif
   10.18      NULL
   10.19  };
   10.20  
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/audio/emscripten/SDL_emscriptenaudio.c	Thu Dec 18 00:19:52 2014 -0500
    11.3 @@ -0,0 +1,271 @@
    11.4 +/*
    11.5 +  Simple DirectMedia Layer
    11.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    11.7 +
    11.8 +  This software is provided 'as-is', without any express or implied
    11.9 +  warranty.  In no event will the authors be held liable for any damages
   11.10 +  arising from the use of this software.
   11.11 +
   11.12 +  Permission is granted to anyone to use this software for any purpose,
   11.13 +  including commercial applications, and to alter it and redistribute it
   11.14 +  freely, subject to the following restrictions:
   11.15 +
   11.16 +  1. The origin of this software must not be misrepresented; you must not
   11.17 +     claim that you wrote the original software. If you use this software
   11.18 +     in a product, an acknowledgment in the product documentation would be
   11.19 +     appreciated but is not required.
   11.20 +  2. Altered source versions must be plainly marked as such, and must not be
   11.21 +     misrepresented as being the original software.
   11.22 +  3. This notice may not be removed or altered from any source distribution.
   11.23 +*/
   11.24 +#include "../../SDL_internal.h"
   11.25 +
   11.26 +#if SDL_AUDIO_DRIVER_EMSCRIPTEN
   11.27 +
   11.28 +#include "SDL_audio.h"
   11.29 +#include "SDL_log.h"
   11.30 +#include "../SDL_audio_c.h"
   11.31 +#include "SDL_emscriptenaudio.h"
   11.32 +
   11.33 +#include <emscripten/emscripten.h>
   11.34 +
   11.35 +static int
   11.36 +copyData(_THIS)
   11.37 +{
   11.38 +    int byte_len;
   11.39 +
   11.40 +    if (this->hidden->write_off + this->convert.len_cvt > this->hidden->mixlen) {
   11.41 +        if (this->hidden->write_off > this->hidden->read_off) {
   11.42 +            SDL_memmove(this->hidden->mixbuf,
   11.43 +                        this->hidden->mixbuf + this->hidden->read_off,
   11.44 +                        this->hidden->mixlen - this->hidden->read_off);
   11.45 +            this->hidden->write_off = this->hidden->write_off - this->hidden->read_off;
   11.46 +        } else {
   11.47 +            this->hidden->write_off = 0;
   11.48 +        }
   11.49 +        this->hidden->read_off = 0;
   11.50 +    }
   11.51 +
   11.52 +    SDL_memcpy(this->hidden->mixbuf + this->hidden->write_off,
   11.53 +               this->convert.buf,
   11.54 +               this->convert.len_cvt);
   11.55 +    this->hidden->write_off += this->convert.len_cvt;
   11.56 +    byte_len = this->hidden->write_off - this->hidden->read_off;
   11.57 +
   11.58 +    return byte_len;
   11.59 +}
   11.60 +
   11.61 +static void
   11.62 +HandleAudioProcess(_THIS)
   11.63 +{
   11.64 +    Uint8 *buf = NULL;
   11.65 +    int byte_len = 0;
   11.66 +    int bytes = SDL_AUDIO_BITSIZE(this->spec.format) / 8;
   11.67 +    int bytes_in = SDL_AUDIO_BITSIZE(this->convert.src_format) / 8;
   11.68 +    int i;
   11.69 +
   11.70 +    /* Only do soemthing if audio is enabled */
   11.71 +    if (!this->enabled)
   11.72 +        return;
   11.73 +
   11.74 +    if (this->paused)
   11.75 +        return;
   11.76 +
   11.77 +    if (this->convert.needed) {
   11.78 +        if (this->hidden->conv_in_len != 0) {
   11.79 +            this->convert.len = this->hidden->conv_in_len * bytes_in * this->spec.channels;
   11.80 +        }
   11.81 +
   11.82 +        (*this->spec.callback) (this->spec.userdata,
   11.83 +                                 this->convert.buf,
   11.84 +                                 this->convert.len);
   11.85 +        SDL_ConvertAudio(&this->convert);
   11.86 +        buf = this->convert.buf;
   11.87 +        byte_len = this->convert.len_cvt;
   11.88 +
   11.89 +        /* size mismatch*/
   11.90 +        if (byte_len != this->spec.size) {
   11.91 +            if (!this->hidden->mixbuf) {
   11.92 +                this->hidden->mixlen = this->spec.size > byte_len ? this->spec.size * 2 : byte_len * 2;
   11.93 +                this->hidden->mixbuf = SDL_malloc(this->hidden->mixlen);
   11.94 +            }
   11.95 +
   11.96 +            /* copy existing data */
   11.97 +            byte_len = copyData(this);
   11.98 +
   11.99 +            /* read more data*/
  11.100 +            while (byte_len < this->spec.size) {
  11.101 +                (*this->spec.callback) (this->spec.userdata,
  11.102 +                                         this->convert.buf,
  11.103 +                                         this->convert.len);
  11.104 +                SDL_ConvertAudio(&this->convert);
  11.105 +                byte_len = copyData(this);
  11.106 +            }
  11.107 +
  11.108 +            byte_len = this->spec.size;
  11.109 +            buf = this->hidden->mixbuf + this->hidden->read_off;
  11.110 +            this->hidden->read_off += byte_len;
  11.111 +        }
  11.112 +
  11.113 +    } else {
  11.114 +        if (!this->hidden->mixbuf) {
  11.115 +            this->hidden->mixlen = this->spec.size;
  11.116 +            this->hidden->mixbuf = SDL_malloc(this->hidden->mixlen);
  11.117 +        }
  11.118 +        (*this->spec.callback) (this->spec.userdata,
  11.119 +                                 this->hidden->mixbuf,
  11.120 +                                 this->hidden->mixlen);
  11.121 +        buf = this->hidden->mixbuf;
  11.122 +        byte_len = this->hidden->mixlen;
  11.123 +    }
  11.124 +
  11.125 +    if (buf) {
  11.126 +        EM_ASM_ARGS({
  11.127 +            var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels'];
  11.128 +            for (var c = 0; c < numChannels; ++c) {
  11.129 +                var channelData = SDL2.audio.currentOutputBuffer['getChannelData'](c);
  11.130 +                if (channelData.length != $1) {
  11.131 +                    throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
  11.132 +                }
  11.133 +
  11.134 +                for (var j = 0; j < $1; ++j) {
  11.135 +                    channelData[j] = getValue($0 + (j*numChannels + c)*4, 'float');
  11.136 +                }
  11.137 +            }
  11.138 +        }, buf, byte_len / bytes / this->spec.channels);
  11.139 +    }
  11.140 +}
  11.141 +
  11.142 +static void
  11.143 +Emscripten_CloseDevice(_THIS)
  11.144 +{
  11.145 +    if (this->hidden != NULL) {
  11.146 +        if (this->hidden->mixbuf != NULL) {
  11.147 +            /* Clean up the audio buffer */
  11.148 +            SDL_free(this->hidden->mixbuf);
  11.149 +            this->hidden->mixbuf = NULL;
  11.150 +        }
  11.151 +
  11.152 +        SDL_free(this->hidden);
  11.153 +        this->hidden = NULL;
  11.154 +    }
  11.155 +}
  11.156 +
  11.157 +static int
  11.158 +Emscripten_OpenDevice(_THIS, const char *devname, int iscapture)
  11.159 +{
  11.160 +    SDL_bool valid_format = SDL_FALSE;
  11.161 +    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
  11.162 +    int i;
  11.163 +    float f;
  11.164 +
  11.165 +    while ((!valid_format) && (test_format)) {
  11.166 +        switch (test_format) {
  11.167 +        case AUDIO_F32: /* web audio only supports floats */
  11.168 +            this->spec.format = test_format;
  11.169 +
  11.170 +            valid_format = SDL_TRUE;
  11.171 +            break;
  11.172 +        }
  11.173 +        test_format = SDL_NextAudioFormat();
  11.174 +    }
  11.175 +
  11.176 +    if (!valid_format) {
  11.177 +        /* Didn't find a compatible format :( */
  11.178 +        return SDL_SetError("No compatible audio format!");
  11.179 +    }
  11.180 +
  11.181 +    /* Initialize all variables that we clean on shutdown */
  11.182 +    this->hidden = (struct SDL_PrivateAudioData *)
  11.183 +        SDL_malloc((sizeof *this->hidden));
  11.184 +    if (this->hidden == NULL) {
  11.185 +        return SDL_OutOfMemory();
  11.186 +    }
  11.187 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  11.188 +
  11.189 +    /* based on parts of library_sdl.js */
  11.190 +
  11.191 +    /* create context (TODO: this puts stuff in the global namespace...)*/
  11.192 +    EM_ASM({
  11.193 +        if(typeof(SDL2) === 'undefined')
  11.194 +            SDL2 = {};
  11.195 +
  11.196 +        if(typeof(SDL2.audio) === 'undefined')
  11.197 +            SDL2.audio = {};
  11.198 +
  11.199 +        if (!SDL2.audioContext) {
  11.200 +            if (typeof(AudioContext) !== 'undefined') {
  11.201 +                SDL2.audioContext = new AudioContext();
  11.202 +            } else if (typeof(webkitAudioContext) !== 'undefined') {
  11.203 +                SDL2.audioContext = new webkitAudioContext();
  11.204 +            } else {
  11.205 +                throw 'Web Audio API is not available!';
  11.206 +            }
  11.207 +        }
  11.208 +    });
  11.209 +
  11.210 +    /* limit to native freq */
  11.211 +    int sampleRate = EM_ASM_INT_V({
  11.212 +        return SDL2.audioContext['sampleRate'];
  11.213 +    });
  11.214 +
  11.215 +    if(this->spec.freq != sampleRate) {
  11.216 +        for (i = this->spec.samples; i > 0; i--) {
  11.217 +            f = (float)i / (float)sampleRate * (float)this->spec.freq;
  11.218 +            if (SDL_floor(f) == f) {
  11.219 +                this->hidden->conv_in_len = SDL_floor(f);
  11.220 +                break;
  11.221 +            }
  11.222 +        }
  11.223 +
  11.224 +        this->spec.freq = sampleRate;
  11.225 +    }
  11.226 +
  11.227 +    SDL_CalculateAudioSpec(&this->spec);
  11.228 +
  11.229 +    /* setup a ScriptProcessorNode */
  11.230 +    EM_ASM_ARGS({
  11.231 +        SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
  11.232 +        SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
  11.233 +            SDL2.audio.currentOutputBuffer = e['outputBuffer'];
  11.234 +            Runtime.dynCall('vi', $2, [$3]);
  11.235 +        };
  11.236 +        SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']);
  11.237 +    }, this->spec.channels, this->spec.samples, HandleAudioProcess, this);
  11.238 +    return 0;
  11.239 +}
  11.240 +
  11.241 +static int
  11.242 +Emscripten_Init(SDL_AudioDriverImpl * impl)
  11.243 +{
  11.244 +    /* Set the function pointers */
  11.245 +    impl->OpenDevice = Emscripten_OpenDevice;
  11.246 +    impl->CloseDevice = Emscripten_CloseDevice;
  11.247 +
  11.248 +    /* only one output */
  11.249 +    impl->OnlyHasDefaultOutputDevice = 1;
  11.250 +
  11.251 +    /* no threads here */
  11.252 +    impl->SkipMixerLock = 1;
  11.253 +    impl->ProvidesOwnCallbackThread = 1;
  11.254 +
  11.255 +    /* check availability */
  11.256 +    int available = EM_ASM_INT_V({
  11.257 +        if (typeof(AudioContext) !== 'undefined') {
  11.258 +            return 1;
  11.259 +        } else if (typeof(webkitAudioContext) !== 'undefined') {
  11.260 +            return 1;
  11.261 +        }
  11.262 +        return 0;
  11.263 +    });
  11.264 +
  11.265 +    return available;
  11.266 +}
  11.267 +
  11.268 +AudioBootStrap EmscriptenAudio_bootstrap = {
  11.269 +    "emscripten", "SDL emscripten audio driver", Emscripten_Init, 0
  11.270 +};
  11.271 +
  11.272 +#endif /* SDL_AUDIO_DRIVER_EMSCRIPTEN */
  11.273 +
  11.274 +/* vi: set ts=4 sw=4 expandtab: */
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/audio/emscripten/SDL_emscriptenaudio.h	Thu Dec 18 00:19:52 2014 -0500
    12.3 @@ -0,0 +1,42 @@
    12.4 +/*
    12.5 +  Simple DirectMedia Layer
    12.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    12.7 +
    12.8 +  This software is provided 'as-is', without any express or implied
    12.9 +  warranty.  In no event will the authors be held liable for any damages
   12.10 +  arising from the use of this software.
   12.11 +
   12.12 +  Permission is granted to anyone to use this software for any purpose,
   12.13 +  including commercial applications, and to alter it and redistribute it
   12.14 +  freely, subject to the following restrictions:
   12.15 +
   12.16 +  1. The origin of this software must not be misrepresented; you must not
   12.17 +     claim that you wrote the original software. If you use this software
   12.18 +     in a product, an acknowledgment in the product documentation would be
   12.19 +     appreciated but is not required.
   12.20 +  2. Altered source versions must be plainly marked as such, and must not be
   12.21 +     misrepresented as being the original software.
   12.22 +  3. This notice may not be removed or altered from any source distribution.
   12.23 +*/
   12.24 +#include "../../SDL_internal.h"
   12.25 +
   12.26 +#ifndef _SDL_emscriptenaudio_h
   12.27 +#define _SDL_emscriptenaudio_h
   12.28 +
   12.29 +#include "../SDL_sysaudio.h"
   12.30 +
   12.31 +/* Hidden "this" pointer for the audio functions */
   12.32 +#define _THIS   SDL_AudioDevice *this
   12.33 +
   12.34 +struct SDL_PrivateAudioData
   12.35 +{
   12.36 +    Uint8 *mixbuf;
   12.37 +    Uint32 mixlen;
   12.38 +
   12.39 +    Uint32 conv_in_len;
   12.40 +
   12.41 +    Uint32 write_off, read_off;
   12.42 +};
   12.43 +
   12.44 +#endif /* _SDL_emscriptenaudio_h */
   12.45 +/* vi: set ts=4 sw=4 expandtab: */
    13.1 --- a/src/cpuinfo/SDL_cpuinfo.c	Sat Dec 13 02:33:52 2014 -0500
    13.2 +++ b/src/cpuinfo/SDL_cpuinfo.c	Thu Dec 18 00:19:52 2014 -0500
    13.3 @@ -79,6 +79,7 @@
    13.4  {
    13.5      int has_CPUID = 0;
    13.6  /* *INDENT-OFF* */
    13.7 +#ifndef SDL_CPUINFO_DISABLED
    13.8  #if defined(__GNUC__) && defined(i386)
    13.9      __asm__ (
   13.10  "        pushfl                      # Get original EFLAGS             \n"
   13.11 @@ -165,6 +166,7 @@
   13.12  "1:                            \n"
   13.13      );
   13.14  #endif
   13.15 +#endif
   13.16  /* *INDENT-ON* */
   13.17      return has_CPUID;
   13.18  }
   13.19 @@ -272,6 +274,7 @@
   13.20  CPU_haveAltiVec(void)
   13.21  {
   13.22      volatile int altivec = 0;
   13.23 +#ifndef SDL_CPUINFO_DISABLED
   13.24  #if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__))
   13.25  #ifdef __OpenBSD__
   13.26      int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC };
   13.27 @@ -292,6 +295,7 @@
   13.28      }
   13.29      signal(SIGILL, handler);
   13.30  #endif
   13.31 +#endif
   13.32      return altivec;
   13.33  }
   13.34  
   13.35 @@ -418,6 +422,7 @@
   13.36  SDL_GetCPUCount(void)
   13.37  {
   13.38      if (!SDL_CPUCount) {
   13.39 +#ifndef SDL_CPUINFO_DISABLED
   13.40  #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
   13.41          if (SDL_CPUCount <= 0) {
   13.42              SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN);
   13.43 @@ -436,6 +441,7 @@
   13.44              SDL_CPUCount = info.dwNumberOfProcessors;
   13.45          }
   13.46  #endif
   13.47 +#endif
   13.48          /* There has to be at least 1, right? :) */
   13.49          if (SDL_CPUCount <= 0) {
   13.50              SDL_CPUCount = 1;
   13.51 @@ -723,6 +729,7 @@
   13.52  SDL_GetSystemRAM(void)
   13.53  {
   13.54      if (!SDL_SystemRAM) {
   13.55 +#ifndef SDL_CPUINFO_DISABLED
   13.56  #if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
   13.57          if (SDL_SystemRAM <= 0) {
   13.58              SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024));
   13.59 @@ -757,6 +764,7 @@
   13.60              }
   13.61          }
   13.62  #endif
   13.63 +#endif
   13.64      }
   13.65      return SDL_SystemRAM;
   13.66  }
    14.1 --- a/src/dynapi/SDL_dynapi.h	Sat Dec 13 02:33:52 2014 -0500
    14.2 +++ b/src/dynapi/SDL_dynapi.h	Thu Dec 18 00:19:52 2014 -0500
    14.3 @@ -43,7 +43,7 @@
    14.4  #include "TargetConditionals.h"
    14.5  #endif
    14.6  
    14.7 -#if TARGET_OS_IPHONE || __native_client__  /* probably not useful on iOS or NACL. */
    14.8 +#if TARGET_OS_IPHONE || __native_client__ || __EMSCRIPTEN__  /* probably not useful on iOS, NACL or Emscripten. */
    14.9  #define SDL_DYNAMIC_API 0
   14.10  #elif SDL_BUILDING_WINRT /* probaly not useful on WinRT, given current .dll loading restrictions */
   14.11  #define SDL_DYNAMIC_API 0
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/filesystem/emscripten/SDL_sysfilesystem.c	Thu Dec 18 00:19:52 2014 -0500
    15.3 @@ -0,0 +1,68 @@
    15.4 +/*
    15.5 +  Simple DirectMedia Layer
    15.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    15.7 +
    15.8 +  This software is provided 'as-is', without any express or implied
    15.9 +  warranty.  In no event will the authors be held liable for any damages
   15.10 +  arising from the use of this software.
   15.11 +
   15.12 +  Permission is granted to anyone to use this software for any purpose,
   15.13 +  including commercial applications, and to alter it and redistribute it
   15.14 +  freely, subject to the following restrictions:
   15.15 +
   15.16 +  1. The origin of this software must not be misrepresented; you must not
   15.17 +     claim that you wrote the original software. If you use this software
   15.18 +     in a product, an acknowledgment in the product documentation would be
   15.19 +     appreciated but is not required.
   15.20 +  2. Altered source versions must be plainly marked as such, and must not be
   15.21 +     misrepresented as being the original software.
   15.22 +  3. This notice may not be removed or altered from any source distribution.
   15.23 +*/
   15.24 +#include "../../SDL_internal.h"
   15.25 +
   15.26 +#ifdef SDL_FILESYSTEM_EMSCRIPTEN
   15.27 +
   15.28 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
   15.29 +/* System dependent filesystem routines                                */
   15.30 +#include <errno.h>
   15.31 +#include <sys/stat.h>
   15.32 +
   15.33 +#include "SDL_error.h"
   15.34 +#include "SDL_filesystem.h"
   15.35 +
   15.36 +#include <emscripten/emscripten.h>
   15.37 +
   15.38 +char *
   15.39 +SDL_GetBasePath(void)
   15.40 +{
   15.41 +    char *retval = "/";
   15.42 +    return SDL_strdup(retval);
   15.43 +}
   15.44 +
   15.45 +char *
   15.46 +SDL_GetPrefPath(const char *org, const char *app)
   15.47 +{
   15.48 +    const char *append = "/libsdl/";
   15.49 +    char *retval;
   15.50 +    size_t len = 0;
   15.51 +
   15.52 +    len = SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3;
   15.53 +    retval = (char *) SDL_malloc(len);
   15.54 +    if (!retval) {
   15.55 +        SDL_OutOfMemory();
   15.56 +        return NULL;
   15.57 +    }
   15.58 +
   15.59 +    SDL_snprintf(retval, len, "%s%s/%s/", append, org, app);
   15.60 +
   15.61 +    if (mkdir(retval, 0700) != 0 && errno != EEXIST) {
   15.62 +        SDL_SetError("Couldn't create directory '%s': '%s'", retval, strerror(errno));
   15.63 +        return NULL;
   15.64 +    }
   15.65 +
   15.66 +    return retval;
   15.67 +}
   15.68 +
   15.69 +#endif /* SDL_FILESYSTEM_EMSCRIPTEN */
   15.70 +
   15.71 +/* vi: set ts=4 sw=4 expandtab: */
    16.1 --- a/src/joystick/SDL_gamecontroller.c	Sat Dec 13 02:33:52 2014 -0500
    16.2 +++ b/src/joystick/SDL_gamecontroller.c	Thu Dec 18 00:19:52 2014 -0500
    16.3 @@ -89,6 +89,7 @@
    16.4  
    16.5  static ControllerMapping_t *s_pSupportedControllers = NULL;
    16.6  static ControllerMapping_t *s_pXInputMapping = NULL;
    16.7 +static ControllerMapping_t *s_pEmscriptenMapping = NULL;
    16.8  
    16.9  /* The SDL game controller structure */
   16.10  struct _SDL_GameController
   16.11 @@ -263,7 +264,13 @@
   16.12          return s_pXInputMapping;
   16.13      }
   16.14      else
   16.15 -#endif /* SDL_JOYSTICK_XINPUT */
   16.16 +#endif
   16.17 +#if defined(SDL_JOYSTICK_EMSCRIPTEN)
   16.18 +    if (s_pEmscriptenMapping) {
   16.19 +        return s_pEmscriptenMapping;
   16.20 +    }
   16.21 +    else
   16.22 +#endif
   16.23      {
   16.24          SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID(device_index);
   16.25          return SDL_PrivateGetControllerMappingForGUID(&jGUID);
   16.26 @@ -668,6 +675,7 @@
   16.27      SDL_JoystickGUID jGUID;
   16.28      ControllerMapping_t *pControllerMapping;
   16.29      SDL_bool is_xinput_mapping = SDL_FALSE;
   16.30 +    SDL_bool is_emscripten_mapping = SDL_FALSE;
   16.31  
   16.32      if (!mappingString) {
   16.33          return SDL_InvalidParamError("mappingString");
   16.34 @@ -680,6 +688,9 @@
   16.35      if (!SDL_strcasecmp(pchGUID, "xinput")) {
   16.36          is_xinput_mapping = SDL_TRUE;
   16.37      }
   16.38 +    if (!SDL_strcasecmp(pchGUID, "emscripten")) {
   16.39 +        is_emscripten_mapping = SDL_TRUE;
   16.40 +    }
   16.41      jGUID = SDL_JoystickGetGUIDFromString(pchGUID);
   16.42      SDL_free(pchGUID);
   16.43  
   16.44 @@ -715,6 +726,9 @@
   16.45          if (is_xinput_mapping) {
   16.46              s_pXInputMapping = pControllerMapping;
   16.47          }
   16.48 +        if (is_emscripten_mapping) {
   16.49 +            s_pEmscriptenMapping = pControllerMapping;
   16.50 +        }
   16.51          pControllerMapping->guid = jGUID;
   16.52          pControllerMapping->name = pchName;
   16.53          pControllerMapping->mapping = pchMapping;
    17.1 --- a/src/joystick/SDL_gamecontrollerdb.h	Sat Dec 13 02:33:52 2014 -0500
    17.2 +++ b/src/joystick/SDL_gamecontrollerdb.h	Thu Dec 18 00:19:52 2014 -0500
    17.3 @@ -76,6 +76,8 @@
    17.4  #endif
    17.5  #if defined(__ANDROID__)
    17.6      "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
    17.7 +#elif defined(SDL_JOYSTICK_EMSCRIPTEN)
    17.8 +    "emscripten,Standard Gamepad,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,back:b8,start:b9,leftstick:b10,rightstick:b11,dpup:b12,dpdown:b13,dpleft:b14,dpright:b15,guide:b16,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
    17.9  #endif
   17.10      NULL
   17.11  };
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/src/joystick/emscripten/SDL_sysjoystick.c	Thu Dec 18 00:19:52 2014 -0500
    18.3 @@ -0,0 +1,426 @@
    18.4 +/*
    18.5 +  Simple DirectMedia Layer
    18.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    18.7 +
    18.8 +  This software is provided 'as-is', without any express or implied
    18.9 +  warranty.  In no event will the authors be held liable for any damages
   18.10 +  arising from the use of this software.
   18.11 +
   18.12 +  Permission is granted to anyone to use this software for any purpose,
   18.13 +  including commercial applications, and to alter it and redistribute it
   18.14 +  freely, subject to the following restrictions:
   18.15 +
   18.16 +  1. The origin of this software must not be misrepresented; you must not
   18.17 +     claim that you wrote the original software. If you use this software
   18.18 +     in a product, an acknowledgment in the product documentation would be
   18.19 +     appreciated but is not required.
   18.20 +  2. Altered source versions must be plainly marked as such, and must not be
   18.21 +     misrepresented as being the original software.
   18.22 +  3. This notice may not be removed or altered from any source distribution.
   18.23 +*/
   18.24 +
   18.25 +#include "../../SDL_internal.h"
   18.26 +
   18.27 +#ifdef SDL_JOYSTICK_EMSCRIPTEN
   18.28 +
   18.29 +#include <stdio.h>              /* For the definition of NULL */
   18.30 +#include "SDL_error.h"
   18.31 +#include "SDL_events.h"
   18.32 +
   18.33 +#if !SDL_EVENTS_DISABLED
   18.34 +#include "../../events/SDL_events_c.h"
   18.35 +#endif
   18.36 +
   18.37 +#include "SDL_joystick.h"
   18.38 +#include "SDL_hints.h"
   18.39 +#include "SDL_assert.h"
   18.40 +#include "SDL_timer.h"
   18.41 +#include "SDL_log.h"
   18.42 +#include "SDL_sysjoystick_c.h"
   18.43 +#include "../SDL_joystick_c.h"
   18.44 +
   18.45 +static SDL_joylist_item * JoystickByIndex(int index);
   18.46 +
   18.47 +static SDL_joylist_item *SDL_joylist = NULL;
   18.48 +static SDL_joylist_item *SDL_joylist_tail = NULL;
   18.49 +static int numjoysticks = 0;
   18.50 +static int instance_counter = 0;
   18.51 +
   18.52 +int
   18.53 +Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
   18.54 +{
   18.55 +    int i;
   18.56 +
   18.57 +    SDL_joylist_item *item;
   18.58 +
   18.59 +    if (JoystickByIndex(gamepadEvent->index) != NULL) {
   18.60 +      return 1;
   18.61 +    }
   18.62 +
   18.63 +#if !SDL_EVENTS_DISABLED
   18.64 +    SDL_Event event;
   18.65 +#endif
   18.66 +
   18.67 +    item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
   18.68 +    if (item == NULL) {
   18.69 +        return 1;
   18.70 +    }
   18.71 +
   18.72 +    SDL_zerop(item);
   18.73 +    item->index = gamepadEvent->index;
   18.74 +
   18.75 +    item->name = SDL_strdup(gamepadEvent->id);
   18.76 +    if ( item->name == NULL ) {
   18.77 +        SDL_free(item);
   18.78 +        return 1;
   18.79 +    }
   18.80 +
   18.81 +    item->mapping = SDL_strdup(gamepadEvent->mapping);
   18.82 +    if ( item->mapping == NULL ) {
   18.83 +        SDL_free(item->name);
   18.84 +        SDL_free(item);
   18.85 +        return 1;
   18.86 +    }
   18.87 +
   18.88 +    item->naxes = gamepadEvent->numAxes;
   18.89 +    item->nbuttons = gamepadEvent->numButtons;
   18.90 +    item->device_instance = instance_counter++;
   18.91 +
   18.92 +    item->timestamp = gamepadEvent->timestamp;
   18.93 +
   18.94 +    for( i = 0; i < item->naxes; i++) {
   18.95 +        item->axis[i] = gamepadEvent->axis[i];
   18.96 +    }
   18.97 +
   18.98 +    for( i = 0; i < item->nbuttons; i++) {
   18.99 +        item->analogButton[i] = gamepadEvent->analogButton[i];
  18.100 +        item->digitalButton[i] = gamepadEvent->digitalButton[i];
  18.101 +    }
  18.102 +
  18.103 +    if (SDL_joylist_tail == NULL) {
  18.104 +        SDL_joylist = SDL_joylist_tail = item;
  18.105 +    } else {
  18.106 +        SDL_joylist_tail->next = item;
  18.107 +        SDL_joylist_tail = item;
  18.108 +    }
  18.109 +
  18.110 +    ++numjoysticks;
  18.111 +    SDL_Log("%d",numjoysticks);
  18.112 +#if !SDL_EVENTS_DISABLED
  18.113 +    event.type = SDL_JOYDEVICEADDED;
  18.114 +
  18.115 +    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  18.116 +        event.jdevice.which = item->device_instance - 1;
  18.117 +        if ( (SDL_EventOK == NULL) ||
  18.118 +             (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
  18.119 +            SDL_PushEvent(&event);
  18.120 +        }
  18.121 +    }
  18.122 +#endif /* !SDL_EVENTS_DISABLED */
  18.123 +
  18.124 +    SDL_Log("Added joystick with index %d", item->index);
  18.125 +
  18.126 +    return 1;
  18.127 +}
  18.128 +
  18.129 +int
  18.130 +Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
  18.131 +{
  18.132 +    SDL_joylist_item *item = SDL_joylist;
  18.133 +    SDL_joylist_item *prev = NULL;
  18.134 +#if !SDL_EVENTS_DISABLED
  18.135 +    SDL_Event event;
  18.136 +#endif
  18.137 +
  18.138 +    while (item != NULL) {
  18.139 +        if (item->index == gamepadEvent->index) {
  18.140 +            break;
  18.141 +        }
  18.142 +        prev = item;
  18.143 +        item = item->next;
  18.144 +    }
  18.145 +
  18.146 +    if (item == NULL) {
  18.147 +        return 1;
  18.148 +    }
  18.149 +
  18.150 +    const int retval = item->device_instance;
  18.151 +    if (item->joystick) {
  18.152 +        item->joystick->hwdata = NULL;
  18.153 +    }
  18.154 +
  18.155 +    if (prev != NULL) {
  18.156 +        prev->next = item->next;
  18.157 +    } else {
  18.158 +        SDL_assert(SDL_joylist == item);
  18.159 +        SDL_joylist = item->next;
  18.160 +    }
  18.161 +    if (item == SDL_joylist_tail) {
  18.162 +        SDL_joylist_tail = prev;
  18.163 +    }
  18.164 +
  18.165 +    /* Need to decrement the joystick count before we post the event */
  18.166 +    --numjoysticks;
  18.167 +
  18.168 +#if !SDL_EVENTS_DISABLED
  18.169 +    event.type = SDL_JOYDEVICEREMOVED;
  18.170 +
  18.171 +    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  18.172 +        event.jdevice.which = item->device_instance;
  18.173 +        if ( (SDL_EventOK == NULL) ||
  18.174 +             (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
  18.175 +            SDL_PushEvent(&event);
  18.176 +        }
  18.177 +    }
  18.178 +#endif /* !SDL_EVENTS_DISABLED */
  18.179 +
  18.180 +    SDL_Log("Removed joystick with index %d", retval);
  18.181 +    SDL_free(item->name);
  18.182 +    SDL_free(item->mapping);
  18.183 +    SDL_free(item);
  18.184 +    return 1;
  18.185 +}
  18.186 +
  18.187 +/* Function to scan the system for joysticks.
  18.188 + * It should return 0, or -1 on an unrecoverable fatal error.
  18.189 + */
  18.190 +int
  18.191 +SDL_SYS_JoystickInit(void)
  18.192 +{
  18.193 +    int retval, i, numjs;
  18.194 +    EmscriptenGamepadEvent gamepadState;
  18.195 +
  18.196 +    numjoysticks = 0;
  18.197 +    numjs = emscripten_get_num_gamepads();
  18.198 +
  18.199 +    /* Check if gamepad is supported by browser */
  18.200 +    if (numjs == EMSCRIPTEN_RESULT_NOT_SUPPORTED) {
  18.201 +        return -1;
  18.202 +    }
  18.203 +
  18.204 +    /* handle already connected gamepads */
  18.205 +    if (numjs > 0) {
  18.206 +        for(i = 0; i < numjs; i++) {
  18.207 +            retval = emscripten_get_gamepad_status(i, &gamepadState);
  18.208 +            if (retval == EMSCRIPTEN_RESULT_SUCCESS) {
  18.209 +                Emscripten_JoyStickConnected(EMSCRIPTEN_EVENT_GAMEPADCONNECTED,
  18.210 +                                             &gamepadState,
  18.211 +                                             NULL);
  18.212 +            }
  18.213 +        }
  18.214 +    }
  18.215 +
  18.216 +    retval = emscripten_set_gamepadconnected_callback(NULL,
  18.217 +                                                      0,
  18.218 +                                                      Emscripten_JoyStickConnected);
  18.219 +
  18.220 +    if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
  18.221 +        return -1;
  18.222 +    }
  18.223 +
  18.224 +    retval = emscripten_set_gamepaddisconnected_callback(NULL,
  18.225 +                                                         0,
  18.226 +                                                         Emscripten_JoyStickDisconnected);
  18.227 +    if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
  18.228 +        return -1;
  18.229 +    }
  18.230 +
  18.231 +    return 0;
  18.232 +}
  18.233 +
  18.234 +static SDL_joylist_item *
  18.235 +JoystickByIndex(int index)
  18.236 +{
  18.237 +    SDL_joylist_item *item = SDL_joylist;
  18.238 +
  18.239 +    if (index < 0) {
  18.240 +        return NULL;
  18.241 +    }
  18.242 +
  18.243 +    while (item != NULL) {
  18.244 +        if (item->index == index) {
  18.245 +            break;
  18.246 +        }
  18.247 +        item = item->next;
  18.248 +    }
  18.249 +
  18.250 +    return item;
  18.251 +}
  18.252 +
  18.253 +int SDL_SYS_NumJoysticks()
  18.254 +{
  18.255 +    return numjoysticks;
  18.256 +}
  18.257 +
  18.258 +void SDL_SYS_JoystickDetect()
  18.259 +{
  18.260 +}
  18.261 +
  18.262 +// we need to poll to see if the gamepad state has changed
  18.263 +SDL_bool SDL_SYS_JoystickNeedsPolling()
  18.264 +{
  18.265 +    return SDL_TRUE;
  18.266 +}
  18.267 +
  18.268 +/* Function to get the device-dependent name of a joystick */
  18.269 +const char *
  18.270 +SDL_SYS_JoystickNameForDeviceIndex(int index)
  18.271 +{
  18.272 +    SDL_joylist_item *item = JoystickByIndex(index);
  18.273 +    if (item == NULL) {
  18.274 +        SDL_SetError("Joystick with index %d not found", index);
  18.275 +        return NULL;
  18.276 +    }
  18.277 +
  18.278 +    return item->name;
  18.279 +}
  18.280 +
  18.281 +/* Function to perform the mapping from device index to the instance id for this index */
  18.282 +SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int index)
  18.283 +{
  18.284 +    SDL_joylist_item *item = JoystickByIndex(index);
  18.285 +    if (item == NULL) {
  18.286 +        SDL_SetError("Joystick with index %d not found", index);
  18.287 +        return NULL;
  18.288 +    }
  18.289 +
  18.290 +    return item->device_instance;
  18.291 +}
  18.292 +
  18.293 +/* Function to open a joystick for use.
  18.294 +   The joystick to open is specified by the index field of the joystick.
  18.295 +   This should fill the nbuttons and naxes fields of the joystick structure.
  18.296 +   It returns 0, or -1 if there is an error.
  18.297 + */
  18.298 +int
  18.299 +SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int index)
  18.300 +{
  18.301 +    SDL_joylist_item *item = JoystickByIndex(index);
  18.302 +
  18.303 +    if (item == NULL ) {
  18.304 +        return SDL_SetError("No such device");
  18.305 +    }
  18.306 +
  18.307 +    if (item->joystick != NULL) {
  18.308 +        return SDL_SetError("Joystick already opened");
  18.309 +    }
  18.310 +
  18.311 +    joystick->instance_id = item->device_instance;
  18.312 +    joystick->hwdata = (struct joystick_hwdata *) item;
  18.313 +    item->joystick = joystick;
  18.314 +
  18.315 +    /* HTML5 Gamepad API doesn't say anything about these */
  18.316 +    joystick->nhats = 0;
  18.317 +    joystick->nballs = 0;
  18.318 +
  18.319 +    joystick->nbuttons = item->nbuttons;
  18.320 +    joystick->naxes = item->naxes;
  18.321 +
  18.322 +    return (0);
  18.323 +}
  18.324 +
  18.325 +/* Function to determine is this joystick is attached to the system right now */
  18.326 +SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
  18.327 +{
  18.328 +    return !joystick->closed && (joystick->hwdata != NULL);
  18.329 +}
  18.330 +
  18.331 +/* Function to update the state of a joystick - called as a device poll.
  18.332 + * This function shouldn't update the joystick structure directly,
  18.333 + * but instead should call SDL_PrivateJoystick*() to deliver events
  18.334 + * and update joystick device state.
  18.335 + */
  18.336 +void
  18.337 +SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
  18.338 +{
  18.339 +    EmscriptenGamepadEvent gamepadState;
  18.340 +    SDL_joylist_item *item = SDL_joylist;
  18.341 +    int i, result, button, buttonState;
  18.342 +
  18.343 +    while (item != NULL) {
  18.344 +        result = emscripten_get_gamepad_status(item->index, &gamepadState);
  18.345 +        if( result == EMSCRIPTEN_RESULT_SUCCESS) {
  18.346 +            if(gamepadState.timestamp == 0 || gamepadState.timestamp != item->timestamp) {
  18.347 +                for(i = 0; i < item->nbuttons; i++) {
  18.348 +                    if(item->digitalButton[i] != gamepadState.digitalButton[i]) {
  18.349 +                        buttonState = gamepadState.digitalButton[i]? SDL_PRESSED: SDL_RELEASED;
  18.350 +                        SDL_PrivateJoystickButton(item->joystick, i, buttonState);
  18.351 +                    }
  18.352 +                }
  18.353 +
  18.354 +                for(i = 0; i < item->naxes; i++) {
  18.355 +                    if(item->axis[i] != gamepadState.axis[i]) {
  18.356 +                        // do we need to do conversion?
  18.357 +                        SDL_PrivateJoystickAxis(item->joystick, i,
  18.358 +                                                  (Sint16) (32767.*gamepadState.axis[i]));
  18.359 +                    }
  18.360 +                }
  18.361 +
  18.362 +                item->timestamp = gamepadState.timestamp;
  18.363 +                for( i = 0; i < item->naxes; i++) {
  18.364 +                    item->axis[i] = gamepadState.axis[i];
  18.365 +                }
  18.366 +
  18.367 +                for( i = 0; i < item->nbuttons; i++) {
  18.368 +                    item->analogButton[i] = gamepadState.analogButton[i];
  18.369 +                    item->digitalButton[i] = gamepadState.digitalButton[i];
  18.370 +                }
  18.371 +            }
  18.372 +        }
  18.373 +        item = item->next;
  18.374 +    }
  18.375 +}
  18.376 +
  18.377 +/* Function to close a joystick after use */
  18.378 +void
  18.379 +SDL_SYS_JoystickClose(SDL_Joystick * joystick)
  18.380 +{
  18.381 +    if (joystick->hwdata) {
  18.382 +        ((SDL_joylist_item*)joystick->hwdata)->joystick = NULL;
  18.383 +        joystick->hwdata = NULL;
  18.384 +    }
  18.385 +    joystick->closed = 1;
  18.386 +}
  18.387 +
  18.388 +/* Function to perform any system-specific joystick related cleanup */
  18.389 +void
  18.390 +SDL_SYS_JoystickQuit(void)
  18.391 +{
  18.392 +    SDL_joylist_item *item = NULL;
  18.393 +    SDL_joylist_item *next = NULL;
  18.394 +
  18.395 +    for (item = SDL_joylist; item; item = next) {
  18.396 +        next = item->next;
  18.397 +        SDL_free(item->mapping);
  18.398 +        SDL_free(item->name);
  18.399 +        SDL_free(item);
  18.400 +    }
  18.401 +
  18.402 +    SDL_joylist = SDL_joylist_tail = NULL;
  18.403 +
  18.404 +    numjoysticks = 0;
  18.405 +    instance_counter = 0;
  18.406 +}
  18.407 +
  18.408 +SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int index)
  18.409 +{
  18.410 +    SDL_JoystickGUID guid;
  18.411 +    /* the GUID is just the first 16 chars of the name for now */
  18.412 +    const char *name = SDL_SYS_JoystickNameForDeviceIndex(index);
  18.413 +    SDL_zero(guid);
  18.414 +    SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name)));
  18.415 +    return guid;
  18.416 +}
  18.417 +
  18.418 +
  18.419 +SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
  18.420 +{
  18.421 +    SDL_JoystickGUID guid;
  18.422 +    /* the GUID is just the first 16 chars of the name for now */
  18.423 +    const char *name = joystick->name;
  18.424 +    SDL_zero(guid);
  18.425 +    SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name)));
  18.426 +    return guid;
  18.427 +}
  18.428 +
  18.429 +#endif /* SDL_JOYSTICK_EMSCRIPTEN */
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/src/joystick/emscripten/SDL_sysjoystick_c.h	Thu Dec 18 00:19:52 2014 -0500
    19.3 @@ -0,0 +1,76 @@
    19.4 +/*
    19.5 + Simple DirectMedia Layer
    19.6 + Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    19.7 +
    19.8 + This software is provided 'as-is', without any express or implied
    19.9 + warranty.  In no event will the authors be held liable for any damages
   19.10 + arising from the use of this software.
   19.11 +
   19.12 + Permission is granted to anyone to use this software for any purpose,
   19.13 + including commercial applications, and to alter it and redistribute it
   19.14 + freely, subject to the following restrictions:
   19.15 +
   19.16 + 1. The origin of this software must not be misrepresented; you must not
   19.17 + claim that you wrote the original software. If you use this software
   19.18 + in a product, an acknowledgment in the product documentation would be
   19.19 + appreciated but is not required.
   19.20 + 2. Altered source versions must be plainly marked as such, and must not be
   19.21 + misrepresented as being the original software.
   19.22 + 3. This notice may not be removed or altered from any source distribution.
   19.23 + */
   19.24 +
   19.25 +#include "SDL_config.h"
   19.26 +
   19.27 +#ifdef SDL_JOYSTICK_EMSCRIPTEN
   19.28 +#include "../SDL_sysjoystick.h"
   19.29 +
   19.30 +
   19.31 +#include <emscripten/html5.h>
   19.32 +
   19.33 +typedef enum
   19.34 +{
   19.35 +    EMSCRIPTEN_CONTROLLER_BUTTON_INVALID = -1,
   19.36 +    EMSCRIPTEN_CONTROLLER_BUTTON_A,
   19.37 +    EMSCRIPTEN_CONTROLLER_BUTTON_B,
   19.38 +    EMSCRIPTEN_CONTROLLER_BUTTON_X,
   19.39 +    EMSCRIPTEN_CONTROLLER_BUTTON_Y,
   19.40 +    EMSCRIPTEN_CONTROLLER_BUTTON_L1,
   19.41 +    EMSCRIPTEN_CONTROLLER_BUTTON_R1,
   19.42 +    EMSCRIPTEN_CONTROLLER_BUTTON_L2,
   19.43 +    EMSCRIPTEN_CONTROLLER_BUTTON_R2,
   19.44 +    EMSCRIPTEN_CONTROLLER_BUTTON_BACK,
   19.45 +    EMSCRIPTEN_CONTROLLER_BUTTON_START,
   19.46 +    EMSCRIPTEN_CONTROLLER_BUTTON_LEFTSTICK,
   19.47 +    EMSCRIPTEN_CONTROLLER_BUTTON_RIGHTSTICK,
   19.48 +    EMSCRIPTEN_CONTROLLER_DPAD_UP,
   19.49 +    EMSCRIPTEN_CONTROLLER_DPAD_DOWN,
   19.50 +    EMSCRIPTEN_CONTROLLER_DPAD_LEFT,
   19.51 +    EMSCRIPTEN_CONTROLLER_DPAD_RIGHT,
   19.52 +    EMSCRIPTEN_CONTROLLER_BUTTON_GUIDE,
   19.53 +} Emscripten_GameControllerButton;
   19.54 +
   19.55 +static int EMSCRIPTEN_MAX_NBUTTONS = 18;
   19.56 +
   19.57 +/* A linked list of available joysticks */
   19.58 +typedef struct SDL_joylist_item
   19.59 +{
   19.60 +  int index;
   19.61 +  char *name;
   19.62 +  char *mapping;
   19.63 +  SDL_JoystickID device_instance;
   19.64 +  SDL_Joystick *joystick;
   19.65 +  int nbuttons;
   19.66 +  int naxes;
   19.67 +  double timestamp;
   19.68 +  double axis[64];
   19.69 +  double analogButton[64];
   19.70 +  EM_BOOL digitalButton[64];
   19.71 +
   19.72 +  struct SDL_joylist_item *next;
   19.73 +} SDL_joylist_item;
   19.74 +
   19.75 +typedef SDL_joylist_item joystick_hwdata;
   19.76 +
   19.77 +#endif /* SDL_JOYSTICK_EMSCRIPTEN */
   19.78 +
   19.79 +/* vi: set ts=4 sw=4 expandtab: */
    20.1 --- a/src/power/SDL_power.c	Sat Dec 13 02:33:52 2014 -0500
    20.2 +++ b/src/power/SDL_power.c	Thu Dec 18 00:19:52 2014 -0500
    20.3 @@ -38,6 +38,7 @@
    20.4  SDL_bool SDL_GetPowerInfo_Android(SDL_PowerState *, int *, int *);
    20.5  SDL_bool SDL_GetPowerInfo_PSP(SDL_PowerState *, int *, int *);
    20.6  SDL_bool SDL_GetPowerInfo_WinRT(SDL_PowerState *, int *, int *);
    20.7 +SDL_bool SDL_GetPowerInfo_Emscripten(SDL_PowerState *, int *, int *);
    20.8  
    20.9  #ifndef SDL_POWER_DISABLED
   20.10  #ifdef SDL_POWER_HARDWIRED
   20.11 @@ -81,6 +82,9 @@
   20.12  #ifdef SDL_POWER_WINRT          /* handles WinRT */
   20.13      SDL_GetPowerInfo_WinRT,
   20.14  #endif
   20.15 +#ifdef SDL_POWER_EMSCRIPTEN     /* handles Emscripten */
   20.16 +    SDL_GetPowerInfo_Emscripten,
   20.17 +#endif
   20.18  
   20.19  #ifdef SDL_POWER_HARDWIRED
   20.20      SDL_GetPowerInfo_Hardwired,
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/power/emscripten/SDL_syspower.c	Thu Dec 18 00:19:52 2014 -0500
    21.3 @@ -0,0 +1,62 @@
    21.4 +/*
    21.5 +  Simple DirectMedia Layer
    21.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    21.7 +
    21.8 +  This software is provided 'as-is', without any express or implied
    21.9 +  warranty.  In no event will the authors be held liable for any damages
   21.10 +  arising from the use of this software.
   21.11 +
   21.12 +  Permission is granted to anyone to use this software for any purpose,
   21.13 +  including commercial applications, and to alter it and redistribute it
   21.14 +  freely, subject to the following restrictions:
   21.15 +
   21.16 +  1. The origin of this software must not be misrepresented; you must not
   21.17 +     claim that you wrote the original software. If you use this software
   21.18 +     in a product, an acknowledgment in the product documentation would be
   21.19 +     appreciated but is not required.
   21.20 +  2. Altered source versions must be plainly marked as such, and must not be
   21.21 +     misrepresented as being the original software.
   21.22 +  3. This notice may not be removed or altered from any source distribution.
   21.23 +*/
   21.24 +#include "../../SDL_internal.h"
   21.25 +
   21.26 +#ifndef SDL_POWER_DISABLED
   21.27 +#if SDL_POWER_EMSCRIPTEN
   21.28 +
   21.29 +#include <emscripten/html5.h>
   21.30 +
   21.31 +#include "SDL_power.h"
   21.32 +
   21.33 +SDL_bool
   21.34 +SDL_GetPowerInfo_Emscripten(SDL_PowerState *state, int *seconds, int *percent)
   21.35 +{
   21.36 +    EmscriptenBatteryEvent batteryState;
   21.37 +    int haveBattery = 0;
   21.38 +
   21.39 +    if (emscripten_get_battery_status(&batteryState) == EMSCRIPTEN_RESULT_NOT_SUPPORTED)
   21.40 +        return SDL_FALSE;
   21.41 +
   21.42 +    haveBattery = batteryState.level != 1.0 || !batteryState.charging || batteryState.chargingTime != 0.0;
   21.43 +
   21.44 +    if (!haveBattery) {
   21.45 +        *state = SDL_POWERSTATE_NO_BATTERY;
   21.46 +        *seconds = -1;
   21.47 +        *percent = -1;
   21.48 +        return SDL_TRUE;
   21.49 +    }
   21.50 +
   21.51 +    if (batteryState.charging)
   21.52 +        *state = batteryState.chargingTime == 0.0 ? SDL_POWERSTATE_CHARGED : SDL_POWERSTATE_CHARGING;
   21.53 +    else
   21.54 +        *state = SDL_POWERSTATE_ON_BATTERY;
   21.55 +
   21.56 +    *seconds = batteryState.dischargingTime;
   21.57 +    *percent = batteryState.level * 100;
   21.58 +
   21.59 +    return SDL_TRUE;
   21.60 +}
   21.61 +
   21.62 +#endif /* SDL_POWER_EMSCRIPTEN */
   21.63 +#endif /* SDL_POWER_DISABLED */
   21.64 +
   21.65 +/* vi: set ts=4 sw=4 expandtab: */
    22.1 --- a/src/render/opengles2/SDL_gles2funcs.h	Sat Dec 13 02:33:52 2014 -0500
    22.2 +++ b/src/render/opengles2/SDL_gles2funcs.h	Thu Dec 18 00:19:52 2014 -0500
    22.3 @@ -69,3 +69,7 @@
    22.4  SDL_PROC(void, glDeleteFramebuffers, (GLsizei, const GLuint *))
    22.5  SDL_PROC(GLint, glGetAttribLocation, (GLuint, const GLchar *))
    22.6  SDL_PROC(void, glGetProgramInfoLog, (GLuint, GLsizei, GLsizei*, GLchar*))
    22.7 +SDL_PROC(void, glGenBuffers, (GLsizei, GLuint *))
    22.8 +SDL_PROC(void, glBindBuffer, (GLenum, GLuint))
    22.9 +SDL_PROC(void, glBufferData, (GLenum, GLsizeiptr, const GLvoid *, GLenum))
   22.10 +SDL_PROC(void, glBufferSubData, (GLenum, GLintptr, GLsizeiptr, const GLvoid *))
    23.1 --- a/src/render/opengles2/SDL_render_gles2.c	Sat Dec 13 02:33:52 2014 -0500
    23.2 +++ b/src/render/opengles2/SDL_render_gles2.c	Thu Dec 18 00:19:52 2014 -0500
    23.3 @@ -180,6 +180,9 @@
    23.4      GLES2_ProgramCache program_cache;
    23.5      GLES2_ProgramCacheEntry *current_program;
    23.6      Uint8 clear_r, clear_g, clear_b, clear_a;
    23.7 +
    23.8 +    GLuint vertex_buffers[4];
    23.9 +    GLsizeiptr vertex_buffer_size[4];
   23.10  } GLES2_DriverContext;
   23.11  
   23.12  #define GLES2_MAX_CACHED_PROGRAMS 8
   23.13 @@ -1386,6 +1389,32 @@
   23.14  }
   23.15  
   23.16  static int
   23.17 +GLES2_UpdateVertexBuffer(SDL_Renderer *renderer, GLES2_Attribute attr,
   23.18 +                         const void *vertexData, size_t dataSizeInBytes)
   23.19 +{
   23.20 +    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
   23.21 +#if 0
   23.22 +    data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, vertexData);
   23.23 +#else
   23.24 +
   23.25 +    if (!data->vertex_buffers[attr])
   23.26 +        data->glGenBuffers(1, &data->vertex_buffers[attr]);
   23.27 +
   23.28 +    data->glBindBuffer(GL_ARRAY_BUFFER, data->vertex_buffers[attr]);
   23.29 +
   23.30 +    if (data->vertex_buffer_size[attr] < dataSizeInBytes) {
   23.31 +        data->glBufferData(GL_ARRAY_BUFFER, dataSizeInBytes, vertexData, GL_STREAM_DRAW);
   23.32 +        data->vertex_buffer_size[attr] = dataSizeInBytes;
   23.33 +    } else {
   23.34 +        data->glBufferSubData(GL_ARRAY_BUFFER, 0, dataSizeInBytes, vertexData);
   23.35 +    }
   23.36 +
   23.37 +    data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, 0);
   23.38 +#endif
   23.39 +    return 0;
   23.40 +}
   23.41 +
   23.42 +static int
   23.43  GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
   23.44  {
   23.45      GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
   23.46 @@ -1405,7 +1434,8 @@
   23.47          vertices[idx * 2] = x;
   23.48          vertices[(idx * 2) + 1] = y;
   23.49      }
   23.50 -    data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
   23.51 +    /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
   23.52 +    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat));
   23.53      data->glDrawArrays(GL_POINTS, 0, count);
   23.54      SDL_stack_free(vertices);
   23.55      return 0;
   23.56 @@ -1431,7 +1461,8 @@
   23.57          vertices[idx * 2] = x;
   23.58          vertices[(idx * 2) + 1] = y;
   23.59      }
   23.60 -    data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
   23.61 +    /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
   23.62 +    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat));
   23.63      data->glDrawArrays(GL_LINE_STRIP, 0, count);
   23.64  
   23.65      /* We need to close the endpoint of the line */
   23.66 @@ -1472,7 +1503,8 @@
   23.67          vertices[5] = yMax;
   23.68          vertices[6] = xMax;
   23.69          vertices[7] = yMax;
   23.70 -        data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
   23.71 +        /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
   23.72 +        GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
   23.73          data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   23.74      }
   23.75      return GL_CheckError("", renderer);
   23.76 @@ -1668,7 +1700,8 @@
   23.77      vertices[5] = (dstrect->y + dstrect->h);
   23.78      vertices[6] = (dstrect->x + dstrect->w);
   23.79      vertices[7] = (dstrect->y + dstrect->h);
   23.80 -    data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
   23.81 +    /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
   23.82 +    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
   23.83      texCoords[0] = srcrect->x / (GLfloat)texture->w;
   23.84      texCoords[1] = srcrect->y / (GLfloat)texture->h;
   23.85      texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
   23.86 @@ -1677,7 +1710,8 @@
   23.87      texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
   23.88      texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
   23.89      texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
   23.90 -    data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
   23.91 +    /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/
   23.92 +    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat));
   23.93      data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   23.94  
   23.95      return GL_CheckError("", renderer);
   23.96 @@ -1727,9 +1761,13 @@
   23.97          vertices[5] = vertices[7] = tmp;
   23.98      }
   23.99  
  23.100 -    data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
  23.101 +    /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
  23.102      data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
  23.103 -    data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
  23.104 +    data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
  23.105 +
  23.106 +    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 4 * sizeof(GLfloat));
  23.107 +    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_CENTER, translate, 8 * sizeof(GLfloat));
  23.108 +    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
  23.109  
  23.110      texCoords[0] = srcrect->x / (GLfloat)texture->w;
  23.111      texCoords[1] = srcrect->y / (GLfloat)texture->h;
  23.112 @@ -1739,7 +1777,8 @@
  23.113      texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  23.114      texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  23.115      texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  23.116 -    data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
  23.117 +    /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/
  23.118 +    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat));
  23.119      data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  23.120      data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
  23.121      data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
    24.1 --- a/src/video/SDL_sysvideo.h	Sat Dec 13 02:33:52 2014 -0500
    24.2 +++ b/src/video/SDL_sysvideo.h	Thu Dec 18 00:19:52 2014 -0500
    24.3 @@ -394,6 +394,9 @@
    24.4  #if SDL_VIDEO_DRIVER_VIVANTE
    24.5  extern VideoBootStrap VIVANTE_bootstrap;
    24.6  #endif
    24.7 +#if SDL_VIDEO_DRIVER_EMSCRIPTEN
    24.8 +extern VideoBootStrap Emscripten_bootstrap;
    24.9 +#endif
   24.10  
   24.11  extern SDL_VideoDevice *SDL_GetVideoDevice(void);
   24.12  extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode);
    25.1 --- a/src/video/SDL_video.c	Sat Dec 13 02:33:52 2014 -0500
    25.2 +++ b/src/video/SDL_video.c	Thu Dec 18 00:19:52 2014 -0500
    25.3 @@ -98,6 +98,9 @@
    25.4  #if SDL_VIDEO_DRIVER_NACL
    25.5      &NACL_bootstrap,
    25.6  #endif
    25.7 +#if SDL_VIDEO_DRIVER_EMSCRIPTEN
    25.8 +    &Emscripten_bootstrap,
    25.9 +#endif
   25.10  #if SDL_VIDEO_DRIVER_DUMMY
   25.11      &DUMMY_bootstrap,
   25.12  #endif
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/src/video/emscripten/SDL_emscriptenevents.c	Thu Dec 18 00:19:52 2014 -0500
    26.3 @@ -0,0 +1,638 @@
    26.4 +/*
    26.5 +  Simple DirectMedia Layer
    26.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    26.7 +
    26.8 +  This software is provided 'as-is', without any express or implied
    26.9 +  warranty.  In no event will the authors be held liable for any damages
   26.10 +  arising from the use of this software.
   26.11 +
   26.12 +  Permission is granted to anyone to use this software for any purpose,
   26.13 +  including commercial applications, and to alter it and redistribute it
   26.14 +  freely, subject to the following restrictions:
   26.15 +
   26.16 +  1. The origin of this software must not be misrepresented; you must not
   26.17 +     claim that you wrote the original software. If you use this software
   26.18 +     in a product, an acknowledgment in the product documentation would be
   26.19 +     appreciated but is not required.
   26.20 +  2. Altered source versions must be plainly marked as such, and must not be
   26.21 +     misrepresented as being the original software.
   26.22 +  3. This notice may not be removed or altered from any source distribution.
   26.23 +*/
   26.24 +
   26.25 +
   26.26 +#include "../../SDL_internal.h"
   26.27 +
   26.28 +#if SDL_VIDEO_DRIVER_EMSCRIPTEN
   26.29 +
   26.30 +#include <emscripten/html5.h>
   26.31 +
   26.32 +#include "../../events/SDL_events_c.h"
   26.33 +#include "../../events/SDL_keyboard_c.h"
   26.34 +#include "../../events/SDL_touch_c.h"
   26.35 +
   26.36 +#include "SDL_emscriptenevents.h"
   26.37 +#include "SDL_emscriptenvideo.h"
   26.38 +
   26.39 +#include "SDL_hints.h"
   26.40 +
   26.41 +#define FULLSCREEN_MASK ( SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN )
   26.42 +
   26.43 +/*
   26.44 +.which to scancode
   26.45 +https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Constants
   26.46 +*/
   26.47 +static const SDL_Scancode emscripten_scancode_table[] = {
   26.48 +    /*  0 */    SDL_SCANCODE_UNKNOWN,
   26.49 +    /*  1 */    SDL_SCANCODE_UNKNOWN,
   26.50 +    /*  2 */    SDL_SCANCODE_UNKNOWN,
   26.51 +    /*  3 */    SDL_SCANCODE_CANCEL,
   26.52 +    /*  4 */    SDL_SCANCODE_UNKNOWN,
   26.53 +    /*  5 */    SDL_SCANCODE_UNKNOWN,
   26.54 +    /*  6 */    SDL_SCANCODE_HELP,
   26.55 +    /*  7 */    SDL_SCANCODE_UNKNOWN,
   26.56 +    /*  8 */    SDL_SCANCODE_BACKSPACE,
   26.57 +    /*  9 */    SDL_SCANCODE_TAB,
   26.58 +    /*  10 */   SDL_SCANCODE_UNKNOWN,
   26.59 +    /*  11 */   SDL_SCANCODE_UNKNOWN,
   26.60 +    /*  12 */   SDL_SCANCODE_UNKNOWN,
   26.61 +    /*  13 */   SDL_SCANCODE_RETURN,
   26.62 +    /*  14 */   SDL_SCANCODE_UNKNOWN,
   26.63 +    /*  15 */   SDL_SCANCODE_UNKNOWN,
   26.64 +    /*  16 */   SDL_SCANCODE_LSHIFT,
   26.65 +    /*  17 */   SDL_SCANCODE_LCTRL,
   26.66 +    /*  18 */   SDL_SCANCODE_LALT,
   26.67 +    /*  19 */   SDL_SCANCODE_PAUSE,
   26.68 +    /*  20 */   SDL_SCANCODE_CAPSLOCK,
   26.69 +    /*  21 */   SDL_SCANCODE_UNKNOWN,
   26.70 +    /*  22 */   SDL_SCANCODE_UNKNOWN,
   26.71 +    /*  23 */   SDL_SCANCODE_UNKNOWN,
   26.72 +    /*  24 */   SDL_SCANCODE_UNKNOWN,
   26.73 +    /*  25 */   SDL_SCANCODE_UNKNOWN,
   26.74 +    /*  26 */   SDL_SCANCODE_UNKNOWN,
   26.75 +    /*  27 */   SDL_SCANCODE_ESCAPE,
   26.76 +    /*  28 */   SDL_SCANCODE_UNKNOWN,
   26.77 +    /*  29 */   SDL_SCANCODE_UNKNOWN,
   26.78 +    /*  30 */   SDL_SCANCODE_UNKNOWN,
   26.79 +    /*  31 */   SDL_SCANCODE_UNKNOWN,
   26.80 +    /*  32 */   SDL_SCANCODE_SPACE,
   26.81 +    /*  33 */   SDL_SCANCODE_PAGEUP,
   26.82 +    /*  34 */   SDL_SCANCODE_PAGEDOWN,
   26.83 +    /*  35 */   SDL_SCANCODE_END,
   26.84 +    /*  36 */   SDL_SCANCODE_HOME,
   26.85 +    /*  37 */   SDL_SCANCODE_LEFT,
   26.86 +    /*  38 */   SDL_SCANCODE_UP,
   26.87 +    /*  39 */   SDL_SCANCODE_RIGHT,
   26.88 +    /*  40 */   SDL_SCANCODE_DOWN,
   26.89 +    /*  41 */   SDL_SCANCODE_UNKNOWN,
   26.90 +    /*  42 */   SDL_SCANCODE_UNKNOWN,
   26.91 +    /*  43 */   SDL_SCANCODE_UNKNOWN,
   26.92 +    /*  44 */   SDL_SCANCODE_UNKNOWN,
   26.93 +    /*  45 */   SDL_SCANCODE_INSERT,
   26.94 +    /*  46 */   SDL_SCANCODE_DELETE,
   26.95 +    /*  47 */   SDL_SCANCODE_UNKNOWN,
   26.96 +    /*  48 */   SDL_SCANCODE_0,
   26.97 +    /*  49 */   SDL_SCANCODE_1,
   26.98 +    /*  50 */   SDL_SCANCODE_2,
   26.99 +    /*  51 */   SDL_SCANCODE_3,
  26.100 +    /*  52 */   SDL_SCANCODE_4,
  26.101 +    /*  53 */   SDL_SCANCODE_5,
  26.102 +    /*  54 */   SDL_SCANCODE_6,
  26.103 +    /*  55 */   SDL_SCANCODE_7,
  26.104 +    /*  56 */   SDL_SCANCODE_8,
  26.105 +    /*  57 */   SDL_SCANCODE_9,
  26.106 +    /*  58 */   SDL_SCANCODE_UNKNOWN,
  26.107 +    /*  59 */   SDL_SCANCODE_SEMICOLON,
  26.108 +    /*  60 */   SDL_SCANCODE_UNKNOWN,
  26.109 +    /*  61 */   SDL_SCANCODE_EQUALS,
  26.110 +    /*  62 */   SDL_SCANCODE_UNKNOWN,
  26.111 +    /*  63 */   SDL_SCANCODE_UNKNOWN,
  26.112 +    /*  64 */   SDL_SCANCODE_UNKNOWN,
  26.113 +    /*  65 */   SDL_SCANCODE_A,
  26.114 +    /*  66 */   SDL_SCANCODE_B,
  26.115 +    /*  67 */   SDL_SCANCODE_C,
  26.116 +    /*  68 */   SDL_SCANCODE_D,
  26.117 +    /*  69 */   SDL_SCANCODE_E,
  26.118 +    /*  70 */   SDL_SCANCODE_F,
  26.119 +    /*  71 */   SDL_SCANCODE_G,
  26.120 +    /*  72 */   SDL_SCANCODE_H,
  26.121 +    /*  73 */   SDL_SCANCODE_I,
  26.122 +    /*  74 */   SDL_SCANCODE_J,
  26.123 +    /*  75 */   SDL_SCANCODE_K,
  26.124 +    /*  76 */   SDL_SCANCODE_L,
  26.125 +    /*  77 */   SDL_SCANCODE_M,
  26.126 +    /*  78 */   SDL_SCANCODE_N,
  26.127 +    /*  79 */   SDL_SCANCODE_O,
  26.128 +    /*  80 */   SDL_SCANCODE_P,
  26.129 +    /*  81 */   SDL_SCANCODE_Q,
  26.130 +    /*  82 */   SDL_SCANCODE_R,
  26.131 +    /*  83 */   SDL_SCANCODE_S,
  26.132 +    /*  84 */   SDL_SCANCODE_T,
  26.133 +    /*  85 */   SDL_SCANCODE_U,
  26.134 +    /*  86 */   SDL_SCANCODE_V,
  26.135 +    /*  87 */   SDL_SCANCODE_W,
  26.136 +    /*  88 */   SDL_SCANCODE_X,
  26.137 +    /*  89 */   SDL_SCANCODE_Y,
  26.138 +    /*  90 */   SDL_SCANCODE_Z,
  26.139 +    /*  91 */   SDL_SCANCODE_LGUI,
  26.140 +    /*  92 */   SDL_SCANCODE_UNKNOWN,
  26.141 +    /*  93 */   SDL_SCANCODE_APPLICATION,
  26.142 +    /*  94 */   SDL_SCANCODE_UNKNOWN,
  26.143 +    /*  95 */   SDL_SCANCODE_UNKNOWN,
  26.144 +    /*  96 */   SDL_SCANCODE_KP_0,
  26.145 +    /*  97 */   SDL_SCANCODE_KP_1,
  26.146 +    /*  98 */   SDL_SCANCODE_KP_2,
  26.147 +    /*  99 */   SDL_SCANCODE_KP_3,
  26.148 +    /* 100 */   SDL_SCANCODE_KP_4,
  26.149 +    /* 101 */   SDL_SCANCODE_KP_5,
  26.150 +    /* 102 */   SDL_SCANCODE_KP_6,
  26.151 +    /* 103 */   SDL_SCANCODE_KP_7,
  26.152 +    /* 104 */   SDL_SCANCODE_KP_8,
  26.153 +    /* 105 */   SDL_SCANCODE_KP_9,
  26.154 +    /* 106 */   SDL_SCANCODE_KP_MULTIPLY,
  26.155 +    /* 107 */   SDL_SCANCODE_KP_PLUS,
  26.156 +    /* 108 */   SDL_SCANCODE_UNKNOWN,
  26.157 +    /* 109 */   SDL_SCANCODE_KP_MINUS,
  26.158 +    /* 110 */   SDL_SCANCODE_KP_PERIOD,
  26.159 +    /* 111 */   SDL_SCANCODE_KP_DIVIDE,
  26.160 +    /* 112 */   SDL_SCANCODE_F1,
  26.161 +    /* 113 */   SDL_SCANCODE_F2,
  26.162 +    /* 114 */   SDL_SCANCODE_F3,
  26.163 +    /* 115 */   SDL_SCANCODE_F4,
  26.164 +    /* 116 */   SDL_SCANCODE_F5,
  26.165 +    /* 117 */   SDL_SCANCODE_F6,
  26.166 +    /* 118 */   SDL_SCANCODE_F7,
  26.167 +    /* 119 */   SDL_SCANCODE_F8,
  26.168 +    /* 120 */   SDL_SCANCODE_F9,
  26.169 +    /* 121 */   SDL_SCANCODE_F10,
  26.170 +    /* 122 */   SDL_SCANCODE_F11,
  26.171 +    /* 123 */   SDL_SCANCODE_F12,
  26.172 +    /* 124 */   SDL_SCANCODE_F13,
  26.173 +    /* 125 */   SDL_SCANCODE_F14,
  26.174 +    /* 126 */   SDL_SCANCODE_F15,
  26.175 +    /* 127 */   SDL_SCANCODE_F16,
  26.176 +    /* 128 */   SDL_SCANCODE_F17,
  26.177 +    /* 129 */   SDL_SCANCODE_F18,
  26.178 +    /* 130 */   SDL_SCANCODE_F19,
  26.179 +    /* 131 */   SDL_SCANCODE_F20,
  26.180 +    /* 132 */   SDL_SCANCODE_F21,
  26.181 +    /* 133 */   SDL_SCANCODE_F22,
  26.182 +    /* 134 */   SDL_SCANCODE_F23,
  26.183 +    /* 135 */   SDL_SCANCODE_F24,
  26.184 +    /* 136 */   SDL_SCANCODE_UNKNOWN,
  26.185 +    /* 137 */   SDL_SCANCODE_UNKNOWN,
  26.186 +    /* 138 */   SDL_SCANCODE_UNKNOWN,
  26.187 +    /* 139 */   SDL_SCANCODE_UNKNOWN,
  26.188 +    /* 140 */   SDL_SCANCODE_UNKNOWN,
  26.189 +    /* 141 */   SDL_SCANCODE_UNKNOWN,
  26.190 +    /* 142 */   SDL_SCANCODE_UNKNOWN,
  26.191 +    /* 143 */   SDL_SCANCODE_UNKNOWN,
  26.192 +    /* 144 */   SDL_SCANCODE_NUMLOCKCLEAR,
  26.193 +    /* 145 */   SDL_SCANCODE_SCROLLLOCK,
  26.194 +    /* 146 */   SDL_SCANCODE_UNKNOWN,
  26.195 +    /* 147 */   SDL_SCANCODE_UNKNOWN,
  26.196 +    /* 148 */   SDL_SCANCODE_UNKNOWN,
  26.197 +    /* 149 */   SDL_SCANCODE_UNKNOWN,
  26.198 +    /* 150 */   SDL_SCANCODE_UNKNOWN,
  26.199 +    /* 151 */   SDL_SCANCODE_UNKNOWN,
  26.200 +    /* 152 */   SDL_SCANCODE_UNKNOWN,
  26.201 +    /* 153 */   SDL_SCANCODE_UNKNOWN,
  26.202 +    /* 154 */   SDL_SCANCODE_UNKNOWN,
  26.203 +    /* 155 */   SDL_SCANCODE_UNKNOWN,
  26.204 +    /* 156 */   SDL_SCANCODE_UNKNOWN,
  26.205 +    /* 157 */   SDL_SCANCODE_UNKNOWN,
  26.206 +    /* 158 */   SDL_SCANCODE_UNKNOWN,
  26.207 +    /* 159 */   SDL_SCANCODE_UNKNOWN,
  26.208 +    /* 160 */   SDL_SCANCODE_UNKNOWN,
  26.209 +    /* 161 */   SDL_SCANCODE_UNKNOWN,
  26.210 +    /* 162 */   SDL_SCANCODE_UNKNOWN,
  26.211 +    /* 163 */   SDL_SCANCODE_UNKNOWN,
  26.212 +    /* 164 */   SDL_SCANCODE_UNKNOWN,
  26.213 +    /* 165 */   SDL_SCANCODE_UNKNOWN,
  26.214 +    /* 166 */   SDL_SCANCODE_UNKNOWN,
  26.215 +    /* 167 */   SDL_SCANCODE_UNKNOWN,
  26.216 +    /* 168 */   SDL_SCANCODE_UNKNOWN,
  26.217 +    /* 169 */   SDL_SCANCODE_UNKNOWN,
  26.218 +    /* 170 */   SDL_SCANCODE_UNKNOWN,
  26.219 +    /* 171 */   SDL_SCANCODE_UNKNOWN,
  26.220 +    /* 172 */   SDL_SCANCODE_UNKNOWN,
  26.221 +    /* 173 */   SDL_SCANCODE_MINUS, /*FX*/
  26.222 +    /* 174 */   SDL_SCANCODE_UNKNOWN,
  26.223 +    /* 175 */   SDL_SCANCODE_UNKNOWN,
  26.224 +    /* 176 */   SDL_SCANCODE_UNKNOWN,
  26.225 +    /* 177 */   SDL_SCANCODE_UNKNOWN,
  26.226 +    /* 178 */   SDL_SCANCODE_UNKNOWN,
  26.227 +    /* 179 */   SDL_SCANCODE_UNKNOWN,
  26.228 +    /* 180 */   SDL_SCANCODE_UNKNOWN,
  26.229 +    /* 181 */   SDL_SCANCODE_UNKNOWN,
  26.230 +    /* 182 */   SDL_SCANCODE_UNKNOWN,
  26.231 +    /* 183 */   SDL_SCANCODE_UNKNOWN,
  26.232 +    /* 184 */   SDL_SCANCODE_UNKNOWN,
  26.233 +    /* 185 */   SDL_SCANCODE_UNKNOWN,
  26.234 +    /* 186 */   SDL_SCANCODE_SEMICOLON, /*IE, Chrome, D3E legacy*/
  26.235 +    /* 187 */   SDL_SCANCODE_EQUALS, /*IE, Chrome, D3E legacy*/
  26.236 +    /* 188 */   SDL_SCANCODE_COMMA,
  26.237 +    /* 189 */   SDL_SCANCODE_MINUS, /*IE, Chrome, D3E legacy*/
  26.238 +    /* 190 */   SDL_SCANCODE_PERIOD,
  26.239 +    /* 191 */   SDL_SCANCODE_SLASH,
  26.240 +    /* 192 */   SDL_SCANCODE_GRAVE, /*FX, D3E legacy (SDL_SCANCODE_APOSTROPHE in IE/Chrome)*/
  26.241 +    /* 193 */   SDL_SCANCODE_UNKNOWN,
  26.242 +    /* 194 */   SDL_SCANCODE_UNKNOWN,
  26.243 +    /* 195 */   SDL_SCANCODE_UNKNOWN,
  26.244 +    /* 196 */   SDL_SCANCODE_UNKNOWN,
  26.245 +    /* 197 */   SDL_SCANCODE_UNKNOWN,
  26.246 +    /* 198 */   SDL_SCANCODE_UNKNOWN,
  26.247 +    /* 199 */   SDL_SCANCODE_UNKNOWN,
  26.248 +    /* 200 */   SDL_SCANCODE_UNKNOWN,
  26.249 +    /* 201 */   SDL_SCANCODE_UNKNOWN,
  26.250 +    /* 202 */   SDL_SCANCODE_UNKNOWN,
  26.251 +    /* 203 */   SDL_SCANCODE_UNKNOWN,
  26.252 +    /* 204 */   SDL_SCANCODE_UNKNOWN,
  26.253 +    /* 205 */   SDL_SCANCODE_UNKNOWN,
  26.254 +    /* 206 */   SDL_SCANCODE_UNKNOWN,
  26.255 +    /* 207 */   SDL_SCANCODE_UNKNOWN,
  26.256 +    /* 208 */   SDL_SCANCODE_UNKNOWN,
  26.257 +    /* 209 */   SDL_SCANCODE_UNKNOWN,
  26.258 +    /* 210 */   SDL_SCANCODE_UNKNOWN,
  26.259 +    /* 211 */   SDL_SCANCODE_UNKNOWN,
  26.260 +    /* 212 */   SDL_SCANCODE_UNKNOWN,
  26.261 +    /* 213 */   SDL_SCANCODE_UNKNOWN,
  26.262 +    /* 214 */   SDL_SCANCODE_UNKNOWN,
  26.263 +    /* 215 */   SDL_SCANCODE_UNKNOWN,
  26.264 +    /* 216 */   SDL_SCANCODE_UNKNOWN,
  26.265 +    /* 217 */   SDL_SCANCODE_UNKNOWN,
  26.266 +    /* 218 */   SDL_SCANCODE_UNKNOWN,
  26.267 +    /* 219 */   SDL_SCANCODE_LEFTBRACKET,
  26.268 +    /* 220 */   SDL_SCANCODE_BACKSLASH,
  26.269 +    /* 221 */   SDL_SCANCODE_RIGHTBRACKET,
  26.270 +    /* 222 */   SDL_SCANCODE_APOSTROPHE, /*FX, D3E legacy*/
  26.271 +};
  26.272 +
  26.273 +
  26.274 +/* "borrowed" from SDL_windowsevents.c */
  26.275 +int
  26.276 +Emscripten_ConvertUTF32toUTF8(Uint32 codepoint, char * text)
  26.277 +{
  26.278 +    if (codepoint <= 0x7F) {
  26.279 +        text[0] = (char) codepoint;
  26.280 +        text[1] = '\0';
  26.281 +    } else if (codepoint <= 0x7FF) {
  26.282 +        text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
  26.283 +        text[1] = 0x80 | (char) (codepoint & 0x3F);
  26.284 +        text[2] = '\0';
  26.285 +    } else if (codepoint <= 0xFFFF) {
  26.286 +        text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
  26.287 +        text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
  26.288 +        text[2] = 0x80 | (char) (codepoint & 0x3F);
  26.289 +        text[3] = '\0';
  26.290 +    } else if (codepoint <= 0x10FFFF) {
  26.291 +        text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
  26.292 +        text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
  26.293 +        text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
  26.294 +        text[3] = 0x80 | (char) (codepoint & 0x3F);
  26.295 +        text[4] = '\0';
  26.296 +    } else {
  26.297 +        return SDL_FALSE;
  26.298 +    }
  26.299 +    return SDL_TRUE;
  26.300 +}
  26.301 +
  26.302 +int
  26.303 +Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
  26.304 +{
  26.305 +    SDL_WindowData *window_data = userData;
  26.306 +    int mx = mouseEvent->canvasX, my = mouseEvent->canvasY;
  26.307 +    EmscriptenPointerlockChangeEvent pointerlock_status;
  26.308 +
  26.309 +    /* check for pointer lock */
  26.310 +    emscripten_get_pointerlock_status(&pointerlock_status);
  26.311 +
  26.312 +    if (pointerlock_status.isActive) {
  26.313 +        mx = mouseEvent->movementX;
  26.314 +        my = mouseEvent->movementY;
  26.315 +    }
  26.316 +
  26.317 +    /* rescale (in case canvas is being scaled)*/
  26.318 +    double client_w, client_h;
  26.319 +    emscripten_get_element_css_size(NULL, &client_w, &client_h);
  26.320 +
  26.321 +    mx = mx * (window_data->window->w / (client_w * window_data->pixel_ratio));
  26.322 +    my = my * (window_data->window->h / (client_h * window_data->pixel_ratio));
  26.323 +
  26.324 +    SDL_SendMouseMotion(window_data->window, 0, pointerlock_status.isActive, mx, my);
  26.325 +    return 0;
  26.326 +}
  26.327 +
  26.328 +int
  26.329 +Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
  26.330 +{
  26.331 +    SDL_WindowData *window_data = userData;
  26.332 +    uint32_t sdl_button;
  26.333 +    switch (mouseEvent->button) {
  26.334 +        case 0:
  26.335 +            sdl_button = SDL_BUTTON_LEFT;
  26.336 +            break;
  26.337 +        case 1:
  26.338 +            sdl_button = SDL_BUTTON_MIDDLE;
  26.339 +            break;
  26.340 +        case 2:
  26.341 +            sdl_button = SDL_BUTTON_RIGHT;
  26.342 +            break;
  26.343 +        default:
  26.344 +            return 0;
  26.345 +    }
  26.346 +    SDL_SendMouseButton(window_data->window, 0, eventType == EMSCRIPTEN_EVENT_MOUSEDOWN ? SDL_PRESSED : SDL_RELEASED, sdl_button);
  26.347 +    return 1;
  26.348 +}
  26.349 +
  26.350 +int
  26.351 +Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
  26.352 +{
  26.353 +    SDL_WindowData *window_data = userData;
  26.354 +    SDL_SendWindowEvent(window_data->window, eventType == EMSCRIPTEN_EVENT_MOUSEENTER ? SDL_WINDOWEVENT_ENTER : SDL_WINDOWEVENT_LEAVE, 0, 0);
  26.355 +    return 1;
  26.356 +}
  26.357 +
  26.358 +int
  26.359 +Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
  26.360 +{
  26.361 +    SDL_WindowData *window_data = userData;
  26.362 +    SDL_SendMouseWheel(window_data->window, 0, wheelEvent->deltaX, -wheelEvent->deltaY, SDL_MOUSEWHEEL_NORMAL);
  26.363 +    return 1;
  26.364 +}
  26.365 +
  26.366 +int
  26.367 +Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, void *userData)
  26.368 +{
  26.369 +    SDL_WindowData *window_data = userData;
  26.370 +    SDL_SendWindowEvent(window_data->window, eventType == EMSCRIPTEN_EVENT_FOCUS ? SDL_WINDOWEVENT_FOCUS_GAINED : SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
  26.371 +    return 1;
  26.372 +}
  26.373 +
  26.374 +int
  26.375 +Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
  26.376 +{
  26.377 +    /*SDL_WindowData *window_data = userData;*/
  26.378 +    int i;
  26.379 +
  26.380 +    SDL_TouchID deviceId = 0;
  26.381 +    if (!SDL_GetTouch(deviceId)) {
  26.382 +        if (SDL_AddTouch(deviceId, "") < 0) {
  26.383 +             return 0;
  26.384 +        }
  26.385 +    }
  26.386 +
  26.387 +    for (i = 0; i < touchEvent->numTouches; i++) {
  26.388 +        long x, y, id;
  26.389 +
  26.390 +        if (!touchEvent->touches[i].isChanged)
  26.391 +            continue;
  26.392 +
  26.393 +        id = touchEvent->touches[i].identifier;
  26.394 +        x = touchEvent->touches[i].canvasX;
  26.395 +        y = touchEvent->touches[i].canvasY;
  26.396 +
  26.397 +        if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) {
  26.398 +            SDL_SendTouchMotion(deviceId, id, x, y, 1.0f);
  26.399 +        } else if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) {
  26.400 +            SDL_SendTouch(deviceId, id, SDL_TRUE, x, y, 1.0f);
  26.401 +        } else {
  26.402 +            SDL_SendTouch(deviceId, id, SDL_FALSE, x, y, 1.0f);
  26.403 +        }
  26.404 +    }
  26.405 +
  26.406 +
  26.407 +    return 1;
  26.408 +}
  26.409 +
  26.410 +int
  26.411 +Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
  26.412 +{
  26.413 +    Uint32 scancode;
  26.414 +
  26.415 +    /* .keyCode is deprecated, but still the most reliable way to get keys */
  26.416 +    if (keyEvent->keyCode < SDL_arraysize(emscripten_scancode_table)) {
  26.417 +        scancode = emscripten_scancode_table[keyEvent->keyCode];
  26.418 +
  26.419 +        if (scancode != SDL_SCANCODE_UNKNOWN) {
  26.420 +
  26.421 +            if (keyEvent->location == DOM_KEY_LOCATION_RIGHT) {
  26.422 +                switch (scancode) {
  26.423 +                    case SDL_SCANCODE_LSHIFT:
  26.424 +                        scancode = SDL_SCANCODE_RSHIFT;
  26.425 +                        break;
  26.426 +                    case SDL_SCANCODE_LCTRL:
  26.427 +                        scancode = SDL_SCANCODE_RCTRL;
  26.428 +                        break;
  26.429 +                    case SDL_SCANCODE_LALT:
  26.430 +                        scancode = SDL_SCANCODE_RALT;
  26.431 +                        break;
  26.432 +                    case SDL_SCANCODE_LGUI:
  26.433 +                        scancode = SDL_SCANCODE_RGUI;
  26.434 +                        break;
  26.435 +                }
  26.436 +            }
  26.437 +            SDL_SendKeyboardKey(eventType == EMSCRIPTEN_EVENT_KEYDOWN ?
  26.438 +                                SDL_PRESSED : SDL_RELEASED, scancode);
  26.439 +        }
  26.440 +    }
  26.441 +
  26.442 +    /* if we prevent keydown, we won't get keypress
  26.443 +     * also we need to ALWAYS prevent backspace and tab otherwise chrome takes action and does bad navigation UX
  26.444 +     */
  26.445 +    return SDL_GetEventState(SDL_TEXTINPUT) != SDL_ENABLE || eventType != EMSCRIPTEN_EVENT_KEYDOWN
  26.446 +            || keyEvent->keyCode == 8 /* backspace */ || keyEvent->keyCode == 9 /* tab */;
  26.447 +}
  26.448 +
  26.449 +int
  26.450 +Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
  26.451 +{
  26.452 +    char text[5];
  26.453 +    Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text);
  26.454 +    SDL_SendKeyboardText(text);
  26.455 +    return 1;
  26.456 +}
  26.457 +
  26.458 +int
  26.459 +Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData)
  26.460 +{
  26.461 +    /*make sure this is actually our element going fullscreen*/
  26.462 +    if(SDL_strcmp(fullscreenChangeEvent->id, "SDLFullscreenElement") != 0)
  26.463 +        return 0;
  26.464 +
  26.465 +    SDL_WindowData *window_data = userData;
  26.466 +    if(fullscreenChangeEvent->isFullscreen)
  26.467 +    {
  26.468 +        SDL_bool is_desktop_fullscreen;
  26.469 +        window_data->window->flags |= window_data->requested_fullscreen_mode;
  26.470 +
  26.471 +        if(!window_data->requested_fullscreen_mode)
  26.472 +            window_data->window->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; /*we didn't reqest fullscreen*/
  26.473 +
  26.474 +        window_data->requested_fullscreen_mode = 0;
  26.475 +
  26.476 +        is_desktop_fullscreen = (window_data->window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
  26.477 +
  26.478 +        /*update size*/
  26.479 +        if(window_data->window->flags & SDL_WINDOW_RESIZABLE || is_desktop_fullscreen)
  26.480 +        {
  26.481 +            emscripten_set_canvas_size(fullscreenChangeEvent->screenWidth, fullscreenChangeEvent->screenHeight);
  26.482 +            SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, fullscreenChangeEvent->screenWidth, fullscreenChangeEvent->screenHeight);
  26.483 +        }
  26.484 +        else
  26.485 +        {
  26.486 +            /*preserve ratio*/
  26.487 +            double w = window_data->window->w;
  26.488 +            double h = window_data->window->h;
  26.489 +            double factor = SDL_min(fullscreenChangeEvent->screenWidth / w, fullscreenChangeEvent->screenHeight / h);
  26.490 +            emscripten_set_element_css_size(NULL, w * factor, h * factor);
  26.491 +        }
  26.492 +    }
  26.493 +    else
  26.494 +    {
  26.495 +        EM_ASM({
  26.496 +            //un-reparent canvas (similar to Module.requestFullscreen)
  26.497 +            var canvas = Module['canvas'];
  26.498 +            if(canvas.parentNode.id == "SDLFullscreenElement") {
  26.499 +                var canvasContainer = canvas.parentNode;
  26.500 +                canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
  26.501 +                canvasContainer.parentNode.removeChild(canvasContainer);
  26.502 +            }
  26.503 +        });
  26.504 +        double unscaled_w = window_data->windowed_width / window_data->pixel_ratio;
  26.505 +        double unscaled_h = window_data->windowed_height / window_data->pixel_ratio;
  26.506 +        emscripten_set_canvas_size(window_data->windowed_width, window_data->windowed_height);
  26.507 +
  26.508 +        if (!window_data->external_size && window_data->pixel_ratio != 1.0f) {
  26.509 +            emscripten_set_element_css_size(NULL, unscaled_w, unscaled_h);
  26.510 +        }
  26.511 +
  26.512 +        SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, unscaled_w, unscaled_h);
  26.513 +
  26.514 +        window_data->window->flags &= ~FULLSCREEN_MASK;
  26.515 +    }
  26.516 +
  26.517 +    return 0;
  26.518 +}
  26.519 +
  26.520 +int
  26.521 +Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData)
  26.522 +{
  26.523 +    SDL_WindowData *window_data = userData;
  26.524 +    if(window_data->window->flags & FULLSCREEN_MASK)
  26.525 +    {
  26.526 +        SDL_bool is_desktop_fullscreen = (window_data->window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
  26.527 +
  26.528 +        if(window_data->window->flags & SDL_WINDOW_RESIZABLE || is_desktop_fullscreen)
  26.529 +        {
  26.530 +            emscripten_set_canvas_size(uiEvent->windowInnerWidth * window_data->pixel_ratio, uiEvent->windowInnerHeight * window_data->pixel_ratio);
  26.531 +            SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, uiEvent->windowInnerWidth, uiEvent->windowInnerHeight);
  26.532 +        }
  26.533 +    }
  26.534 +    else
  26.535 +    {
  26.536 +        /* this will only work if the canvas size is set through css */
  26.537 +        if(window_data->window->flags & SDL_WINDOW_RESIZABLE)
  26.538 +        {
  26.539 +            double w = window_data->window->w;
  26.540 +            double h = window_data->window->h;
  26.541 +
  26.542 +            if(window_data->external_size) {
  26.543 +                emscripten_get_element_css_size(NULL, &w, &h);
  26.544 +            }
  26.545 +
  26.546 +            emscripten_set_canvas_size(w * window_data->pixel_ratio, h * window_data->pixel_ratio);
  26.547 +
  26.548 +            /* set_canvas_size unsets this */
  26.549 +            if (!window_data->external_size && window_data->pixel_ratio != 1.0f) {
  26.550 +                emscripten_set_element_css_size(NULL, w, h);
  26.551 +            }
  26.552 +
  26.553 +            SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, w, h);
  26.554 +        }
  26.555 +    }
  26.556 +
  26.557 +    return 0;
  26.558 +}
  26.559 +
  26.560 +int
  26.561 +Emscripten_HandleVisibilityChange(int eventType, const EmscriptenVisibilityChangeEvent *visEvent, void *userData)
  26.562 +{
  26.563 +    SDL_WindowData *window_data = userData;
  26.564 +    SDL_SendWindowEvent(window_data->window, visEvent->hidden ? SDL_WINDOWEVENT_HIDDEN : SDL_WINDOWEVENT_SHOWN, 0, 0);
  26.565 +    return 0;
  26.566 +}
  26.567 +
  26.568 +void
  26.569 +Emscripten_RegisterEventHandlers(SDL_WindowData *data)
  26.570 +{
  26.571 +    /* There is only one window and that window is the canvas */
  26.572 +    emscripten_set_mousemove_callback("#canvas", data, 0, Emscripten_HandleMouseMove);
  26.573 +
  26.574 +    emscripten_set_mousedown_callback("#canvas", data, 0, Emscripten_HandleMouseButton);
  26.575 +    emscripten_set_mouseup_callback("#canvas", data, 0, Emscripten_HandleMouseButton);
  26.576 +
  26.577 +    emscripten_set_mouseenter_callback("#canvas", data, 0, Emscripten_HandleMouseFocus);
  26.578 +    emscripten_set_mouseleave_callback("#canvas", data, 0, Emscripten_HandleMouseFocus);
  26.579 +
  26.580 +    emscripten_set_wheel_callback("#canvas", data, 0, Emscripten_HandleWheel);
  26.581 +
  26.582 +    emscripten_set_focus_callback("#canvas", data, 0, Emscripten_HandleFocus);
  26.583 +    emscripten_set_blur_callback("#canvas", data, 0, Emscripten_HandleFocus);
  26.584 +
  26.585 +    emscripten_set_touchstart_callback("#canvas", data, 0, Emscripten_HandleTouch);
  26.586 +    emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
  26.587 +    emscripten_set_touchmove_callback("#canvas", data, 0, Emscripten_HandleTouch);
  26.588 +    emscripten_set_touchcancel_callback("#canvas", data, 0, Emscripten_HandleTouch);
  26.589 +
  26.590 +    /* Keyboard events are awkward */
  26.591 +    const char *keyElement = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
  26.592 +    if (!keyElement) keyElement = "#window";
  26.593 +
  26.594 +    emscripten_set_keydown_callback(keyElement, data, 0, Emscripten_HandleKey);
  26.595 +    emscripten_set_keyup_callback(keyElement, data, 0, Emscripten_HandleKey);
  26.596 +    emscripten_set_keypress_callback(keyElement, data, 0, Emscripten_HandleKeyPress);
  26.597 +
  26.598 +    emscripten_set_fullscreenchange_callback("#document", data, 0, Emscripten_HandleFullscreenChange);
  26.599 +
  26.600 +    emscripten_set_resize_callback("#window", data, 0, Emscripten_HandleResize);
  26.601 +
  26.602 +    emscripten_set_visibilitychange_callback(data, 0, Emscripten_HandleVisibilityChange);
  26.603 +}
  26.604 +
  26.605 +void
  26.606 +Emscripten_UnregisterEventHandlers(SDL_WindowData *data)
  26.607 +{
  26.608 +    /* only works due to having one window */
  26.609 +    emscripten_set_mousemove_callback("#canvas", NULL, 0, NULL);
  26.610 +
  26.611 +    emscripten_set_mousedown_callback("#canvas", NULL, 0, NULL);
  26.612 +    emscripten_set_mouseup_callback("#canvas", NULL, 0, NULL);
  26.613 +
  26.614 +    emscripten_set_mouseenter_callback("#canvas", NULL, 0, NULL);
  26.615 +    emscripten_set_mouseleave_callback("#canvas", NULL, 0, NULL);
  26.616 +
  26.617 +    emscripten_set_wheel_callback("#canvas", NULL, 0, NULL);
  26.618 +
  26.619 +    emscripten_set_focus_callback("#canvas", NULL, 0, NULL);
  26.620 +    emscripten_set_blur_callback("#canvas", NULL, 0, NULL);
  26.621 +
  26.622 +    emscripten_set_touchstart_callback("#canvas", NULL, 0, NULL);
  26.623 +    emscripten_set_touchend_callback("#canvas", NULL, 0, NULL);
  26.624 +    emscripten_set_touchmove_callback("#canvas", NULL, 0, NULL);
  26.625 +    emscripten_set_touchcancel_callback("#canvas", NULL, 0, NULL);
  26.626 +
  26.627 +    emscripten_set_keydown_callback("#window", NULL, 0, NULL);
  26.628 +    emscripten_set_keyup_callback("#window", NULL, 0, NULL);
  26.629 +
  26.630 +    emscripten_set_keypress_callback("#window", NULL, 0, NULL);
  26.631 +
  26.632 +    emscripten_set_fullscreenchange_callback("#document", NULL, 0, NULL);
  26.633 +
  26.634 +    emscripten_set_resize_callback("#window", NULL, 0, NULL);
  26.635 +
  26.636 +    emscripten_set_visibilitychange_callback(NULL, 0, NULL);
  26.637 +}
  26.638 +
  26.639 +#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
  26.640 +
  26.641 +/* vi: set ts=4 sw=4 expandtab: */
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/src/video/emscripten/SDL_emscriptenevents.h	Thu Dec 18 00:19:52 2014 -0500
    27.3 @@ -0,0 +1,36 @@
    27.4 +/*
    27.5 +  Simple DirectMedia Layer
    27.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    27.7 +
    27.8 +  This software is provided 'as-is', without any express or implied
    27.9 +  warranty.  In no event will the authors be held liable for any damages
   27.10 +  arising from the use of this software.
   27.11 +
   27.12 +  Permission is granted to anyone to use this software for any purpose,
   27.13 +  including commercial applications, and to alter it and redistribute it
   27.14 +  freely, subject to the following restrictions:
   27.15 +
   27.16 +  1. The origin of this software must not be misrepresented; you must not
   27.17 +     claim that you wrote the original software. If you use this software
   27.18 +     in a product, an acknowledgment in the product documentation would be
   27.19 +     appreciated but is not required.
   27.20 +  2. Altered source versions must be plainly marked as such, and must not be
   27.21 +     misrepresented as being the original software.
   27.22 +  3. This notice may not be removed or altered from any source distribution.
   27.23 +*/
   27.24 +
   27.25 +
   27.26 +#ifndef _SDL_emscriptenevents_h
   27.27 +#define _SDL_emscriptenevents_h
   27.28 +
   27.29 +#include "SDL_emscriptenvideo.h"
   27.30 +
   27.31 +extern void
   27.32 +Emscripten_RegisterEventHandlers(SDL_WindowData *data);
   27.33 +
   27.34 +extern void
   27.35 +Emscripten_UnregisterEventHandlers(SDL_WindowData *data);
   27.36 +#endif /* _SDL_emscriptenevents_h */
   27.37 +
   27.38 +/* vi: set ts=4 sw=4 expandtab: */
   27.39 +
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/src/video/emscripten/SDL_emscriptenframebuffer.c	Thu Dec 18 00:19:52 2014 -0500
    28.3 @@ -0,0 +1,136 @@
    28.4 +/*
    28.5 +  Simple DirectMedia Layer
    28.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    28.7 +
    28.8 +  This software is provided 'as-is', without any express or implied
    28.9 +  warranty.  In no event will the authors be held liable for any damages
   28.10 +  arising from the use of this software.
   28.11 +
   28.12 +  Permission is granted to anyone to use this software for any purpose,
   28.13 +  including commercial applications, and to alter it and redistribute it
   28.14 +  freely, subject to the following restrictions:
   28.15 +
   28.16 +  1. The origin of this software must not be misrepresented; you must not
   28.17 +     claim that you wrote the original software. If you use this software
   28.18 +     in a product, an acknowledgment in the product documentation would be
   28.19 +     appreciated but is not required.
   28.20 +  2. Altered source versions must be plainly marked as such, and must not be
   28.21 +     misrepresented as being the original software.
   28.22 +  3. This notice may not be removed or altered from any source distribution.
   28.23 +*/
   28.24 +#include "../../SDL_internal.h"
   28.25 +
   28.26 +#if SDL_VIDEO_DRIVER_EMSCRIPTEN
   28.27 +
   28.28 +#include "SDL_emscriptenvideo.h"
   28.29 +#include "SDL_emscriptenframebuffer.h"
   28.30 +
   28.31 +
   28.32 +int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
   28.33 +{
   28.34 +    SDL_Surface *surface;
   28.35 +    const Uint32 surface_format = SDL_PIXELFORMAT_BGR888;
   28.36 +    int w, h;
   28.37 +    int bpp;
   28.38 +    Uint32 Rmask, Gmask, Bmask, Amask;
   28.39 +
   28.40 +    /* Free the old framebuffer surface */
   28.41 +    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   28.42 +    surface = data->surface;
   28.43 +    SDL_FreeSurface(surface);
   28.44 +
   28.45 +    /* Create a new one */
   28.46 +    SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
   28.47 +    SDL_GetWindowSize(window, &w, &h);
   28.48 +
   28.49 +    surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask);
   28.50 +    if (!surface) {
   28.51 +        return -1;
   28.52 +    }
   28.53 +
   28.54 +    /* Save the info and return! */
   28.55 +    data->surface = surface;
   28.56 +    *format = surface_format;
   28.57 +    *pixels = surface->pixels;
   28.58 +    *pitch = surface->pitch;
   28.59 +    return 0;
   28.60 +}
   28.61 +
   28.62 +int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
   28.63 +{
   28.64 +    static int frame_number;
   28.65 +    SDL_Surface *surface;
   28.66 +
   28.67 +    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   28.68 +    surface = data->surface;
   28.69 +    if (!surface) {
   28.70 +        return SDL_SetError("Couldn't find dummy surface for window");
   28.71 +    }
   28.72 +
   28.73 +    /* Send the data to the display */
   28.74 +
   28.75 +    EM_ASM_INT({
   28.76 +        //TODO: don't create context every update
   28.77 +        var ctx = Module['canvas'].getContext('2d');
   28.78 +
   28.79 +        //library_sdl.js SDL_UnlockSurface
   28.80 +        var image = ctx.createImageData($0, $1);
   28.81 +        var data = image.data;
   28.82 +        var src = $2 >> 2;
   28.83 +        var dst = 0;
   28.84 +        var isScreen = true;
   28.85 +        var num;
   28.86 +        if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) {
   28.87 +            // IE10/IE11: ImageData objects are backed by the deprecated CanvasPixelArray,
   28.88 +            // not UInt8ClampedArray. These don't have buffers, so we need to revert
   28.89 +            // to copying a byte at a time. We do the undefined check because modern
   28.90 +            // browsers do not define CanvasPixelArray anymore.
   28.91 +            num = data.length;
   28.92 +            while (dst < num) {
   28.93 +                var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
   28.94 +                data[dst  ] = val & 0xff;
   28.95 +                data[dst+1] = (val >> 8) & 0xff;
   28.96 +                data[dst+2] = (val >> 16) & 0xff;
   28.97 +                data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
   28.98 +                src++;
   28.99 +                dst += 4;
  28.100 +            }
  28.101 +        } else {
  28.102 +            var data32 = new Uint32Array(data.buffer);
  28.103 +            num = data32.length;
  28.104 +            if (isScreen) {
  28.105 +                while (dst < num) {
  28.106 +                    // HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
  28.107 +                    data32[dst++] = HEAP32[src++] | 0xff000000;
  28.108 +                }
  28.109 +            } else {
  28.110 +                while (dst < num) {
  28.111 +                    data32[dst++] = HEAP32[src++];
  28.112 +                }
  28.113 +            }
  28.114 +        }
  28.115 +
  28.116 +        ctx.putImageData(image, 0, 0);
  28.117 +        return 0;
  28.118 +    }, surface->w, surface->h, surface->pixels);
  28.119 +
  28.120 +    /*if (SDL_getenv("SDL_VIDEO_Emscripten_SAVE_FRAMES")) {
  28.121 +        char file[128];
  28.122 +        SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp",
  28.123 +                     SDL_GetWindowID(window), ++frame_number);
  28.124 +        SDL_SaveBMP(surface, file);
  28.125 +    }*/
  28.126 +    return 0;
  28.127 +}
  28.128 +
  28.129 +void Emscripten_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
  28.130 +{
  28.131 +    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  28.132 +
  28.133 +    SDL_FreeSurface(data->surface);
  28.134 +    data->surface = NULL;
  28.135 +}
  28.136 +
  28.137 +#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
  28.138 +
  28.139 +/* vi: set ts=4 sw=4 expandtab: */
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/src/video/emscripten/SDL_emscriptenframebuffer.h	Thu Dec 18 00:19:52 2014 -0500
    29.3 @@ -0,0 +1,32 @@
    29.4 +/*
    29.5 +  Simple DirectMedia Layer
    29.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    29.7 +
    29.8 +  This software is provided 'as-is', without any express or implied
    29.9 +  warranty.  In no event will the authors be held liable for any damages
   29.10 +  arising from the use of this software.
   29.11 +
   29.12 +  Permission is granted to anyone to use this software for any purpose,
   29.13 +  including commercial applications, and to alter it and redistribute it
   29.14 +  freely, subject to the following restrictions:
   29.15 +
   29.16 +  1. The origin of this software must not be misrepresented; you must not
   29.17 +     claim that you wrote the original software. If you use this software
   29.18 +     in a product, an acknowledgment in the product documentation would be
   29.19 +     appreciated but is not required.
   29.20 +  2. Altered source versions must be plainly marked as such, and must not be
   29.21 +     misrepresented as being the original software.
   29.22 +  3. This notice may not be removed or altered from any source distribution.
   29.23 +*/
   29.24 +#include "../../SDL_internal.h"
   29.25 +
   29.26 +#ifndef _SDL_emscriptenframebuffer_h
   29.27 +#define _SDL_emscriptenframebuffer_h
   29.28 +
   29.29 +extern int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
   29.30 +extern int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
   29.31 +extern void Emscripten_DestroyWindowFramebuffer(_THIS, SDL_Window * window);
   29.32 +
   29.33 +#endif /* _SDL_emsctiptenframebuffer_h */
   29.34 +
   29.35 +/* vi: set ts=4 sw=4 expandtab: */
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/src/video/emscripten/SDL_emscriptenmouse.c	Thu Dec 18 00:19:52 2014 -0500
    30.3 @@ -0,0 +1,218 @@
    30.4 +/*
    30.5 +  Simple DirectMedia Layer
    30.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    30.7 +
    30.8 +  This software is provided 'as-is', without any express or implied
    30.9 +  warranty.  In no event will the authors be held liable for any damages
   30.10 +  arising from the use of this software.
   30.11 +
   30.12 +  Permission is granted to anyone to use this software for any purpose,
   30.13 +  including commercial applications, and to alter it and redistribute it
   30.14 +  freely, subject to the following restrictions:
   30.15 +
   30.16 +  1. The origin of this software must not be misrepresented; you must not
   30.17 +     claim that you wrote the original software. If you use this software
   30.18 +     in a product, an acknowledgment in the product documentation would be
   30.19 +     appreciated but is not required.
   30.20 +  2. Altered source versions must be plainly marked as such, and must not be
   30.21 +     misrepresented as being the original software.
   30.22 +  3. This notice may not be removed or altered from any source distribution.
   30.23 +*/
   30.24 +
   30.25 +
   30.26 +#include "../../SDL_internal.h"
   30.27 +
   30.28 +#if SDL_VIDEO_DRIVER_EMSCRIPTEN
   30.29 +
   30.30 +#include <emscripten/emscripten.h>
   30.31 +#include <emscripten/html5.h>
   30.32 +
   30.33 +#include "SDL_emscriptenmouse.h"
   30.34 +
   30.35 +#include "../../events/SDL_mouse_c.h"
   30.36 +#include "SDL_assert.h"
   30.37 +
   30.38 +
   30.39 +static SDL_Cursor*
   30.40 +Emscripten_CreateDefaultCursor()
   30.41 +{
   30.42 +    SDL_Cursor* cursor;
   30.43 +    Emscripten_CursorData *curdata;
   30.44 +
   30.45 +    cursor = SDL_calloc(1, sizeof(SDL_Cursor));
   30.46 +    if (cursor) {
   30.47 +        curdata = (Emscripten_CursorData *) SDL_calloc(1, sizeof(*curdata));
   30.48 +
   30.49 +        curdata->system_cursor = "default";
   30.50 +        cursor->driverdata = curdata;
   30.51 +    }
   30.52 +    else {
   30.53 +        SDL_OutOfMemory();
   30.54 +    }
   30.55 +
   30.56 +    return cursor;
   30.57 +}
   30.58 +
   30.59 +static SDL_Cursor*
   30.60 +Emscripten_CreateCursor(SDL_Surface* sruface, int hot_x, int hot_y)
   30.61 +{
   30.62 +    return Emscripten_CreateDefaultCursor();
   30.63 +}
   30.64 +
   30.65 +static SDL_Cursor*
   30.66 +Emscripten_CreateSystemCursor(SDL_SystemCursor id)
   30.67 +{
   30.68 +    SDL_Cursor *cursor;
   30.69 +    Emscripten_CursorData *curdata;
   30.70 +    const char *cursor_name = NULL;
   30.71 +
   30.72 +    switch(id) {
   30.73 +        case SDL_SYSTEM_CURSOR_ARROW:
   30.74 +            cursor_name = "default";
   30.75 +            break;
   30.76 +        case SDL_SYSTEM_CURSOR_IBEAM:
   30.77 +            cursor_name = "text";
   30.78 +            break;
   30.79 +        case SDL_SYSTEM_CURSOR_WAIT:
   30.80 +            cursor_name = "wait";
   30.81 +            break;
   30.82 +        case SDL_SYSTEM_CURSOR_CROSSHAIR:
   30.83 +            cursor_name = "crosshair";
   30.84 +            break;
   30.85 +        case SDL_SYSTEM_CURSOR_WAITARROW:
   30.86 +            cursor_name = "progress";
   30.87 +            break;
   30.88 +        case SDL_SYSTEM_CURSOR_SIZENWSE:
   30.89 +            cursor_name = "nwse-resize";
   30.90 +            break;
   30.91 +        case SDL_SYSTEM_CURSOR_SIZENESW:
   30.92 +            cursor_name = "nesw-resize";
   30.93 +            break;
   30.94 +        case SDL_SYSTEM_CURSOR_SIZEWE:
   30.95 +            cursor_name = "ew-resize";
   30.96 +            break;
   30.97 +        case SDL_SYSTEM_CURSOR_SIZENS:
   30.98 +            cursor_name = "ns-resize";
   30.99 +            break;
  30.100 +        case SDL_SYSTEM_CURSOR_SIZEALL:
  30.101 +            break;
  30.102 +        case SDL_SYSTEM_CURSOR_NO:
  30.103 +            cursor_name = "not-allowed";
  30.104 +            break;
  30.105 +        case SDL_SYSTEM_CURSOR_HAND:
  30.106 +            cursor_name = "pointer";
  30.107 +            break;
  30.108 +        default:
  30.109 +            SDL_assert(0);
  30.110 +            return NULL;
  30.111 +    }
  30.112 +
  30.113 +    cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
  30.114 +    curdata = (Emscripten_CursorData *) SDL_calloc(1, sizeof(*curdata));
  30.115 +
  30.116 +    curdata->system_cursor = cursor_name;
  30.117 +    cursor->driverdata = curdata;
  30.118 +
  30.119 +    return cursor;
  30.120 +}
  30.121 +
  30.122 +static void
  30.123 +Emscripten_FreeCursor(SDL_Cursor* cursor)
  30.124 +{
  30.125 +    Emscripten_CursorData *curdata;
  30.126 +    if (cursor) {
  30.127 +        curdata = (Emscripten_CursorData *) cursor->driverdata;
  30.128 +
  30.129 +        if (curdata != NULL) {
  30.130 +            SDL_free(cursor->driverdata);
  30.131 +        }
  30.132 +
  30.133 +        SDL_free(cursor);
  30.134 +    }
  30.135 +}
  30.136 +
  30.137 +static int
  30.138 +Emscripten_ShowCursor(SDL_Cursor* cursor)
  30.139 +{
  30.140 +    Emscripten_CursorData *curdata;
  30.141 +    if (SDL_GetMouseFocus() != NULL) {
  30.142 +        if(cursor && cursor->driverdata) {
  30.143 +            curdata = (Emscripten_CursorData *) cursor->driverdata;
  30.144 +
  30.145 +            if(curdata->system_cursor) {
  30.146 +                EM_ASM_INT({
  30.147 +                    if (Module['canvas']) {
  30.148 +                        Module['canvas'].style['cursor'] = Module['Pointer_stringify']($0);
  30.149 +                    }
  30.150 +                    return 0;
  30.151 +                }, curdata->system_cursor);
  30.152 +            }
  30.153 +        }
  30.154 +        else {
  30.155 +            EM_ASM(
  30.156 +                if (Module['canvas']) {
  30.157 +                    Module['canvas'].style['cursor'] = 'none';
  30.158 +                }
  30.159 +            );
  30.160 +        }
  30.161 +    }
  30.162 +    return 0;
  30.163 +}
  30.164 +
  30.165 +static void
  30.166 +Emscripten_WarpMouse(SDL_Window* window, int x, int y)
  30.167 +{
  30.168 +    SDL_Unsupported();
  30.169 +}
  30.170 +
  30.171 +static int
  30.172 +Emscripten_SetRelativeMouseMode(SDL_bool enabled)
  30.173 +{
  30.174 +    /* TODO: pointer lock isn't actually enabled yet */
  30.175 +    if(enabled) {
  30.176 +        if(emscripten_request_pointerlock(NULL, 1) >= EMSCRIPTEN_RESULT_SUCCESS) {
  30.177 +            return 0;
  30.178 +        }
  30.179 +    } else {
  30.180 +        if(emscripten_exit_pointerlock() >= EMSCRIPTEN_RESULT_SUCCESS) {
  30.181 +            return 0;
  30.182 +        }
  30.183 +    }
  30.184 +    return -1;
  30.185 +}
  30.186 +
  30.187 +void
  30.188 +Emscripten_InitMouse()
  30.189 +{
  30.190 +    SDL_Mouse* mouse = SDL_GetMouse();
  30.191 +
  30.192 +    mouse->CreateCursor         = Emscripten_CreateCursor;
  30.193 +    mouse->ShowCursor           = Emscripten_ShowCursor;
  30.194 +    mouse->FreeCursor           = Emscripten_FreeCursor;
  30.195 +    mouse->WarpMouse            = Emscripten_WarpMouse;
  30.196 +    mouse->CreateSystemCursor   = Emscripten_CreateSystemCursor;
  30.197 +    mouse->SetRelativeMouseMode = Emscripten_SetRelativeMouseMode;
  30.198 +
  30.199 +    SDL_SetDefaultCursor(Emscripten_CreateDefaultCursor());
  30.200 +}
  30.201 +
  30.202 +void
  30.203 +Emscripten_FiniMouse()
  30.204 +{
  30.205 +    SDL_Mouse* mouse = SDL_GetMouse();
  30.206 +
  30.207 +    Emscripten_FreeCursor(mouse->def_cursor);
  30.208 +    mouse->def_cursor = NULL;
  30.209 +
  30.210 +    mouse->CreateCursor         = NULL;
  30.211 +    mouse->ShowCursor           = NULL;
  30.212 +    mouse->FreeCursor           = NULL;
  30.213 +    mouse->WarpMouse            = NULL;
  30.214 +    mouse->CreateSystemCursor   = NULL;
  30.215 +    mouse->SetRelativeMouseMode = NULL;
  30.216 +}
  30.217 +
  30.218 +#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
  30.219 +
  30.220 +/* vi: set ts=4 sw=4 expandtab: */
  30.221 +
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/src/video/emscripten/SDL_emscriptenmouse.h	Thu Dec 18 00:19:52 2014 -0500
    31.3 @@ -0,0 +1,39 @@
    31.4 +/*
    31.5 +  Simple DirectMedia Layer
    31.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    31.7 +
    31.8 +  This software is provided 'as-is', without any express or implied
    31.9 +  warranty.  In no event will the authors be held liable for any damages
   31.10 +  arising from the use of this software.
   31.11 +
   31.12 +  Permission is granted to anyone to use this software for any purpose,
   31.13 +  including commercial applications, and to alter it and redistribute it
   31.14 +  freely, subject to the following restrictions:
   31.15 +
   31.16 +  1. The origin of this software must not be misrepresented; you must not
   31.17 +     claim that you wrote the original software. If you use this software
   31.18 +     in a product, an acknowledgment in the product documentation would be
   31.19 +     appreciated but is not required.
   31.20 +  2. Altered source versions must be plainly marked as such, and must not be
   31.21 +     misrepresented as being the original software.
   31.22 +  3. This notice may not be removed or altered from any source distribution.
   31.23 +*/
   31.24 +
   31.25 +
   31.26 +#ifndef _SDL_emscriptenmouse_h
   31.27 +#define _SDL_emscriptenmouse_h
   31.28 +
   31.29 +typedef struct _Emscripten_CursorData
   31.30 +{
   31.31 +    const char *system_cursor;
   31.32 +} Emscripten_CursorData;
   31.33 +
   31.34 +extern void
   31.35 +Emscripten_InitMouse();
   31.36 +
   31.37 +extern void
   31.38 +Emscripten_FiniMouse();
   31.39 +
   31.40 +#endif /* _SDL_emscriptenmouse_h */
   31.41 +
   31.42 +/* vi: set ts=4 sw=4 expandtab: */
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/src/video/emscripten/SDL_emscriptenopengles.c	Thu Dec 18 00:19:52 2014 -0500
    32.3 @@ -0,0 +1,117 @@
    32.4 +/*
    32.5 +  Simple DirectMedia Layer
    32.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    32.7 +
    32.8 +  This software is provided 'as-is', without any express or implied
    32.9 +  warranty.  In no event will the authors be held liable for any damages
   32.10 +  arising from the use of this software.
   32.11 +
   32.12 +  Permission is granted to anyone to use this software for any purpose,
   32.13 +  including commercial applications, and to alter it and redistribute it
   32.14 +  freely, subject to the following restrictions:
   32.15 +
   32.16 +  1. The origin of this software must not be misrepresented; you must not
   32.17 +     claim that you wrote the original software. If you use this software
   32.18 +     in a product, an acknowledgment in the product documentation would be
   32.19 +     appreciated but is not required.
   32.20 +  2. Altered source versions must be plainly marked as such, and must not be
   32.21 +     misrepresented as being the original software.
   32.22 +  3. This notice may not be removed or altered from any source distribution.
   32.23 +*/
   32.24 +#include "../../SDL_internal.h"
   32.25 +
   32.26 +#if SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL
   32.27 +
   32.28 +#include <emscripten/emscripten.h>
   32.29 +#include <GLES2/gl2.h>
   32.30 +
   32.31 +#include "SDL_emscriptenvideo.h"
   32.32 +#include "SDL_emscriptenopengles.h"
   32.33 +
   32.34 +#define LOAD_FUNC(NAME) _this->egl_data->NAME = NAME;
   32.35 +
   32.36 +/* EGL implementation of SDL OpenGL support */
   32.37 +
   32.38 +int
   32.39 +Emscripten_GLES_LoadLibrary(_THIS, const char *path) {
   32.40 +    /*we can't load EGL dynamically*/
   32.41 +    _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
   32.42 +    if (!_this->egl_data) {
   32.43 +        return SDL_OutOfMemory();
   32.44 +    }
   32.45 +    
   32.46 +    LOAD_FUNC(eglGetDisplay);
   32.47 +    LOAD_FUNC(eglInitialize);
   32.48 +    LOAD_FUNC(eglTerminate);
   32.49 +    LOAD_FUNC(eglGetProcAddress);
   32.50 +    LOAD_FUNC(eglChooseConfig);
   32.51 +    LOAD_FUNC(eglGetConfigAttrib);
   32.52 +    LOAD_FUNC(eglCreateContext);
   32.53 +    LOAD_FUNC(eglDestroyContext);
   32.54 +    LOAD_FUNC(eglCreateWindowSurface);
   32.55 +    LOAD_FUNC(eglDestroySurface);
   32.56 +    LOAD_FUNC(eglMakeCurrent);
   32.57 +    LOAD_FUNC(eglSwapBuffers);
   32.58 +    LOAD_FUNC(eglSwapInterval);
   32.59 +    LOAD_FUNC(eglWaitNative);
   32.60 +    LOAD_FUNC(eglWaitGL);
   32.61 +    LOAD_FUNC(eglBindAPI);
   32.62 +    
   32.63 +    _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(EGL_DEFAULT_DISPLAY);
   32.64 +    if (!_this->egl_data->egl_display) {
   32.65 +        return SDL_SetError("Could not get EGL display");
   32.66 +    }
   32.67 +    
   32.68 +    if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
   32.69 +        return SDL_SetError("Could not initialize EGL");
   32.70 +    }
   32.71 +
   32.72 +    _this->gl_config.driver_loaded = 1;
   32.73 +
   32.74 +    if (path) {
   32.75 +        SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
   32.76 +    } else {
   32.77 +        *_this->gl_config.driver_path = '\0';
   32.78 +    }
   32.79 +    
   32.80 +    return 0;
   32.81 +}
   32.82 +
   32.83 +void
   32.84 +Emscripten_GLES_DeleteContext(_THIS, SDL_GLContext context)
   32.85 +{
   32.86 +    /*
   32.87 +    WebGL contexts can't actually be deleted, so we need to reset it.
   32.88 +    ES2 renderer resets state on init anyway, clearing the canvas should be enough
   32.89 +    */
   32.90 +
   32.91 +    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
   32.92 +
   32.93 +    SDL_EGL_DeleteContext(_this, context);
   32.94 +}
   32.95 +
   32.96 +SDL_EGL_CreateContext_impl(Emscripten)
   32.97 +SDL_EGL_SwapWindow_impl(Emscripten)
   32.98 +SDL_EGL_MakeCurrent_impl(Emscripten)
   32.99 +
  32.100 +void
  32.101 +Emscripten_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
  32.102 +{
  32.103 +    SDL_WindowData *data;
  32.104 +    if (window->driverdata) {
  32.105 +        data = (SDL_WindowData *) window->driverdata;
  32.106 +
  32.107 +        if (w) {
  32.108 +            *w = window->w * data->pixel_ratio;
  32.109 +        }
  32.110 +
  32.111 +        if (h) {
  32.112 +            *h = window->h * data->pixel_ratio;
  32.113 +        }
  32.114 +    }
  32.115 +}
  32.116 +
  32.117 +#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL */
  32.118 +
  32.119 +/* vi: set ts=4 sw=4 expandtab: */
  32.120 +
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/src/video/emscripten/SDL_emscriptenopengles.h	Thu Dec 18 00:19:52 2014 -0500
    33.3 @@ -0,0 +1,49 @@
    33.4 +/*
    33.5 +  Simple DirectMedia Layer
    33.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    33.7 +
    33.8 +  This software is provided 'as-is', without any express or implied
    33.9 +  warranty.  In no event will the authors be held liable for any damages
   33.10 +  arising from the use of this software.
   33.11 +
   33.12 +  Permission is granted to anyone to use this software for any purpose,
   33.13 +  including commercial applications, and to alter it and redistribute it
   33.14 +  freely, subject to the following restrictions:
   33.15 +
   33.16 +  1. The origin of this software must not be misrepresented; you must not
   33.17 +     claim that you wrote the original software. If you use this software
   33.18 +     in a product, an acknowledgment in the product documentation would be
   33.19 +     appreciated but is not required.
   33.20 +  2. Altered source versions must be plainly marked as such, and must not be
   33.21 +     misrepresented as being the original software.
   33.22 +  3. This notice may not be removed or altered from any source distribution.
   33.23 +*/
   33.24 +#include "../../SDL_internal.h"
   33.25 +
   33.26 +#ifndef _SDL_emscriptenopengles_h
   33.27 +#define _SDL_emscriptenopengles_h
   33.28 +
   33.29 +#if SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL
   33.30 +
   33.31 +#include "../SDL_sysvideo.h"
   33.32 +#include "../SDL_egl_c.h"
   33.33 +
   33.34 +/* OpenGLES functions */
   33.35 +#define Emscripten_GLES_GetAttribute SDL_EGL_GetAttribute
   33.36 +#define Emscripten_GLES_GetProcAddress SDL_EGL_GetProcAddress
   33.37 +#define Emscripten_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
   33.38 +#define Emscripten_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
   33.39 +#define Emscripten_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
   33.40 +
   33.41 +extern int Emscripten_GLES_LoadLibrary(_THIS, const char *path);
   33.42 +extern void Emscripten_GLES_DeleteContext(_THIS, SDL_GLContext context);
   33.43 +extern SDL_GLContext Emscripten_GLES_CreateContext(_THIS, SDL_Window * window);
   33.44 +extern void Emscripten_GLES_SwapWindow(_THIS, SDL_Window * window);
   33.45 +extern int Emscripten_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
   33.46 +extern void Emscripten_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h);
   33.47 +
   33.48 +#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL */
   33.49 +
   33.50 +#endif /* _SDL_emscriptenopengles_h */
   33.51 +
   33.52 +/* vi: set ts=4 sw=4 expandtab: */
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/src/video/emscripten/SDL_emscriptenvideo.c	Thu Dec 18 00:19:52 2014 -0500
    34.3 @@ -0,0 +1,320 @@
    34.4 +/*
    34.5 +  Simple DirectMedia Layer
    34.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    34.7 +
    34.8 +  This software is provided 'as-is', without any express or implied
    34.9 +  warranty.  In no event will the authors be held liable for any damages
   34.10 +  arising from the use of this software.
   34.11 +
   34.12 +  Permission is granted to anyone to use this software for any purpose,
   34.13 +  including commercial applications, and to alter it and redistribute it
   34.14 +  freely, subject to the following restrictions:
   34.15 +
   34.16 +  1. The origin of this software must not be misrepresented; you must not
   34.17 +     claim that you wrote the original software. If you use this software
   34.18 +     in a product, an acknowledgment in the product documentation would be
   34.19 +     appreciated but is not required.
   34.20 +  2. Altered source versions must be plainly marked as such, and must not be
   34.21 +     misrepresented as being the original software.
   34.22 +  3. This notice may not be removed or altered from any source distribution.
   34.23 +*/
   34.24 +#include "../../SDL_internal.h"
   34.25 +
   34.26 +#if SDL_VIDEO_DRIVER_EMSCRIPTEN
   34.27 +
   34.28 +#include "SDL_video.h"
   34.29 +#include "SDL_mouse.h"
   34.30 +#include "../SDL_sysvideo.h"
   34.31 +#include "../SDL_pixels_c.h"
   34.32 +#include "../SDL_egl_c.h"
   34.33 +#include "../../events/SDL_events_c.h"
   34.34 +
   34.35 +#include "SDL_emscriptenvideo.h"
   34.36 +#include "SDL_emscriptenopengles.h"
   34.37 +#include "SDL_emscriptenframebuffer.h"
   34.38 +#include "SDL_emscriptenevents.h"
   34.39 +#include "SDL_emscriptenmouse.h"
   34.40 +
   34.41 +#define EMSCRIPTENVID_DRIVER_NAME "emscripten"
   34.42 +
   34.43 +/* Initialization/Query functions */
   34.44 +static int Emscripten_VideoInit(_THIS);
   34.45 +static int Emscripten_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
   34.46 +static void Emscripten_VideoQuit(_THIS);
   34.47 +
   34.48 +static int Emscripten_CreateWindow(_THIS, SDL_Window * window);
   34.49 +static void Emscripten_SetWindowSize(_THIS, SDL_Window * window);
   34.50 +static void Emscripten_DestroyWindow(_THIS, SDL_Window * window);
   34.51 +static void Emscripten_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
   34.52 +static void Emscripten_PumpEvents(_THIS);
   34.53 +
   34.54 +
   34.55 +/* Emscripten driver bootstrap functions */
   34.56 +
   34.57 +static int
   34.58 +Emscripten_Available(void)
   34.59 +{
   34.60 +    return (1);
   34.61 +}
   34.62 +
   34.63 +static void
   34.64 +Emscripten_DeleteDevice(SDL_VideoDevice * device)
   34.65 +{
   34.66 +    SDL_free(device);
   34.67 +}
   34.68 +
   34.69 +static SDL_VideoDevice *
   34.70 +Emscripten_CreateDevice(int devindex)
   34.71 +{
   34.72 +    SDL_VideoDevice *device;
   34.73 +
   34.74 +    /* Initialize all variables that we clean on shutdown */
   34.75 +    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
   34.76 +    if (!device) {
   34.77 +        SDL_OutOfMemory();
   34.78 +        SDL_free(device);
   34.79 +        return (0);
   34.80 +    }
   34.81 +
   34.82 +    /* Set the function pointers */
   34.83 +    device->VideoInit = Emscripten_VideoInit;
   34.84 +    device->VideoQuit = Emscripten_VideoQuit;
   34.85 +    device->SetDisplayMode = Emscripten_SetDisplayMode;
   34.86 +
   34.87 +
   34.88 +    device->PumpEvents = Emscripten_PumpEvents;
   34.89 +
   34.90 +    device->CreateWindow = Emscripten_CreateWindow;
   34.91 +    /*device->CreateWindowFrom = Emscripten_CreateWindowFrom;
   34.92 +    device->SetWindowTitle = Emscripten_SetWindowTitle;
   34.93 +    device->SetWindowIcon = Emscripten_SetWindowIcon;
   34.94 +    device->SetWindowPosition = Emscripten_SetWindowPosition;*/
   34.95 +    device->SetWindowSize = Emscripten_SetWindowSize;
   34.96 +    /*device->ShowWindow = Emscripten_ShowWindow;
   34.97 +    device->HideWindow = Emscripten_HideWindow;
   34.98 +    device->RaiseWindow = Emscripten_RaiseWindow;
   34.99 +    device->MaximizeWindow = Emscripten_MaximizeWindow;
  34.100 +    device->MinimizeWindow = Emscripten_MinimizeWindow;
  34.101 +    device->RestoreWindow = Emscripten_RestoreWindow;
  34.102 +    device->SetWindowGrab = Emscripten_SetWindowGrab;*/
  34.103 +    device->DestroyWindow = Emscripten_DestroyWindow;
  34.104 +    device->SetWindowFullscreen = Emscripten_SetWindowFullscreen;
  34.105 +
  34.106 +    device->CreateWindowFramebuffer = Emscripten_CreateWindowFramebuffer;
  34.107 +    device->UpdateWindowFramebuffer = Emscripten_UpdateWindowFramebuffer;
  34.108 +    device->DestroyWindowFramebuffer = Emscripten_DestroyWindowFramebuffer;
  34.109 +
  34.110 +    device->GL_LoadLibrary = Emscripten_GLES_LoadLibrary;
  34.111 +    device->GL_GetProcAddress = Emscripten_GLES_GetProcAddress;
  34.112 +    device->GL_UnloadLibrary = Emscripten_GLES_UnloadLibrary;
  34.113 +    device->GL_CreateContext = Emscripten_GLES_CreateContext;
  34.114 +    device->GL_MakeCurrent = Emscripten_GLES_MakeCurrent;
  34.115 +    device->GL_SetSwapInterval = Emscripten_GLES_SetSwapInterval;
  34.116 +    device->GL_GetSwapInterval = Emscripten_GLES_GetSwapInterval;
  34.117 +    device->GL_SwapWindow = Emscripten_GLES_SwapWindow;
  34.118 +    device->GL_DeleteContext = Emscripten_GLES_DeleteContext;
  34.119 +    device->GL_GetDrawableSize = Emscripten_GLES_GetDrawableSize;
  34.120 +
  34.121 +    device->free = Emscripten_DeleteDevice;
  34.122 +
  34.123 +    return device;
  34.124 +}
  34.125 +
  34.126 +VideoBootStrap Emscripten_bootstrap = {
  34.127 +    EMSCRIPTENVID_DRIVER_NAME, "SDL emscripten video driver",
  34.128 +    Emscripten_Available, Emscripten_CreateDevice
  34.129 +};
  34.130 +
  34.131 +
  34.132 +int
  34.133 +Emscripten_VideoInit(_THIS)
  34.134 +{
  34.135 +    SDL_DisplayMode mode;
  34.136 +    double css_w, css_h;
  34.137 +
  34.138 +    /* Use a fake 32-bpp desktop mode */
  34.139 +    mode.format = SDL_PIXELFORMAT_RGB888;
  34.140 +
  34.141 +    emscripten_get_element_css_size(NULL, &css_w, &css_h);
  34.142 +
  34.143 +    mode.w = css_w;
  34.144 +    mode.h = css_h;
  34.145 +
  34.146 +    mode.refresh_rate = 0;
  34.147 +    mode.driverdata = NULL;
  34.148 +    if (SDL_AddBasicVideoDisplay(&mode) < 0) {
  34.149 +        return -1;
  34.150 +    }
  34.151 +
  34.152 +    SDL_zero(mode);
  34.153 +    SDL_AddDisplayMode(&_this->displays[0], &mode);
  34.154 +
  34.155 +    Emscripten_InitMouse();
  34.156 +
  34.157 +    /* We're done! */
  34.158 +    return 0;
  34.159 +}
  34.160 +
  34.161 +static int
  34.162 +Emscripten_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
  34.163 +{
  34.164 +    /* can't do this */
  34.165 +    return 0;
  34.166 +}
  34.167 +
  34.168 +static void
  34.169 +Emscripten_VideoQuit(_THIS)
  34.170 +{
  34.171 +    Emscripten_FiniMouse();
  34.172 +}
  34.173 +
  34.174 +static void
  34.175 +Emscripten_PumpEvents(_THIS)
  34.176 +{
  34.177 +    /* do nothing. */
  34.178 +}
  34.179 +
  34.180 +static int
  34.181 +Emscripten_CreateWindow(_THIS, SDL_Window * window)
  34.182 +{
  34.183 +    SDL_WindowData *wdata;
  34.184 +    double scaled_w, scaled_h;
  34.185 +    double css_w, css_h;
  34.186 +
  34.187 +    /* Allocate window internal data */
  34.188 +    wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
  34.189 +    if (wdata == NULL) {
  34.190 +        return SDL_OutOfMemory();
  34.191 +    }
  34.192 +
  34.193 +    if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
  34.194 +        wdata->pixel_ratio = emscripten_get_device_pixel_ratio();
  34.195 +    } else {
  34.196 +        wdata->pixel_ratio = 1.0f;
  34.197 +    }
  34.198 +
  34.199 +    scaled_w = SDL_floor(window->w * wdata->pixel_ratio);
  34.200 +    scaled_h = SDL_floor(window->h * wdata->pixel_ratio);
  34.201 +
  34.202 +    emscripten_set_canvas_size(scaled_w, scaled_h);
  34.203 +
  34.204 +    emscripten_get_element_css_size(NULL, &css_w, &css_h);
  34.205 +
  34.206 +    wdata->external_size = css_w != scaled_w || css_h != scaled_h;
  34.207 +
  34.208 +    if ((window->flags & SDL_WINDOW_RESIZABLE) && wdata->external_size) {
  34.209 +        /* external css has resized us */
  34.210 +        scaled_w = css_w * wdata->pixel_ratio;
  34.211 +        scaled_h = css_h * wdata->pixel_ratio;
  34.212 +
  34.213 +        emscripten_set_canvas_size(scaled_w, scaled_h);
  34.214 +        SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, css_w, css_h);
  34.215 +    }
  34.216 +
  34.217 +    /* if the size is not being controlled by css, we need to scale down for hidpi */
  34.218 +    if (!wdata->external_size) {
  34.219 +        if (wdata->pixel_ratio != 1.0f) {
  34.220 +            /*scale canvas down*/
  34.221 +            emscripten_set_element_css_size(NULL, window->w, window->h);
  34.222 +        }
  34.223 +    }
  34.224 +
  34.225 +    wdata->windowed_width = scaled_w;
  34.226 +    wdata->windowed_height = scaled_h;
  34.227 +
  34.228 +    if (window->flags & SDL_WINDOW_OPENGL) {
  34.229 +        if (!_this->egl_data) {
  34.230 +            if (SDL_GL_LoadLibrary(NULL) < 0) {
  34.231 +                return -1;
  34.232 +            }
  34.233 +        }
  34.234 +        wdata->egl_surface = SDL_EGL_CreateSurface(_this, NULL);
  34.235 +
  34.236 +        if (wdata->egl_surface == EGL_NO_SURFACE) {
  34.237 +            return SDL_SetError("Could not create GLES window surface");
  34.238 +        }
  34.239 +    }
  34.240 +
  34.241 +    wdata->window = window;
  34.242 +
  34.243 +    /* Setup driver data for this window */
  34.244 +    window->driverdata = wdata;
  34.245 +
  34.246 +    /* One window, it always has focus */
  34.247 +    SDL_SetMouseFocus(window);
  34.248 +    SDL_SetKeyboardFocus(window);
  34.249 +
  34.250 +    Emscripten_RegisterEventHandlers(wdata);
  34.251 +
  34.252 +    /* Window has been successfully created */
  34.253 +    return 0;
  34.254 +}
  34.255 +
  34.256 +static void Emscripten_SetWindowSize(_THIS, SDL_Window * window)
  34.257 +{
  34.258 +    SDL_WindowData *data;
  34.259 +
  34.260 +    if (window->driverdata) {
  34.261 +        data = (SDL_WindowData *) window->driverdata;
  34.262 +        emscripten_set_canvas_size(window->w * data->pixel_ratio, window->h * data->pixel_ratio);
  34.263 +
  34.264 +        /*scale canvas down*/
  34.265 +        if (!data->external_size && data->pixel_ratio != 1.0f) {
  34.266 +            emscripten_set_element_css_size(NULL, window->w, window->h);
  34.267 +        }
  34.268 +    }
  34.269 +}
  34.270 +
  34.271 +static void
  34.272 +Emscripten_DestroyWindow(_THIS, SDL_Window * window)
  34.273 +{
  34.274 +    SDL_WindowData *data;
  34.275 +
  34.276 +    if(window->driverdata) {
  34.277 +        data = (SDL_WindowData *) window->driverdata;
  34.278 +
  34.279 +        Emscripten_UnregisterEventHandlers(data);
  34.280 +        if (data->egl_surface != EGL_NO_SURFACE) {
  34.281 +            SDL_EGL_DestroySurface(_this, data->egl_surface);
  34.282 +            data->egl_surface = EGL_NO_SURFACE;
  34.283 +        }
  34.284 +        SDL_free(window->driverdata);
  34.285 +        window->driverdata = NULL;
  34.286 +    }
  34.287 +}
  34.288 +
  34.289 +static void
  34.290 +Emscripten_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
  34.291 +{
  34.292 +    SDL_WindowData *data;
  34.293 +    if(window->driverdata) {
  34.294 +        data = (SDL_WindowData *) window->driverdata;
  34.295 +
  34.296 +        if(fullscreen) {
  34.297 +            data->requested_fullscreen_mode = window->flags & (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN);
  34.298 +            /*unset the fullscreen flags as we're not actually fullscreen yet*/
  34.299 +            window->flags &= ~(SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN);
  34.300 +
  34.301 +            EM_ASM({
  34.302 +                //reparent canvas (similar to Module.requestFullscreen)
  34.303 +                var canvas = Module['canvas'];
  34.304 +                if(canvas.parentNode.id != "SDLFullscreenElement") {
  34.305 +                    var canvasContainer = document.createElement("div");
  34.306 +                    canvasContainer.id = "SDLFullscreenElement";
  34.307 +                    canvas.parentNode.insertBefore(canvasContainer, canvas);
  34.308 +                    canvasContainer.appendChild(canvas);
  34.309 +                }
  34.310 +            });
  34.311 +
  34.312 +            int is_fullscreen;
  34.313 +            emscripten_get_canvas_size(&data->windowed_width, &data->windowed_height, &is_fullscreen);
  34.314 +            emscripten_request_fullscreen("SDLFullscreenElement", 1);
  34.315 +        }
  34.316 +        else
  34.317 +            emscripten_exit_fullscreen();
  34.318 +    }
  34.319 +}
  34.320 +
  34.321 +#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
  34.322 +
  34.323 +/* vi: set ts=4 sw=4 expandtab: */
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/src/video/emscripten/SDL_emscriptenvideo.h	Thu Dec 18 00:19:52 2014 -0500
    35.3 @@ -0,0 +1,52 @@
    35.4 +/*
    35.5 +  Simple DirectMedia Layer
    35.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    35.7 +
    35.8 +  This software is provided 'as-is', without any express or implied
    35.9 +  warranty.  In no event will the authors be held liable for any damages
   35.10 +  arising from the use of this software.
   35.11 +
   35.12 +  Permission is granted to anyone to use this software for any purpose,
   35.13 +  including commercial applications, and to alter it and redistribute it
   35.14 +  freely, subject to the following restrictions:
   35.15 +
   35.16 +  1. The origin of this software must not be misrepresented; you must not
   35.17 +     claim that you wrote the original software. If you use this software
   35.18 +     in a product, an acknowledgment in the product documentation would be
   35.19 +     appreciated but is not required.
   35.20 +  2. Altered source versions must be plainly marked as such, and must not be
   35.21 +     misrepresented as being the original software.
   35.22 +  3. This notice may not be removed or altered from any source distribution.
   35.23 +*/
   35.24 +#include "../../SDL_internal.h"
   35.25 +
   35.26 +#ifndef _SDL_emscriptenvideo_h
   35.27 +#define _SDL_emscriptenvideo_h
   35.28 +
   35.29 +#include "../SDL_sysvideo.h"
   35.30 +#include <emscripten/emscripten.h>
   35.31 +#include <emscripten/html5.h>
   35.32 +
   35.33 +#include <EGL/egl.h>
   35.34 +
   35.35 +typedef struct SDL_WindowData
   35.36 +{
   35.37 +#if SDL_VIDEO_OPENGL_EGL
   35.38 +    EGLSurface egl_surface;
   35.39 +#endif
   35.40 +    SDL_Window *window;
   35.41 +    SDL_Surface *surface;
   35.42 +
   35.43 +    int windowed_width;
   35.44 +    int windowed_height;
   35.45 +
   35.46 +    float pixel_ratio;
   35.47 +
   35.48 +    SDL_bool external_size;
   35.49 +
   35.50 +    int requested_fullscreen_mode;
   35.51 +} SDL_WindowData;
   35.52 +
   35.53 +#endif /* _SDL_emscriptenvideo_h */
   35.54 +
   35.55 +/* vi: set ts=4 sw=4 expandtab: */
    36.1 --- a/test/Makefile.in	Sat Dec 13 02:33:52 2014 -0500
    36.2 +++ b/test/Makefile.in	Thu Dec 18 00:19:52 2014 -0500
    36.3 @@ -38,6 +38,7 @@
    36.4  	testloadso$(EXE) \
    36.5  	testlock$(EXE) \
    36.6  	testmultiaudio$(EXE) \
    36.7 +	testmultiaudio2$(EXE) \
    36.8  	testnative$(EXE) \
    36.9  	testoverlay2$(EXE) \
   36.10  	testplatform$(EXE) \
   36.11 @@ -105,6 +106,9 @@
   36.12  testmultiaudio$(EXE): $(srcdir)/testmultiaudio.c
   36.13  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
   36.14  
   36.15 +testmultiaudio2$(EXE): $(srcdir)/testmultiaudio2.c
   36.16 +	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
   36.17 +
   36.18  testatomic$(EXE): $(srcdir)/testatomic.c
   36.19  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
   36.20  
   36.21 @@ -196,6 +200,15 @@
   36.22  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @XLIB@
   36.23  endif
   36.24  
   36.25 +#there's probably a better way of doing this
   36.26 +ifeq (@ISMACOSX@,false)
   36.27 +ifeq (@ISWINDOWS@,false)
   36.28 +ifeq (@ISUNIX@,false)
   36.29 +testnative$(EXE): ;
   36.30 +endif
   36.31 +endif
   36.32 +endif
   36.33 +
   36.34  testoverlay2$(EXE): $(srcdir)/testoverlay2.c
   36.35  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
   36.36  
    37.1 --- a/test/checkkeys.c	Sat Dec 13 02:33:52 2014 -0500
    37.2 +++ b/test/checkkeys.c	Thu Dec 18 00:19:52 2014 -0500
    37.3 @@ -19,8 +19,14 @@
    37.4  #include <stdlib.h>
    37.5  #include <string.h>
    37.6  
    37.7 +#ifdef __EMSCRIPTEN__
    37.8 +#include <emscripten/emscripten.h>
    37.9 +#endif
   37.10 +
   37.11  #include "SDL.h"
   37.12  
   37.13 +int done;
   37.14 +
   37.15  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   37.16  static void
   37.17  quit(int rc)
   37.18 @@ -128,12 +134,37 @@
   37.19      SDL_Log("Text (%s): \"%s%s\"\n", expanded, *text == '"' ? "\\" : "", text);
   37.20  }
   37.21  
   37.22 +void
   37.23 +loop()
   37.24 +{
   37.25 +    SDL_Event event;
   37.26 +    /* Check for events */
   37.27 +    /*SDL_WaitEvent(&event); emscripten does not like waiting*/
   37.28 +
   37.29 +    while (SDL_PollEvent(&event)) {
   37.30 +        switch (event.type) {
   37.31 +        case SDL_KEYDOWN:
   37.32 +        //case SDL_KEYUP:
   37.33 +		    PrintKey(&event.key.keysym, (event.key.state == SDL_PRESSED) ? SDL_TRUE : SDL_FALSE, (event.key.repeat) ? SDL_TRUE : SDL_FALSE);
   37.34 +            break;
   37.35 +        case SDL_TEXTINPUT:
   37.36 +            PrintText(event.text.text);
   37.37 +            break;
   37.38 +        case SDL_MOUSEBUTTONDOWN:
   37.39 +            /* Any button press quits the app... */
   37.40 +        case SDL_QUIT:
   37.41 +            done = 1;
   37.42 +            break;
   37.43 +        default:
   37.44 +            break;
   37.45 +        }
   37.46 +    }
   37.47 +}
   37.48 +
   37.49  int
   37.50  main(int argc, char *argv[])
   37.51  {
   37.52      SDL_Window *window;
   37.53 -    SDL_Event event;
   37.54 -    int done;
   37.55  	
   37.56  	/* Enable standard application logging */
   37.57  	SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   37.58 @@ -163,26 +194,14 @@
   37.59  
   37.60      /* Watch keystrokes */
   37.61      done = 0;
   37.62 +
   37.63 +#ifdef __EMSCRIPTEN__
   37.64 +    emscripten_set_main_loop(loop, 0, 1);
   37.65 +#else
   37.66      while (!done) {
   37.67 -        /* Check for events */
   37.68 -        SDL_WaitEvent(&event);
   37.69 -        switch (event.type) {
   37.70 -        case SDL_KEYDOWN:
   37.71 -        case SDL_KEYUP:
   37.72 -			PrintKey(&event.key.keysym, (event.key.state == SDL_PRESSED) ? SDL_TRUE : SDL_FALSE, (event.key.repeat) ? SDL_TRUE : SDL_FALSE);
   37.73 -            break;
   37.74 -        case SDL_TEXTINPUT:
   37.75 -            PrintText(event.text.text);
   37.76 -            break;
   37.77 -        case SDL_MOUSEBUTTONDOWN:
   37.78 -            /* Any button press quits the app... */
   37.79 -        case SDL_QUIT:
   37.80 -            done = 1;
   37.81 -            break;
   37.82 -        default:
   37.83 -            break;
   37.84 -        }
   37.85 +        loop();
   37.86      }
   37.87 +#endif
   37.88  
   37.89      SDL_Quit();
   37.90      return (0);
    38.1 --- a/test/configure	Sat Dec 13 02:33:52 2014 -0500
    38.2 +++ b/test/configure	Thu Dec 18 00:19:52 2014 -0500
    38.3 @@ -2980,6 +2980,11 @@
    38.4          MATHLIB=""
    38.5          SYS_GL_LIBS="-lGLES_CM"
    38.6          ;;
    38.7 +    *-*-emscripten* )
    38.8 +                EXE=".bc"
    38.9 +        MATHLIB=""
   38.10 +        SYS_GL_LIBS=""
   38.11 +        ;;
   38.12      *)
   38.13                  ISUNIX="true"
   38.14          EXE=""
    39.1 --- a/test/configure.in	Sat Dec 13 02:33:52 2014 -0500
    39.2 +++ b/test/configure.in	Thu Dec 18 00:19:52 2014 -0500
    39.3 @@ -65,6 +65,12 @@
    39.4          MATHLIB=""
    39.5          SYS_GL_LIBS="-lGLES_CM"
    39.6          ;;
    39.7 +    *-*-emscripten* )
    39.8 +        dnl This should really be .js, but we need to specify extra flags when compiling to js
    39.9 +        EXE=".bc"
   39.10 +        MATHLIB=""
   39.11 +        SYS_GL_LIBS=""
   39.12 +        ;;
   39.13      *)
   39.14          dnl Oh well, call it Unix...
   39.15          ISUNIX="true"
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/test/emscripten/joystick-pre.js	Thu Dec 18 00:19:52 2014 -0500
    40.3 @@ -0,0 +1,25 @@
    40.4 +Module['arguments'] = ['0'];
    40.5 +//Gamepads don't appear until a button is pressed and the joystick/gamepad tests expect one to be connected
    40.6 +Module['preRun'].push(function()
    40.7 +{
    40.8 +    Module['print']("Waiting for gamepad...");
    40.9 +    Module['addRunDependency']("gamepad");
   40.10 +    window.addEventListener('gamepadconnected', function()
   40.11 +    {
   40.12 +        //OK, got one
   40.13 +        Module['removeRunDependency']("gamepad");
   40.14 +    }, false);
   40.15 +
   40.16 +    //chrome
   40.17 +    if(!!navigator.webkitGetGamepads)
   40.18 +    {
   40.19 +        var timeout = function()
   40.20 +        {
   40.21 +            if(navigator.webkitGetGamepads()[0] !== undefined)
   40.22 +                Module['removeRunDependency']("gamepad");
   40.23 +            else
   40.24 +                setTimeout(timeout, 100);
   40.25 +        }
   40.26 +        setTimeout(timeout, 100);
   40.27 +    }
   40.28 +});
    41.1 --- a/test/loopwave.c	Sat Dec 13 02:33:52 2014 -0500
    41.2 +++ b/test/loopwave.c	Thu Dec 18 00:19:52 2014 -0500
    41.3 @@ -24,6 +24,10 @@
    41.4  #include <signal.h>
    41.5  #endif
    41.6  
    41.7 +#ifdef __EMSCRIPTEN__
    41.8 +#include <emscripten/emscripten.h>
    41.9 +#endif
   41.10 +
   41.11  #include "SDL.h"
   41.12  #include "SDL_audio.h"
   41.13  
   41.14 @@ -75,6 +79,13 @@
   41.15      done = 1;
   41.16  }
   41.17  
   41.18 +void
   41.19 +loop()
   41.20 +{
   41.21 +    if(done || (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING))
   41.22 +        emscripten_cancel_main_loop();
   41.23 +}
   41.24 +
   41.25  int
   41.26  main(int argc, char *argv[])
   41.27  {
   41.28 @@ -131,8 +142,13 @@
   41.29  
   41.30      /* Let the audio run */
   41.31      SDL_PauseAudio(0);
   41.32 +
   41.33 +#ifdef __EMSCRIPTEN__
   41.34 +    emscripten_set_main_loop(loop, 0, 1);
   41.35 +#else
   41.36      while (!done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING))
   41.37          SDL_Delay(1000);
   41.38 +#endif
   41.39  
   41.40      /* Clean up on signal */
   41.41      SDL_CloseAudio();
    42.1 --- a/test/testautomation_surface.c	Sat Dec 13 02:33:52 2014 -0500
    42.2 +++ b/test/testautomation_surface.c	Thu Dec 18 00:19:52 2014 -0500
    42.3 @@ -8,6 +8,7 @@
    42.4  #define _CRT_NONSTDC_NO_DEPRECATE
    42.5  
    42.6  #include <stdio.h>
    42.7 +#include <unistd.h>
    42.8  #include <sys/stat.h>
    42.9  
   42.10  #include "SDL.h"
    43.1 --- a/test/testdraw2.c	Sat Dec 13 02:33:52 2014 -0500
    43.2 +++ b/test/testdraw2.c	Thu Dec 18 00:19:52 2014 -0500
    43.3 @@ -16,6 +16,10 @@
    43.4  #include <stdio.h>
    43.5  #include <time.h>
    43.6  
    43.7 +#ifdef __EMSCRIPTEN__
    43.8 +#include <emscripten/emscripten.h>
    43.9 +#endif
   43.10 +
   43.11  #include "SDL_test_common.h"
   43.12  
   43.13  #define NUM_OBJECTS 100
   43.14 @@ -29,6 +33,8 @@
   43.15  static int current_color = 255;
   43.16  static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE;
   43.17  
   43.18 +int done;
   43.19 +
   43.20  void
   43.21  DrawPoints(SDL_Renderer * renderer)
   43.22  {
   43.23 @@ -169,11 +175,35 @@
   43.24      }
   43.25  }
   43.26  
   43.27 +void
   43.28 +loop()
   43.29 +{
   43.30 +    int i;
   43.31 +    SDL_Event event;
   43.32 +
   43.33 +    /* Check for events */
   43.34 +    while (SDL_PollEvent(&event)) {
   43.35 +        SDLTest_CommonEvent(state, &event, &done);
   43.36 +    }
   43.37 +    for (i = 0; i < state->num_windows; ++i) {
   43.38 +        SDL_Renderer *renderer = state->renderers[i];
   43.39 +        if (state->windows[i] == NULL)
   43.40 +            continue;
   43.41 +        SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
   43.42 +        SDL_RenderClear(renderer);
   43.43 +
   43.44 +        DrawRects(renderer);
   43.45 +        DrawLines(renderer);
   43.46 +        DrawPoints(renderer);
   43.47 +
   43.48 +        SDL_RenderPresent(renderer);
   43.49 +    }
   43.50 +}
   43.51 +
   43.52  int
   43.53  main(int argc, char *argv[])
   43.54  {
   43.55 -    int i, done;
   43.56 -    SDL_Event event;
   43.57 +    int i;
   43.58      Uint32 then, now, frames;
   43.59  
   43.60  	/* Enable standard application logging */
   43.61 @@ -245,26 +275,16 @@
   43.62      frames = 0;
   43.63      then = SDL_GetTicks();
   43.64      done = 0;
   43.65 +
   43.66 +#ifdef __EMSCRIPTEN__
   43.67 +    emscripten_set_main_loop(loop, 0, 1);
   43.68 +#else
   43.69      while (!done) {
   43.70 -        /* Check for events */
   43.71          ++frames;
   43.72 -        while (SDL_PollEvent(&event)) {
   43.73 -            SDLTest_CommonEvent(state, &event, &done);
   43.74 +        loop();
   43.75          }
   43.76 -        for (i = 0; i < state->num_windows; ++i) {
   43.77 -            SDL_Renderer *renderer = state->renderers[i];
   43.78 -            if (state->windows[i] == NULL)
   43.79 -                continue;
   43.80 -            SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
   43.81 -            SDL_RenderClear(renderer);
   43.82 +#endif
   43.83  
   43.84 -            DrawRects(renderer);
   43.85 -            DrawLines(renderer);
   43.86 -            DrawPoints(renderer);
   43.87 -
   43.88 -            SDL_RenderPresent(renderer);
   43.89 -        }
   43.90 -    }
   43.91  
   43.92      SDLTest_CommonQuit(state);
   43.93  
    44.1 --- a/test/testdrawchessboard.c	Sat Dec 13 02:33:52 2014 -0500
    44.2 +++ b/test/testdrawchessboard.c	Thu Dec 18 00:19:52 2014 -0500
    44.3 @@ -14,8 +14,19 @@
    44.4  
    44.5  /* Sample program:  Draw a Chess Board  by using SDL_CreateSoftwareRenderer API */
    44.6  
    44.7 +#include <stdlib.h>
    44.8 +#include <stdio.h>
    44.9 +
   44.10 +#ifdef __EMSCRIPTEN__
   44.11 +#include <emscripten/emscripten.h>
   44.12 +#endif
   44.13 +
   44.14  #include "SDL.h"
   44.15  
   44.16 +SDL_Window *window;
   44.17 +SDL_Renderer *renderer;
   44.18 +int done;
   44.19 +
   44.20  void
   44.21  DrawChessBoard(SDL_Renderer * renderer)
   44.22  {
   44.23 @@ -44,12 +55,33 @@
   44.24  	}
   44.25  }
   44.26  
   44.27 +void
   44.28 +loop()
   44.29 +{
   44.30 +    SDL_Event e;
   44.31 +	if (SDL_PollEvent(&e)) {
   44.32 +		if (e.type == SDL_QUIT) {
   44.33 +			done = 1;
   44.34 +			return;
   44.35 +		}
   44.36 +
   44.37 +		if(e.key.keysym.sym == SDLK_ESCAPE) {
   44.38 +			done = 1;
   44.39 +			return;
   44.40 +		}
   44.41 +	}
   44.42 +	
   44.43 +	DrawChessBoard(renderer);
   44.44 +	
   44.45 +	/* Got everything on rendering surface,
   44.46 +	   now Update the drawing image on window screen */
   44.47 +	SDL_UpdateWindowSurface(window);
   44.48 +}
   44.49 +
   44.50  int
   44.51  main(int argc, char *argv[])
   44.52  {
   44.53 -	SDL_Window *window;
   44.54  	SDL_Surface *surface;
   44.55 -	SDL_Renderer *renderer;
   44.56  
   44.57      /* Enable standard application logging */
   44.58      SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   44.59 @@ -83,24 +115,14 @@
   44.60  
   44.61  
   44.62  	/* Draw the Image on rendering surface */
   44.63 -	while(1)
   44.64 -	{
   44.65 -		SDL_Event e;
   44.66 -		if (SDL_PollEvent(&e)) {
   44.67 -			if (e.type == SDL_QUIT) 
   44.68 -				break;
   44.69 -
   44.70 -			if(e.key.keysym.sym == SDLK_ESCAPE)
   44.71 -				break;
   44.72 -		}
   44.73 -		
   44.74 -		DrawChessBoard(renderer);
   44.75 -		
   44.76 -		/* Got everything on rendering surface,
   44.77 - 		   now Update the drawing image on window screen */
   44.78 -		SDL_UpdateWindowSurface(window);
   44.79 -
   44.80 +	done = 0;
   44.81 +#ifdef __EMSCRIPTEN__
   44.82 +    emscripten_set_main_loop(loop, 0, 1);
   44.83 +#else
   44.84 +    while (!done) {
   44.85 +        loop();
   44.86  	}
   44.87 +#endif
   44.88  
   44.89  	return 0;
   44.90  }
    45.1 --- a/test/testfilesystem.c	Sat Dec 13 02:33:52 2014 -0500
    45.2 +++ b/test/testfilesystem.c	Thu Dec 18 00:19:52 2014 -0500
    45.3 @@ -25,6 +25,25 @@
    45.4          return 1;
    45.5      }
    45.6  
    45.7 +    char *base_path = SDL_GetBasePath();
    45.8 +    if(base_path == NULL){
    45.9 +      SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find base path: %s\n",
   45.10 +                   SDL_GetError());
   45.11 +      return 0;
   45.12 +    }
   45.13 +
   45.14 +    SDL_Log("base path: '%s'\n", SDL_GetBasePath());
   45.15 +    SDL_free(base_path);
   45.16 +
   45.17 +    char *pref_path = SDL_GetPrefPath("libsdl", "testfilesystem");
   45.18 +    if(pref_path == NULL){
   45.19 +      SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find pref path: %s\n",
   45.20 +                   SDL_GetError());
   45.21 +      return 0;
   45.22 +    }
   45.23 +    SDL_Log("pref path: '%s'\n", SDL_GetPrefPath("libsdl", "testfilesystem"));
   45.24 +    SDL_free(pref_path);
   45.25 +
   45.26      SDL_Log("base path: '%s'\n", SDL_GetBasePath());
   45.27      SDL_Log("pref path: '%s'\n", SDL_GetPrefPath("libsdl", "testfilesystem"));
   45.28  
    46.1 --- a/test/testgamecontroller.c	Sat Dec 13 02:33:52 2014 -0500
    46.2 +++ b/test/testgamecontroller.c	Thu Dec 18 00:19:52 2014 -0500
    46.3 @@ -18,6 +18,10 @@
    46.4  
    46.5  #include "SDL.h"
    46.6  
    46.7 +#ifdef __EMSCRIPTEN__
    46.8 +#include <emscripten/emscripten.h>
    46.9 +#endif
   46.10 +
   46.11  #ifndef SDL_JOYSTICK_DISABLED
   46.12  
   46.13  #ifdef __IPHONEOS__
   46.14 @@ -28,6 +32,40 @@
   46.15  #define SCREEN_HEIGHT   317
   46.16  #endif
   46.17  
   46.18 +/* This is indexed by SDL_GameControllerButton. */
   46.19 +static const struct { int x; int y; } button_positions[] = {
   46.20 +    {387, 167},  /* A */
   46.21 +    {431, 132},  /* B */
   46.22 +    {342, 132},  /* X */
   46.23 +    {389, 101},  /* Y */
   46.24 +    {174, 132},  /* BACK */
   46.25 +    {233, 132},  /* GUIDE */
   46.26 +    {289, 132},  /* START */
   46.27 +    {75,  154},  /* LEFTSTICK */
   46.28 +    {305, 230},  /* RIGHTSTICK */
   46.29 +    {77,  40},   /* LEFTSHOULDER */
   46.30 +    {396, 36},   /* RIGHTSHOULDER */
   46.31 +    {154, 188},  /* DPAD_UP */
   46.32 +    {154, 249},  /* DPAD_DOWN */
   46.33 +    {116, 217},  /* DPAD_LEFT */
   46.34 +    {186, 217},  /* DPAD_RIGHT */
   46.35 +};
   46.36 +
   46.37 +/* This is indexed by SDL_GameControllerAxis. */
   46.38 +static const struct { int x; int y; double angle; } axis_positions[] = {
   46.39 +    {75,  154, 0.0},  /* LEFTX */
   46.40 +    {75,  154, 90.0},  /* LEFTY */
   46.41 +    {305, 230, 0.0},  /* RIGHTX */
   46.42 +    {305, 230, 90.0},  /* RIGHTY */
   46.43 +    {91, 0, 90.0},     /* TRIGGERLEFT */
   46.44 +    {375, 0, 90.0},    /* TRIGGERRIGHT */
   46.45 +};
   46.46 +
   46.47 +SDL_Renderer *screen = NULL;
   46.48 +SDL_bool retval = SDL_FALSE;
   46.49 +SDL_bool done = SDL_FALSE;
   46.50 +SDL_Texture *background, *button, *axis;
   46.51 +
   46.52  static SDL_Texture *
   46.53  LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
   46.54  {
   46.55 @@ -60,50 +98,71 @@
   46.56      return texture;
   46.57  }
   46.58  
   46.59 +void
   46.60 +loop(void *arg)
   46.61 +{
   46.62 +    SDL_Event event;
   46.63 +    int i;
   46.64 +    SDL_GameController *gamecontroller = (SDL_GameController *)arg;
   46.65 +
   46.66 +    /* blank screen, set up for drawing this frame. */
   46.67 +    SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
   46.68 +    SDL_RenderClear(screen);
   46.69 +    SDL_RenderCopy(screen, background, NULL, NULL);
   46.70 +
   46.71 +    while (SDL_PollEvent(&event)) {
   46.72 +        switch (event.type) {
   46.73 +        case SDL_KEYDOWN:
   46.74 +            if (event.key.keysym.sym != SDLK_ESCAPE) {
   46.75 +                break;
   46.76 +            }
   46.77 +            /* Fall through to signal quit */
   46.78 +        case SDL_QUIT:
   46.79 +            done = SDL_TRUE;
   46.80 +            break;
   46.81 +        default:
   46.82 +            break;
   46.83 +        }
   46.84 +    }
   46.85 +
   46.86 +    /* Update visual controller state */
   46.87 +    for (i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) {
   46.88 +        if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) {
   46.89 +            const SDL_Rect dst = { button_positions[i].x, button_positions[i].y, 50, 50 };
   46.90 +            SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, 0);
   46.91 +        }
   46.92 +    }
   46.93 +
   46.94 +    for (i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) {
   46.95 +        const Sint16 deadzone = 8000;  /* !!! FIXME: real deadzone */
   46.96 +        const Sint16 value = SDL_GameControllerGetAxis(gamecontroller, (SDL_GameControllerAxis)(i));
   46.97 +        if (value < -deadzone) {
   46.98 +            const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
   46.99 +            const double angle = axis_positions[i].angle;
  46.100 +            SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, 0);
  46.101 +        } else if (value > deadzone) {
  46.102 +            const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
  46.103 +            const double angle = axis_positions[i].angle + 180.0;
  46.104 +            SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, 0);
  46.105 +        }
  46.106 +    }
  46.107 +
  46.108 +    SDL_RenderPresent(screen);
  46.109 +
  46.110 +    if (!SDL_GameControllerGetAttached(gamecontroller)) {
  46.111 +        done = SDL_TRUE;
  46.112 +        retval = SDL_TRUE;  /* keep going, wait for reattach. */
  46.113 +    }
  46.114 +}
  46.115 +
  46.116  SDL_bool
  46.117  WatchGameController(SDL_GameController * gamecontroller)
  46.118  {
  46.119 -    /* This is indexed by SDL_GameControllerButton. */
  46.120 -    static const struct { int x; int y; } button_positions[] = {
  46.121 -        {387, 167},  /* A */
  46.122 -        {431, 132},  /* B */
  46.123 -        {342, 132},  /* X */
  46.124 -        {389, 101},  /* Y */
  46.125 -        {174, 132},  /* BACK */
  46.126 -        {233, 132},  /* GUIDE */
  46.127 -        {289, 132},  /* START */
  46.128 -        {75,  154},  /* LEFTSTICK */
  46.129 -        {305, 230},  /* RIGHTSTICK */
  46.130 -        {77,  40},   /* LEFTSHOULDER */
  46.131 -        {396, 36},   /* RIGHTSHOULDER */
  46.132 -        {154, 188},  /* DPAD_UP */
  46.133 -        {154, 249},  /* DPAD_DOWN */
  46.134 -        {116, 217},  /* DPAD_LEFT */
  46.135 -        {186, 217},  /* DPAD_RIGHT */
  46.136 -    };
  46.137 -
  46.138 -    /* This is indexed by SDL_GameControllerAxis. */
  46.139 -    static const struct { int x; int y; double angle; } axis_positions[] = {
  46.140 -        {75,  154, 0.0},  /* LEFTX */
  46.141 -        {75,  154, 90.0},  /* LEFTY */
  46.142 -        {305, 230, 0.0},  /* RIGHTX */
  46.143 -        {305, 230, 90.0},  /* RIGHTY */
  46.144 -        {91, 0, 90.0},     /* TRIGGERLEFT */
  46.145 -        {375, 0, 90.0},    /* TRIGGERRIGHT */
  46.146 -    };
  46.147 -
  46.148      const char *name = SDL_GameControllerName(gamecontroller);
  46.149      const char *basetitle = "Game Controller Test: ";
  46.150      const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + 1;
  46.151      char *title = (char *)SDL_malloc(titlelen);
  46.152 -    SDL_Texture *background, *button, *axis;
  46.153      SDL_Window *window = NULL;
  46.154 -    SDL_Renderer *screen = NULL;
  46.155 -    SDL_bool retval = SDL_FALSE;
  46.156 -    SDL_bool done = SDL_FALSE;
  46.157 -    SDL_Event event;
  46.158 -    int i;
  46.159 -
  46.160      if (title) {
  46.161          SDL_snprintf(title, titlelen, "%s%s", basetitle, name);
  46.162      }
  46.163 @@ -151,56 +210,13 @@
  46.164      SDL_Log("Watching controller %s\n",  name ? name : "Unknown Controller");
  46.165  
  46.166      /* Loop, getting controller events! */
  46.167 +#ifdef __EMSCRIPTEN__
  46.168 +    emscripten_set_main_loop_arg(loop, gamecontroller, 0, 1);
  46.169 +#else
  46.170      while (!done) {
  46.171 -        /* blank screen, set up for drawing this frame. */
  46.172 -        SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
  46.173 -        SDL_RenderClear(screen);
  46.174 -        SDL_RenderCopy(screen, background, NULL, NULL);
  46.175 -
  46.176 -        while (SDL_PollEvent(&event)) {
  46.177 -            switch (event.type) {
  46.178 -            case SDL_KEYDOWN:
  46.179 -                if (event.key.keysym.sym != SDLK_ESCAPE) {
  46.180 -                    break;
  46.181 -                }
  46.182 -                /* Fall through to signal quit */
  46.183 -            case SDL_QUIT:
  46.184 -                done = SDL_TRUE;
  46.185 -                break;
  46.186 -            default:
  46.187 -                break;
  46.188 -            }
  46.189 -        }
  46.190 -
  46.191 -        /* Update visual controller state */
  46.192 -        for (i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) {
  46.193 -            if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) {
  46.194 -                const SDL_Rect dst = { button_positions[i].x, button_positions[i].y, 50, 50 };
  46.195 -                SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, 0);
  46.196 -            }
  46.197 -        }
  46.198 -
  46.199 -        for (i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) {
  46.200 -            const Sint16 deadzone = 8000;  /* !!! FIXME: real deadzone */
  46.201 -            const Sint16 value = SDL_GameControllerGetAxis(gamecontroller, (SDL_GameControllerAxis)(i));
  46.202 -            if (value < -deadzone) {
  46.203 -                const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
  46.204 -                const double angle = axis_positions[i].angle;
  46.205 -                SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, 0);
  46.206 -            } else if (value > deadzone) {
  46.207 -                const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
  46.208 -                const double angle = axis_positions[i].angle + 180.0;
  46.209 -                SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, 0);
  46.210 -            }
  46.211 -        }
  46.212 -
  46.213 -        SDL_RenderPresent(screen);
  46.214 -
  46.215 -        if (!SDL_GameControllerGetAttached(gamecontroller)) {
  46.216 -            done = SDL_TRUE;
  46.217 -            retval = SDL_TRUE;  /* keep going, wait for reattach. */
  46.218 -        }
  46.219 +        loop(gamecontroler);
  46.220      }
  46.221 +#endif
  46.222  
  46.223      SDL_DestroyRenderer(screen);
  46.224      SDL_DestroyWindow(window);
    47.1 --- a/test/testgesture.c	Sat Dec 13 02:33:52 2014 -0500
    47.2 +++ b/test/testgesture.c	Thu Dec 18 00:19:52 2014 -0500
    47.3 @@ -17,6 +17,10 @@
    47.4  
    47.5  #include "SDL.h"
    47.6  
    47.7 +#ifdef __EMSCRIPTEN__
    47.8 +#include <emscripten/emscripten.h>
    47.9 +#endif
   47.10 +
   47.11  #define WIDTH 640
   47.12  #define HEIGHT 480
   47.13  #define BPP 4
   47.14 @@ -34,6 +38,9 @@
   47.15  
   47.16  static int colors[7] = {0xFF,0xFF00,0xFF0000,0xFFFF00,0x00FFFF,0xFF00FF,0xFFFFFF};
   47.17  
   47.18 +SDL_Surface *screen;
   47.19 +SDL_bool quitting = SDL_FALSE;
   47.20 +
   47.21  typedef struct {
   47.22    float x,y;
   47.23  } Point;
   47.24 @@ -161,33 +168,13 @@
   47.25    return window;
   47.26  }
   47.27  
   47.28 -int main(int argc, char* argv[])
   47.29 +void loop()
   47.30  {
   47.31 -  SDL_Window *window = NULL;
   47.32 -  SDL_Surface *screen;
   47.33 -  SDL_Event event;
   47.34 -  SDL_bool quitting = SDL_FALSE;
   47.35 -  SDL_RWops *stream;
   47.36 +    SDL_Event event;
   47.37 +    SDL_RWops *stream;
   47.38  
   47.39 -  /* Enable standard application logging */
   47.40 -  SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   47.41 -
   47.42 -  /* gesture variables */
   47.43 -  knob.r = .1f;
   47.44 -  knob.ang = 0;
   47.45 -
   47.46 -  if (SDL_Init(SDL_INIT_VIDEO) < 0 ) return 1;
   47.47 -
   47.48 -  if (!(window = initWindow(window, WIDTH, HEIGHT)) ||
   47.49 -      !(screen = SDL_GetWindowSurface(window)))
   47.50 +    while(SDL_PollEvent(&event))
   47.51      {
   47.52 -      SDL_Quit();
   47.53 -      return 1;
   47.54 -    }
   47.55 -
   47.56 -  while(!quitting) {
   47.57 -    while(SDL_PollEvent(&event))
   47.58 -      {
   47.59      /* Record _all_ events */
   47.60      events[eventWrite & (EVENT_BUF_SIZE-1)] = event;
   47.61      eventWrite++;
   47.62 @@ -233,7 +220,7 @@
   47.63                !(screen = SDL_GetWindowSurface(window)))
   47.64            {
   47.65          SDL_Quit();
   47.66 -        return 1;
   47.67 +        exit(1);
   47.68            }
   47.69              }
   47.70          break;
   47.71 @@ -278,9 +265,36 @@
   47.72          SDL_Log("Recorded gesture: %"SDL_PRIs64"",event.dgesture.gestureId);
   47.73          break;
   47.74        }
   47.75 -      }
   47.76 -    DrawScreen(screen, window);
   47.77 +    }
   47.78 +    DrawScreen(screen);
   47.79 +}
   47.80 +
   47.81 +int main(int argc, char* argv[])
   47.82 +{
   47.83 +
   47.84 +  /* Enable standard application logging */
   47.85 +  SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   47.86 +
   47.87 +  /* gesture variables */
   47.88 +  knob.r = .1f;
   47.89 +  knob.ang = 0;
   47.90 +
   47.91 +  if (SDL_Init(SDL_INIT_VIDEO) < 0 ) return 1;
   47.92 +
   47.93 +  if (!(screen = initScreen(WIDTH,HEIGHT)))
   47.94 +  {
   47.95 +      SDL_Quit();
   47.96 +      return 1;
   47.97    }
   47.98 +
   47.99 +#ifdef __EMSCRIPTEN__
  47.100 +    emscripten_set_main_loop(loop, 0, 1);
  47.101 +#else
  47.102 +    while(!quitting) {
  47.103 +        loop();
  47.104 +    }
  47.105 +#endif
  47.106 +
  47.107    SDL_Quit();
  47.108    return 0;
  47.109  }
    48.1 --- a/test/testgles2.c	Sat Dec 13 02:33:52 2014 -0500
    48.2 +++ b/test/testgles2.c	Thu Dec 18 00:19:52 2014 -0500
    48.3 @@ -14,6 +14,10 @@
    48.4  #include <string.h>
    48.5  #include <math.h>
    48.6  
    48.7 +#ifdef __EMSCRIPTEN__
    48.8 +#include <emscripten/emscripten.h>
    48.9 +#endif
   48.10 +
   48.11  #include "SDL_test_common.h"
   48.12  
   48.13  #if defined(__IPHONEOS__) || defined(__ANDROID__) || defined(__NACL__)
   48.14 @@ -408,17 +412,72 @@
   48.15      GL_CHECK(ctx.glDrawArrays(GL_TRIANGLES, 0, 36));
   48.16  }
   48.17  
   48.18 +int done;
   48.19 +Uint32 frames;
   48.20 +shader_data *datas;
   48.21 +
   48.22 +void loop()
   48.23 +{
   48.24 +    SDL_Event event;
   48.25 +    int i;
   48.26 +    int status;
   48.27 +
   48.28 +    /* Check for events */
   48.29 +    ++frames;
   48.30 +    while (SDL_PollEvent(&event) && !done) {
   48.31 +        switch (event.type) {
   48.32 +        case SDL_WINDOWEVENT:
   48.33 +            switch (event.window.event) {
   48.34 +                case SDL_WINDOWEVENT_RESIZED:
   48.35 +                    for (i = 0; i < state->num_windows; ++i) {
   48.36 +                        if (event.window.windowID == SDL_GetWindowID(state->windows[i])) {
   48.37 +                            int w, h;
   48.38 +                            status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
   48.39 +                            if (status) {
   48.40 +                                SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
   48.41 +                                break;
   48.42 +                            }
   48.43 +                            /* Change view port to the new window dimensions */
   48.44 +                            SDL_GL_GetDrawableSize(state->windows[i], &w, &h);
   48.45 +                            ctx.glViewport(0, 0, w, h);
   48.46 +                            state->window_w = event.window.data1;
   48.47 +                            state->window_h = event.window.data2;
   48.48 +                            /* Update window content */
   48.49 +                            Render(event.window.data1, event.window.data2, &datas[i]);
   48.50 +                            SDL_GL_SwapWindow(state->windows[i]);
   48.51 +                            break;
   48.52 +                        }
   48.53 +                    }
   48.54 +                    break;
   48.55 +            }
   48.56 +        }
   48.57 +        SDLTest_CommonEvent(state, &event, &done);
   48.58 +    }
   48.59 +    if (!done) {
   48.60 +      for (i = 0; i < state->num_windows; ++i) {
   48.61 +          status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
   48.62 +          if (status) {
   48.63 +              SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
   48.64 +
   48.65 +              /* Continue for next window */
   48.66 +              continue;
   48.67 +          }
   48.68 +          Render(state->window_w, state->window_h, &datas[i]);
   48.69 +          SDL_GL_SwapWindow(state->windows[i]);
   48.70 +      }
   48.71 +    }
   48.72 +}
   48.73 +
   48.74  int
   48.75  main(int argc, char *argv[])
   48.76  {
   48.77      int fsaa, accel;
   48.78      int value;
   48.79 -    int i, done;
   48.80 +    int i;
   48.81      SDL_DisplayMode mode;
   48.82 -    SDL_Event event;
   48.83 -    Uint32 then, now, frames;
   48.84 +    Uint32 then, now;
   48.85      int status;
   48.86 -    shader_data *datas, *data;
   48.87 +    shader_data *data;
   48.88  
   48.89      /* Initialize parameters */
   48.90      fsaa = 0;
   48.91 @@ -581,6 +640,7 @@
   48.92      /* Set rendering settings for each context */
   48.93      for (i = 0; i < state->num_windows; ++i) {
   48.94  
   48.95 +        int w, h;
   48.96          status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
   48.97          if (status) {
   48.98              SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
   48.99 @@ -588,7 +648,8 @@
  48.100              /* Continue for next window */
  48.101              continue;
  48.102          }
  48.103 -        ctx.glViewport(0, 0, state->window_w, state->window_h);
  48.104 +        SDL_GL_GetDrawableSize(state->windows[i], &w, &h);
  48.105 +        ctx.glViewport(0, 0, w, h);
  48.106  
  48.107          data = &datas[i];
  48.108          data->angle_x = 0; data->angle_y = 0; data->angle_z = 0;
  48.109 @@ -630,48 +691,14 @@
  48.110      frames = 0;
  48.111      then = SDL_GetTicks();
  48.112      done = 0;
  48.113 +
  48.114 +#ifdef __EMSCRIPTEN__
  48.115 +    emscripten_set_main_loop(loop, 0, 1);
  48.116 +#else
  48.117      while (!done) {
  48.118 -        /* Check for events */
  48.119 -        ++frames;
  48.120 -        while (SDL_PollEvent(&event) && !done) {
  48.121 -            switch (event.type) {
  48.122 -            case SDL_WINDOWEVENT:
  48.123 -                switch (event.window.event) {
  48.124 -                    case SDL_WINDOWEVENT_RESIZED:
  48.125 -                        for (i = 0; i < state->num_windows; ++i) {
  48.126 -                            if (event.window.windowID == SDL_GetWindowID(state->windows[i])) {
  48.127 -                                status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
  48.128 -                                if (status) {
  48.129 -                                    SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
  48.130 -                                    break;
  48.131 -                                }
  48.132 -                                /* Change view port to the new window dimensions */
  48.133 -                                ctx.glViewport(0, 0, event.window.data1, event.window.data2);
  48.134 -                                /* Update window content */
  48.135 -                                Render(event.window.data1, event.window.data2, &datas[i]);
  48.136 -                                SDL_GL_SwapWindow(state->windows[i]);
  48.137 -                                break;
  48.138 -                            }
  48.139 -                        }
  48.140 -                        break;
  48.141 -                }
  48.142 -            }
  48.143 -            SDLTest_CommonEvent(state, &event, &done);
  48.144 -        }
  48.145 -        if (!done) {
  48.146 -          for (i = 0; i < state->num_windows; ++i) {
  48.147 -              status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
  48.148 -              if (status) {
  48.149 -                  SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
  48.150 -
  48.151 -                  /* Continue for next window */
  48.152 -                  continue;
  48.153 -              }
  48.154 -              Render(state->window_w, state->window_h, &datas[i]);
  48.155 -              SDL_GL_SwapWindow(state->windows[i]);
  48.156 -          }
  48.157 -        }
  48.158 +        loop();
  48.159      }
  48.160 +#endif
  48.161  
  48.162      /* Print out some timing information */
  48.163      now = SDL_GetTicks();
    49.1 --- a/test/testintersections.c	Sat Dec 13 02:33:52 2014 -0500
    49.2 +++ b/test/testintersections.c	Thu Dec 18 00:19:52 2014 -0500
    49.3 @@ -16,6 +16,10 @@
    49.4  #include <stdio.h>
    49.5  #include <time.h>
    49.6  
    49.7 +#ifdef __EMSCRIPTEN__
    49.8 +#include <emscripten/emscripten.h>
    49.9 +#endif
   49.10 +
   49.11  #include "SDL_test_common.h"
   49.12  
   49.13  #define SWAP(typ,a,b) do{typ t=a;a=b;b=t;}while(0)
   49.14 @@ -30,6 +34,9 @@
   49.15  static int current_color = 255;
   49.16  static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE;
   49.17  
   49.18 +int mouse_begin_x = -1, mouse_begin_y = -1;
   49.19 +int done;
   49.20 +
   49.21  void
   49.22  DrawPoints(SDL_Renderer * renderer)
   49.23  {
   49.24 @@ -191,12 +198,71 @@
   49.25          }
   49.26  }
   49.27  
   49.28 +void
   49.29 +loop()
   49.30 +{
   49.31 +    int i;
   49.32 +    SDL_Event event;
   49.33 +
   49.34 +    /* Check for events */
   49.35 +    while (SDL_PollEvent(&event)) {
   49.36 +        SDLTest_CommonEvent(state, &event, &done);
   49.37 +        switch (event.type) {
   49.38 +        case SDL_MOUSEBUTTONDOWN:
   49.39 +            mouse_begin_x = event.button.x;
   49.40 +            mouse_begin_y = event.button.y;
   49.41 +            break;
   49.42 +        case SDL_MOUSEBUTTONUP:
   49.43 +            if (event.button.button == 3)
   49.44 +                add_line(mouse_begin_x, mouse_begin_y, event.button.x,
   49.45 +                         event.button.y);
   49.46 +            if (event.button.button == 1)
   49.47 +                add_rect(mouse_begin_x, mouse_begin_y, event.button.x,
   49.48 +                         event.button.y);
   49.49 +            break;
   49.50 +        case SDL_KEYDOWN:
   49.51 +            switch (event.key.keysym.sym) {
   49.52 +            case 'l':
   49.53 +                if (event.key.keysym.mod & KMOD_SHIFT)
   49.54 +                    num_lines = 0;
   49.55 +                else
   49.56 +                    add_line(rand() % 640, rand() % 480, rand() % 640,
   49.57 +                             rand() % 480);
   49.58 +                break;
   49.59 +            case 'r':
   49.60 +                if (event.key.keysym.mod & KMOD_SHIFT)
   49.61 +                    num_rects = 0;
   49.62 +                else
   49.63 +                    add_rect(rand() % 640, rand() % 480, rand() % 640,
   49.64 +                             rand() % 480);
   49.65 +                break;
   49.66 +            }
   49.67 +            break;
   49.68 +        default:
   49.69 +            break;
   49.70 +        }
   49.71 +    }
   49.72 +    for (i = 0; i < state->num_windows; ++i) {
   49.73 +        SDL_Renderer *renderer = state->renderers[i];
   49.74 +        if (state->windows[i] == NULL)
   49.75 +            continue;
   49.76 +        SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
   49.77 +        SDL_RenderClear(renderer);
   49.78 +
   49.79 +        DrawRects(renderer);
   49.80 +        DrawPoints(renderer);
   49.81 +        DrawRectRectIntersections(renderer);
   49.82 +        DrawLines(renderer);
   49.83 +        DrawRectLineIntersections(renderer);
   49.84 +
   49.85 +        SDL_RenderPresent(renderer);
   49.86 +    }
   49.87 +}
   49.88 +
   49.89  int
   49.90  main(int argc, char *argv[])
   49.91  {
   49.92 -    int mouse_begin_x = -1, mouse_begin_y = -1;
   49.93 -    int i, done;
   49.94 -    SDL_Event event;
   49.95 +    int i;
   49.96      Uint32 then, now, frames;
   49.97  
   49.98      /* Enable standard application logging */
   49.99 @@ -268,62 +334,15 @@
  49.100      frames = 0;
  49.101      then = SDL_GetTicks();
  49.102      done = 0;
  49.103 +
  49.104 +#ifdef __EMSCRIPTEN__
  49.105 +    emscripten_set_main_loop(loop, 0, 1);
  49.106 +#else
  49.107      while (!done) {
  49.108 -        /* Check for events */
  49.109          ++frames;
  49.110 -        while (SDL_PollEvent(&event)) {
  49.111 -            SDLTest_CommonEvent(state, &event, &done);
  49.112 -            switch (event.type) {
  49.113 -            case SDL_MOUSEBUTTONDOWN:
  49.114 -                mouse_begin_x = event.button.x;
  49.115 -                mouse_begin_y = event.button.y;
  49.116 -                break;
  49.117 -            case SDL_MOUSEBUTTONUP:
  49.118 -                if (event.button.button == 3)
  49.119 -                    add_line(mouse_begin_x, mouse_begin_y, event.button.x,
  49.120 -                             event.button.y);
  49.121 -                if (event.button.button == 1)
  49.122 -                    add_rect(mouse_begin_x, mouse_begin_y, event.button.x,
  49.123 -                             event.button.y);
  49.124 -                break;
  49.125 -            case SDL_KEYDOWN:
  49.126 -                switch (event.key.keysym.sym) {
  49.127 -                case 'l':
  49.128 -                    if (event.key.keysym.mod & KMOD_SHIFT)
  49.129 -                        num_lines = 0;
  49.130 -                    else
  49.131 -                        add_line(rand() % 640, rand() % 480, rand() % 640,
  49.132 -                                 rand() % 480);
  49.133 -                    break;
  49.134 -                case 'r':
  49.135 -                    if (event.key.keysym.mod & KMOD_SHIFT)
  49.136 -                        num_rects = 0;
  49.137 -                    else
  49.138 -                        add_rect(rand() % 640, rand() % 480, rand() % 640,
  49.139 -                                 rand() % 480);
  49.140 -                    break;
  49.141 -                }
  49.142 -                break;
  49.143 -            default:
  49.144 -                break;
  49.145 -            }
  49.146 -        }
  49.147 -        for (i = 0; i < state->num_windows; ++i) {
  49.148 -            SDL_Renderer *renderer = state->renderers[i];
  49.149 -            if (state->windows[i] == NULL)
  49.150 -                continue;
  49.151 -            SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
  49.152 -            SDL_RenderClear(renderer);
  49.153 -
  49.154 -            DrawRects(renderer);
  49.155 -            DrawPoints(renderer);
  49.156 -            DrawRectRectIntersections(renderer);
  49.157 -            DrawLines(renderer);
  49.158 -            DrawRectLineIntersections(renderer);
  49.159 -
  49.160 -            SDL_RenderPresent(renderer);
  49.161 -        }
  49.162 +        loop();
  49.163      }
  49.164 +#endif
  49.165  
  49.166      SDLTest_CommonQuit(state);
  49.167  
    50.1 --- a/test/testjoystick.c	Sat Dec 13 02:33:52 2014 -0500
    50.2 +++ b/test/testjoystick.c	Thu Dec 18 00:19:52 2014 -0500
    50.3 @@ -18,6 +18,10 @@
    50.4  
    50.5  #include "SDL.h"
    50.6  
    50.7 +#ifdef __EMSCRIPTEN__
    50.8 +#include <emscripten/emscripten.h>
    50.9 +#endif
   50.10 +
   50.11  #ifndef SDL_JOYSTICK_DISABLED
   50.12  
   50.13  #ifdef __IPHONEOS__
   50.14 @@ -28,6 +32,9 @@
   50.15  #define SCREEN_HEIGHT   480
   50.16  #endif
   50.17  
   50.18 +SDL_Renderer *screen = NULL;
   50.19 +SDL_bool retval = SDL_FALSE;
   50.20 +SDL_bool done = SDL_FALSE;
   50.21  
   50.22  static void
   50.23  DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h)
   50.24 @@ -36,50 +43,15 @@
   50.25      SDL_RenderFillRect(r, &area);
   50.26  }
   50.27  
   50.28 -static SDL_bool
   50.29 -WatchJoystick(SDL_Joystick * joystick)
   50.30 +void
   50.31 +loop(void *arg)
   50.32  {
   50.33 -    SDL_Window *window = NULL;
   50.34 -    SDL_Renderer *screen = NULL;
   50.35 -    const char *name = NULL;
   50.36 -    SDL_bool retval = SDL_FALSE;
   50.37 -    SDL_bool done = SDL_FALSE;
   50.38      SDL_Event event;
   50.39      int i;
   50.40 +    SDL_Joystick *joystick = (SDL_Joystick *)arg;
   50.41  
   50.42 -    /* Create a window to display joystick axis position */
   50.43 -    window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
   50.44 -                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
   50.45 -                              SCREEN_HEIGHT, 0);
   50.46 -    if (window == NULL) {
   50.47 -        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
   50.48 -        return SDL_FALSE;
   50.49 -    }
   50.50 -
   50.51 -    screen = SDL_CreateRenderer(window, -1, 0);
   50.52 -    if (screen == NULL) {
   50.53 -        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
   50.54 -        SDL_DestroyWindow(window);
   50.55 -        return SDL_FALSE;
   50.56 -    }
   50.57 -
   50.58 -    SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   50.59 -    SDL_RenderClear(screen);
   50.60 -    SDL_RenderPresent(screen);
   50.61 -    SDL_RaiseWindow(window);
   50.62 -
   50.63 -    /* Print info about the joystick we are watching */
   50.64 -    name = SDL_JoystickName(joystick);
   50.65 -    SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
   50.66 -           name ? name : "Unknown Joystick");
   50.67 -    SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
   50.68 -           SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
   50.69 -           SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
   50.70 -
   50.71 -    /* Loop, getting joystick events! */
   50.72 -    while (!done) {
   50.73          /* blank screen, set up for drawing this frame. */
   50.74 -        SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   50.75 +    SDL_SetRenderDrawColor(screen, 0x0, 0x0, 0x0, SDL_ALPHA_OPAQUE);
   50.76          SDL_RenderClear(screen);
   50.77  
   50.78          while (SDL_PollEvent(&event)) {
   50.79 @@ -197,8 +169,53 @@
   50.80              done = SDL_TRUE;
   50.81              retval = SDL_TRUE;  /* keep going, wait for reattach. */
   50.82          }
   50.83 +}
   50.84 +
   50.85 +static SDL_bool
   50.86 +WatchJoystick(SDL_Joystick * joystick)
   50.87 +{
   50.88 +    SDL_Window *window = NULL;
   50.89 +    const char *name = NULL;
   50.90 +
   50.91 +
   50.92 +    /* Create a window to display joystick axis position */
   50.93 +    window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
   50.94 +                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
   50.95 +                              SCREEN_HEIGHT, 0);
   50.96 +    if (window == NULL) {
   50.97 +        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
   50.98 +        return SDL_FALSE;
   50.99      }
  50.100  
  50.101 +    screen = SDL_CreateRenderer(window, -1, 0);
  50.102 +    if (screen == NULL) {
  50.103 +        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
  50.104 +        SDL_DestroyWindow(window);
  50.105 +        return SDL_FALSE;
  50.106 +    }
  50.107 +
  50.108 +    SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
  50.109 +    SDL_RenderClear(screen);
  50.110 +    SDL_RenderPresent(screen);
  50.111 +    SDL_RaiseWindow(window);
  50.112 +
  50.113 +    /* Print info about the joystick we are watching */
  50.114 +    name = SDL_JoystickName(joystick);
  50.115 +    SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
  50.116 +           name ? name : "Unknown Joystick");
  50.117 +    SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
  50.118 +           SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
  50.119 +           SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
  50.120 +
  50.121 +    /* Loop, getting joystick events! */
  50.122 +#ifdef __EMSCRIPTEN__
  50.123 +    emscripten_set_main_loop_arg(loop, joystick, 0, 1);
  50.124 +#else
  50.125 +    while (!done) {
  50.126 +        loop(joystick);
  50.127 +    }
  50.128 +#endif
  50.129 +
  50.130      SDL_DestroyRenderer(screen);
  50.131      SDL_DestroyWindow(window);
  50.132      return retval;
    51.1 --- a/test/testmultiaudio.c	Sat Dec 13 02:33:52 2014 -0500
    51.2 +++ b/test/testmultiaudio.c	Thu Dec 18 00:19:52 2014 -0500
    51.3 @@ -13,6 +13,10 @@
    51.4  
    51.5  #include <stdio.h> /* for fflush() and stdout */
    51.6  
    51.7 +#ifdef __EMSCRIPTEN__
    51.8 +#include <emscripten/emscripten.h>
    51.9 +#endif
   51.10 +
   51.11  static SDL_AudioSpec spec;
   51.12  static Uint8 *sound = NULL;     /* Pointer to wave data */
   51.13  static Uint32 soundlen = 0;     /* Length of wave data */
   51.14 @@ -24,6 +28,8 @@
   51.15      volatile int done;
   51.16  } callback_data;
   51.17  
   51.18 +callback_data cbd[64];
   51.19 +
   51.20  void SDLCALL
   51.21  play_through_once(void *arg, Uint8 * stream, int len)
   51.22  {
   51.23 @@ -44,10 +50,21 @@
   51.24      }
   51.25  }
   51.26  
   51.27 +void
   51.28 +loop()
   51.29 +{
   51.30 +    if(cbd[0].done) {
   51.31 +        emscripten_cancel_main_loop();
   51.32 +        SDL_PauseAudioDevice(cbd[0].dev, 1);
   51.33 +        SDL_CloseAudioDevice(cbd[0].dev);
   51.34 +        SDL_FreeWAV(sound);
   51.35 +        SDL_Quit();
   51.36 +    }
   51.37 +}
   51.38 +
   51.39  static void
   51.40  test_multi_audio(int devcount)
   51.41  {
   51.42 -    callback_data cbd[64];
   51.43      int keep_going = 1;
   51.44      int i;
   51.45      
   51.46 @@ -78,14 +95,19 @@
   51.47              SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device failed: %s\n", SDL_GetError());
   51.48          } else {
   51.49              SDL_PauseAudioDevice(cbd[0].dev, 0);
   51.50 -            while (!cbd[0].done) {
   51.51 -#ifdef __ANDROID__                
   51.52 +#ifdef __EMSCRIPTEN__
   51.53 +            emscripten_set_main_loop(loop, 0, 1);
   51.54 +#else
   51.55 +            while (!cbd[0].done)
   51.56 +            {
   51.57 +                #ifdef __ANDROID__                
   51.58                  /* Empty queue, some application events would prevent pause. */
   51.59                  while (SDL_PollEvent(&event)){}
   51.60 -#endif                
   51.61 +                #endif                
   51.62                  SDL_Delay(100);
   51.63              }
   51.64              SDL_PauseAudioDevice(cbd[0].dev, 1);
   51.65 +#endif
   51.66              SDL_Log("done.\n");
   51.67              SDL_CloseAudioDevice(cbd[0].dev);
   51.68          }
   51.69 @@ -116,21 +138,13 @@
   51.70                  keep_going = 1;
   51.71              }
   51.72          }
   51.73 -#ifdef __ANDROID__        
   51.74 +        #ifdef __ANDROID__        
   51.75          /* Empty queue, some application events would prevent pause. */
   51.76          while (SDL_PollEvent(&event)){}
   51.77 -#endif        
   51.78 +        #endif        
   51.79 +
   51.80          SDL_Delay(100);
   51.81      }
   51.82 -
   51.83 -    for (i = 0; i < devcount; i++) {
   51.84 -        if (cbd[i].dev) {
   51.85 -            SDL_PauseAudioDevice(cbd[i].dev, 1);
   51.86 -            SDL_CloseAudioDevice(cbd[i].dev);
   51.87 -        }
   51.88 -    }
   51.89 -
   51.90 -    SDL_Log("All done!\n");
   51.91  }
   51.92  
   51.93  
    52.1 --- a/test/testoverlay2.c	Sat Dec 13 02:33:52 2014 -0500
    52.2 +++ b/test/testoverlay2.c	Thu Dec 18 00:19:52 2014 -0500
    52.3 @@ -20,6 +20,10 @@
    52.4  #include <stdio.h>
    52.5  #include <string.h>
    52.6  
    52.7 +#ifdef __EMSCRIPTEN__
    52.8 +#include <emscripten/emscripten.h>
    52.9 +#endif
   52.10 +
   52.11  #include "SDL.h"
   52.12  
   52.13  #define MOOSEPIC_W 64
   52.14 @@ -135,6 +139,18 @@
   52.15      , {239, 206, 173}
   52.16  };
   52.17  
   52.18 +Uint8 MooseFrame[MOOSEFRAMES_COUNT][MOOSEFRAME_SIZE*2];
   52.19 +SDL_Texture *MooseTexture;
   52.20 +SDL_Rect displayrect;
   52.21 +int window_w;
   52.22 +int window_h;
   52.23 +SDL_Window *window;
   52.24 +SDL_Renderer *renderer;
   52.25 +int paused = 0;
   52.26 +int i;
   52.27 +SDL_bool done = SDL_FALSE;
   52.28 +Uint32 pixel_format = SDL_PIXELFORMAT_YV12;
   52.29 +int fpsdelay;
   52.30  
   52.31  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   52.32  static void
   52.33 @@ -246,21 +262,65 @@
   52.34      SDL_Log("\n");
   52.35  }
   52.36  
   52.37 +void
   52.38 +loop()
   52.39 +{
   52.40 +    SDL_Event event;
   52.41 +
   52.42 +    while (SDL_PollEvent(&event)) {
   52.43 +        switch (event.type) {
   52.44 +        case SDL_WINDOWEVENT:
   52.45 +            if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
   52.46 +                SDL_RenderSetViewport(renderer, NULL);
   52.47 +                displayrect.w = window_w = event.window.data1;
   52.48 +                displayrect.h = window_h = event.window.data2;
   52.49 +            }
   52.50 +            break;
   52.51 +        case SDL_MOUSEBUTTONDOWN:
   52.52 +            displayrect.x = event.button.x - window_w / 2;
   52.53 +            displayrect.y = event.button.y - window_h / 2;
   52.54 +            break;
   52.55 +        case SDL_MOUSEMOTION:
   52.56 +            if (event.motion.state) {
   52.57 +                displayrect.x = event.motion.x - window_w / 2;
   52.58 +                displayrect.y = event.motion.y - window_h / 2;
   52.59 +            }
   52.60 +            break;
   52.61 +        case SDL_KEYDOWN:
   52.62 +            if (event.key.keysym.sym == SDLK_SPACE) {
   52.63 +                paused = !paused;
   52.64 +                break;
   52.65 +            }
   52.66 +            if (event.key.keysym.sym != SDLK_ESCAPE) {
   52.67 +                break;
   52.68 +            }
   52.69 +        case SDL_QUIT:
   52.70 +            done = SDL_TRUE;
   52.71 +            break;
   52.72 +        }
   52.73 +    }
   52.74 +
   52.75 +#ifndef __EMSCRIPTEN__
   52.76 +    SDL_Delay(fpsdelay);
   52.77 +#endif
   52.78 +
   52.79 +    if (!paused) {
   52.80 +        i = (i + 1) % MOOSEFRAMES_COUNT;
   52.81 +
   52.82 +        SDL_UpdateTexture(MooseTexture, NULL, MooseFrame[i], MOOSEPIC_W*SDL_BYTESPERPIXEL(pixel_format));
   52.83 +    }
   52.84 +    SDL_RenderClear(renderer);
   52.85 +    SDL_RenderCopy(renderer, MooseTexture, NULL, &displayrect);
   52.86 +    SDL_RenderPresent(renderer);
   52.87 +}
   52.88 +
   52.89  int
   52.90  main(int argc, char **argv)
   52.91  {
   52.92      Uint8 *RawMooseData;
   52.93      SDL_RWops *handle;
   52.94 -    int window_w;
   52.95 -    int window_h;
   52.96      SDL_Window *window;
   52.97 -    SDL_Renderer *renderer;
   52.98 -    Uint8 MooseFrame[MOOSEFRAMES_COUNT][MOOSEFRAME_SIZE*2];
   52.99 -    SDL_Texture *MooseTexture;
  52.100 -    SDL_Rect displayrect;
  52.101 -    SDL_Event event;
  52.102 -    int paused = 0;
  52.103 -    int i, j;
  52.104 +    int j;
  52.105      int fps = 12;
  52.106      int fpsdelay;
  52.107      int nodelay = 0;
  52.108 @@ -270,7 +330,6 @@
  52.109      Uint32 pixel_format = SDL_PIXELFORMAT_YV12;
  52.110  #endif
  52.111      int scale = 5;
  52.112 -    SDL_bool done = SDL_FALSE;
  52.113  
  52.114      /* Enable standard application logging */
  52.115      SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
  52.116 @@ -430,50 +489,14 @@
  52.117      SDL_EventState(SDL_KEYUP, SDL_IGNORE);
  52.118  
  52.119      /* Loop, waiting for QUIT or RESIZE */
  52.120 +#ifdef __EMSCRIPTEN__
  52.121 +    emscripten_set_main_loop(loop, nodelay ? 0 : fps, 1);
  52.122 +#else
  52.123      while (!done) {
  52.124 -        while (SDL_PollEvent(&event)) {
  52.125 -            switch (event.type) {
  52.126 -            case SDL_WINDOWEVENT:
  52.127 -                if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
  52.128 -                    SDL_RenderSetViewport(renderer, NULL);
  52.129 -                    displayrect.w = window_w = event.window.data1;
  52.130 -                    displayrect.h = window_h = event.window.data2;
  52.131 -                }
  52.132 -                break;
  52.133 -            case SDL_MOUSEBUTTONDOWN:
  52.134 -                displayrect.x = event.button.x - window_w / 2;
  52.135 -                displayrect.y = event.button.y - window_h / 2;
  52.136 -                break;
  52.137 -            case SDL_MOUSEMOTION:
  52.138 -                if (event.motion.state) {
  52.139 -                    displayrect.x = event.motion.x - window_w / 2;
  52.140 -                    displayrect.y = event.motion.y - window_h / 2;
  52.141 -                }
  52.142 -                break;
  52.143 -            case SDL_KEYDOWN:
  52.144 -                if (event.key.keysym.sym == SDLK_SPACE) {
  52.145 -                    paused = !paused;
  52.146 -                    break;
  52.147 -                }
  52.148 -                if (event.key.keysym.sym != SDLK_ESCAPE) {
  52.149 -                    break;
  52.150 -                }
  52.151 -            case SDL_QUIT:
  52.152 -                done = SDL_TRUE;
  52.153 -                break;
  52.154 +        loop();
  52.155              }
  52.156 -        }
  52.157 -        SDL_Delay(fpsdelay);
  52.158 +#endif
  52.159  
  52.160 -        if (!paused) {
  52.161 -            i = (i + 1) % MOOSEFRAMES_COUNT;
  52.162 -
  52.163 -            SDL_UpdateTexture(MooseTexture, NULL, MooseFrame[i], MOOSEPIC_W*SDL_BYTESPERPIXEL(pixel_format));
  52.164 -        }
  52.165 -        SDL_RenderClear(renderer);
  52.166 -        SDL_RenderCopy(renderer, MooseTexture, NULL, &displayrect);
  52.167 -        SDL_RenderPresent(renderer);
  52.168 -    }
  52.169      SDL_DestroyRenderer(renderer);
  52.170      quit(0);
  52.171      return 0;
    53.1 --- a/test/testrelative.c	Sat Dec 13 02:33:52 2014 -0500
    53.2 +++ b/test/testrelative.c	Thu Dec 18 00:19:52 2014 -0500
    53.3 @@ -18,8 +18,14 @@
    53.4  
    53.5  #include "SDL_test_common.h"
    53.6  
    53.7 +#ifdef __EMSCRIPTEN__
    53.8 +#include <emscripten/emscripten.h>
    53.9 +#endif
   53.10  
   53.11  static SDLTest_CommonState *state;
   53.12 +int i, done;
   53.13 +SDL_Rect rect;
   53.14 +SDL_Event event;
   53.15  
   53.16  static void
   53.17  DrawRects(SDL_Renderer * renderer, SDL_Rect * rect)
   53.18 @@ -28,12 +34,36 @@
   53.19      SDL_RenderFillRect(renderer, rect);
   53.20  }
   53.21  
   53.22 +static void
   53.23 +loop(){
   53.24 +    /* Check for events */
   53.25 +    while (SDL_PollEvent(&event)) {
   53.26 +        SDLTest_CommonEvent(state, &event, &done);
   53.27 +        switch(event.type) {
   53.28 +        case SDL_MOUSEMOTION:
   53.29 +            {
   53.30 +                rect.x += event.motion.xrel;
   53.31 +                rect.y += event.motion.yrel;
   53.32 +            }
   53.33 +            break;
   53.34 +        }
   53.35 +    }
   53.36 +    for (i = 0; i < state->num_windows; ++i) {
   53.37 +        SDL_Renderer *renderer = state->renderers[i];
   53.38 +        if (state->windows[i] == NULL)
   53.39 +            continue;
   53.40 +        SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
   53.41 +        SDL_RenderClear(renderer);
   53.42 +
   53.43 +        DrawRects(renderer, &rect);
   53.44 +
   53.45 +        SDL_RenderPresent(renderer);
   53.46 +    }
   53.47 +}
   53.48 +
   53.49  int
   53.50  main(int argc, char *argv[])
   53.51  {
   53.52 -    int i, done;
   53.53 -    SDL_Rect rect;
   53.54 -    SDL_Event event;
   53.55  
   53.56      /* Enable standard application logging */
   53.57      SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   53.58 @@ -69,32 +99,13 @@
   53.59      rect.h = 10;
   53.60      /* Main render loop */
   53.61      done = 0;
   53.62 +#ifdef __EMSCRIPTEN__
   53.63 +    emscripten_set_main_loop(loop, 0, 1);
   53.64 +#else
   53.65      while (!done) {
   53.66 -        /* Check for events */
   53.67 -        while (SDL_PollEvent(&event)) {
   53.68 -            SDLTest_CommonEvent(state, &event, &done);
   53.69 -            switch(event.type) {
   53.70 -                case SDL_MOUSEMOTION:
   53.71 -                {
   53.72 -                    rect.x += event.motion.xrel;
   53.73 -                    rect.y += event.motion.yrel;
   53.74 -                }
   53.75 -                break;
   53.76 -            }
   53.77 +        loop();
   53.78          }
   53.79 -        for (i = 0; i < state->num_windows; ++i) {
   53.80 -            SDL_Renderer *renderer = state->renderers[i];
   53.81 -            if (state->windows[i] == NULL)
   53.82 -                continue;
   53.83 -            SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
   53.84 -            SDL_RenderClear(renderer);
   53.85 -
   53.86 -            DrawRects(renderer, &rect);
   53.87 -
   53.88 -            SDL_RenderPresent(renderer);
   53.89 -        }
   53.90 -    }
   53.91 -
   53.92 +#endif
   53.93      SDLTest_CommonQuit(state);
   53.94      return 0;
   53.95  }
    54.1 --- a/test/testrendercopyex.c	Sat Dec 13 02:33:52 2014 -0500
    54.2 +++ b/test/testrendercopyex.c	Thu Dec 18 00:19:52 2014 -0500
    54.3 @@ -15,6 +15,10 @@
    54.4  #include <stdio.h>
    54.5  #include <time.h>
    54.6  
    54.7 +#ifdef __EMSCRIPTEN__
    54.8 +#include <emscripten/emscripten.h>
    54.9 +#endif
   54.10 +
   54.11  #include "SDL_test_common.h"
   54.12  
   54.13  
   54.14 @@ -29,6 +33,9 @@
   54.15      int scale_direction;
   54.16  } DrawState;
   54.17  
   54.18 +DrawState *drawstates;
   54.19 +int done;
   54.20 +
   54.21  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   54.22  static void
   54.23  quit(int rc)
   54.24 @@ -130,12 +137,27 @@
   54.25      /* SDL_Delay(10); */
   54.26  }
   54.27  
   54.28 +void loop()
   54.29 +{
   54.30 +    int i;
   54.31 +    SDL_Event event;
   54.32 +
   54.33 +    /* Check for events */
   54.34 +
   54.35 +    while (SDL_PollEvent(&event)) {
   54.36 +        SDLTest_CommonEvent(state, &event, &done);
   54.37 +    }
   54.38 +    for (i = 0; i < state->num_windows; ++i) {
   54.39 +        if (state->windows[i] == NULL)
   54.40 +            continue;
   54.41 +        Draw(&drawstates[i]);
   54.42 +    }
   54.43 +}
   54.44 +
   54.45  int
   54.46  main(int argc, char *argv[])
   54.47  {
   54.48 -    DrawState *drawstates;
   54.49 -    int i, done;
   54.50 -    SDL_Event event;
   54.51 +    int i;
   54.52      int frames;
   54.53      Uint32 then, now;
   54.54  
   54.55 @@ -181,19 +203,15 @@
   54.56      frames = 0;
   54.57      then = SDL_GetTicks();
   54.58      done = 0;
   54.59 +
   54.60 +#ifdef __EMSCRIPTEN__
   54.61 +    emscripten_set_main_loop(loop, 0, 1);
   54.62 +#else
   54.63      while (!done) {
   54.64 -        /* Check for events */
   54.65          ++frames;
   54.66 -        while (SDL_PollEvent(&event)) {
   54.67 -            SDLTest_CommonEvent(state, &event, &done);
   54.68 +        loop();
   54.69          }
   54.70 -        for (i = 0; i < state->num_windows; ++i) {
   54.71 -            if (state->windows[i] == NULL)
   54.72 -                continue;
   54.73 -            Draw(&drawstates[i]);
   54.74 -        }
   54.75 -    }
   54.76 -
   54.77 +#endif
   54.78      /* Print out some timing information */
   54.79      now = SDL_GetTicks();
   54.80      if (now > then) {
    55.1 --- a/test/testrendertarget.c	Sat Dec 13 02:33:52 2014 -0500
    55.2 +++ b/test/testrendertarget.c	Thu Dec 18 00:19:52 2014 -0500
    55.3 @@ -15,6 +15,10 @@
    55.4  #include <stdio.h>
    55.5  #include <time.h>
    55.6  
    55.7 +#ifdef __EMSCRIPTEN__
    55.8 +#include <emscripten/emscripten.h>
    55.9 +#endif
   55.10 +
   55.11  #include "SDL_test_common.h"
   55.12  
   55.13  
   55.14 @@ -29,6 +33,10 @@
   55.15      int scale_direction;
   55.16  } DrawState;
   55.17  
   55.18 +DrawState *drawstates;
   55.19 +int done;
   55.20 +SDL_bool test_composite = SDL_FALSE;
   55.21 +
   55.22  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   55.23  static void
   55.24  quit(int rc)
   55.25 @@ -214,15 +222,33 @@
   55.26      return SDL_TRUE;
   55.27  }
   55.28  
   55.29 +void
   55.30 +loop()
   55.31 +{
   55.32 +    int i;
   55.33 +    SDL_Event event;
   55.34 +
   55.35 +    /* Check for events */
   55.36 +    while (SDL_PollEvent(&event)) {
   55.37 +        SDLTest_CommonEvent(state, &event, &done);
   55.38 +    }
   55.39 +    for (i = 0; i < state->num_windows; ++i) {
   55.40 +        if (state->windows[i] == NULL)
   55.41 +            continue;
   55.42 +        if (test_composite) {
   55.43 +            if (!DrawComposite(&drawstates[i])) done = 1;
   55.44 +        } else {
   55.45 +            if (!Draw(&drawstates[i])) done = 1;
   55.46 +        }
   55.47 +    }
   55.48 +}
   55.49 +
   55.50  int
   55.51  main(int argc, char *argv[])
   55.52  {
   55.53 -    DrawState *drawstates;
   55.54 -    int i, done;
   55.55 -    SDL_Event event;
   55.56 +    int i;
   55.57      int frames;
   55.58      Uint32 then, now;
   55.59 -    SDL_bool test_composite = SDL_FALSE;
   55.60  
   55.61      /* Enable standard application logging */
   55.62      SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   55.63 @@ -278,22 +304,15 @@
   55.64      frames = 0;
   55.65      then = SDL_GetTicks();
   55.66      done = 0;
   55.67 +
   55.68 +#ifdef __EMSCRIPTEN__
   55.69 +    emscripten_set_main_loop(loop, 0, 1);
   55.70 +#else
   55.71      while (!done) {
   55.72 -        /* Check for events */
   55.73          ++frames;
   55.74 -        while (SDL_PollEvent(&event)) {
   55.75 -            SDLTest_CommonEvent(state, &event, &done);
   55.76 -        }
   55.77 -        for (i = 0; i < state->num_windows; ++i) {
   55.78 -            if (state->windows[i] == NULL)
   55.79 -                continue;
   55.80 -            if (test_composite) {
   55.81 -                if (!DrawComposite(&drawstates[i])) done = 1;
   55.82 -            } else {
   55.83 -                if (!Draw(&drawstates[i])) done = 1;
   55.84 -            }
   55.85 -        }
   55.86 +        loop();
   55.87      }
   55.88 +#endif
   55.89  
   55.90      /* Print out some timing information */
   55.91      now = SDL_GetTicks();
    56.1 --- a/test/testscale.c	Sat Dec 13 02:33:52 2014 -0500
    56.2 +++ b/test/testscale.c	Thu Dec 18 00:19:52 2014 -0500
    56.3 @@ -15,6 +15,10 @@
    56.4  #include <stdio.h>
    56.5  #include <time.h>
    56.6  
    56.7 +#ifdef __EMSCRIPTEN__
    56.8 +#include <emscripten/emscripten.h>
    56.9 +#endif
   56.10 +
   56.11  #include "SDL_test_common.h"
   56.12  
   56.13  #define WINDOW_WIDTH    640
   56.14 @@ -31,6 +35,9 @@
   56.15      int scale_direction;
   56.16  } DrawState;
   56.17  
   56.18 +DrawState *drawstates;
   56.19 +int done;
   56.20 +
   56.21  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   56.22  static void
   56.23  quit(int rc)
   56.24 @@ -120,12 +127,27 @@
   56.25      SDL_RenderPresent(s->renderer);
   56.26  }
   56.27  
   56.28 +void
   56.29 +loop()
   56.30 +{
   56.31 +    int i;
   56.32 +    SDL_Event event;
   56.33 +
   56.34 +    /* Check for events */
   56.35 +    while (SDL_PollEvent(&event)) {
   56.36 +        SDLTest_CommonEvent(state, &event, &done);
   56.37 +    }
   56.38 +    for (i = 0; i < state->num_windows; ++i) {
   56.39 +        if (state->windows[i] == NULL)
   56.40 +            continue;
   56.41 +        Draw(&drawstates[i]);
   56.42 +    }
   56.43 +}
   56.44 +
   56.45  int
   56.46  main(int argc, char *argv[])
   56.47  {
   56.48 -    DrawState *drawstates;
   56.49 -    int i, done;
   56.50 -    SDL_Event event;
   56.51 +    int i;
   56.52      int frames;
   56.53      Uint32 then, now;
   56.54  
   56.55 @@ -171,18 +193,15 @@
   56.56      frames = 0;
   56.57      then = SDL_GetTicks();
   56.58      done = 0;
   56.59 +
   56.60 +#ifdef __EMSCRIPTEN__
   56.61 +    emscripten_set_main_loop(loop, 0, 1);
   56.62 +#else
   56.63      while (!done) {
   56.64 -        /* Check for events */
   56.65          ++frames;
   56.66 -        while (SDL_PollEvent(&event)) {
   56.67 -            SDLTest_CommonEvent(state, &event, &done);
   56.68 -        }
   56.69 -        for (i = 0; i < state->num_windows; ++i) {
   56.70 -            if (state->windows[i] == NULL)
   56.71 -                continue;
   56.72 -            Draw(&drawstates[i]);
   56.73 -        }
   56.74 +        loop();
   56.75      }
   56.76 +#endif
   56.77  
   56.78      /* Print out some timing information */
   56.79      now = SDL_GetTicks();
    57.1 --- a/test/testsprite2.c	Sat Dec 13 02:33:52 2014 -0500
    57.2 +++ b/test/testsprite2.c	Thu Dec 18 00:19:52 2014 -0500
    57.3 @@ -15,6 +15,10 @@
    57.4  #include <stdio.h>
    57.5  #include <time.h>
    57.6  
    57.7 +#ifdef __EMSCRIPTEN__
    57.8 +#include <emscripten/emscripten.h>
    57.9 +#endif
   57.10 +
   57.11  #include "SDL_test.h"
   57.12  #include "SDL_test_common.h"
   57.13  
   57.14 @@ -38,6 +42,8 @@
   57.15  /* -1: infinite random moves (default); >=0: enables N deterministic moves */
   57.16  static int iterations = -1;
   57.17  
   57.18 +int done;
   57.19 +
   57.20  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   57.21  static void
   57.22  quit(int rc)
   57.23 @@ -230,11 +236,27 @@
   57.24      SDL_RenderPresent(renderer);
   57.25  }
   57.26  
   57.27 +void
   57.28 +loop()
   57.29 +{
   57.30 +    int i;
   57.31 +    SDL_Event event;
   57.32 +
   57.33 +    /* Check for events */
   57.34 +    while (SDL_PollEvent(&event)) {
   57.35 +        SDLTest_CommonEvent(state, &event, &done);
   57.36 +    }
   57.37 +    for (i = 0; i < state->num_windows; ++i) {
   57.38 +        if (state->windows[i] == NULL)
   57.39 +            continue;
   57.40 +        MoveSprites(state->renderers[i], sprites[i]);
   57.41 +    }
   57.42 +}
   57.43 +
   57.44  int
   57.45  main(int argc, char *argv[])
   57.46  {
   57.47 -    int i, done;
   57.48 -    SDL_Event event;
   57.49 +    int i;
   57.50      Uint32 then, now, frames;
   57.51  	Uint64 seed;
   57.52      const char *icon = "icon.bmp";
   57.53 @@ -351,18 +373,15 @@
   57.54      frames = 0;
   57.55      then = SDL_GetTicks();
   57.56      done = 0;
   57.57 +
   57.58 +#ifdef __EMSCRIPTEN__
   57.59 +    emscripten_set_main_loop(loop, 0, 1);
   57.60 +#else
   57.61      while (!done) {
   57.62 -        /* Check for events */
   57.63          ++frames;
   57.64 -        while (SDL_PollEvent(&event)) {
   57.65 -            SDLTest_CommonEvent(state, &event, &done);
   57.66 -        }
   57.67 -        for (i = 0; i < state->num_windows; ++i) {
   57.68 -            if (state->windows[i] == NULL)
   57.69 -                continue;
   57.70 -            MoveSprites(state->renderers[i], sprites[i]);
   57.71 -        }
   57.72 +        loop();
   57.73      }
   57.74 +#endif
   57.75  
   57.76      /* Print out some timing information */
   57.77      now = SDL_GetTicks();
    58.1 --- a/test/testspriteminimal.c	Sat Dec 13 02:33:52 2014 -0500
    58.2 +++ b/test/testspriteminimal.c	Thu Dec 18 00:19:52 2014 -0500
    58.3 @@ -15,6 +15,10 @@
    58.4  #include <stdio.h>
    58.5  #include <time.h>
    58.6  
    58.7 +#ifdef __EMSCRIPTEN__
    58.8 +#include <emscripten/emscripten.h>
    58.9 +#endif
   58.10 +
   58.11  #include "SDL.h"
   58.12  
   58.13  #define WINDOW_WIDTH    640
   58.14 @@ -27,6 +31,9 @@
   58.15  static SDL_Rect velocities[NUM_SPRITES];
   58.16  static int sprite_w, sprite_h;
   58.17  
   58.18 +SDL_Renderer *renderer;
   58.19 +int done;
   58.20 +
   58.21  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   58.22  static void
   58.23  quit(int rc)
   58.24 @@ -118,13 +125,25 @@
   58.25      SDL_RenderPresent(renderer);
   58.26  }
   58.27  
   58.28 +void loop()
   58.29 +{
   58.30 +    SDL_Event event;
   58.31 +
   58.32 +    /* Check for events */
   58.33 +    while (SDL_PollEvent(&event)) {
   58.34 +        if (event.type == SDL_QUIT || event.type == SDL_KEYDOWN) {
   58.35 +            done = 1;
   58.36 +        }
   58.37 +    }
   58.38 +    MoveSprites(renderer, sprite);
   58.39 +}
   58.40 +
   58.41  int
   58.42  main(int argc, char *argv[])
   58.43  {
   58.44      SDL_Window *window;
   58.45 -    SDL_Renderer *renderer;
   58.46 -    int i, done;
   58.47 -    SDL_Event event;
   58.48 +    int i;
   58.49 +
   58.50  
   58.51  	/* Enable standard application logging */
   58.52      SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   58.53 @@ -154,16 +173,14 @@
   58.54  
   58.55      /* Main render loop */
   58.56      done = 0;
   58.57 +
   58.58 +#ifdef __EMSCRIPTEN__
   58.59 +    emscripten_set_main_loop(loop, 0, 1);
   58.60 +#else
   58.61      while (!done) {
   58.62 -        /* Check for events */
   58.63 -        while (SDL_PollEvent(&event)) {
   58.64 -            if (event.type == SDL_QUIT || event.type == SDL_KEYDOWN) {
   58.65 -                done = 1;
   58.66 -            }
   58.67 +        loop();
   58.68          }
   58.69 -        MoveSprites(renderer, sprite);
   58.70 -    }
   58.71 -
   58.72 +#endif
   58.73      quit(0);
   58.74  
   58.75      return 0; /* to prevent compiler warning */
    59.1 --- a/test/teststreaming.c	Sat Dec 13 02:33:52 2014 -0500
    59.2 +++ b/test/teststreaming.c	Thu Dec 18 00:19:52 2014 -0500
    59.3 @@ -18,6 +18,10 @@
    59.4  #include <stdlib.h>
    59.5  #include <stdio.h>
    59.6  
    59.7 +#ifdef __EMSCRIPTEN__
    59.8 +#include <emscripten/emscripten.h>
    59.9 +#endif
   59.10 +
   59.11  #include "SDL.h"
   59.12  
   59.13  #define MOOSEPIC_W 64
   59.14 @@ -52,6 +56,11 @@
   59.15  
   59.16  Uint8 MooseFrames[MOOSEFRAMES_COUNT][MOOSEFRAME_SIZE];
   59.17  
   59.18 +SDL_Renderer *renderer;
   59.19 +int frame;
   59.20 +SDL_Texture *MooseTexture;
   59.21 +SDL_bool done = SDL_FALSE;
   59.22 +
   59.23  void quit(int rc)
   59.24  {
   59.25      SDL_Quit();
   59.26 @@ -82,16 +91,37 @@
   59.27      SDL_UnlockTexture(texture);
   59.28  }
   59.29  
   59.30 +void
   59.31 +loop()
   59.32 +{
   59.33 +    SDL_Event event;
   59.34 +
   59.35 +    while (SDL_PollEvent(&event)) {
   59.36 +        switch (event.type) {
   59.37 +        case SDL_KEYDOWN:
   59.38 +            if (event.key.keysym.sym == SDLK_ESCAPE) {
   59.39 +                done = SDL_TRUE;
   59.40 +            }
   59.41 +            break;
   59.42 +        case SDL_QUIT:
   59.43 +            done = SDL_TRUE;
   59.44 +            break;
   59.45 +        }
   59.46 +    }
   59.47 +
   59.48 +    frame = (frame + 1) % MOOSEFRAMES_COUNT;
   59.49 +    UpdateTexture(MooseTexture, frame);
   59.50 +
   59.51 +    SDL_RenderClear(renderer);
   59.52 +    SDL_RenderCopy(renderer, MooseTexture, NULL, NULL);
   59.53 +    SDL_RenderPresent(renderer);
   59.54 +}
   59.55 +
   59.56  int
   59.57  main(int argc, char **argv)
   59.58  {
   59.59      SDL_Window *window;
   59.60 -    SDL_Renderer *renderer;
   59.61      SDL_RWops *handle;
   59.62 -    SDL_Texture *MooseTexture;
   59.63 -    SDL_Event event;
   59.64 -    SDL_bool done = SDL_FALSE;
   59.65 -    int frame;
   59.66  
   59.67  	/* Enable standard application logging */
   59.68      SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   59.69 @@ -136,27 +166,15 @@
   59.70  
   59.71      /* Loop, waiting for QUIT or the escape key */
   59.72      frame = 0;
   59.73 +
   59.74 +#ifdef __EMSCRIPTEN__
   59.75 +    emscripten_set_main_loop(loop, 0, 1);
   59.76 +#else
   59.77      while (!done) {
   59.78 -        while (SDL_PollEvent(&event)) {
   59.79 -            switch (event.type) {
   59.80 -            case SDL_KEYDOWN:
   59.81 -                if (event.key.keysym.sym == SDLK_ESCAPE) {
   59.82 -                    done = SDL_TRUE;
   59.83 -                }
   59.84 -                break;
   59.85 -            case SDL_QUIT:
   59.86 -                done = SDL_TRUE;
   59.87 -                break;
   59.88 -            }
   59.89 +        loop();
   59.90          }
   59.91 +#endif
   59.92  
   59.93 -        frame = (frame + 1) % MOOSEFRAMES_COUNT;
   59.94 -        UpdateTexture(MooseTexture, frame);
   59.95 -
   59.96 -        SDL_RenderClear(renderer);
   59.97 -        SDL_RenderCopy(renderer, MooseTexture, NULL, NULL);
   59.98 -        SDL_RenderPresent(renderer);
   59.99 -    }
  59.100      SDL_DestroyRenderer(renderer);
  59.101  
  59.102      quit(0);
    60.1 --- a/test/testviewport.c	Sat Dec 13 02:33:52 2014 -0500
    60.2 +++ b/test/testviewport.c	Thu Dec 18 00:19:52 2014 -0500
    60.3 @@ -15,12 +15,23 @@
    60.4  #include <stdio.h>
    60.5  #include <time.h>
    60.6  
    60.7 +#ifdef __EMSCRIPTEN__
    60.8 +#include <emscripten/emscripten.h>
    60.9 +#endif
   60.10 +
   60.11  #include "SDL_test.h"
   60.12  #include "SDL_test_common.h"
   60.13  
   60.14  
   60.15  static SDLTest_CommonState *state;
   60.16  
   60.17 +SDL_Rect viewport;
   60.18 +int done, j;
   60.19 +SDL_bool use_target = SDL_FALSE;
   60.20 +#ifdef __EMSCRIPTEN__
   60.21 +Uint32 wait_start;
   60.22 +#endif
   60.23 +
   60.24  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   60.25  static void
   60.26  quit(int rc)
   60.27 @@ -77,14 +88,54 @@
   60.28      SDL_RenderFillRect(renderer, &rect);
   60.29  }
   60.30  
   60.31 +void
   60.32 +loop()
   60.33 +{
   60.34 +#ifdef __EMSCRIPTEN__
   60.35 +    /* Avoid using delays */
   60.36 +    if(SDL_GetTicks() - wait_start < 1000)
   60.37 +        return;
   60.38 +    wait_start = SDL_GetTicks();
   60.39 +#endif
   60.40 +    SDL_Event event;
   60.41 +    int i;
   60.42 +    /* Check for events */
   60.43 +    while (SDL_PollEvent(&event)) {
   60.44 +        SDLTest_CommonEvent(state, &event, &done);
   60.45 +    }
   60.46 +
   60.47 +    /* Move a viewport box in steps around the screen */
   60.48 +    viewport.x = j * 100;
   60.49 +    viewport.y = viewport.x;
   60.50 +    viewport.w = 100 + j * 50;
   60.51 +    viewport.h = 100 + j * 50;
   60.52 +    j = (j + 1) % 4;
   60.53 +    SDL_Log("Current Viewport x=%i y=%i w=%i h=%i", viewport.x, viewport.y, viewport.w, viewport.h);
   60.54 +
   60.55 +    for (i = 0; i < state->num_windows; ++i) {
   60.56 +        if (state->windows[i] == NULL)
   60.57 +            continue;
   60.58 +
   60.59 +        /* Draw using viewport */
   60.60 +        DrawOnViewport(state->renderers[i], viewport);
   60.61 +
   60.62 +        /* Update the screen! */
   60.63 +        if (use_target) {
   60.64 +            SDL_SetRenderTarget(state->renderers[i], NULL);
   60.65 +            SDL_RenderCopy(state->renderers[i], state->targets[i], NULL, NULL);
   60.66 +            SDL_RenderPresent(state->renderers[i]);
   60.67 +            SDL_SetRenderTarget(state->renderers[i], state->targets[i]);
   60.68 +        } else {
   60.69 +            SDL_RenderPresent(state->renderers[i]);
   60.70 +        }
   60.71 +    }
   60.72 +}
   60.73 +
   60.74  int
   60.75  main(int argc, char *argv[])
   60.76  {
   60.77 -    int i, j, done;
   60.78 -    SDL_Event event;
   60.79 +    int i;
   60.80      Uint32 then, now, frames;
   60.81 -    SDL_Rect viewport;
   60.82 -    SDL_bool use_target = SDL_FALSE;
   60.83  
   60.84      /* Initialize test framework */
   60.85      state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
   60.86 @@ -135,41 +186,17 @@
   60.87      then = SDL_GetTicks();
   60.88      done = 0;
   60.89      j = 0;
   60.90 +
   60.91 +#ifdef __EMSCRIPTEN__
   60.92 +    wait_start = SDL_GetTicks();
   60.93 +    emscripten_set_main_loop(loop, 0, 1);
   60.94 +#else
   60.95      while (!done) {
   60.96 -        /* Check for events */
   60.97          ++frames;
   60.98 -        while (SDL_PollEvent(&event)) {
   60.99 -            SDLTest_CommonEvent(state, &event, &done);
  60.100 -        }
  60.101 -        
  60.102 -        /* Move a viewport box in steps around the screen */                
  60.103 -        viewport.x = j * 100;
  60.104 -        viewport.y = viewport.x;
  60.105 -        viewport.w = 100 + j * 50;
  60.106 -        viewport.h = 100 + j * 50;
  60.107 -        j = (j + 1) % 4;            
  60.108 -        SDL_Log("Current Viewport x=%i y=%i w=%i h=%i", viewport.x, viewport.y, viewport.w, viewport.h);
  60.109 -        
  60.110 -        for (i = 0; i < state->num_windows; ++i) {
  60.111 -            if (state->windows[i] == NULL)
  60.112 -                continue;
  60.113 -                
  60.114 -            /* Draw using viewport */        
  60.115 -            DrawOnViewport(state->renderers[i], viewport);
  60.116 -
  60.117 -            /* Update the screen! */
  60.118 -            if (use_target) {
  60.119 -                SDL_SetRenderTarget(state->renderers[i], NULL);
  60.120 -                SDL_RenderCopy(state->renderers[i], state->targets[i], NULL, NULL);
  60.121 -                SDL_RenderPresent(state->renderers[i]);
  60.122 -                SDL_SetRenderTarget(state->renderers[i], state->targets[i]);
  60.123 -            } else {
  60.124 -                SDL_RenderPresent(state->renderers[i]);
  60.125 -            }
  60.126 -        }
  60.127 -        
  60.128 +        loop();
  60.129          SDL_Delay(1000);
  60.130      }
  60.131 +#endif
  60.132  
  60.133      /* Print out some timing information */
  60.134      now = SDL_GetTicks();
    61.1 --- a/test/testwm2.c	Sat Dec 13 02:33:52 2014 -0500
    61.2 +++ b/test/testwm2.c	Thu Dec 18 00:19:52 2014 -0500
    61.3 @@ -13,22 +13,16 @@
    61.4  #include <stdlib.h>
    61.5  #include <stdio.h>
    61.6  
    61.7 +#ifdef __EMSCRIPTEN__
    61.8 +#include <emscripten/emscripten.h>
    61.9 +#endif
   61.10 +
   61.11  #include "SDL_test_common.h"
   61.12  
   61.13  static SDLTest_CommonState *state;
   61.14 +int done;
   61.15  
   61.16 -/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   61.17 -static void
   61.18 -quit(int rc)
   61.19 -{
   61.20 -    SDLTest_CommonQuit(state);
   61.21 -    exit(rc);
   61.22 -}
   61.23 -
   61.24 -int
   61.25 -main(int argc, char *argv[])
   61.26 -{
   61.27 -    static const char *cursorNames[] = {
   61.28 +static const char *cursorNames[] = {
   61.29          "arrow",
   61.30          "ibeam",
   61.31          "wait",
   61.32 @@ -41,44 +35,22 @@
   61.33          "sizeALL",
   61.34          "NO",
   61.35          "hand",
   61.36 -    };
   61.37 +};
   61.38 +int system_cursor = -1;
   61.39 +SDL_Cursor *cursor = NULL;
   61.40  
   61.41 -    int i, done;
   61.42 +/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   61.43 +static void
   61.44 +quit(int rc)
   61.45 +{
   61.46 +    SDLTest_CommonQuit(state);
   61.47 +    exit(rc);
   61.48 +}
   61.49 +
   61.50 +void
   61.51 +loop()
   61.52 +{
   61.53      SDL_Event event;
   61.54 -    int system_cursor = -1;
   61.55 -    SDL_Cursor *cursor = NULL;
   61.56 -
   61.57 -	/* Enable standard application logging */
   61.58 -    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   61.59 -
   61.60 -    SDL_assert(SDL_arraysize(cursorNames) == SDL_NUM_SYSTEM_CURSORS);
   61.61 -
   61.62 -    /* Initialize test framework */
   61.63 -    state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
   61.64 -    if (!state) {
   61.65 -        return 1;
   61.66 -    }
   61.67 -    state->skip_renderer = SDL_TRUE;
   61.68 -    for (i = 1; i < argc;) {
   61.69 -        int consumed;
   61.70 -
   61.71 -        consumed = SDLTest_CommonArg(state, i);
   61.72 -        if (consumed == 0) {
   61.73 -            consumed = -1;
   61.74 -        }
   61.75 -        if (consumed < 0) {
   61.76 -            SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state));
   61.77 -            quit(1);
   61.78 -        }
   61.79 -        i += consumed;
   61.80 -    }
   61.81 -    if (!SDLTest_CommonInit(state)) {
   61.82 -        quit(2);
   61.83 -    }
   61.84 -
   61.85 -    /* Main render loop */
   61.86 -    done = 0;
   61.87 -    while (!done) {
   61.88          /* Check for events */
   61.89          while (SDL_PollEvent(&event)) {
   61.90              SDLTest_CommonEvent(state, &event, &done);
   61.91 @@ -128,7 +100,50 @@
   61.92                  }
   61.93              }
   61.94          }
   61.95 +}
   61.96 +
   61.97 +int
   61.98 +main(int argc, char *argv[])
   61.99 +{
  61.100 +    int i;
  61.101 +
  61.102 +	/* Enable standard application logging */
  61.103 +    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
  61.104 +
  61.105 +    SDL_assert(SDL_arraysize(cursorNames) == SDL_NUM_SYSTEM_CURSORS);
  61.106 +
  61.107 +    /* Initialize test framework */
  61.108 +    state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
  61.109 +    if (!state) {
  61.110 +        return 1;
  61.111      }
  61.112 +    state->skip_renderer = SDL_TRUE;
  61.113 +    for (i = 1; i < argc;) {
  61.114 +        int consumed;
  61.115 +
  61.116 +        consumed = SDLTest_CommonArg(state, i);
  61.117 +        if (consumed == 0) {
  61.118 +            consumed = -1;
  61.119 +        }
  61.120 +        if (consumed < 0) {
  61.121 +            SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state));
  61.122 +            quit(1);
  61.123 +        }
  61.124 +        i += consumed;
  61.125 +    }
  61.126 +    if (!SDLTest_CommonInit(state)) {
  61.127 +        quit(2);
  61.128 +    }
  61.129 +
  61.130 +    /* Main render loop */
  61.131 +    done = 0;
  61.132 +#ifdef __EMSCRIPTEN__
  61.133 +    emscripten_set_main_loop(loop, 0, 1);
  61.134 +#else
  61.135 +    while (!done) {
  61.136 +        loop();
  61.137 +    }
  61.138 +#endif
  61.139      SDL_FreeCursor(cursor);
  61.140  
  61.141      quit(0);