From 80c6d052f2532ef49173fee61562d2cf7bcf7bd8 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 21 Jul 2017 14:02:12 +0200 Subject: [PATCH] [ion] Emscripten display uses an internal framebuffer We operate on a framebuffer (push/pull rect), and then copy it all to the screen at once. This avoids reading back from video memory. All in all, it goes *much* faster this way. Change-Id: I472d35988fde876906a9be71e0666b2c238114b3 --- ion/src/emscripten/display.cpp | 49 +++++++++++++++++++++------------- ion/src/emscripten/display.h | 1 + ion/src/emscripten/events.cpp | 2 ++ 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/ion/src/emscripten/display.cpp b/ion/src/emscripten/display.cpp index 4fc647955..9406f2815 100644 --- a/ion/src/emscripten/display.cpp +++ b/ion/src/emscripten/display.cpp @@ -1,39 +1,30 @@ #include "display.h" +#include + extern "C" { #include #include +#include +#include } SDL_Surface * screen = nullptr; +static KDColor sPixels[Ion::Display::Width*Ion::Display::Height]; +static KDFrameBuffer sFrameBuffer = KDFrameBuffer(sPixels, KDSize(Ion::Display::Width, Ion::Display::Height)); namespace Ion { namespace Display { void pushRect(KDRect r, const KDColor * pixels) { - if (SDL_MUSTLOCK(screen)) { - SDL_LockSurface(screen); - } - int pixelNumber = 0; - for (int j=r.top(); jpixels + j * Ion::Display::Width + i) = SDL_MapRGB(screen->format, c.red(), c.green(), c.blue()); - } - } - if (SDL_MUSTLOCK(screen)) { - SDL_UnlockSurface(screen); - } - SDL_UpdateRect(screen, r.x(), r.y(), r.width(), r.height()); + sFrameBuffer.pushRect(r, pixels); } void pushRectUniform(KDRect r, KDColor c) { - Uint32 sdlColor = SDL_MapRGB(screen->format, c.red(), c.green(), c.blue()); - SDL_Rect sdlRect = { r.x(), r.y(), r.width(), r.height() }; - SDL_FillRect(screen, &sdlRect, sdlColor); - SDL_UpdateRect(screen, r.x(), r.y(), r.width(), r.height()); + sFrameBuffer.pushRectUniform(r, c); } void pullRect(KDRect r, KDColor * pixels) { + sFrameBuffer.pullRect(r, pixels); } void waitForVBlank() { @@ -48,7 +39,27 @@ namespace Emscripten { void init() { SDL_Init(SDL_INIT_VIDEO); - screen = SDL_SetVideoMode(Ion::Display::Width, Ion::Display::Height, 32, SDL_HWSURFACE); + screen = SDL_SetVideoMode(Ion::Display::Width, Ion::Display::Height, 32, SDL_SWSURFACE); + EM_ASM("SDL.defaults.copyOnLock = false; SDL.defaults.discardOnLock = true; SDL.defaults.opaqueFrontBuffer = false;"); +} + +void refresh() { + // Simply push the whole buffer to the surface + if (SDL_MUSTLOCK(screen)) { + SDL_LockSurface(screen); + } + int pixelNumber = 0; + for (int j=0; jpixels + j * Ion::Display::Width + i) = SDL_MapRGB(screen->format, c.red(), c.green(), c.blue()); + } + } + + if (SDL_MUSTLOCK(screen)) { + SDL_UnlockSurface(screen); + } + SDL_UpdateRect(screen, 0, 0, Ion::Display::Width, Ion::Display::Height); } } diff --git a/ion/src/emscripten/display.h b/ion/src/emscripten/display.h index 0dcfa63ee..1d8094187 100644 --- a/ion/src/emscripten/display.h +++ b/ion/src/emscripten/display.h @@ -8,6 +8,7 @@ namespace Display { namespace Emscripten { void init(); +void refresh(); } } diff --git a/ion/src/emscripten/events.cpp b/ion/src/emscripten/events.cpp index 65eb378b7..3b814b8ba 100644 --- a/ion/src/emscripten/events.cpp +++ b/ion/src/emscripten/events.cpp @@ -1,4 +1,5 @@ #include +#include "display.h" extern "C" { #include } @@ -28,6 +29,7 @@ static constexpr Event sEventForASCIICharAbove32[95] = { }; Event getEvent(int * timeout) { + Ion::Display::Emscripten::refresh(); if (sEvent != Ion::Events::None) { Ion::Events::Event event = sEvent; sEvent = Ion::Events::None;