From 64cb6895be844152e80ae00add3eca3dd873d483 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sat, 27 Dec 2025 13:15:33 -0600 Subject: [PATCH] wrap --- gpu.c | 36 ++++++++++++++++++++++++++++++++++-- input.c | 34 ++++++++++++++++++++++++++++------ sdl.h | 3 +++ 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/gpu.c b/gpu.c index b5a9794..1b8754f 100644 --- a/gpu.c +++ b/gpu.c @@ -3,19 +3,20 @@ #include #include "cell.h" - + // Macro for GPU wrapper classes that need cleanup #define QJSCLASSGPUWRAPPER(WRAPPERTYPE, SDLTYPE) \ typedef struct { \ SDL_GPUDevice *device; \ JSValue js_device; \ SDL_##SDLTYPE *type; \ + int owned; \ } WRAPPERTYPE; \ JSClassID js_SDL_##SDLTYPE##_id; \ static void js_SDL_##SDLTYPE##_finalizer(JSRuntime *rt, JSValue val) { \ WRAPPERTYPE *wrapper = JS_GetOpaque(val, js_SDL_##SDLTYPE##_id); \ JS_FreeValueRT(rt, wrapper->js_device); \ - if (wrapper && wrapper->device && wrapper->type) \ + if (wrapper && wrapper->device && wrapper->type && wrapper->owned) \ SDL_Release##SDLTYPE(wrapper->device, wrapper->type); \ free(wrapper); \ } \ @@ -33,6 +34,7 @@ JSValue SDL_##SDLTYPE##2js(JSContext *js, JSValue device, SDL_##SDLTYPE *member) wrapper->js_device = JS_DupValue(js,device); \ wrapper->device = js2SDL_GPUDevice(js, device); \ wrapper->type = member; \ + wrapper->owned = 1; \ JSValue j = JS_NewObjectClass(js, js_SDL_##SDLTYPE##_id); \ JS_SetOpaque(j, wrapper); \ return j; \ @@ -1429,6 +1431,35 @@ JSC_CCALL(cmd_swapchain_pass, return SDL_GPURenderPass2js(js, renderPass); ) +JSC_CCALL(cmd_acquire_swapchain_texture, + SDL_GPUCommandBuffer *cmdbuf = js2SDL_GPUCommandBuffer(js, self); + SDL_Window *window = js2SDL_Window(js, argv[0]); + + SDL_GPUTexture* swapchainTexture; + Uint32 w, h; + if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, window, &swapchainTexture, &w, &h)) { + return JS_ThrowReferenceError(js, "WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); + } + + if (!swapchainTexture) return JS_NULL; + + // Manually construct a non-owning texture wrapper + gpu_texture_wrapper *wrapper = malloc(sizeof(gpu_texture_wrapper)); + wrapper->js_device = JS_NULL; // We don't hold a reference to the JS device + wrapper->device = NULL; // We don't need the device pointer as we don't release + wrapper->type = swapchainTexture; + wrapper->owned = 0; // CRITICAL: Do not release this texture + + JSValue jstex = JS_NewObjectClass(js, js_SDL_GPUTexture_id); + JS_SetOpaque(jstex, wrapper); + + JS_SetPropertyStr(js, jstex, "width", number2js(js, w)); + JS_SetPropertyStr(js, jstex, "height", number2js(js, h)); + JS_SetPropertyStr(js, jstex, "dim", vec22js(js, (vec2){w, h})); + + return jstex; +) + JSC_CCALL(cmd_compute_pass, SDL_GPUCommandBuffer *cmd = js2SDL_GPUCommandBuffer(js,self); JSValue textures = argv[0]; @@ -1477,6 +1508,7 @@ static const JSCFunctionListEntry js_SDL_GPUCommandBuffer_funcs[] = { MIST_FUNC_DEF(cmd, debug_label, 1), MIST_FUNC_DEF(cmd, blit, 1), MIST_FUNC_DEF(cmd, swapchain_pass, 2), + MIST_FUNC_DEF(cmd, acquire_swapchain_texture, 1), }; JSC_CCALL(copypass_end, diff --git a/input.c b/input.c index 51b11aa..0e8e76d 100644 --- a/input.c +++ b/input.c @@ -2,6 +2,14 @@ #include "wota.h" #include +#include "sdl.h" + +void SDL_Event_free(JSRuntime *rt, SDL_Event *e) +{ + free(e); +} + +QJSCLASS(SDL_Event,) // Internal keymod function for input module static JSValue js_keymod(JSContext *js) @@ -750,18 +758,25 @@ JSC_CCALL(input_get_events, int event_count = 0; while (SDL_PollEvent(&event)) { -// gui_input(&event); - - WotaBuffer wb = event2wota(&event); - JSValue event_obj = wota2value(js, wb.data); + SDL_Event *e = (SDL_Event *)malloc(sizeof(SDL_Event)); + memcpy(e, &event, sizeof(SDL_Event)); + JSValue event_obj = SDL_Event2js(js, e); JS_SetPropertyUint32(js, events_array, event_count, event_obj); - wota_buffer_free(&wb); event_count++; } return events_array; ) +JSC_CCALL(input_objectify, + SDL_Event *e = js2SDL_Event(js, argv[0]); + if (!e) return JS_ThrowTypeError(js, "Expected SDL_Event object"); + WotaBuffer wb = event2wota(e); + JSValue event_obj = wota2value(js, wb.data); + wota_buffer_free(&wb); + return event_obj; +) + JSC_CCALL(input_gamepad_id_to_type, int id = js2number(js, argv[0]); return JS_NewString(js, SDL_GetGamepadStringForType(SDL_GetGamepadTypeForID(id))); @@ -774,7 +789,14 @@ static const JSCFunctionListEntry js_input_funcs[] = { MIST_FUNC_DEF(input, keymod, 0), MIST_FUNC_DEF(input, mousestate, 0), MIST_FUNC_DEF(input, get_events, 0), + MIST_FUNC_DEF(input, objectify, 1), MIST_FUNC_DEF(input, gamepad_id_to_type, 1), }; -CELL_USE_FUNCS(js_input_funcs) +CELL_USE_INIT( + QJSCLASSPREP_NO_FUNCS(SDL_Event); + + JSValue mod = JS_NewObject(js); + JS_SetPropertyFunctionList(js, mod, js_input_funcs, countof(js_input_funcs)); + return mod; +) diff --git a/sdl.h b/sdl.h index bde49e0..f79f1f6 100644 --- a/sdl.h +++ b/sdl.h @@ -29,6 +29,9 @@ typedef union { SDL_Window *js2SDL_Window(JSContext *js, JSValue v); JSValue SDL_Window2js(JSContext *js, SDL_Window *w); +SDL_Event *js2SDL_Event(JSContext *js, JSValue v); +JSValue SDL_Event2js(JSContext *js, SDL_Event *e); + SDL_PixelFormat str2pixelformat(const char *str); SDL_PixelFormat js2pixelformat(JSContext *js, JSValue v); JSValue pixelformat2js(JSContext *js, SDL_PixelFormat format);