src/video/emscripten/SDL_emscriptenframebuffer.c
author Ryan C. Gordon
Thu, 18 Dec 2014 00:19:52 -0500
changeset 9278 8900afb78a19
child 9300 0293f45e4814
permissions -rw-r--r--
Initial merge of Emscripten port!

With this commit, you can compile SDL2 with Emscripten
( http://emscripten.org/ ), and make your SDL-based C/C++ program
into a web app.

This port was due to the efforts of several people, including: Charlie Birks,
Sathyanarayanan Gunasekaran, Jukka Jylänki, Alon Zakai, Edward Rudd,
Bruce Mitchener, and Martin Gerhardy. (Thanks, everyone!)
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
     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_emscriptenvideo.h"
    26 #include "SDL_emscriptenframebuffer.h"
    27 
    28 
    29 int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
    30 {
    31     SDL_Surface *surface;
    32     const Uint32 surface_format = SDL_PIXELFORMAT_BGR888;
    33     int w, h;
    34     int bpp;
    35     Uint32 Rmask, Gmask, Bmask, Amask;
    36 
    37     /* Free the old framebuffer surface */
    38     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
    39     surface = data->surface;
    40     SDL_FreeSurface(surface);
    41 
    42     /* Create a new one */
    43     SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
    44     SDL_GetWindowSize(window, &w, &h);
    45 
    46     surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask);
    47     if (!surface) {
    48         return -1;
    49     }
    50 
    51     /* Save the info and return! */
    52     data->surface = surface;
    53     *format = surface_format;
    54     *pixels = surface->pixels;
    55     *pitch = surface->pitch;
    56     return 0;
    57 }
    58 
    59 int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
    60 {
    61     static int frame_number;
    62     SDL_Surface *surface;
    63 
    64     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
    65     surface = data->surface;
    66     if (!surface) {
    67         return SDL_SetError("Couldn't find dummy surface for window");
    68     }
    69 
    70     /* Send the data to the display */
    71 
    72     EM_ASM_INT({
    73         //TODO: don't create context every update
    74         var ctx = Module['canvas'].getContext('2d');
    75 
    76         //library_sdl.js SDL_UnlockSurface
    77         var image = ctx.createImageData($0, $1);
    78         var data = image.data;
    79         var src = $2 >> 2;
    80         var dst = 0;
    81         var isScreen = true;
    82         var num;
    83         if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) {
    84             // IE10/IE11: ImageData objects are backed by the deprecated CanvasPixelArray,
    85             // not UInt8ClampedArray. These don't have buffers, so we need to revert
    86             // to copying a byte at a time. We do the undefined check because modern
    87             // browsers do not define CanvasPixelArray anymore.
    88             num = data.length;
    89             while (dst < num) {
    90                 var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
    91                 data[dst  ] = val & 0xff;
    92                 data[dst+1] = (val >> 8) & 0xff;
    93                 data[dst+2] = (val >> 16) & 0xff;
    94                 data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
    95                 src++;
    96                 dst += 4;
    97             }
    98         } else {
    99             var data32 = new Uint32Array(data.buffer);
   100             num = data32.length;
   101             if (isScreen) {
   102                 while (dst < num) {
   103                     // HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
   104                     data32[dst++] = HEAP32[src++] | 0xff000000;
   105                 }
   106             } else {
   107                 while (dst < num) {
   108                     data32[dst++] = HEAP32[src++];
   109                 }
   110             }
   111         }
   112 
   113         ctx.putImageData(image, 0, 0);
   114         return 0;
   115     }, surface->w, surface->h, surface->pixels);
   116 
   117     /*if (SDL_getenv("SDL_VIDEO_Emscripten_SAVE_FRAMES")) {
   118         char file[128];
   119         SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp",
   120                      SDL_GetWindowID(window), ++frame_number);
   121         SDL_SaveBMP(surface, file);
   122     }*/
   123     return 0;
   124 }
   125 
   126 void Emscripten_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
   127 {
   128     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   129 
   130     SDL_FreeSurface(data->surface);
   131     data->surface = NULL;
   132 }
   133 
   134 #endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
   135 
   136 /* vi: set ts=4 sw=4 expandtab: */