Atlas - SDL_emscriptenvideo.c

Home / ext / SDL2 / src / video / emscripten Lines: 1 | Size: 11244 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#if SDL_VIDEO_DRIVER_EMSCRIPTEN 24 25#include "SDL_video.h" 26#include "SDL_mouse.h" 27#include "SDL_hints.h" 28#include "../SDL_sysvideo.h" 29#include "../SDL_pixels_c.h" 30#include "../SDL_egl_c.h" 31#include "../../events/SDL_events_c.h" 32 33#include "SDL_emscriptenvideo.h" 34#include "SDL_emscriptenopengles.h" 35#include "SDL_emscriptenframebuffer.h" 36#include "SDL_emscriptenevents.h" 37#include "SDL_emscriptenmouse.h" 38 39#define EMSCRIPTENVID_DRIVER_NAME "emscripten" 40 41/* Initialization/Query functions */ 42static int Emscripten_VideoInit(_THIS); 43static int Emscripten_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); 44static void Emscripten_VideoQuit(_THIS); 45 46static int Emscripten_CreateWindow(_THIS, SDL_Window * window); 47static void Emscripten_SetWindowSize(_THIS, SDL_Window * window); 48static void Emscripten_DestroyWindow(_THIS, SDL_Window * window); 49static void Emscripten_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen); 50static void Emscripten_PumpEvents(_THIS); 51static void Emscripten_SetWindowTitle(_THIS, SDL_Window * window); 52 53 54/* Emscripten driver bootstrap functions */ 55 56static int 57Emscripten_Available(void) 58{ 59 return (1); 60} 61 62static void 63Emscripten_DeleteDevice(SDL_VideoDevice * device) 64{ 65 SDL_free(device); 66} 67 68static SDL_VideoDevice * 69Emscripten_CreateDevice(int devindex) 70{ 71 SDL_VideoDevice *device; 72 73 /* Initialize all variables that we clean on shutdown */ 74 device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); 75 if (!device) { 76 SDL_OutOfMemory(); 77 return (0); 78 } 79 80 /* Firefox sends blur event which would otherwise prevent full screen 81 * when the user clicks to allow full screen. 82 * See https://bugzilla.mozilla.org/show_bug.cgi?id=1144964 83 */ 84 SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); 85 86 /* Set the function pointers */ 87 device->VideoInit = Emscripten_VideoInit; 88 device->VideoQuit = Emscripten_VideoQuit; 89 device->SetDisplayMode = Emscripten_SetDisplayMode; 90 91 92 device->PumpEvents = Emscripten_PumpEvents; 93 94 device->CreateSDLWindow = Emscripten_CreateWindow; 95 device->SetWindowTitle = Emscripten_SetWindowTitle; 96 /*device->SetWindowIcon = Emscripten_SetWindowIcon; 97 device->SetWindowPosition = Emscripten_SetWindowPosition;*/ 98 device->SetWindowSize = Emscripten_SetWindowSize; 99 /*device->ShowWindow = Emscripten_ShowWindow; 100 device->HideWindow = Emscripten_HideWindow; 101 device->RaiseWindow = Emscripten_RaiseWindow; 102 device->MaximizeWindow = Emscripten_MaximizeWindow; 103 device->MinimizeWindow = Emscripten_MinimizeWindow; 104 device->RestoreWindow = Emscripten_RestoreWindow; 105 device->SetWindowGrab = Emscripten_SetWindowGrab;*/ 106 device->DestroyWindow = Emscripten_DestroyWindow; 107 device->SetWindowFullscreen = Emscripten_SetWindowFullscreen; 108 109 device->CreateWindowFramebuffer = Emscripten_CreateWindowFramebuffer; 110 device->UpdateWindowFramebuffer = Emscripten_UpdateWindowFramebuffer; 111 device->DestroyWindowFramebuffer = Emscripten_DestroyWindowFramebuffer; 112 113#if SDL_VIDEO_OPENGL_EGL 114 device->GL_LoadLibrary = Emscripten_GLES_LoadLibrary; 115 device->GL_GetProcAddress = Emscripten_GLES_GetProcAddress; 116 device->GL_UnloadLibrary = Emscripten_GLES_UnloadLibrary; 117 device->GL_CreateContext = Emscripten_GLES_CreateContext; 118 device->GL_MakeCurrent = Emscripten_GLES_MakeCurrent; 119 device->GL_SetSwapInterval = Emscripten_GLES_SetSwapInterval; 120 device->GL_GetSwapInterval = Emscripten_GLES_GetSwapInterval; 121 device->GL_SwapWindow = Emscripten_GLES_SwapWindow; 122 device->GL_DeleteContext = Emscripten_GLES_DeleteContext; 123 device->GL_GetDrawableSize = Emscripten_GLES_GetDrawableSize; 124#endif 125 126 device->free = Emscripten_DeleteDevice; 127 128 return device; 129} 130 131VideoBootStrap Emscripten_bootstrap = { 132 EMSCRIPTENVID_DRIVER_NAME, "SDL emscripten video driver", 133 Emscripten_Available, Emscripten_CreateDevice 134}; 135 136 137int 138Emscripten_VideoInit(_THIS) 139{ 140 SDL_DisplayMode mode; 141 142 /* Use a fake 32-bpp desktop mode */ 143 mode.format = SDL_PIXELFORMAT_RGB888; 144 145 mode.w = EM_ASM_INT_V({ 146 return screen.width; 147 }); 148 149 mode.h = EM_ASM_INT_V({ 150 return screen.height; 151 }); 152 153 mode.refresh_rate = 0; 154 mode.driverdata = NULL; 155 if (SDL_AddBasicVideoDisplay(&mode) < 0) { 156 return -1; 157 } 158 159 SDL_zero(mode); 160 SDL_AddDisplayMode(&_this->displays[0], &mode); 161 162 Emscripten_InitMouse(); 163 164 /* We're done! */ 165 return 0; 166} 167 168static int 169Emscripten_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) 170{ 171 /* can't do this */ 172 return 0; 173} 174 175static void 176Emscripten_VideoQuit(_THIS) 177{ 178 Emscripten_FiniMouse(); 179} 180 181static void 182Emscripten_PumpEvents(_THIS) 183{ 184 /* do nothing. */ 185} 186 187static int 188Emscripten_CreateWindow(_THIS, SDL_Window * window) 189{ 190 SDL_WindowData *wdata; 191 double scaled_w, scaled_h; 192 double css_w, css_h; 193 194 /* Allocate window internal data */ 195 wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData)); 196 if (wdata == NULL) { 197 return SDL_OutOfMemory(); 198 } 199 200 if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) { 201 wdata->pixel_ratio = emscripten_get_device_pixel_ratio(); 202 } else { 203 wdata->pixel_ratio = 1.0f; 204 } 205 206 scaled_w = SDL_floor(window->w * wdata->pixel_ratio); 207 scaled_h = SDL_floor(window->h * wdata->pixel_ratio); 208 209 emscripten_set_canvas_size(scaled_w, scaled_h); 210 211 emscripten_get_element_css_size(NULL, &css_w, &css_h); 212 213 wdata->external_size = SDL_floor(css_w) != scaled_w || SDL_floor(css_h) != scaled_h; 214 215 if ((window->flags & SDL_WINDOW_RESIZABLE) && wdata->external_size) { 216 /* external css has resized us */ 217 scaled_w = css_w * wdata->pixel_ratio; 218 scaled_h = css_h * wdata->pixel_ratio; 219 220 emscripten_set_canvas_size(scaled_w, scaled_h); 221 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, css_w, css_h); 222 } 223 224 /* if the size is not being controlled by css, we need to scale down for hidpi */ 225 if (!wdata->external_size) { 226 if (wdata->pixel_ratio != 1.0f) { 227 /*scale canvas down*/ 228 emscripten_set_element_css_size(NULL, window->w, window->h); 229 } 230 } 231 232#if SDL_VIDEO_OPENGL_EGL 233 if (window->flags & SDL_WINDOW_OPENGL) { 234 if (!_this->egl_data) { 235 if (SDL_GL_LoadLibrary(NULL) < 0) { 236 return -1; 237 } 238 } 239 wdata->egl_surface = SDL_EGL_CreateSurface(_this, 0); 240 241 if (wdata->egl_surface == EGL_NO_SURFACE) { 242 return SDL_SetError("Could not create GLES window surface"); 243 } 244 } 245#endif 246 247 wdata->window = window; 248 249 /* Setup driver data for this window */ 250 window->driverdata = wdata; 251 252 /* One window, it always has focus */ 253 SDL_SetMouseFocus(window); 254 SDL_SetKeyboardFocus(window); 255 256 Emscripten_RegisterEventHandlers(wdata); 257 258 /* Window has been successfully created */ 259 return 0; 260} 261 262static void Emscripten_SetWindowSize(_THIS, SDL_Window * window) 263{ 264 SDL_WindowData *data; 265 266 if (window->driverdata) { 267 data = (SDL_WindowData *) window->driverdata; 268 /* update pixel ratio */ 269 if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) { 270 data->pixel_ratio = emscripten_get_device_pixel_ratio(); 271 } 272 emscripten_set_canvas_size(window->w * data->pixel_ratio, window->h * data->pixel_ratio); 273 274 /*scale canvas down*/ 275 if (!data->external_size && data->pixel_ratio != 1.0f) { 276 emscripten_set_element_css_size(NULL, window->w, window->h); 277 } 278 } 279} 280 281static void 282Emscripten_DestroyWindow(_THIS, SDL_Window * window) 283{ 284 SDL_WindowData *data; 285 286 if(window->driverdata) { 287 data = (SDL_WindowData *) window->driverdata; 288 289 Emscripten_UnregisterEventHandlers(data); 290#if SDL_VIDEO_OPENGL_EGL 291 if (data->egl_surface != EGL_NO_SURFACE) { 292 SDL_EGL_DestroySurface(_this, data->egl_surface); 293 data->egl_surface = EGL_NO_SURFACE; 294 } 295#endif 296 SDL_free(window->driverdata); 297 window->driverdata = NULL; 298 } 299} 300 301static void 302Emscripten_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) 303{ 304 SDL_WindowData *data; 305 if(window->driverdata) { 306 data = (SDL_WindowData *) window->driverdata; 307 308 if(fullscreen) { 309 EmscriptenFullscreenStrategy strategy; 310 SDL_bool is_desktop_fullscreen = (window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP; 311 int res; 312 313 strategy.scaleMode = is_desktop_fullscreen ? EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH : EMSCRIPTEN_FULLSCREEN_SCALE_ASPECT; 314 315 if(!is_desktop_fullscreen) { 316 strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_NONE; 317 } else if(window->flags & SDL_WINDOW_ALLOW_HIGHDPI) { 318 strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF; 319 } else { 320 strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; 321 } 322 323 strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; 324 325 strategy.canvasResizedCallback = Emscripten_HandleCanvasResize; 326 strategy.canvasResizedCallbackUserData = data; 327 328 data->requested_fullscreen_mode = window->flags & (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN); 329 data->fullscreen_resize = is_desktop_fullscreen; 330 331 res = emscripten_request_fullscreen_strategy(NULL, 1, &strategy); 332 if(res != EMSCRIPTEN_RESULT_SUCCESS && res != EMSCRIPTEN_RESULT_DEFERRED) { 333 /* unset flags, fullscreen failed */ 334 window->flags &= ~(SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN); 335 } 336 } 337 else 338 emscripten_exit_fullscreen(); 339 } 340} 341 342static void 343Emscripten_SetWindowTitle(_THIS, SDL_Window * window) { 344 EM_ASM_INT({ 345 if (typeof Module['setWindowTitle'] !== 'undefined') { 346 Module['setWindowTitle'](Module['Pointer_stringify']($0)); 347 } 348 return 0; 349 }, window->title); 350} 351 352#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */ 353 354/* vi: set ts=4 sw=4 expandtab: */ 355
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.