src/video/emscripten/SDL_emscriptenframebuffer.c
author Sam Lantinga
Sat, 02 Jan 2016 10:10:34 -0800
changeset 9998 f67cf37e9cd4
parent 9619 b94b6d0bff0f
child 10323 abfc071013af
permissions -rw-r--r--
Updated copyright to 2016
icculus@9278
     1
/*
icculus@9278
     2
  Simple DirectMedia Layer
slouken@9998
     3
  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
icculus@9278
     4
icculus@9278
     5
  This software is provided 'as-is', without any express or implied
icculus@9278
     6
  warranty.  In no event will the authors be held liable for any damages
icculus@9278
     7
  arising from the use of this software.
icculus@9278
     8
icculus@9278
     9
  Permission is granted to anyone to use this software for any purpose,
icculus@9278
    10
  including commercial applications, and to alter it and redistribute it
icculus@9278
    11
  freely, subject to the following restrictions:
icculus@9278
    12
icculus@9278
    13
  1. The origin of this software must not be misrepresented; you must not
icculus@9278
    14
     claim that you wrote the original software. If you use this software
icculus@9278
    15
     in a product, an acknowledgment in the product documentation would be
icculus@9278
    16
     appreciated but is not required.
icculus@9278
    17
  2. Altered source versions must be plainly marked as such, and must not be
icculus@9278
    18
     misrepresented as being the original software.
icculus@9278
    19
  3. This notice may not be removed or altered from any source distribution.
icculus@9278
    20
*/
icculus@9278
    21
#include "../../SDL_internal.h"
icculus@9278
    22
icculus@9278
    23
#if SDL_VIDEO_DRIVER_EMSCRIPTEN
icculus@9278
    24
icculus@9278
    25
#include "SDL_emscriptenvideo.h"
icculus@9278
    26
#include "SDL_emscriptenframebuffer.h"
icculus@9278
    27
icculus@9278
    28
icculus@9278
    29
int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
icculus@9278
    30
{
icculus@9278
    31
    SDL_Surface *surface;
icculus@9278
    32
    const Uint32 surface_format = SDL_PIXELFORMAT_BGR888;
icculus@9278
    33
    int w, h;
icculus@9278
    34
    int bpp;
icculus@9278
    35
    Uint32 Rmask, Gmask, Bmask, Amask;
icculus@9278
    36
icculus@9278
    37
    /* Free the old framebuffer surface */
icculus@9278
    38
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
icculus@9278
    39
    surface = data->surface;
icculus@9278
    40
    SDL_FreeSurface(surface);
icculus@9278
    41
icculus@9278
    42
    /* Create a new one */
icculus@9278
    43
    SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
icculus@9278
    44
    SDL_GetWindowSize(window, &w, &h);
icculus@9278
    45
icculus@9278
    46
    surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask);
icculus@9278
    47
    if (!surface) {
icculus@9278
    48
        return -1;
icculus@9278
    49
    }
icculus@9278
    50
icculus@9278
    51
    /* Save the info and return! */
icculus@9278
    52
    data->surface = surface;
icculus@9278
    53
    *format = surface_format;
icculus@9278
    54
    *pixels = surface->pixels;
icculus@9278
    55
    *pitch = surface->pitch;
icculus@9278
    56
    return 0;
icculus@9278
    57
}
icculus@9278
    58
icculus@9278
    59
int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
icculus@9278
    60
{
icculus@9278
    61
    SDL_Surface *surface;
icculus@9278
    62
icculus@9278
    63
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
icculus@9278
    64
    surface = data->surface;
icculus@9278
    65
    if (!surface) {
philipp@9342
    66
        return SDL_SetError("Couldn't find framebuffer surface for window");
icculus@9278
    67
    }
icculus@9278
    68
icculus@9278
    69
    /* Send the data to the display */
icculus@9278
    70
icculus@9278
    71
    EM_ASM_INT({
icculus@9278
    72
        //TODO: don't create context every update
icculus@9278
    73
        var ctx = Module['canvas'].getContext('2d');
icculus@9278
    74
icculus@9278
    75
        //library_sdl.js SDL_UnlockSurface
icculus@9278
    76
        var image = ctx.createImageData($0, $1);
icculus@9278
    77
        var data = image.data;
icculus@9278
    78
        var src = $2 >> 2;
icculus@9278
    79
        var dst = 0;
icculus@9278
    80
        var isScreen = true;
icculus@9278
    81
        var num;
icculus@9278
    82
        if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) {
icculus@9278
    83
            // IE10/IE11: ImageData objects are backed by the deprecated CanvasPixelArray,
icculus@9278
    84
            // not UInt8ClampedArray. These don't have buffers, so we need to revert
icculus@9278
    85
            // to copying a byte at a time. We do the undefined check because modern
icculus@9278
    86
            // browsers do not define CanvasPixelArray anymore.
icculus@9278
    87
            num = data.length;
icculus@9278
    88
            while (dst < num) {
icculus@9278
    89
                var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
icculus@9278
    90
                data[dst  ] = val & 0xff;
icculus@9278
    91
                data[dst+1] = (val >> 8) & 0xff;
icculus@9278
    92
                data[dst+2] = (val >> 16) & 0xff;
icculus@9278
    93
                data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
icculus@9278
    94
                src++;
icculus@9278
    95
                dst += 4;
icculus@9278
    96
            }
icculus@9278
    97
        } else {
icculus@9278
    98
            var data32 = new Uint32Array(data.buffer);
icculus@9278
    99
            num = data32.length;
icculus@9278
   100
            if (isScreen) {
icculus@9278
   101
                while (dst < num) {
icculus@9278
   102
                    // HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
icculus@9278
   103
                    data32[dst++] = HEAP32[src++] | 0xff000000;
icculus@9278
   104
                }
icculus@9278
   105
            } else {
icculus@9278
   106
                while (dst < num) {
icculus@9278
   107
                    data32[dst++] = HEAP32[src++];
icculus@9278
   108
                }
icculus@9278
   109
            }
icculus@9278
   110
        }
icculus@9278
   111
icculus@9278
   112
        ctx.putImageData(image, 0, 0);
icculus@9278
   113
        return 0;
icculus@9278
   114
    }, surface->w, surface->h, surface->pixels);
icculus@9278
   115
icculus@9278
   116
    /*if (SDL_getenv("SDL_VIDEO_Emscripten_SAVE_FRAMES")) {
icculus@9300
   117
        static int frame_number = 0;
icculus@9278
   118
        char file[128];
icculus@9278
   119
        SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp",
icculus@9278
   120
                     SDL_GetWindowID(window), ++frame_number);
icculus@9278
   121
        SDL_SaveBMP(surface, file);
icculus@9278
   122
    }*/
icculus@9278
   123
    return 0;
icculus@9278
   124
}
icculus@9278
   125
icculus@9278
   126
void Emscripten_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
icculus@9278
   127
{
icculus@9278
   128
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
icculus@9278
   129
icculus@9278
   130
    SDL_FreeSurface(data->surface);
icculus@9278
   131
    data->surface = NULL;
icculus@9278
   132
}
icculus@9278
   133
icculus@9278
   134
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
icculus@9278
   135
icculus@9278
   136
/* vi: set ts=4 sw=4 expandtab: */