emscripten: Use emscripten_webgl_ API directly
This commit is contained in:
parent
f6c2c22d38
commit
eebbf3457c
4 changed files with 101 additions and 94 deletions
|
@ -20,83 +20,123 @@
|
||||||
*/
|
*/
|
||||||
#include "../../SDL_internal.h"
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
#if SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL
|
#if SDL_VIDEO_DRIVER_EMSCRIPTEN
|
||||||
|
|
||||||
#include <emscripten/emscripten.h>
|
#include <emscripten/emscripten.h>
|
||||||
|
#include <emscripten/html5_webgl.h>
|
||||||
#include <GLES2/gl2.h>
|
#include <GLES2/gl2.h>
|
||||||
|
|
||||||
#include "SDL_emscriptenvideo.h"
|
#include "SDL_emscriptenvideo.h"
|
||||||
#include "SDL_emscriptenopengles.h"
|
#include "SDL_emscriptenopengles.h"
|
||||||
#include "SDL_hints.h"
|
#include "SDL_hints.h"
|
||||||
|
|
||||||
#define LOAD_FUNC(NAME) _this->egl_data->NAME = NAME;
|
|
||||||
|
|
||||||
/* EGL implementation of SDL OpenGL support */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Emscripten_GLES_LoadLibrary(_THIS, const char *path) {
|
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 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path) {
|
|
||||||
SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
|
|
||||||
} else {
|
|
||||||
*_this->gl_config.driver_path = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_EGL_CreateContext_impl(Emscripten)
|
void
|
||||||
SDL_EGL_MakeCurrent_impl(Emscripten)
|
Emscripten_GLES_UnloadLibrary(_THIS)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
Emscripten_GLES_GetProcAddress(_THIS, const char *proc)
|
||||||
|
{
|
||||||
|
return emscripten_webgl_get_proc_address(proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (emscripten_webgl_make_context_current(context) != EMSCRIPTEN_RESULT_SUCCESS) {
|
||||||
|
emscripten_webgl_destroy_context(context);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (SDL_GLContext)context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Emscripten_GLES_DeleteContext(_THIS, SDL_GLContext context)
|
||||||
|
{
|
||||||
|
emscripten_webgl_destroy_context((EMSCRIPTEN_WEBGL_CONTEXT_HANDLE)context);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Emscripten_GLES_SwapWindow(_THIS, SDL_Window * window)
|
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)) {
|
if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) {
|
||||||
/* give back control to browser for screen refresh */
|
/* give back control to browser for screen refresh */
|
||||||
emscripten_sleep(0);
|
emscripten_sleep(0);
|
||||||
}
|
}
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL */
|
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 */
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
||||||
|
|
|
@ -23,25 +23,23 @@
|
||||||
#ifndef SDL_emscriptenopengles_h_
|
#ifndef SDL_emscriptenopengles_h_
|
||||||
#define 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_sysvideo.h"
|
||||||
#include "../SDL_egl_c.h"
|
|
||||||
|
|
||||||
/* OpenGLES functions */
|
/* 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 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 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_SwapWindow(_THIS, SDL_Window * window);
|
||||||
extern int Emscripten_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
|
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_ */
|
#endif /* SDL_emscriptenopengles_h_ */
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "SDL_hints.h"
|
#include "SDL_hints.h"
|
||||||
#include "../SDL_sysvideo.h"
|
#include "../SDL_sysvideo.h"
|
||||||
#include "../SDL_pixels_c.h"
|
#include "../SDL_pixels_c.h"
|
||||||
#include "../SDL_egl_c.h"
|
|
||||||
#include "../../events/SDL_events_c.h"
|
#include "../../events/SDL_events_c.h"
|
||||||
|
|
||||||
#include "SDL_emscriptenvideo.h"
|
#include "SDL_emscriptenvideo.h"
|
||||||
|
@ -110,7 +109,6 @@ Emscripten_CreateDevice(void)
|
||||||
device->UpdateWindowFramebuffer = Emscripten_UpdateWindowFramebuffer;
|
device->UpdateWindowFramebuffer = Emscripten_UpdateWindowFramebuffer;
|
||||||
device->DestroyWindowFramebuffer = Emscripten_DestroyWindowFramebuffer;
|
device->DestroyWindowFramebuffer = Emscripten_DestroyWindowFramebuffer;
|
||||||
|
|
||||||
#if SDL_VIDEO_OPENGL_EGL
|
|
||||||
device->GL_LoadLibrary = Emscripten_GLES_LoadLibrary;
|
device->GL_LoadLibrary = Emscripten_GLES_LoadLibrary;
|
||||||
device->GL_GetProcAddress = Emscripten_GLES_GetProcAddress;
|
device->GL_GetProcAddress = Emscripten_GLES_GetProcAddress;
|
||||||
device->GL_UnloadLibrary = Emscripten_GLES_UnloadLibrary;
|
device->GL_UnloadLibrary = Emscripten_GLES_UnloadLibrary;
|
||||||
|
@ -120,7 +118,6 @@ Emscripten_CreateDevice(void)
|
||||||
device->GL_GetSwapInterval = Emscripten_GLES_GetSwapInterval;
|
device->GL_GetSwapInterval = Emscripten_GLES_GetSwapInterval;
|
||||||
device->GL_SwapWindow = Emscripten_GLES_SwapWindow;
|
device->GL_SwapWindow = Emscripten_GLES_SwapWindow;
|
||||||
device->GL_DeleteContext = Emscripten_GLES_DeleteContext;
|
device->GL_DeleteContext = Emscripten_GLES_DeleteContext;
|
||||||
#endif
|
|
||||||
|
|
||||||
device->free = Emscripten_DeleteDevice;
|
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;
|
wdata->window = window;
|
||||||
|
|
||||||
/* Setup driver data for this window */
|
/* Setup driver data for this window */
|
||||||
|
@ -329,12 +311,6 @@ Emscripten_DestroyWindow(_THIS, SDL_Window * window)
|
||||||
data = (SDL_WindowData *) window->driverdata;
|
data = (SDL_WindowData *) window->driverdata;
|
||||||
|
|
||||||
Emscripten_UnregisterEventHandlers(data);
|
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 */
|
/* We can't destroy the canvas, so resize it to zero instead */
|
||||||
emscripten_set_canvas_element_size(data->canvas_id, 0, 0);
|
emscripten_set_canvas_element_size(data->canvas_id, 0, 0);
|
||||||
|
|
|
@ -28,15 +28,8 @@
|
||||||
#include <emscripten/emscripten.h>
|
#include <emscripten/emscripten.h>
|
||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
|
|
||||||
#if SDL_VIDEO_OPENGL_EGL
|
|
||||||
#include <EGL/egl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct SDL_WindowData
|
typedef struct SDL_WindowData
|
||||||
{
|
{
|
||||||
#if SDL_VIDEO_OPENGL_EGL
|
|
||||||
EGLSurface egl_surface;
|
|
||||||
#endif
|
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
SDL_Surface *surface;
|
SDL_Surface *surface;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue