SDL_emscriptenvideo.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_EMSCRIPTEN
#include "SDL_video.h"
#include "SDL_mouse.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"
#include "SDL_emscriptenopengles.h"
#include "SDL_emscriptenframebuffer.h"
#include "SDL_emscriptenevents.h"
#include "SDL_emscriptenmouse.h"
#define EMSCRIPTENVID_DRIVER_NAME "emscripten"
/* Initialization/Query functions */
static int Emscripten_VideoInit(_THIS);
static int Emscripten_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
static void Emscripten_VideoQuit(_THIS);
static int Emscripten_CreateWindow(_THIS, SDL_Window * window);
static void Emscripten_SetWindowSize(_THIS, SDL_Window * window);
static void Emscripten_DestroyWindow(_THIS, SDL_Window * window);
static void Emscripten_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
static void Emscripten_PumpEvents(_THIS);
/* Emscripten driver bootstrap functions */
static int
Emscripten_Available(void)
{
return (1);
}
static void
Emscripten_DeleteDevice(SDL_VideoDevice * device)
{
SDL_free(device);
}
static SDL_VideoDevice *
Emscripten_CreateDevice(int devindex)
{
SDL_VideoDevice *device;
/* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
if (!device) {
SDL_OutOfMemory();
return (0);
}
/* Set the function pointers */
device->VideoInit = Emscripten_VideoInit;
device->VideoQuit = Emscripten_VideoQuit;
device->SetDisplayMode = Emscripten_SetDisplayMode;
device->PumpEvents = Emscripten_PumpEvents;
device->CreateWindow = Emscripten_CreateWindow;
/*device->CreateWindowFrom = Emscripten_CreateWindowFrom;
device->SetWindowTitle = Emscripten_SetWindowTitle;
device->SetWindowIcon = Emscripten_SetWindowIcon;
device->SetWindowPosition = Emscripten_SetWindowPosition;*/
device->SetWindowSize = Emscripten_SetWindowSize;
/*device->ShowWindow = Emscripten_ShowWindow;
device->HideWindow = Emscripten_HideWindow;
device->RaiseWindow = Emscripten_RaiseWindow;
device->MaximizeWindow = Emscripten_MaximizeWindow;
device->MinimizeWindow = Emscripten_MinimizeWindow;
device->RestoreWindow = Emscripten_RestoreWindow;
device->SetWindowGrab = Emscripten_SetWindowGrab;*/
device->DestroyWindow = Emscripten_DestroyWindow;
device->SetWindowFullscreen = Emscripten_SetWindowFullscreen;
device->CreateWindowFramebuffer = Emscripten_CreateWindowFramebuffer;
device->UpdateWindowFramebuffer = Emscripten_UpdateWindowFramebuffer;
device->DestroyWindowFramebuffer = Emscripten_DestroyWindowFramebuffer;
device->GL_LoadLibrary = Emscripten_GLES_LoadLibrary;
device->GL_GetProcAddress = Emscripten_GLES_GetProcAddress;
device->GL_UnloadLibrary = Emscripten_GLES_UnloadLibrary;
device->GL_CreateContext = Emscripten_GLES_CreateContext;
device->GL_MakeCurrent = Emscripten_GLES_MakeCurrent;
device->GL_SetSwapInterval = Emscripten_GLES_SetSwapInterval;
device->GL_GetSwapInterval = Emscripten_GLES_GetSwapInterval;
device->GL_SwapWindow = Emscripten_GLES_SwapWindow;
device->GL_DeleteContext = Emscripten_GLES_DeleteContext;
device->GL_GetDrawableSize = Emscripten_GLES_GetDrawableSize;
device->free = Emscripten_DeleteDevice;
return device;
}
VideoBootStrap Emscripten_bootstrap = {
EMSCRIPTENVID_DRIVER_NAME, "SDL emscripten video driver",
Emscripten_Available, Emscripten_CreateDevice
};
int
Emscripten_VideoInit(_THIS)
{
SDL_DisplayMode mode;
double css_w, css_h;
/* Use a fake 32-bpp desktop mode */
mode.format = SDL_PIXELFORMAT_RGB888;
emscripten_get_element_css_size(NULL, &css_w, &css_h);
mode.w = css_w;
mode.h = css_h;
mode.refresh_rate = 0;
mode.driverdata = NULL;
if (SDL_AddBasicVideoDisplay(&mode) < 0) {
return -1;
}
SDL_zero(mode);
SDL_AddDisplayMode(&_this->displays[0], &mode);
Emscripten_InitMouse();
/* We're done! */
return 0;
}
static int
Emscripten_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
{
/* can't do this */
return 0;
}
static void
Emscripten_VideoQuit(_THIS)
{
Emscripten_FiniMouse();
}
static void
Emscripten_PumpEvents(_THIS)
{
/* do nothing. */
}
static int
Emscripten_CreateWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *wdata;
double scaled_w, scaled_h;
double css_w, css_h;
/* Allocate window internal data */
wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
if (wdata == NULL) {
return SDL_OutOfMemory();
}
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
wdata->pixel_ratio = emscripten_get_device_pixel_ratio();
} else {
wdata->pixel_ratio = 1.0f;
}
scaled_w = SDL_floor(window->w * wdata->pixel_ratio);
scaled_h = SDL_floor(window->h * wdata->pixel_ratio);
emscripten_set_canvas_size(scaled_w, scaled_h);
emscripten_get_element_css_size(NULL, &css_w, &css_h);
wdata->external_size = css_w != scaled_w || css_h != scaled_h;
if ((window->flags & SDL_WINDOW_RESIZABLE) && wdata->external_size) {
/* external css has resized us */
scaled_w = css_w * wdata->pixel_ratio;
scaled_h = css_h * wdata->pixel_ratio;
emscripten_set_canvas_size(scaled_w, scaled_h);
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, css_w, css_h);
}
/* if the size is not being controlled by css, we need to scale down for hidpi */
if (!wdata->external_size) {
if (wdata->pixel_ratio != 1.0f) {
/*scale canvas down*/
emscripten_set_element_css_size(NULL, window->w, window->h);
}
}
wdata->windowed_width = scaled_w;
wdata->windowed_height = scaled_h;
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");
}
}
wdata->window = window;
/* Setup driver data for this window */
window->driverdata = wdata;
/* One window, it always has focus */
SDL_SetMouseFocus(window);
SDL_SetKeyboardFocus(window);
Emscripten_RegisterEventHandlers(wdata);
/* Window has been successfully created */
return 0;
}
static void Emscripten_SetWindowSize(_THIS, SDL_Window * window)
{
SDL_WindowData *data;
if (window->driverdata) {
data = (SDL_WindowData *) window->driverdata;
emscripten_set_canvas_size(window->w * data->pixel_ratio, window->h * data->pixel_ratio);
/*scale canvas down*/
if (!data->external_size && data->pixel_ratio != 1.0f) {
emscripten_set_element_css_size(NULL, window->w, window->h);
}
}
}
static void
Emscripten_DestroyWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data;
if(window->driverdata) {
data = (SDL_WindowData *) window->driverdata;
Emscripten_UnregisterEventHandlers(data);
if (data->egl_surface != EGL_NO_SURFACE) {
SDL_EGL_DestroySurface(_this, data->egl_surface);
data->egl_surface = EGL_NO_SURFACE;
}
SDL_free(window->driverdata);
window->driverdata = NULL;
}
}
static void
Emscripten_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
{
SDL_WindowData *data;
if(window->driverdata) {
data = (SDL_WindowData *) window->driverdata;
if(fullscreen) {
data->requested_fullscreen_mode = window->flags & (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN);
/*unset the fullscreen flags as we're not actually fullscreen yet*/
window->flags &= ~(SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN);
EM_ASM({
//reparent canvas (similar to Module.requestFullscreen)
var canvas = Module['canvas'];
if(canvas.parentNode.id != "SDLFullscreenElement") {
var canvasContainer = document.createElement("div");
canvasContainer.id = "SDLFullscreenElement";
canvas.parentNode.insertBefore(canvasContainer, canvas);
canvasContainer.appendChild(canvas);
}
});
int is_fullscreen;
emscripten_get_canvas_size(&data->windowed_width, &data->windowed_height, &is_fullscreen);
emscripten_request_fullscreen("SDLFullscreenElement", 1);
}
else
emscripten_exit_fullscreen();
}
}
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
/* vi: set ts=4 sw=4 expandtab: */
SDL_WindowData::pixel_ratio
float pixel_ratio
Definition: SDL_emscriptenvideo.h:43
SDL_SetKeyboardFocus
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:612
SDL_emscriptenvideo.h
SDL_Window::w
int w
Definition: SDL_sysvideo.h:78
SDL_DisplayMode::w
int w
Definition: SDL_video.h:56
window
SDL_Window * window
Definition: testautomation_render.c:26
Emscripten_FiniMouse
void Emscripten_FiniMouse()
SDL_VideoDevice::free
void(* free)(_THIS)
Definition: SDL_sysvideo.h:345
SDL_AddBasicVideoDisplay
int SDL_AddBasicVideoDisplay(const SDL_DisplayMode *desktop_mode)
Definition: SDL_video.c:579
SDL_emscriptenmouse.h
SDL_VideoDevice::GL_SetSwapInterval
int(* GL_SetSwapInterval)(_THIS, int interval)
Definition: SDL_sysvideo.h:240
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
SDL_WindowData::windowed_height
int windowed_height
Definition: SDL_emscriptenvideo.h:41
SDL_DisplayMode
The structure that defines a display mode.
Definition: SDL_video.h:53
SDL_VideoDevice::SetWindowSize
void(* SetWindowSize)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:200
SDL_DisplayMode::refresh_rate
int refresh_rate
Definition: SDL_video.h:58
SDL_SendWindowEvent
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
Definition: SDL_windowevents.c:74
SDL_WindowData::window
SDL_Window * window
Definition: SDL_cocoawindow.h:110
SDL_emscriptenevents.h
SDL_SetMouseFocus
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:103
SDL_VideoDevice::GL_SwapWindow
void(* GL_SwapWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:242
Emscripten_DestroyWindowFramebuffer
void Emscripten_DestroyWindowFramebuffer(_THIS, SDL_Window *window)
SDL_GL_LoadLibrary
#define SDL_GL_LoadLibrary
Definition: SDL_dynapi_overrides.h:557
SDL_floor
#define SDL_floor
Definition: SDL_dynapi_overrides.h:437
Emscripten_RegisterEventHandlers
void Emscripten_RegisterEventHandlers(SDL_WindowData *data)
SDL_VideoDevice::GL_LoadLibrary
int(* GL_LoadLibrary)(_THIS, const char *path)
Definition: SDL_sysvideo.h:234
SDL_PIXELFORMAT_RGB888
Definition: SDL_pixels.h:235
SDL_VideoDevice::SetDisplayMode
int(* SetDisplayMode)(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
Definition: SDL_sysvideo.h:189
SDL_WindowData
Definition: SDL_androidwindow.h:34
SDL_VideoDevice::GL_GetDrawableSize
void(* GL_GetDrawableSize)(_THIS, SDL_Window *window, int *w, int *h)
Definition: SDL_sysvideo.h:239
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:114
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:126
Emscripten_CreateWindowFramebuffer
int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch)
SDL_video.h
SDL_calloc
void * SDL_calloc(size_t nmemb, size_t size)
SDL_VideoDevice::GL_CreateContext
SDL_GLContext(* GL_CreateContext)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:237
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_VideoDevice::GL_MakeCurrent
int(* GL_MakeCurrent)(_THIS, SDL_Window *window, SDL_GLContext context)
Definition: SDL_sysvideo.h:238
SDL_WindowData::external_size
SDL_bool external_size
Definition: SDL_emscriptenvideo.h:45
SDL_free
void SDL_free(void *mem)
SDL_DisplayMode::driverdata
void * driverdata
Definition: SDL_video.h:59
SDL_mouse.h
VideoBootStrap
Definition: SDL_sysvideo.h:348
SDL_WINDOW_ALLOW_HIGHDPI
Definition: SDL_video.h:111
SDL_emscriptenopengles.h
mode
GLenum mode
Definition: SDL_opengl_glext.h:1122
SDL_VideoDevice::displays
SDL_VideoDisplay * displays
Definition: SDL_sysvideo.h:280
SDL_VideoDevice::DestroyWindow
void(* DestroyWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:214
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:357
SDL_DisplayMode::h
int h
Definition: SDL_video.h:57
SDL_WindowData::windowed_width
int windowed_width
Definition: SDL_emscriptenvideo.h:40
SDL_VideoDisplay
Definition: SDL_sysvideo.h:120
SDL_VideoDevice::DestroyWindowFramebuffer
void(* DestroyWindowFramebuffer)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:217
SDL_Window::h
int h
Definition: SDL_sysvideo.h:78
SDL_VideoDevice::GL_UnloadLibrary
void(* GL_UnloadLibrary)(_THIS)
Definition: SDL_sysvideo.h:236
NULL
#define NULL
Definition: begin_code.h:143
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_WINDOW_RESIZABLE
Definition: SDL_video.h:103
SDL_VideoDevice::VideoQuit
void(* VideoQuit)(_THIS)
Definition: SDL_sysvideo.h:161
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:36
SDL_WindowData::requested_fullscreen_mode
int requested_fullscreen_mode
Definition: SDL_emscriptenvideo.h:47
SDL_emscriptenframebuffer.h
SDL_VideoDevice::CreateWindow
int(* CreateWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:195
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:71
SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:98
SDL_VideoDevice
Definition: SDL_sysvideo.h:142
SDL_AddDisplayMode
SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode)
Definition: SDL_video.c:709
SDL_VideoDevice::VideoInit
int(* VideoInit)(_THIS)
Definition: SDL_sysvideo.h:155
SDL_VideoDevice::SetWindowFullscreen
void(* SetWindowFullscreen)(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
Definition: SDL_sysvideo.h:210
SDL_WINDOW_OPENGL
Definition: SDL_video.h:99
SDL_WINDOWEVENT_RESIZED
Definition: SDL_video.h:145
SDL_VideoDevice::UpdateWindowFramebuffer
int(* UpdateWindowFramebuffer)(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects)
Definition: SDL_sysvideo.h:216
SDL_Window::driverdata
void * driverdata
Definition: SDL_sysvideo.h:106
SDL_VideoDevice::GL_DeleteContext
void(* GL_DeleteContext)(_THIS, SDL_GLContext context)
Definition: SDL_sysvideo.h:243
SDL_DisplayMode::format
Uint32 format
Definition: SDL_video.h:55
Emscripten_UnregisterEventHandlers
void Emscripten_UnregisterEventHandlers(SDL_WindowData *data)
SDL_VideoDevice::GL_GetSwapInterval
int(* GL_GetSwapInterval)(_THIS)
Definition: SDL_sysvideo.h:241
SDL_Window::flags
Uint32 flags
Definition: SDL_sysvideo.h:81
Emscripten_UpdateWindowFramebuffer
int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects)
SDL_VideoDevice::CreateWindowFramebuffer
int(* CreateWindowFramebuffer)(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch)
Definition: SDL_sysvideo.h:215
SDL_VideoDevice::GL_GetProcAddress
void *(* GL_GetProcAddress)(_THIS, const char *proc)
Definition: SDL_sysvideo.h:235
SDL_WINDOW_FULLSCREEN_DESKTOP
Definition: SDL_video.h:109
SDL_WindowData::egl_surface
EGLSurface egl_surface
Definition: SDL_androidwindow.h:36
Emscripten_InitMouse
void Emscripten_InitMouse()
SDL_VideoDevice::PumpEvents
void(* PumpEvents)(_THIS)
Definition: SDL_sysvideo.h:249