From 3ad9c38a4655f9c809539334753676cc16b20ad6 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 11 Jan 2025 15:14:36 -0500 Subject: [PATCH] emscripten: Don't set OpenGL swap intervals until first PumpEvents. Any requested swap interval will be saved and set on the first PumpEvents. Once PumpEvents has been called at least once, swap intervals are set immediately. This assumes that events won't be pumped until after an Emscripten main loop has been defined, and so prevents a warning on the javascript console: "emscripten_set_main_loop_timing: Cannot set timing mode for main loop since a main loop does not exist! Call emscripten_set_main_loop first to set one up." Fixes #9969. --- src/video/emscripten/SDL_emscriptenopengles.c | 12 ++++++--- src/video/emscripten/SDL_emscriptenvideo.c | 25 ++++++++++++++++++- src/video/emscripten/SDL_emscriptenvideo.h | 2 ++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/video/emscripten/SDL_emscriptenopengles.c b/src/video/emscripten/SDL_emscriptenopengles.c index 11d50e788..227cdc556 100644 --- a/src/video/emscripten/SDL_emscriptenopengles.c +++ b/src/video/emscripten/SDL_emscriptenopengles.c @@ -47,10 +47,14 @@ bool Emscripten_GLES_SetSwapInterval(SDL_VideoDevice *_this, int interval) { if (interval < 0) { return SDL_SetError("Late swap tearing currently unsupported"); - } else if (interval == 0) { - emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, 0); - } else { - emscripten_set_main_loop_timing(EM_TIMING_RAF, interval); + } + + if (Emscripten_ShouldSetSwapInterval(interval)) { + if (interval == 0) { + emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, 0); + } else { + emscripten_set_main_loop_timing(EM_TIMING_RAF, interval); + } } return true; diff --git a/src/video/emscripten/SDL_emscriptenvideo.c b/src/video/emscripten/SDL_emscriptenvideo.c index 587a3aed3..833af7eb0 100644 --- a/src/video/emscripten/SDL_emscriptenvideo.c +++ b/src/video/emscripten/SDL_emscriptenvideo.c @@ -48,6 +48,10 @@ static SDL_FullscreenResult Emscripten_SetWindowFullscreen(SDL_VideoDevice *_thi static void Emscripten_PumpEvents(SDL_VideoDevice *_this); static void Emscripten_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); +static bool pumpevents_has_run = false; +static int pending_swap_interval = -1; + + // Emscripten driver bootstrap functions static void Emscripten_DeleteDevice(SDL_VideoDevice *device) @@ -228,6 +232,8 @@ static void Emscripten_VideoQuit(SDL_VideoDevice *_this) { Emscripten_QuitMouse(); Emscripten_UnlistenSystemTheme(); + pumpevents_has_run = false; + pending_swap_interval = -1; } static bool Emscripten_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect) @@ -245,9 +251,26 @@ static bool Emscripten_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoD return true; } +bool Emscripten_ShouldSetSwapInterval(int interval) +{ + if (!pumpevents_has_run) { + pending_swap_interval = interval; + return false; + } + return true; +} + static void Emscripten_PumpEvents(SDL_VideoDevice *_this) { - // do nothing. + if (!pumpevents_has_run) { + // we assume you've set a mainloop by the time you've called pumpevents, so we delay initial SetInterval changes until then. + // otherwise you'll get a warning on the javascript console. + pumpevents_has_run = true; + if (pending_swap_interval >= 0) { + Emscripten_GLES_SetSwapInterval(_this, pending_swap_interval); + pending_swap_interval = -1; + } + } } static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) diff --git a/src/video/emscripten/SDL_emscriptenvideo.h b/src/video/emscripten/SDL_emscriptenvideo.h index 97e780648..ccd02d891 100644 --- a/src/video/emscripten/SDL_emscriptenvideo.h +++ b/src/video/emscripten/SDL_emscriptenvideo.h @@ -47,4 +47,6 @@ struct SDL_WindowData bool has_pointer_lock; }; +bool Emscripten_ShouldSetSwapInterval(int interval); + #endif // SDL_emscriptenvideo_h_