SDL: SDL2 thread proxying fixes

From 4dca8f7fb4c63d1b42c31c7dd821197832714c3f Mon Sep 17 00:00:00 2001
From: Reinhold Gschweicher <[EMAIL REDACTED]>
Date: Thu, 24 Feb 2022 21:09:03 +0100
Subject: [PATCH] SDL2 thread proxying fixes

This PR uses new APIs added in [emscripten-core/emscripten#9336](https://github.com/emscripten-core/emscripten/pull/9336)
to improve compatibility with USE_PTHREADS=1.

Original PR: https://github.com/emscripten-ports/SDL2/pull/127
By: @jakogut
Reviewed by: Daft-Freak
---
 .../emscripten/SDL_emscriptenframebuffer.c    | 37 +++++++++----
 src/video/emscripten/SDL_emscriptenmouse.c    | 54 +++++++++++++------
 2 files changed, 65 insertions(+), 26 deletions(-)

diff --git a/src/video/emscripten/SDL_emscriptenframebuffer.c b/src/video/emscripten/SDL_emscriptenframebuffer.c
index d4e9cb8e8d7..d7f41ef9297 100644
--- a/src/video/emscripten/SDL_emscriptenframebuffer.c
+++ b/src/video/emscripten/SDL_emscriptenframebuffer.c
@@ -26,6 +26,8 @@
 #include "SDL_emscriptenframebuffer.h"
 #include "SDL_hints.h"
 
+#include <emscripten/threading.h>
+
 
 int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
 {
@@ -57,18 +59,8 @@ int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * form
     return 0;
 }
 
-int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
+static void Emscripten_UpdateWindowFramebufferWorker(SDL_Surface *surface)
 {
-    SDL_Surface *surface;
-
-    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
-    surface = data->surface;
-    if (!surface) {
-        return SDL_SetError("Couldn't find framebuffer surface for window");
-    }
-
-    /* Send the data to the display */
-
     EM_ASM_INT({
         var w = $0;
         var h = $1;
@@ -156,6 +148,29 @@ int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rec
         SDL2.ctx.putImageData(SDL2.image, 0, 0);
         return 0;
     }, surface->w, surface->h, surface->pixels);
+}
+
+int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
+{
+    SDL_Surface *surface;
+
+    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+    surface = data->surface;
+    if (!surface) {
+        return SDL_SetError("Couldn't find framebuffer surface for window");
+    }
+
+    /* Send the data to the display */
+
+    if (emscripten_is_main_runtime_thread()) {
+        Emscripten_UpdateWindowFramebufferWorker(surface);
+    } else {
+        emscripten_sync_run_in_main_runtime_thread(
+            EM_FUNC_SIG_VI,
+            Emscripten_UpdateWindowFramebufferWorker,
+            (uint32_t)surface
+        );
+    }
 
     if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) {
         /* give back control to browser for screen refresh */
diff --git a/src/video/emscripten/SDL_emscriptenmouse.c b/src/video/emscripten/SDL_emscriptenmouse.c
index e7307259091..976716afdb1 100644
--- a/src/video/emscripten/SDL_emscriptenmouse.c
+++ b/src/video/emscripten/SDL_emscriptenmouse.c
@@ -24,6 +24,7 @@
 
 #include <emscripten/emscripten.h>
 #include <emscripten/html5.h>
+#include <emscripten/threading.h>
 
 #include "SDL_emscriptenmouse.h"
 #include "SDL_emscriptenvideo.h"
@@ -62,19 +63,9 @@ Emscripten_CreateDefaultCursor()
     return Emscripten_CreateCursorFromString("default", SDL_FALSE);
 }
 
-static SDL_Cursor*
-Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
+static const char *Emscripten_GetCursorUrl(int w, int h, int hot_x, int hot_y, int pixels)
 {
-    const char *cursor_url = NULL;
-    SDL_Surface *conv_surf;
-
-    conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
-
-    if (!conv_surf) {
-        return NULL;
-    }
-
-    cursor_url = (const char *)EM_ASM_INT({
+    return (const char *)EM_ASM_INT({
         var w = $0;
         var h = $1;
         var hot_x = $2;
@@ -122,7 +113,40 @@ Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
         stringToUTF8(url, urlBuf, url.length + 1);
 
         return urlBuf;
-    }, surface->w, surface->h, hot_x, hot_y, conv_surf->pixels);
+    }, w, h, hot_x, hot_y, pixels);
+}
+
+static SDL_Cursor*
+Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
+{
+    const char *cursor_url = NULL;
+    SDL_Surface *conv_surf;
+
+    conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
+
+    if (!conv_surf) {
+        return NULL;
+    }
+
+    if (emscripten_is_main_runtime_thread()) {
+        cursor_url = Emscripten_GetCursorUrl(
+            surface->w,
+            surface->h,
+            hot_x,
+            hot_y,
+            conv_surf->pixels
+        );
+    } else {
+        cursor_url = emscripten_sync_run_in_main_runtime_thread(
+            EM_FUNC_SIG_IIIIIII,
+            Emscripten_GetCursorUrl,
+            surface->w,
+            surface->h,
+            hot_x,
+            hot_y,
+            conv_surf->pixels
+        );
+    }
 
     SDL_FreeSurface(conv_surf);
 
@@ -206,7 +230,7 @@ Emscripten_ShowCursor(SDL_Cursor* cursor)
             curdata = (Emscripten_CursorData *) cursor->driverdata;
 
             if(curdata->system_cursor) {
-                EM_ASM_INT({
+                MAIN_THREAD_EM_ASM_INT({
                     if (Module['canvas']) {
                         Module['canvas'].style['cursor'] = UTF8ToString($0);
                     }
@@ -215,7 +239,7 @@ Emscripten_ShowCursor(SDL_Cursor* cursor)
             }
         }
         else {
-            EM_ASM(
+            MAIN_THREAD_EM_ASM_INT(
                 if (Module['canvas']) {
                     Module['canvas'].style['cursor'] = 'none';
                 }