Browse Source

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.
Ryan C. Gordon 3 months ago
parent
commit
3ad9c38a46

+ 8 - 4
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;

+ 24 - 1
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)

+ 2 - 0
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_