From eebbf3457ccb7ebca9a83cd77e8673a5f822e772 Mon Sep 17 00:00:00 2001
From: Charlie Birks <[EMAIL REDACTED]>
Date: Fri, 25 Feb 2022 17:19:25 +0000
Subject: [PATCH] emscripten: Use emscripten_webgl_ API directly
---
src/video/emscripten/SDL_emscriptenopengles.c | 138 +++++++++++-------
src/video/emscripten/SDL_emscriptenopengles.h | 16 +-
src/video/emscripten/SDL_emscriptenvideo.c | 24 ---
src/video/emscripten/SDL_emscriptenvideo.h | 7 -
4 files changed, 96 insertions(+), 89 deletions(-)
diff --git a/src/video/emscripten/SDL_emscriptenopengles.c b/src/video/emscripten/SDL_emscriptenopengles.c
index 10c6285cf325..a3219372c147 100644
--- a/src/video/emscripten/SDL_emscriptenopengles.c
+++ b/src/video/emscripten/SDL_emscriptenopengles.c
@@ -20,83 +20,123 @@
*/
#include "../../SDL_internal.h"
-#if SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL
+#if SDL_VIDEO_DRIVER_EMSCRIPTEN
#include <emscripten/emscripten.h>
+#include <emscripten/html5_webgl.h>
#include <GLES2/gl2.h>
#include "SDL_emscriptenvideo.h"
#include "SDL_emscriptenopengles.h"
#include "SDL_hints.h"
-#define LOAD_FUNC(NAME) _this->egl_data->NAME = NAME;
-/* EGL implementation of SDL OpenGL support */
+int
+Emscripten_GLES_LoadLibrary(_THIS, const char *path)
+{
+ return 0;
+}
+
+void
+Emscripten_GLES_UnloadLibrary(_THIS)
+{
+}
+
+void *
+Emscripten_GLES_GetProcAddress(_THIS, const char *proc)
+{
+ return emscripten_webgl_get_proc_address(proc);
+}
int
-Emscripten_GLES_LoadLibrary(_THIS, const char *path) {
- /*we can't load EGL dynamically*/
- _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
- if (!_this->egl_data) {
- return SDL_OutOfMemory();
+Emscripten_GLES_SetSwapInterval(_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);
}
- /* Emscripten forces you to manually cast eglGetProcAddress to the real
- function type; grep for "__eglMustCastToProperFunctionPointerType" in
- Emscripten's egl.h for details. */
- _this->egl_data->eglGetProcAddress = (void *(EGLAPIENTRY *)(const char *)) eglGetProcAddress;
-
- LOAD_FUNC(eglGetDisplay);
- LOAD_FUNC(eglInitialize);
- LOAD_FUNC(eglTerminate);
- LOAD_FUNC(eglChooseConfig);
- LOAD_FUNC(eglGetConfigAttrib);
- LOAD_FUNC(eglCreateContext);
- LOAD_FUNC(eglDestroyContext);
- LOAD_FUNC(eglCreateWindowSurface);
- LOAD_FUNC(eglDestroySurface);
- LOAD_FUNC(eglMakeCurrent);
- LOAD_FUNC(eglSwapBuffers);
- LOAD_FUNC(eglSwapInterval);
- LOAD_FUNC(eglWaitNative);
- LOAD_FUNC(eglWaitGL);
- LOAD_FUNC(eglBindAPI);
- LOAD_FUNC(eglQueryString);
- LOAD_FUNC(eglGetError);
-
- _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (!_this->egl_data->egl_display) {
- return SDL_SetError("Could not get EGL display");
- }
-
- if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
- return SDL_SetError("Could not initialize EGL");
+ return 0;
+}
+
+int
+Emscripten_GLES_GetSwapInterval(_THIS)
+{
+ int mode, value;
+
+ emscripten_get_main_loop_timing(&mode, &value);
+
+ if(mode == EM_TIMING_RAF)
+ return value;
+
+ return 0;
+}
+
+SDL_GLContext
+Emscripten_GLES_CreateContext(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *window_data;
+
+ EmscriptenWebGLContextAttributes attribs;
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context;
+
+ emscripten_webgl_init_context_attributes(&attribs);
+
+ attribs.alpha = _this->gl_config.alpha_size > 0;
+ attribs.depth = _this->gl_config.depth_size > 0;
+ attribs.stencil = _this->gl_config.stencil_size > 0;
+ attribs.antialias = _this->gl_config.multisamplebuffers == 1;
+
+ if(_this->gl_config.major_version == 3)
+ attribs.majorVersion = 2; /* WebGL 2.0 ~= GLES 3.0 */
+
+ window_data = (SDL_WindowData *) window->driverdata;
+ context = emscripten_webgl_create_context(window_data->canvas_id, &attribs);
+
+ if (context < 0) {
+ SDL_SetError("Could not create webgl context");
+ return NULL;
}
- if (path) {
- SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
- } else {
- *_this->gl_config.driver_path = '\0';
+ if (emscripten_webgl_make_context_current(context) != EMSCRIPTEN_RESULT_SUCCESS) {
+ emscripten_webgl_destroy_context(context);
+ return NULL;
}
-
- return 0;
+
+
+ return (SDL_GLContext)context;
}
-SDL_EGL_CreateContext_impl(Emscripten)
-SDL_EGL_MakeCurrent_impl(Emscripten)
+void
+Emscripten_GLES_DeleteContext(_THIS, SDL_GLContext context)
+{
+ emscripten_webgl_destroy_context((EMSCRIPTEN_WEBGL_CONTEXT_HANDLE)context);
+}
int
Emscripten_GLES_SwapWindow(_THIS, SDL_Window * window)
{
- EGLBoolean ret = SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) {
/* give back control to browser for screen refresh */
emscripten_sleep(0);
}
- return ret;
+ return 0;
+}
+
+int
+Emscripten_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
+{
+ /* ignores window, as it isn't possible to reuse contexts across canvases */
+ if (emscripten_webgl_make_context_current((EMSCRIPTEN_WEBGL_CONTEXT_HANDLE)context) != EMSCRIPTEN_RESULT_SUCCESS) {
+ return SDL_SetError("Unable to make context current");
+ }
+ return 0;
}
-#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL */
+#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/emscripten/SDL_emscriptenopengles.h b/src/video/emscripten/SDL_emscriptenopengles.h
index 9d178f6902d9..6d58ac10dfd4 100644
--- a/src/video/emscripten/SDL_emscriptenopengles.h
+++ b/src/video/emscripten/SDL_emscriptenopengles.h
@@ -23,25 +23,23 @@
#ifndef SDL_emscriptenopengles_h_
#define SDL_emscriptenopengles_h_
-#if SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL
+#if SDL_VIDEO_DRIVER_EMSCRIPTEN
#include "../SDL_sysvideo.h"
-#include "../SDL_egl_c.h"
/* OpenGLES functions */
-#define Emscripten_GLES_GetAttribute SDL_EGL_GetAttribute
-#define Emscripten_GLES_GetProcAddress SDL_EGL_GetProcAddress
-#define Emscripten_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
-#define Emscripten_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
-#define Emscripten_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
-#define Emscripten_GLES_DeleteContext SDL_EGL_DeleteContext
extern int Emscripten_GLES_LoadLibrary(_THIS, const char *path);
+extern void Emscripten_GLES_UnloadLibrary(_THIS);
+extern void * Emscripten_GLES_GetProcAddress(_THIS, const char *proc);
+extern int Emscripten_GLES_SetSwapInterval(_THIS, int interval);
+extern int Emscripten_GLES_GetSwapInterval(_THIS);
extern SDL_GLContext Emscripten_GLES_CreateContext(_THIS, SDL_Window * window);
+extern void Emscripten_GLES_DeleteContext(_THIS, SDL_GLContext context);
extern int Emscripten_GLES_SwapWindow(_THIS, SDL_Window * window);
extern int Emscripten_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
-#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL */
+#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
#endif /* SDL_emscriptenopengles_h_ */
diff --git a/src/video/emscripten/SDL_emscriptenvideo.c b/src/video/emscripten/SDL_emscriptenvideo.c
index 550031d3fbea..46813a721798 100644
--- a/src/video/emscripten/SDL_emscriptenvideo.c
+++ b/src/video/emscripten/SDL_emscriptenvideo.c
@@ -27,7 +27,6 @@
#include "SDL_hints.h"
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
-#include "../SDL_egl_c.h"
#include "../../events/SDL_events_c.h"
#include "SDL_emscriptenvideo.h"
@@ -110,7 +109,6 @@ Emscripten_CreateDevice(void)
device->UpdateWindowFramebuffer = Emscripten_UpdateWindowFramebuffer;
device->DestroyWindowFramebuffer = Emscripten_DestroyWindowFramebuffer;
-#if SDL_VIDEO_OPENGL_EGL
device->GL_LoadLibrary = Emscripten_GLES_LoadLibrary;
device->GL_GetProcAddress = Emscripten_GLES_GetProcAddress;
device->GL_UnloadLibrary = Emscripten_GLES_UnloadLibrary;
@@ -120,7 +118,6 @@ Emscripten_CreateDevice(void)
device->GL_GetSwapInterval = Emscripten_GLES_GetSwapInterval;
device->GL_SwapWindow = Emscripten_GLES_SwapWindow;
device->GL_DeleteContext = Emscripten_GLES_DeleteContext;
-#endif
device->free = Emscripten_DeleteDevice;
@@ -259,21 +256,6 @@ Emscripten_CreateWindow(_THIS, SDL_Window * window)
}
}
-#if SDL_VIDEO_OPENGL_EGL
- if (window->flags & SDL_WINDOW_OPENGL) {
- if (!_this->egl_data) {
- if (SDL_GL_LoadLibrary(NULL) < 0) {
- return -1;
- }
- }
- wdata->egl_surface = SDL_EGL_CreateSurface(_this, 0);
-
- if (wdata->egl_surface == EGL_NO_SURFACE) {
- return SDL_SetError("Could not create GLES window surface");
- }
- }
-#endif
-
wdata->window = window;
/* Setup driver data for this window */
@@ -329,12 +311,6 @@ Emscripten_DestroyWindow(_THIS, SDL_Window * window)
data = (SDL_WindowData *) window->driverdata;
Emscripten_UnregisterEventHandlers(data);
-#if SDL_VIDEO_OPENGL_EGL
- if (data->egl_surface != EGL_NO_SURFACE) {
- SDL_EGL_DestroySurface(_this, data->egl_surface);
- data->egl_surface = EGL_NO_SURFACE;
- }
-#endif
/* We can't destroy the canvas, so resize it to zero instead */
emscripten_set_canvas_element_size(data->canvas_id, 0, 0);
diff --git a/src/video/emscripten/SDL_emscriptenvideo.h b/src/video/emscripten/SDL_emscriptenvideo.h
index e87788d3f815..20481235e5b5 100644
--- a/src/video/emscripten/SDL_emscriptenvideo.h
+++ b/src/video/emscripten/SDL_emscriptenvideo.h
@@ -28,15 +28,8 @@
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
-#if SDL_VIDEO_OPENGL_EGL
-#include <EGL/egl.h>
-#endif
-
typedef struct SDL_WindowData
{
-#if SDL_VIDEO_OPENGL_EGL
- EGLSurface egl_surface;
-#endif
SDL_Window *window;
SDL_Surface *surface;