Skip to content

Commit

Permalink
emscripten: Use emscripten_webgl_ API directly
Browse files Browse the repository at this point in the history
  • Loading branch information
Daft-Freak committed Apr 6, 2022
1 parent 279aeb5 commit cb6d810
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 89 deletions.
138 changes: 89 additions & 49 deletions src/video/emscripten/SDL_emscriptenopengles.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,80 +20,120 @@
*/
#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;
}

void
Expand All @@ -113,7 +153,7 @@ Emscripten_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
}
}

#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL */
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */

/* vi: set ts=4 sw=4 expandtab: */

16 changes: 7 additions & 9 deletions src/video/emscripten/SDL_emscriptenopengles.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,24 @@
#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);
extern void Emscripten_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h);

#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL */
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */

#endif /* SDL_emscriptenopengles_h_ */

Expand Down
24 changes: 0 additions & 24 deletions src/video/emscripten/SDL_emscriptenvideo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -108,7 +107,6 @@ Emscripten_CreateDevice(int devindex)
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;
Expand All @@ -119,7 +117,6 @@ Emscripten_CreateDevice(int devindex)
device->GL_SwapWindow = Emscripten_GLES_SwapWindow;
device->GL_DeleteContext = Emscripten_GLES_DeleteContext;
device->GL_GetDrawableSize = Emscripten_GLES_GetDrawableSize;
#endif

device->free = Emscripten_DeleteDevice;

Expand Down Expand Up @@ -258,21 +255,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 */
Expand Down Expand Up @@ -316,12 +298,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);
Expand Down
7 changes: 0 additions & 7 deletions src/video/emscripten/SDL_emscriptenvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit cb6d810

Please sign in to comment.