#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_EMSCRIPTEN
#include "SDL_emscriptenvideo.h"
#include "SDL_emscriptenframebuffer.h"
#include <emscripten/threading.h>
bool Emscripten_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, SDL_PixelFormat *format, void **pixels, int *pitch)
{
SDL_Surface *surface;
const SDL_PixelFormat surface_format = SDL_PIXELFORMAT_RGBA32;
int w, h;
SDL_WindowData *data = window->internal;
surface = data->surface;
SDL_DestroySurface(surface);
SDL_GetWindowSizeInPixels(window, &w, &h);
surface = SDL_CreateSurface(w, h, surface_format);
if (!surface) {
return false;
}
data->surface = surface;
*format = surface_format;
*pixels = surface->pixels;
*pitch = surface->pitch;
return true;
}
bool Emscripten_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects)
{
SDL_Surface *surface;
SDL_WindowData *data = window->internal;
surface = data->surface;
if (!surface) {
return SDL_SetError("Couldn't find framebuffer surface for window");
}
int updated = MAIN_THREAD_EM_ASM_INT({
var w = $0;
var h = $1;
var pixels = $2;
var canvasId = UTF8ToString($3);
var canvas = document.querySelector(canvasId);
var SDL3 = Module['SDL3'];
if (SDL3.ctxCanvas !== canvas) {
SDL3.ctx = Browser.createContext(canvas, false, true);
if (!SDL3.ctx) {
return false;
}
SDL3.ctxCanvas = canvas;
}
if (SDL3.w !== w || SDL3.h !== h || SDL3.imageCtx !== SDL3.ctx) {
SDL3.image = SDL3.ctx.createImageData(w, h);
SDL3.w = w;
SDL3.h = h;
SDL3.imageCtx = SDL3.ctx;
}
var data = SDL3.image.data;
var src = pixels / 4;
if (SDL3.data32Data !== data) {
SDL3.data32 = new Int32Array(data.buffer);
SDL3.data32Data = data;
}
var data32 = SDL3.data32;
data32.set(HEAP32.subarray(src, src + data32.length));
SDL3.ctx.putImageData(SDL3.image, 0, 0);
return true;
}, surface->w, surface->h, surface->pixels, data->canvas_id);
if (!updated) {
return SDL_SetError("Couldn't create context for canvas update");
}
if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, true)) {
emscripten_sleep(0);
}
return true;
}
void Emscripten_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_WindowData *data = window->internal;
SDL_DestroySurface(data->surface);
data->surface = NULL;
}
#endif