src/video/emscripten/SDL_emscriptenframebuffer.c
changeset 10323 abfc071013af
parent 9998 f67cf37e9cd4
child 10336 4779f884f8d2
     1.1 --- a/src/video/emscripten/SDL_emscriptenframebuffer.c	Tue Sep 13 00:03:41 2016 -0700
     1.2 +++ b/src/video/emscripten/SDL_emscriptenframebuffer.c	Tue Sep 13 00:03:43 2016 -0700
     1.3 @@ -69,15 +69,25 @@
     1.4      /* Send the data to the display */
     1.5  
     1.6      EM_ASM_INT({
     1.7 -        //TODO: don't create context every update
     1.8 -        var ctx = Module['canvas'].getContext('2d');
     1.9 +        var w = $0;
    1.10 +        var h = $1;
    1.11 +        var pixels = $2;
    1.12  
    1.13 -        //library_sdl.js SDL_UnlockSurface
    1.14 -        var image = ctx.createImageData($0, $1);
    1.15 -        var data = image.data;
    1.16 -        var src = $2 >> 2;
    1.17 +        if (!Module['SDL2']) Module['SDL2'] = {};
    1.18 +        var SDL2 = Module['SDL2'];
    1.19 +        if (SDL2.ctxCanvas !== Module['canvas']) {
    1.20 +            SDL2.ctx = Module['canvas'].getContext('2d');
    1.21 +            SDL2.ctxCanvas = Module['canvas'];
    1.22 +        }
    1.23 +        if (SDL2.w !== w || SDL2.h !== h || SDL2.imageCtx !== SDL2.ctx) {
    1.24 +            SDL2.image = SDL2.ctx.createImageData(w, h);
    1.25 +            SDL2.w = w;
    1.26 +            SDL2.h = h;
    1.27 +            SDL2.imageCtx = SDL2.ctx;
    1.28 +        }
    1.29 +        var data = SDL2.image.data;
    1.30 +        var src = pixels >> 2;
    1.31          var dst = 0;
    1.32 -        var isScreen = true;
    1.33          var num;
    1.34          if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) {
    1.35              // IE10/IE11: ImageData objects are backed by the deprecated CanvasPixelArray,
    1.36 @@ -90,26 +100,58 @@
    1.37                  data[dst  ] = val & 0xff;
    1.38                  data[dst+1] = (val >> 8) & 0xff;
    1.39                  data[dst+2] = (val >> 16) & 0xff;
    1.40 -                data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
    1.41 +                data[dst+3] = 0xff;
    1.42                  src++;
    1.43                  dst += 4;
    1.44              }
    1.45          } else {
    1.46 -            var data32 = new Uint32Array(data.buffer);
    1.47 +            if (SDL2.data32Data !== data) {
    1.48 +                SDL2.data32 = new Int32Array(data.buffer);
    1.49 +                SDL2.data8 = new Uint8Array(data.buffer);
    1.50 +            }
    1.51 +            var data32 = SDL2.data32;
    1.52              num = data32.length;
    1.53 -            if (isScreen) {
    1.54 -                while (dst < num) {
    1.55 -                    // HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
    1.56 -                    data32[dst++] = HEAP32[src++] | 0xff000000;
    1.57 +            // logically we need to do
    1.58 +            //      while (dst < num) {
    1.59 +            //          data32[dst++] = HEAP32[src++] | 0xff000000
    1.60 +            //      }
    1.61 +            // the following code is faster though, because
    1.62 +            // .set() is almost free - easily 10x faster due to
    1.63 +            // native memcpy efficiencies, and the remaining loop
    1.64 +            // just stores, not load + store, so it is faster
    1.65 +            data32.set(HEAP32.subarray(src, src + num));
    1.66 +            var data8 = SDL2.data8;
    1.67 +            var i = 3;
    1.68 +            var j = i + 4*num;
    1.69 +            if (num % 8 == 0) {
    1.70 +                // unrolling gives big speedups
    1.71 +                while (i < j) {
    1.72 +                  data8[i] = 0xff;
    1.73 +                  i = i + 4 | 0;
    1.74 +                  data8[i] = 0xff;
    1.75 +                  i = i + 4 | 0;
    1.76 +                  data8[i] = 0xff;
    1.77 +                  i = i + 4 | 0;
    1.78 +                  data8[i] = 0xff;
    1.79 +                  i = i + 4 | 0;
    1.80 +                  data8[i] = 0xff;
    1.81 +                  i = i + 4 | 0;
    1.82 +                  data8[i] = 0xff;
    1.83 +                  i = i + 4 | 0;
    1.84 +                  data8[i] = 0xff;
    1.85 +                  i = i + 4 | 0;
    1.86 +                  data8[i] = 0xff;
    1.87 +                  i = i + 4 | 0;
    1.88                  }
    1.89 -            } else {
    1.90 -                while (dst < num) {
    1.91 -                    data32[dst++] = HEAP32[src++];
    1.92 +             } else {
    1.93 +                while (i < j) {
    1.94 +                  data8[i] = 0xff;
    1.95 +                  i = i + 4 | 0;
    1.96                  }
    1.97              }
    1.98          }
    1.99  
   1.100 -        ctx.putImageData(image, 0, 0);
   1.101 +        SDL2.ctx.putImageData(SDL2.image, 0, 0);
   1.102          return 0;
   1.103      }, surface->w, surface->h, surface->pixels);
   1.104