SDL: emscripten: Return an error for webgl context limitations

From 539efc1bbaec197cb0d6663824fd29fd71060785 Mon Sep 17 00:00:00 2001
From: Charlie Birks <[EMAIL REDACTED]>
Date: Sat, 26 Feb 2022 12:24:32 +0000
Subject: [PATCH] emscripten: Return an error for webgl context limitations

---
 src/video/emscripten/SDL_emscriptenopengles.c | 30 ++++++++++++++++++-
 src/video/emscripten/SDL_emscriptenvideo.h    |  2 ++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/src/video/emscripten/SDL_emscriptenopengles.c b/src/video/emscripten/SDL_emscriptenopengles.c
index a3219372c147..ccec124ce20f 100644
--- a/src/video/emscripten/SDL_emscriptenopengles.c
+++ b/src/video/emscripten/SDL_emscriptenopengles.c
@@ -94,6 +94,12 @@ Emscripten_GLES_CreateContext(_THIS, SDL_Window * window)
         attribs.majorVersion = 2; /* WebGL 2.0 ~= GLES 3.0 */
 
     window_data = (SDL_WindowData *) window->driverdata;
+
+    if (window_data->gl_context) {
+        SDL_SetError("Cannot create multiple webgl contexts per window");
+        return NULL;
+    }
+
     context = emscripten_webgl_create_context(window_data->canvas_id, &attribs);
 
     if (context < 0) {
@@ -106,6 +112,7 @@ Emscripten_GLES_CreateContext(_THIS, SDL_Window * window)
         return NULL;
     }
 
+    window_data->gl_context = (SDL_GLContext)context;
 
     return (SDL_GLContext)context;
 }
@@ -113,6 +120,18 @@ Emscripten_GLES_CreateContext(_THIS, SDL_Window * window)
 void
 Emscripten_GLES_DeleteContext(_THIS, SDL_GLContext context)
 {
+    SDL_Window *window;
+
+    /* remove the context from its window */
+    for (window = _this->windows; window != NULL; window = window->next) {
+        SDL_WindowData *window_data;
+        window_data = (SDL_WindowData *) window->driverdata;
+
+        if (window_data->gl_context == context) {
+            window_data->gl_context = NULL;
+        }
+    }
+
     emscripten_webgl_destroy_context((EMSCRIPTEN_WEBGL_CONTEXT_HANDLE)context);
 }
 
@@ -129,7 +148,16 @@ Emscripten_GLES_SwapWindow(_THIS, SDL_Window * window)
 int
 Emscripten_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
 {
-    /* ignores window, as it isn't possible to reuse contexts across canvases */
+    /* it isn't possible to reuse contexts across canvases */
+    if (window && context) {
+        SDL_WindowData *window_data;
+        window_data = (SDL_WindowData *) window->driverdata;
+
+        if (context != window_data->gl_context) {
+            return SDL_SetError("Cannot make context current to another window");
+        }
+    }
+
     if (emscripten_webgl_make_context_current((EMSCRIPTEN_WEBGL_CONTEXT_HANDLE)context) != EMSCRIPTEN_RESULT_SUCCESS) {
         return SDL_SetError("Unable to make context current");
     }
diff --git a/src/video/emscripten/SDL_emscriptenvideo.h b/src/video/emscripten/SDL_emscriptenvideo.h
index 20481235e5b5..4cd0a5ce59e2 100644
--- a/src/video/emscripten/SDL_emscriptenvideo.h
+++ b/src/video/emscripten/SDL_emscriptenvideo.h
@@ -33,6 +33,8 @@ typedef struct SDL_WindowData
     SDL_Window *window;
     SDL_Surface *surface;
 
+    SDL_GLContext gl_context;
+
     char *canvas_id;
 
     float pixel_ratio;