https://github.com/libsdl-org/SDL/commit/3ad9c38a4655f9c809539334753676cc16b20ad6
From 3ad9c38a4655f9c809539334753676cc16b20ad6 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
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 11d50e78852ab..227cdc55606ad 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 587a3aed30fe6..833af7eb0d2aa 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 97e780648e6f8..ccd02d891acd2 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_