1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/video/emscripten/SDL_emscriptenframebuffer.c Thu Dec 18 00:19:52 2014 -0500
1.3 @@ -0,0 +1,136 @@
1.4 +/*
1.5 + Simple DirectMedia Layer
1.6 + Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
1.7 +
1.8 + This software is provided 'as-is', without any express or implied
1.9 + warranty. In no event will the authors be held liable for any damages
1.10 + arising from the use of this software.
1.11 +
1.12 + Permission is granted to anyone to use this software for any purpose,
1.13 + including commercial applications, and to alter it and redistribute it
1.14 + freely, subject to the following restrictions:
1.15 +
1.16 + 1. The origin of this software must not be misrepresented; you must not
1.17 + claim that you wrote the original software. If you use this software
1.18 + in a product, an acknowledgment in the product documentation would be
1.19 + appreciated but is not required.
1.20 + 2. Altered source versions must be plainly marked as such, and must not be
1.21 + misrepresented as being the original software.
1.22 + 3. This notice may not be removed or altered from any source distribution.
1.23 +*/
1.24 +#include "../../SDL_internal.h"
1.25 +
1.26 +#if SDL_VIDEO_DRIVER_EMSCRIPTEN
1.27 +
1.28 +#include "SDL_emscriptenvideo.h"
1.29 +#include "SDL_emscriptenframebuffer.h"
1.30 +
1.31 +
1.32 +int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
1.33 +{
1.34 + SDL_Surface *surface;
1.35 + const Uint32 surface_format = SDL_PIXELFORMAT_BGR888;
1.36 + int w, h;
1.37 + int bpp;
1.38 + Uint32 Rmask, Gmask, Bmask, Amask;
1.39 +
1.40 + /* Free the old framebuffer surface */
1.41 + SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1.42 + surface = data->surface;
1.43 + SDL_FreeSurface(surface);
1.44 +
1.45 + /* Create a new one */
1.46 + SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
1.47 + SDL_GetWindowSize(window, &w, &h);
1.48 +
1.49 + surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask);
1.50 + if (!surface) {
1.51 + return -1;
1.52 + }
1.53 +
1.54 + /* Save the info and return! */
1.55 + data->surface = surface;
1.56 + *format = surface_format;
1.57 + *pixels = surface->pixels;
1.58 + *pitch = surface->pitch;
1.59 + return 0;
1.60 +}
1.61 +
1.62 +int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
1.63 +{
1.64 + static int frame_number;
1.65 + SDL_Surface *surface;
1.66 +
1.67 + SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1.68 + surface = data->surface;
1.69 + if (!surface) {
1.70 + return SDL_SetError("Couldn't find dummy surface for window");
1.71 + }
1.72 +
1.73 + /* Send the data to the display */
1.74 +
1.75 + EM_ASM_INT({
1.76 + //TODO: don't create context every update
1.77 + var ctx = Module['canvas'].getContext('2d');
1.78 +
1.79 + //library_sdl.js SDL_UnlockSurface
1.80 + var image = ctx.createImageData($0, $1);
1.81 + var data = image.data;
1.82 + var src = $2 >> 2;
1.83 + var dst = 0;
1.84 + var isScreen = true;
1.85 + var num;
1.86 + if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) {
1.87 + // IE10/IE11: ImageData objects are backed by the deprecated CanvasPixelArray,
1.88 + // not UInt8ClampedArray. These don't have buffers, so we need to revert
1.89 + // to copying a byte at a time. We do the undefined check because modern
1.90 + // browsers do not define CanvasPixelArray anymore.
1.91 + num = data.length;
1.92 + while (dst < num) {
1.93 + var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
1.94 + data[dst ] = val & 0xff;
1.95 + data[dst+1] = (val >> 8) & 0xff;
1.96 + data[dst+2] = (val >> 16) & 0xff;
1.97 + data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
1.98 + src++;
1.99 + dst += 4;
1.100 + }
1.101 + } else {
1.102 + var data32 = new Uint32Array(data.buffer);
1.103 + num = data32.length;
1.104 + if (isScreen) {
1.105 + while (dst < num) {
1.106 + // HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
1.107 + data32[dst++] = HEAP32[src++] | 0xff000000;
1.108 + }
1.109 + } else {
1.110 + while (dst < num) {
1.111 + data32[dst++] = HEAP32[src++];
1.112 + }
1.113 + }
1.114 + }
1.115 +
1.116 + ctx.putImageData(image, 0, 0);
1.117 + return 0;
1.118 + }, surface->w, surface->h, surface->pixels);
1.119 +
1.120 + /*if (SDL_getenv("SDL_VIDEO_Emscripten_SAVE_FRAMES")) {
1.121 + char file[128];
1.122 + SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp",
1.123 + SDL_GetWindowID(window), ++frame_number);
1.124 + SDL_SaveBMP(surface, file);
1.125 + }*/
1.126 + return 0;
1.127 +}
1.128 +
1.129 +void Emscripten_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
1.130 +{
1.131 + SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1.132 +
1.133 + SDL_FreeSurface(data->surface);
1.134 + data->surface = NULL;
1.135 +}
1.136 +
1.137 +#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
1.138 +
1.139 +/* vi: set ts=4 sw=4 expandtab: */