|
| 1 | +#include <cstring> |
| 2 | +#include <emscripten.h> |
| 3 | +#include <memory> |
| 4 | + |
| 5 | +#include "sysjs.h" |
| 6 | + |
| 7 | +JSSystemDisplay::JSSystemDisplay( |
| 8 | + const DisplayCharacteristics &chr, int redraw_ms) |
| 9 | + : SystemDisplay(chr, redraw_ms) { |
| 10 | + mClientChar = chr; |
| 11 | + int frameBufferSize = |
| 12 | + mClientChar.width * mClientChar.height * mClientChar.bytesPerPixel; |
| 13 | + gFrameBuffer = (byte*)malloc(frameBufferSize); |
| 14 | + memset(gFrameBuffer, 0, frameBufferSize); |
| 15 | + |
| 16 | + jsFrameBufferSize = mClientChar.width * mClientChar.height * 4; |
| 17 | + jsFrameBuffer.reset(new byte[jsFrameBufferSize]); |
| 18 | + |
| 19 | + damageFrameBufferAll(); |
| 20 | + |
| 21 | + EM_ASM_({ workerApi.didOpenVideo($0, $1); }, mClientChar.width, mClientChar.height); |
| 22 | +} |
| 23 | + |
| 24 | +void JSSystemDisplay::blit() { |
| 25 | + // See comments in SDLSystemDisplay::displayShow for the need for the +3. |
| 26 | + if (gDamageAreaFirstAddr > gDamageAreaLastAddr+3) { |
| 27 | + EM_ASM({ workerApi.blit(0, 0); }); |
| 28 | + return; |
| 29 | + } |
| 30 | + |
| 31 | + // TODO: take into account damage area and only blit that part. |
| 32 | + healFrameBuffer(); |
| 33 | + |
| 34 | + byte *jsFrameBuffer = this->jsFrameBuffer.get(); |
| 35 | + int frameBufferSize = |
| 36 | + mClientChar.width * mClientChar.height * mClientChar.bytesPerPixel; |
| 37 | + |
| 38 | + // Invert endianess and generate the RGBA that the JS side expects. |
| 39 | + if (mClientChar.bytesPerPixel == 2) { |
| 40 | + for (int src = 0, dst = 0; src < frameBufferSize; src += 2, dst += 4) { |
| 41 | + uint16 pixel555 = gFrameBuffer[src + 1] | (gFrameBuffer[src] << 8); |
| 42 | + uint8 red5 = (pixel555 & 0x7c00) >> 10; |
| 43 | + uint8 green5 = (pixel555 & 0x3e0) >> 5; |
| 44 | + uint8 blue5 = (pixel555 & 0x1f); |
| 45 | + |
| 46 | + uint8 red8 = (red5 * 255 + 15) / 31; |
| 47 | + uint8 green8 = (green5 * 255 + 15) / 31; |
| 48 | + uint8 blue8 = (blue5 * 255 + 15) / 31; |
| 49 | + |
| 50 | + jsFrameBuffer[dst + 0] = red8; |
| 51 | + jsFrameBuffer[dst + 1] = green8; |
| 52 | + jsFrameBuffer[dst + 2] = blue8; |
| 53 | + jsFrameBuffer[dst + 3] = 0xff; |
| 54 | + } |
| 55 | + } else { |
| 56 | + // Offset by 1 to go from ARGB to RGBA and ensure that the alpha is set, |
| 57 | + // the Mac defaults to it being 0, which the browser renders as |
| 58 | + // transparent. |
| 59 | + uint32 *jsFrameBuffer32 = reinterpret_cast<uint32 *>(jsFrameBuffer); |
| 60 | + byte *jsFrameBufferAlpha = jsFrameBuffer + 3; |
| 61 | + uint32 *frameBuffer32 = reinterpret_cast<uint32 *>(gFrameBuffer + 1); |
| 62 | + uint32 frameBufferSize32 = frameBufferSize / 4; |
| 63 | + for (int i = 0; i < frameBufferSize32; i++) { |
| 64 | + *jsFrameBuffer32++ = *frameBuffer32++; |
| 65 | + *jsFrameBufferAlpha = 0xFF; |
| 66 | + jsFrameBufferAlpha += 4; |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + EM_ASM_({ workerApi.blit($0, $1); }, jsFrameBuffer, jsFrameBufferSize); |
| 71 | +} |
| 72 | + |
| 73 | +void JSSystemDisplay::finishMenu() { |
| 74 | +} |
| 75 | + |
| 76 | +void JSSystemDisplay::updateTitle() { |
| 77 | +} |
| 78 | + |
| 79 | +void JSSystemDisplay::displayShow() { |
| 80 | + blit(); |
| 81 | +} |
| 82 | + |
| 83 | +void JSSystemDisplay::convertCharacteristicsToHost(DisplayCharacteristics &aHostChar, const DisplayCharacteristics &aClientChar) { |
| 84 | + aHostChar = aClientChar; |
| 85 | + aHostChar.bytesPerPixel = 4; |
| 86 | + aHostChar.scanLineLength = aHostChar.bytesPerPixel * aHostChar.width; |
| 87 | +} |
| 88 | + |
| 89 | +bool JSSystemDisplay::changeResolution(const DisplayCharacteristics &aCharacteristics) { |
| 90 | + mClientChar = aCharacteristics; |
| 91 | + gFrameBuffer = (byte*)realloc( |
| 92 | + gFrameBuffer, |
| 93 | + mClientChar.width * mClientChar.height * mClientChar.bytesPerPixel); |
| 94 | + |
| 95 | + jsFrameBufferSize = mClientChar.width * mClientChar.height * 4; |
| 96 | + jsFrameBuffer.reset(new byte[jsFrameBufferSize]); |
| 97 | + |
| 98 | + EM_ASM_({ workerApi.didOpenVideo($0, $1); }, mClientChar.width, mClientChar.height); |
| 99 | + damageFrameBufferAll(); |
| 100 | + return true; |
| 101 | +} |
| 102 | + |
| 103 | +void JSSystemDisplay::getHostCharacteristics(Container &modes) { |
| 104 | + DisplayCharacteristics *hostChar = new DisplayCharacteristics(); |
| 105 | + convertCharacteristicsToHost(*hostChar, mClientChar); |
| 106 | + modes.insert(hostChar); |
| 107 | +} |
| 108 | + |
| 109 | +void JSSystemDisplay::setMouseGrab(bool enable) { |
| 110 | + ::printf("JSSystemDisplay::setMouseGrab\n"); |
| 111 | +} |
| 112 | + |
| 113 | +SystemDisplay *allocSystemDisplay(const char *title, const DisplayCharacteristics &chr, int redraw_ms) { |
| 114 | + return new JSSystemDisplay(chr, redraw_ms); |
| 115 | +} |
0 commit comments