This commit is contained in:
2025-12-27 13:15:33 -06:00
parent 8b9bee0011
commit 64cb6895be
3 changed files with 65 additions and 8 deletions

36
gpu.c
View File

@@ -3,19 +3,20 @@
#include <SDL3/SDL_gpu.h> #include <SDL3/SDL_gpu.h>
#include "cell.h" #include "cell.h"
// Macro for GPU wrapper classes that need cleanup // Macro for GPU wrapper classes that need cleanup
#define QJSCLASSGPUWRAPPER(WRAPPERTYPE, SDLTYPE) \ #define QJSCLASSGPUWRAPPER(WRAPPERTYPE, SDLTYPE) \
typedef struct { \ typedef struct { \
SDL_GPUDevice *device; \ SDL_GPUDevice *device; \
JSValue js_device; \ JSValue js_device; \
SDL_##SDLTYPE *type; \ SDL_##SDLTYPE *type; \
int owned; \
} WRAPPERTYPE; \ } WRAPPERTYPE; \
JSClassID js_SDL_##SDLTYPE##_id; \ JSClassID js_SDL_##SDLTYPE##_id; \
static void js_SDL_##SDLTYPE##_finalizer(JSRuntime *rt, JSValue val) { \ static void js_SDL_##SDLTYPE##_finalizer(JSRuntime *rt, JSValue val) { \
WRAPPERTYPE *wrapper = JS_GetOpaque(val, js_SDL_##SDLTYPE##_id); \ WRAPPERTYPE *wrapper = JS_GetOpaque(val, js_SDL_##SDLTYPE##_id); \
JS_FreeValueRT(rt, wrapper->js_device); \ 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); \ SDL_Release##SDLTYPE(wrapper->device, wrapper->type); \
free(wrapper); \ 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->js_device = JS_DupValue(js,device); \
wrapper->device = js2SDL_GPUDevice(js, device); \ wrapper->device = js2SDL_GPUDevice(js, device); \
wrapper->type = member; \ wrapper->type = member; \
wrapper->owned = 1; \
JSValue j = JS_NewObjectClass(js, js_SDL_##SDLTYPE##_id); \ JSValue j = JS_NewObjectClass(js, js_SDL_##SDLTYPE##_id); \
JS_SetOpaque(j, wrapper); \ JS_SetOpaque(j, wrapper); \
return j; \ return j; \
@@ -1429,6 +1431,35 @@ JSC_CCALL(cmd_swapchain_pass,
return SDL_GPURenderPass2js(js, renderPass); 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, JSC_CCALL(cmd_compute_pass,
SDL_GPUCommandBuffer *cmd = js2SDL_GPUCommandBuffer(js,self); SDL_GPUCommandBuffer *cmd = js2SDL_GPUCommandBuffer(js,self);
JSValue textures = argv[0]; 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, debug_label, 1),
MIST_FUNC_DEF(cmd, blit, 1), MIST_FUNC_DEF(cmd, blit, 1),
MIST_FUNC_DEF(cmd, swapchain_pass, 2), MIST_FUNC_DEF(cmd, swapchain_pass, 2),
MIST_FUNC_DEF(cmd, acquire_swapchain_texture, 1),
}; };
JSC_CCALL(copypass_end, JSC_CCALL(copypass_end,

34
input.c
View File

@@ -2,6 +2,14 @@
#include "wota.h" #include "wota.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include "sdl.h"
void SDL_Event_free(JSRuntime *rt, SDL_Event *e)
{
free(e);
}
QJSCLASS(SDL_Event,)
// Internal keymod function for input module // Internal keymod function for input module
static JSValue js_keymod(JSContext *js) static JSValue js_keymod(JSContext *js)
@@ -750,18 +758,25 @@ JSC_CCALL(input_get_events,
int event_count = 0; int event_count = 0;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
// gui_input(&event); SDL_Event *e = (SDL_Event *)malloc(sizeof(SDL_Event));
memcpy(e, &event, sizeof(SDL_Event));
WotaBuffer wb = event2wota(&event); JSValue event_obj = SDL_Event2js(js, e);
JSValue event_obj = wota2value(js, wb.data);
JS_SetPropertyUint32(js, events_array, event_count, event_obj); JS_SetPropertyUint32(js, events_array, event_count, event_obj);
wota_buffer_free(&wb);
event_count++; event_count++;
} }
return events_array; 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, JSC_CCALL(input_gamepad_id_to_type,
int id = js2number(js, argv[0]); int id = js2number(js, argv[0]);
return JS_NewString(js, SDL_GetGamepadStringForType(SDL_GetGamepadTypeForID(id))); 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, keymod, 0),
MIST_FUNC_DEF(input, mousestate, 0), MIST_FUNC_DEF(input, mousestate, 0),
MIST_FUNC_DEF(input, get_events, 0), MIST_FUNC_DEF(input, get_events, 0),
MIST_FUNC_DEF(input, objectify, 1),
MIST_FUNC_DEF(input, gamepad_id_to_type, 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;
)

3
sdl.h
View File

@@ -29,6 +29,9 @@ typedef union {
SDL_Window *js2SDL_Window(JSContext *js, JSValue v); SDL_Window *js2SDL_Window(JSContext *js, JSValue v);
JSValue SDL_Window2js(JSContext *js, SDL_Window *w); 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 str2pixelformat(const char *str);
SDL_PixelFormat js2pixelformat(JSContext *js, JSValue v); SDL_PixelFormat js2pixelformat(JSContext *js, JSValue v);
JSValue pixelformat2js(JSContext *js, SDL_PixelFormat format); JSValue pixelformat2js(JSContext *js, SDL_PixelFormat format);