mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[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
This commit is contained in:
@@ -1,39 +1,30 @@
|
||||
#include "display.h"
|
||||
#include <kandinsky.h>
|
||||
|
||||
extern "C" {
|
||||
#include <SDL/SDL.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <emscripten.h>
|
||||
}
|
||||
|
||||
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(); j<r.bottom(); j++) {
|
||||
for (int i=r.left(); i<r.right(); i++) {
|
||||
KDColor c = pixels[pixelNumber++];
|
||||
*((Uint32*)screen->pixels + 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; j<Ion::Display::Height; j++) {
|
||||
for (int i=0; i<Ion::Display::Width; i++) {
|
||||
KDColor c = sPixels[pixelNumber++];
|
||||
*((Uint32*)screen->pixels + 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Display {
|
||||
namespace Emscripten {
|
||||
|
||||
void init();
|
||||
void refresh();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <ion/events.h>
|
||||
#include "display.h"
|
||||
extern "C" {
|
||||
#include <SDL/SDL.h>
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user