From 6aaedb813fa11ba0679c3051bc2eb28646b9506c Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 30 Aug 2025 16:53:58 -0700 Subject: Update to SDL3 --- src/contrib/SDL-2.30.2/docs/README-emscripten.md | 374 ----------------------- 1 file changed, 374 deletions(-) delete mode 100644 src/contrib/SDL-2.30.2/docs/README-emscripten.md (limited to 'src/contrib/SDL-2.30.2/docs/README-emscripten.md') diff --git a/src/contrib/SDL-2.30.2/docs/README-emscripten.md b/src/contrib/SDL-2.30.2/docs/README-emscripten.md deleted file mode 100644 index 1a13eb1..0000000 --- a/src/contrib/SDL-2.30.2/docs/README-emscripten.md +++ /dev/null @@ -1,374 +0,0 @@ -# Emscripten - -## The state of things - -(As of September 2023, but things move quickly and we don't update this -document often.) - -In modern times, all the browsers you probably care about (Chrome, Firefox, -Edge, and Safari, on Windows, macOS, Linux, iOS and Android), support some -reasonable base configurations: - -- WebAssembly (don't bother with asm.js any more) -- WebGL (which will look like OpenGL ES 2 or 3 to your app). -- Threads (see caveats, though!) -- Game controllers -- Autoupdating (so you can assume they have a recent version of the browser) - -All this to say we're at the point where you don't have to make a lot of -concessions to get even a fairly complex SDL-based game up and running. - - -## RTFM - -This document is a quick rundown of some high-level details. The -documentation at [emscripten.org](https://emscripten.org/) is vast -and extremely detailed for a wide variety of topics, and you should at -least skim through it at some point. - - -## Porting your app to Emscripten - -Many many things just need some simple adjustments and they'll compile -like any other C/C++ code, as long as SDL was handling the platform-specific -work for your program. - -First, you probably need this in at least one of your source files: - -```c -#ifdef __EMSCRIPTEN__ -#include -#endif -``` - -Second: assembly language code has to go. Replace it with C. You can even use -[x86 SIMD intrinsic functions in Emscripten](https://emscripten.org/docs/porting/simd.html)! - -Third: Middleware has to go. If you have a third-party library you link -against, you either need an Emscripten port of it, or the source code to it -to compile yourself, or you need to remove it. - -Fourth: You still start in a function called main(), but you need to get out of -it and into a function that gets called repeatedly, and returns quickly, -called a mainloop. - -Somewhere in your program, you probably have something that looks like a more -complicated version of this: - -```c -void main(void) -{ - initialize_the_game(); - while (game_is_still_running) { - check_for_new_input(); - think_about_stuff(); - draw_the_next_frame(); - } - deinitialize_the_game(); -} -``` - -This will not work on Emscripten, because the main thread needs to be free -to do stuff and can't sit in this loop forever. So Emscripten lets you set up -a [mainloop](https://emscripten.org/docs/porting/emscripten-runtime-environment.html#browser-main-loop). - -```c -static void mainloop(void) /* this will run often, possibly at the monitor's refresh rate */ -{ - if (!game_is_still_running) { - deinitialize_the_game(); - #ifdef __EMSCRIPTEN__ - emscripten_cancel_main_loop(); /* this should "kill" the app. */ - #else - exit(0); - #endif - } - - check_for_new_input(); - think_about_stuff(); - draw_the_next_frame(); -} - -void main(void) -{ - initialize_the_game(); - #ifdef __EMSCRIPTEN__ - emscripten_set_main_loop(mainloop, 0, 1); - #else - while (1) { mainloop(); } - #endif -} -``` - -Basically, `emscripten_set_main_loop(mainloop, 0, 1);` says "run -`mainloop` over and over until I end the program." The function will -run, and return, freeing the main thread for other tasks, and then -run again when it's time. The `1` parameter does some magic to make -your main() function end immediately; this is useful because you -don't want any shutdown code that might be sitting below this code -to actually run if main() were to continue on, since we're just -getting started. - -There's a lot of little details that are beyond the scope of this -document, but that's the biggest intial set of hurdles to porting -your app to the web. - - -## Do you need threads? - -If you plan to use threads, they work on all major browsers now. HOWEVER, -they bring with them a lot of careful considerations. Rendering _must_ -be done on the main thread. This is a general guideline for many -platforms, but a hard requirement on the web. - -Many other things also must happen on the main thread; often times SDL -and Emscripten make efforts to "proxy" work to the main thread that -must be there, but you have to be careful (and read more detailed -documentation than this for the finer points). - -Even when using threads, your main thread needs to set an Emscripten -mainloop that runs quickly and returns, or things will fail to work -correctly. - -You should definitely read [Emscripten's pthreads docs](https://emscripten.org/docs/porting/pthreads.html) -for all the finer points. Mostly SDL's thread API will work as expected, -but is built on pthreads, so it shares the same little incompatibilities -that are documented there, such as where you can use a mutex, and when -a thread will start running, etc. - - -IMPORTANT: You have to decide to either build something that uses -threads or something that doesn't; you can't have one build -that works everywhere. This is an Emscripten (or maybe WebAssembly? -Or just web browsers in general?) limitation. If you aren't using -threads, it's easier to not enable them at all, at build time. - -If you use threads, you _have to_ run from a web server that has -[COOP/COEP headers set correctly](https://web.dev/why-coop-coep/) -or your program will fail to start at all. - -If building with threads, `__EMSCRIPTEN_PTHREADS__` will be defined -for checking with the C preprocessor, so you can build something -different depending on what sort of build you're compiling. - - -## Audio - -Audio works as expected at the API level, but not exactly like other -platforms. - -You'll only see a single default audio device. Audio capture also works; -if the browser pops up a prompt to ask for permission to access the -microphone, the SDL_OpenAudioDevice call will succeed and start producing -silence at a regular interval. Once the user approves the request, real -audio data will flow. If the user denies it, the app is not informed and -will just continue to receive silence. - -Modern web browsers will not permit web pages to produce sound before the -user has interacted with them (clicked or tapped on them, usually); this is -for several reasons, not the least of which being that no one likes when a -random browser tab suddenly starts making noise and the user has to scramble -to figure out which and silence it. - -SDL will allow you to open the audio device for playback in this -circumstance, and your audio callback will fire, but SDL will throw the audio -data away until the user interacts with the page. This helps apps that depend -on the audio callback to make progress, and also keeps audio playback in sync -once the app is finally allowed to make noise. - -There are two reasonable ways to deal with the silence at the app level: -if you are writing some sort of media player thing, where the user expects -there to be a volume control when you mouseover the canvas, just default -that control to a muted state; if the user clicks on the control to unmute -it, on this first click, open the audio device. This allows the media to -play at start, and the user can reasonably opt-in to listening. - -Many games do not have this sort of UI, and are more rigid about starting -audio along with everything else at the start of the process. For these, your -best bet is to write a little Javascript that puts up a "Click here to play!" -UI, and upon the user clicking, remove that UI and then call the Emscripten -app's main() function. As far as the application knows, the audio device was -available to be opened as soon as the program started, and since this magic -happens in a little Javascript, you don't have to change your C/C++ code at -all to make it happen. - -Please see the discussion at https://github.com/libsdl-org/SDL/issues/6385 -for some Javascript code to steal for this approach. - - -## Rendering - -If you use SDL's 2D render API, it will use GLES2 internally, which -Emscripten will turn into WebGL calls. You can also use OpenGL ES 2 -directly by creating a GL context and drawing into it. - -Calling SDL_RenderPresent (or SDL_GL_SwapWindow) will not actually -present anything on the screen until your return from your mainloop -function. - - -## Building SDL/emscripten - -First: do you _really_ need to build SDL from source? - -If you aren't developing SDL itself, have a desire to mess with its source -code, or need something on the bleeding edge, don't build SDL. Just use -Emscripten's packaged version! - -Compile and link your app with `-sUSE_SDL=2` and it'll use a build of -SDL packaged with Emscripten. This comes from the same source code and -fixes the Emscripten project makes to SDL are generally merged into SDL's -revision control, so often this is much easier for app developers. - -`-sUSE_SDL=1` will select Emscripten's JavaScript reimplementation of SDL -1.2 instead; if you need SDL 1.2, this might be fine, but we generally -recommend you don't use SDL 1.2 in modern times. - - -If you want to build SDL, though... - -SDL currently requires at least Emscripten 3.1.35 to build. Newer versions -are likely to work, as well. - - -Build: - -This works on Linux/Unix and macOS. Please send comments about Windows. - -Make sure you've [installed emsdk](https://emscripten.org/docs/getting_started/downloads.html) -first, and run `source emsdk_env.sh` at the command line so it finds the -tools. - -(These configure options might be overkill, but this has worked for me.) - -```bash -cd SDL -mkdir build -cd build -emconfigure ../configure --host=wasm32-unknown-emscripten --disable-pthreads --disable-assembly --disable-cpuinfo CFLAGS="-sUSE_SDL=0 -O3" -emmake make -j4 -``` - -If you want to build with thread support, something like this works: - -```bash -emconfigure ../configure --host=wasm32-unknown-emscripten --enable-pthreads --disable-assembly --disable-cpuinfo CFLAGS="-sUSE_SDL=0 -O3 -pthread" LDFLAGS="-pthread" -``` - -Or with cmake: - -```bash -mkdir build -cd build -emcmake cmake .. -emmake make -j4 -``` - -To build one of the tests: - -```bash -cd test/ -emcc -O2 --js-opts 0 -g4 testdraw2.c -I../include ../build/.libs/libSDL2.a ../build/libSDL2_test.a -o a.html -``` - -## Building your app - -You need to compile with `emcc` instead of `gcc` or `clang` or whatever, but -mostly it uses the same command line arguments as Clang. - -Link against the SDL/build/.libs/libSDL2.a file you generated by building SDL, -link with `-sUSE_SDL=2` to use Emscripten's prepackaged SDL2 build. - -Usually you would produce a binary like this: - -```bash -gcc -o mygame mygame.c # or whatever -``` - -But for Emscripten, you want to output something else: - -```bash -emcc -o index.html mygame.c -``` - -This will produce several files...support Javascript and WebAssembly (.wasm) -files. The `-o index.html` will produce a simple HTML page that loads and -runs your app. You will (probably) eventually want to replace or customize -that file and do `-o index.js` instead to just build the code pieces. - -If you're working on a program of any serious size, you'll likely need to -link with `-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=1gb` to get access -to more memory. If using pthreads, you'll need the `-sMAXIMUM_MEMORY=1gb` -or the app will fail to start on iOS browsers, but this might be a bug that -goes away in the future. - - -## Data files - -Your game probably has data files. Here's how to access them. - -Filesystem access works like a Unix filesystem; you have a single directory -tree, possibly interpolated from several mounted locations, no drive letters, -'/' for a path separator. You can access them with standard file APIs like -open() or fopen() or SDL_RWops. You can read or write from the filesystem. - -By default, you probably have a "MEMFS" filesystem (all files are stored in -memory, but access to them is immediate and doesn't need to block). There are -other options, like "IDBFS" (files are stored in a local database, so they -don't need to be in RAM all the time and they can persist between runs of the -program, but access is not synchronous). You can mix and match these file -systems, mounting a MEMFS filesystem at one place and idbfs elsewhere, etc, -but that's beyond the scope of this document. Please refer to Emscripten's -[page on the topic](https://emscripten.org/docs/porting/files/file_systems_overview.html) -for more info. - -The _easiest_ (but not the best) way to get at your data files is to embed -them in the app itself. Emscripten's linker has support for automating this. - -```bash -emcc -o index.html loopwave.c --embed-file=../test/sample.wav@/sounds/sample.wav -``` - -This will pack ../test/sample.wav in your app, and make it available at -"/sounds/sample.wav" at runtime. Emscripten makes sure this data is available -before your main() function runs, and since it's in MEMFS, you can just -read it like you do on other platforms. `--embed-file` can also accept a -directory to pack an entire tree, and you can specify the argument multiple -times to pack unrelated things into the final installation. - -Note that this is absolutely the best approach if you have a few small -files to include and shouldn't worry about the issue further. However, if you -have hundreds of megabytes and/or thousands of files, this is not so great, -since the user will download it all every time they load your page, and it -all has to live in memory at runtime. - -[Emscripten's documentation on the matter](https://emscripten.org/docs/porting/files/packaging_files.html) -gives other options and details, and is worth a read. - - -## Debugging - -Debugging web apps is a mixed bag. You should compile and link with -`-gsource-map`, which embeds a ton of source-level debugging information into -the build, and make sure _the app source code is available on the web server_, -which is often a scary proposition for various reasons. - -When you debug from the browser's tools and hit a breakpoint, you can step -through the actual C/C++ source code, though, which can be nice. - -If you try debugging in Firefox and it doesn't work well for no apparent -reason, try Chrome, and vice-versa. These tools are still relatively new, -and improving all the time. - -SDL_Log() (or even plain old printf) will write to the Javascript console, -and honestly I find printf-style debugging to be easier than setting up a build -for proper debugging, so use whatever tools work best for you. - - -## Questions? - -Please give us feedback on this document at [the SDL bug tracker](https://github.com/libsdl-org/SDL/issues). -If something is wrong or unclear, we want to know! - - - -- cgit v1.2.3