rm dupavlue and freevalue

This commit is contained in:
2026-02-25 09:41:57 -06:00
parent ba6a0c2e12
commit c004a8d463
6 changed files with 37 additions and 165 deletions

View File

@@ -105,7 +105,6 @@ JSC_CCALL(camera_open,
if (argc > 1 && !JS_IsNull(argv[1])) {
JSValue format_val = JS_GetPropertyStr(js, argv[1], "format");
spec_val.format = js2SDL_PixelFormat(js, format_val);
JS_FreeValue(js, format_val);
JS_GETATOM(js, spec_val.width, argv[1], width, number);
JS_GETATOM(js, spec_val.height, argv[1], height, number);

64
gpu.c
View File

@@ -35,7 +35,7 @@ static void js_SDL_##SDLTYPE##_finalizer(JSRuntime *rt, JSValue val) { \
wrapper->device && wrapper->type && wrapper->owned) \
SDL_Release##SDLTYPE(wrapper->device, wrapper->type); \
gpu_device_state_unref(wrapper->state); \
JS_FreeValueRT(rt, wrapper->js_device); \
\
free(wrapper); \
} \
static JSClassDef js_SDL_##SDLTYPE##_class = { \
@@ -49,7 +49,7 @@ SDL_##SDLTYPE *js2SDL_##SDLTYPE(JSContext *js, JSValue val) { \
} \
JSValue SDL_##SDLTYPE##2js(JSContext *js, JSValue device, SDL_##SDLTYPE *member) { \
WRAPPERTYPE *wrapper = malloc(sizeof(WRAPPERTYPE)); \
wrapper->js_device = JS_DupValue(js,device); \
wrapper->js_device = device; \
wrapper->device = js2SDL_GPUDevice(js, device); \
wrapper->type = member; \
wrapper->owned = 1; \
@@ -590,19 +590,15 @@ SDL_GPUStencilOpState js2SDL_GPUStencilOpState(JSContext *js, JSValue v)
JSValue compare_val = JS_GetPropertyStr(js, v, "compare");
if(!JS_IsNull(compare_val)) state.compare_op = js2SDL_GPUCompareOp(js, compare_val);
JS_FreeValue(js, compare_val);
JSValue fail_val = JS_GetPropertyStr(js, v, "fail");
if(!JS_IsNull(fail_val)) state.fail_op = js2SDL_GPUStencilOp(js, fail_val);
JS_FreeValue(js, fail_val);
JSValue depth_fail_val = JS_GetPropertyStr(js, v, "depth_fail");
if(!JS_IsNull(depth_fail_val)) state.depth_fail_op = js2SDL_GPUStencilOp(js, depth_fail_val);
JS_FreeValue(js, depth_fail_val);
JSValue pass_val = JS_GetPropertyStr(js, v, "pass");
if(!JS_IsNull(pass_val)) state.pass_op = js2SDL_GPUStencilOp(js, pass_val);
JS_FreeValue(js, pass_val);
return state;
}
@@ -647,27 +643,21 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst
Uint32 slot = 0;
JS_ToUint32(js, &slot, slot_val);
JS_FreeValue(js, slot_val);
Uint32 pitch = 0;
JS_ToUint32(js, &pitch, pitch_val);
JS_FreeValue(js, pitch_val);
SDL_GPUVertexInputRate input_rate = js2SDL_GPUVertexInputRate(js, rate_val);
JS_FreeValue(js, rate_val);
Uint32 step_rate = 0;
JS_ToUint32(js, &step_rate, step_val);
JS_FreeValue(js, step_val);
vbd[i].slot = slot;
vbd[i].pitch = pitch;
vbd[i].input_rate = input_rate;
vbd[i].instance_step_rate = step_rate;
}
JS_FreeValue(js, elem);
}
JS_FreeValue(js, vbd_val);
JSValue vat_val = JS_GetPropertyStr(js, pipe, "vertex_attributes");
Uint32 vat_len = JS_ArrayLength(js,vat_val);
@@ -683,27 +673,21 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst
Uint32 location = 0;
JS_ToUint32(js, &location, loc_val);
JS_FreeValue(js, loc_val);
Uint32 buffer_slot = 0;
JS_ToUint32(js, &buffer_slot, slot_val);
JS_FreeValue(js, slot_val);
SDL_GPUVertexElementFormat format = js2SDL_GPUVertexElementFormat(js, fmt_val);
JS_FreeValue(js, fmt_val);
Uint32 offset = 0;
JS_ToUint32(js, &offset, off_val);
JS_FreeValue(js, off_val);
vat[i].location = location;
vat[i].buffer_slot = buffer_slot;
vat[i].format = format;
vat[i].offset = offset;
}
JS_FreeValue(js, elem);
}
JS_FreeValue(js, vat_val);
info.vertex_input_state = (SDL_GPUVertexInputState){
.vertex_buffer_descriptions = vbd,
@@ -730,7 +714,6 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst
JS_GETPROP(js,info.rasterizer_state.depth_bias_slope_factor, depth_val,bias_slope_scale, number)
JS_GETPROP(js,info.rasterizer_state.depth_bias_clamp, depth_val,bias_clamp_val, number)
}
JS_FreeValue(js, depth_val);
JSValue stencil_val = JS_GetPropertyStr(js, pipe, "stencil");
if (JS_IsObject(stencil_val)) {
@@ -743,7 +726,6 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst
uint32_t tmp;
JS_ToUint32(js, &tmp, compare_mask_val);
info.depth_stencil_state.compare_mask = tmp;
JS_FreeValue(js, compare_mask_val);
// Write Mask
JSValue write_mask_val = JS_GetPropertyStr(js, stencil_val, "write_mask");
@@ -751,7 +733,6 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst
info.depth_stencil_state.write_mask = tmp;
}
}
JS_FreeValue(js, stencil_val);
JSValue js_tar = JS_GetPropertyStr(js,pipe,"target");
@@ -764,16 +745,14 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst
for (int i = 0; i < target_info.num_color_targets; i++) {
JSValue c = JS_GetPropertyNumber(js,color_tars,i);
dsc[i] = js2SDL_GPUColorTargetDescription(js,c);
JS_FreeValue(js,c);
}
JS_FreeValue(js,color_tars);
JS_GETPROP(js,target_info.depth_stencil_format,js_tar,depth,SDL_GPUTextureFormat);
if (target_info.depth_stencil_format) target_info.has_depth_stencil_target = 1;
info.target_info = target_info;
JS_FreeValue(js, js_tar);
// Create the pipeline
SDL_GPUGraphicsPipeline *pipeline = SDL_CreateGPUGraphicsPipeline(gpu, &info);
@@ -833,7 +812,6 @@ static JSValue js_gpu_shader_constructor(JSContext *js, JSValueConst self, int a
JSValue code_val = JS_GetPropertyStr(js, obj, "code");
size_t code_size;
void *code_data = js_get_blob_data(js, &code_size, code_val);
JS_FreeValue(js, code_val);
if (code_data == -1)
return JS_EXCEPTION;
if (!code_data)
@@ -846,7 +824,6 @@ static JSValue js_gpu_shader_constructor(JSContext *js, JSValueConst self, int a
else if (!strcmp(stage_str, "fragment")) info.stage = SDL_GPU_SHADERSTAGE_FRAGMENT;
JS_FreeCString(js, stage_str);
} // TODO: Make this its own function
JS_FreeValue(js, stage_val);
// num_samplers
JS_GETPROP(js, info.num_samplers, obj, num_samplers, number)
@@ -857,7 +834,6 @@ static JSValue js_gpu_shader_constructor(JSContext *js, JSValueConst self, int a
JSValue entry_val = JS_GetPropertyStr(js,obj,"entrypoint");
info.entrypoint = JS_ToCString(js,entry_val);
JS_FreeValue(js,entry_val);
info.code_size = code_size;
info.code = code_data;
@@ -886,7 +862,6 @@ JSC_CCALL(gpu_wait_for_fences,
for (int i = 0; i < n; i++) {
JSValue a = JS_GetPropertyNumber(js,argv[0],i);
fences[i] = js2SDL_GPUFence(js,a);
JS_FreeValue(js,a);
}
int wait_all = JS_ToBool(js,argv[1]);
@@ -938,7 +913,6 @@ static JSValue js_gpu_compute_pipeline_constructor(JSContext *js, JSValueConst s
JSValue shader = JS_GetPropertyStr(js,pipe,"shader");
info.code = js_get_blob_data(js,&info.code_size, shader);
JS_FreeValue(js,shader);
if (info.code == -1)
return JS_EXCEPTION;
if (!info.code)
@@ -954,7 +928,6 @@ int JS_GETBOOL(JSContext *js, JSValue obj, const char *prop)
{
JSValue v = JS_GetPropertyStr(js,obj,prop);
int ret = JS_ToBool(js,v);
JS_FreeValue(js,v);
return ret;
}
@@ -1104,7 +1077,6 @@ JSC_CCALL(renderpass_bind_buffers,
for (int i = 0; i < len; i++) {
JSValue buffer = JS_GetPropertyNumber(js,buffers,i);
bindings[i] = js2SDL_GPUBufferBinding(js, buffer);
JS_FreeValue(js,buffer);
}
SDL_BindGPUVertexBuffers(
@@ -1136,7 +1108,6 @@ JSC_CCALL(renderpass_bind_samplers,
for (int i = 0; i < num; i++) {
JSValue val = JS_GetPropertyNumber(js,arr,i);
binds[i] = js2SDL_GPUTextureSamplerBinding(js, val);
JS_FreeValue(js,val);
}
int vertex = JS_ToBool(js,argv[0]);
if (vertex)
@@ -1186,7 +1157,6 @@ JSC_CCALL(renderpass_bind_vertex_samplers,
for (int i = 0; i < num; i++) {
JSValue val = JS_GetPropertyNumber(js,arr,i);
binds[i] = js2SDL_GPUTextureSamplerBinding(js,val);
JS_FreeValue(js,val);
}
SDL_BindGPUVertexSamplers(pass, first_slot, binds, num);
)
@@ -1200,7 +1170,6 @@ JSC_CCALL(renderpass_bind_fragment_samplers,
for (int i = 0; i < num; i++) {
JSValue val = JS_GetPropertyNumber(js,arr,i);
binds[i] = js2SDL_GPUTextureSamplerBinding(js,val);
JS_FreeValue(js,val);
}
SDL_BindGPUFragmentSamplers(pass, first_slot, binds, num);
)
@@ -1215,7 +1184,6 @@ JSC_CCALL(renderpass_bind_vertex_buffers,
JSValue val = JS_GetPropertyNumber(js,arr,i);
JS_GETPROP(js, binds[i].buffer, val, buffer, SDL_GPUBuffer)
JS_GETPROP(js, binds[i].offset, val, offset, number)
JS_FreeValue(js,val);
}
SDL_BindGPUVertexBuffers(pass, first_slot, binds, num);
)
@@ -1263,7 +1231,6 @@ JSC_CCALL(cmd_render_pass,
for (uint32_t i = 0; i < colorCount; i++) {
JSValue ctargetVal = JS_GetPropertyNumber(js, colorTargetsVal, i);
colortars[i] = js2SDL_GPUColorTargetInfo(js,ctargetVal);
JS_FreeValue(js, ctargetVal);
}
// Optional depth_stencil
@@ -1281,7 +1248,6 @@ JSC_CCALL(cmd_render_pass,
// If texture was null/invalid, treat as no depth attachment.
if (!depthtar.texture) has_depth = 0;
}
JS_FreeValue(js, depthval);
SDL_GPURenderPass *pass = SDL_BeginGPURenderPass(
cmds,
@@ -1290,7 +1256,7 @@ JSC_CCALL(cmd_render_pass,
has_depth ? &depthtar : NULL
);
JS_FreeValue(js, colorTargetsVal);
if (!pass) return JS_ThrowInternalError(js, "render_pass: Failed to begin render pass: %s", SDL_GetError());
@@ -1390,7 +1356,6 @@ SDL_GPUBlitRegion js2SDL_GPUBlitRegion(JSContext *js, JSValue v)
if (!info.w) JS_GETPROP(js,info.w,tex,width,number)
if (!info.h) JS_GETPROP(js,info.h,tex,height,number)
JS_FreeValue(js,tex);
return info;
}
@@ -1430,21 +1395,17 @@ JSC_CCALL(cmd_swapchain_pass,
JSValue colorTargetsVal = JS_GetPropertyStr(js, passObj, "color_targets");
if (!JS_IsArray(colorTargetsVal)) {
JS_FreeValue(js, colorTargetsVal);
return JS_ThrowTypeError(js, "swapchain_pass: color_targets must be an array");
return JS_ThrowTypeError(js, "swapchain_pass: color_targets must be an array");
}
uint32_t colorCount = JS_ArrayLength(js, colorTargetsVal);
if (colorCount != 1) {
JS_FreeValue(js, colorTargetsVal);
return JS_ThrowTypeError(js, "swapchain_pass: only 1 color target is supported");
return JS_ThrowTypeError(js, "swapchain_pass: only 1 color target is supported");
}
JSValue ctargetVal = JS_GetPropertyNumber(js, colorTargetsVal, 0);
SDL_GPUColorTargetInfo colorTargetInfo = js2SDL_GPUColorTargetInfo(js, ctargetVal);
JS_FreeValue(js, ctargetVal);
JS_FreeValue(js, colorTargetsVal);
colorTargetInfo.texture = swapchainTexture;
SDL_GPUDepthStencilTargetInfo depthtar = (SDL_GPUDepthStencilTargetInfo){0};
@@ -1464,8 +1425,7 @@ JSC_CCALL(cmd_swapchain_pass,
// If texture was null/invalid, treat as no depth attachment.
if (!depthtar.texture) has_depth = 0;
}
JS_FreeValue(js, depthval);
SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(
cmdbuf,
&colorTargetInfo,
@@ -1537,7 +1497,6 @@ JSC_CCALL(cmd_compute_pass,
JS_GETPROP(js, t_bind[i].texture, T, texture, SDL_GPUTexture)
JS_GETPROP(js,t_bind[i].mip_level,T,mip, number)
JS_GETPROP(js,t_bind[i].layer,T,layer, number)
JS_FreeValue(js,T);
}
int b_n = JS_ArrayLength(js,buffers);
@@ -1716,7 +1675,6 @@ JSC_CCALL(compute_samplers,
for (int i = 0; i < n; i++) {
JSValue s = JS_GetPropertyNumber(js,samplers,i);
b[i] = js2SDL_GPUTextureSamplerBinding(js,s);
JS_FreeValue(js,s);
}
SDL_BindGPUComputeSamplers(pass,js2number(js,argv[1]),b,n);
)
@@ -1729,7 +1687,6 @@ JSC_CCALL(compute_storage_textures,
for (int i = 0; i < n; i++) {
JSValue s = JS_GetPropertyNumber(js,textures,i);
b[i] = js2SDL_GPUTexture(js,s);
JS_FreeValue(js,s);
}
SDL_BindGPUComputeStorageTextures(pass,js2number(js,argv[1]),b,n);
)
@@ -1742,7 +1699,6 @@ JSC_CCALL(compute_storage_buffers,
for (int i = 0; i < n; i++) {
JSValue s = JS_GetPropertyNumber(js,buffers,i);
b[i] = js2SDL_GPUBuffer(js,s);
JS_FreeValue(js,s);
}
SDL_BindGPUComputeStorageBuffers(pass,js2number(js,argv[1]),b,n);
)
@@ -1773,7 +1729,7 @@ static JSValue js_gpu_constructor(JSContext *js, JSValueConst new_target, int ar
if (!JS_IsNull(val)) { \
SDL_SetBooleanProperty(props, sdl_prop, JS_ToBool(js, val)); \
} \
JS_FreeValue(js, val); \
\
} while(0)
SET_BOOL_PROP("debug", SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN);
@@ -1798,7 +1754,6 @@ static JSValue js_gpu_constructor(JSContext *js, JSValueConst new_target, int ar
JS_FreeCString(js, name);
}
}
JS_FreeValue(js, name_val);
// D3D12 semantic name
JSValue semantic_val = JS_GetPropertyStr(js, opts, "d3d12_semantic_name");
@@ -1809,7 +1764,6 @@ static JSValue js_gpu_constructor(JSContext *js, JSValueConst new_target, int ar
JS_FreeCString(js, semantic);
}
}
JS_FreeValue(js, semantic_val);
}
// Create GPU device with properties

View File

@@ -47,7 +47,6 @@ JSC_CCALL(SDL_Renderer_rect,
for (int i = 0; i < len; i++) {
JSValue val = JS_GetPropertyNumber(js,argv[0],i);
rects[i] = js2rect(js,val);
JS_FreeValue(js,val);
}
SDL_RenderFillRects(r,rects,len);
} else {
@@ -69,7 +68,6 @@ JSC_CCALL(SDL_Renderer_fillrect,
for (int i = 0; i < len; i++) {
JSValue val = JS_GetPropertyNumber(js,argv[0],i);
rects[i] = js2rect(js,val);
JS_FreeValue(js,val);
}
SDL_RenderFillRects(r,rects,len);
} else {
@@ -138,7 +136,6 @@ JSC_CCALL(renderer_line,
for (int i = 0; i < len; i++) {
JSValue val = JS_GetPropertyNumber(js,argv[0],i);
points[i] = js2vec2(js,val);
JS_FreeValue(js,val);
}
SDL_RenderLines(r,points,len);
}
@@ -158,7 +155,6 @@ JSC_CCALL(renderer_point,
for (int i = 0; i < len; i++) {
JSValue val = JS_GetPropertyNumber(js,argv[0],i);
points[i] = js2vec2(js,val);
JS_FreeValue(js,val);
}
SDL_RenderPoints(r, points, len);
return JS_NULL;

16
sdl.c
View File

@@ -17,7 +17,6 @@ colorf js2color(JSContext *js,JSValue v) {
color.z = js2number(js,c[2]);
color.w = JS_IsNull(c[3]) ? 1.0 : js2number(js,c[3]);
for (int i = 0; i < 4; i++) JS_FreeValue(js,c[i]);
} else if (JS_IsObject(v)) {
JS_GETPROP(js, color.x, v, r, number)
JS_GETPROP(js, color.y, v, g, number)
@@ -45,8 +44,8 @@ vec2 js2vec2(JSContext *js,JSValue v)
// Check if it's an array
if (JS_IsArray(v)) {
{ JSValue val = JS_GetPropertyNumber(js,v,0); v2.x = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js,v,1); v2.y = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js,v,0); v2.x = js2number(js, val); }
{ JSValue val = JS_GetPropertyNumber(js,v,1); v2.y = js2number(js, val); }
} else {
// Try to get x,y properties from object
JSValue x_val = JS_GetPropertyStr(js, v, "x");
@@ -55,8 +54,6 @@ vec2 js2vec2(JSContext *js,JSValue v)
v2.x = js2number(js, x_val);
v2.y = js2number(js, y_val);
JS_FreeValue(js, x_val);
JS_FreeValue(js, y_val);
}
return v2;
@@ -65,9 +62,9 @@ vec2 js2vec2(JSContext *js,JSValue v)
vec3 js2vec3(JSContext *js,JSValue v)
{
vec3 v3;
{ JSValue val = JS_GetPropertyNumber(js, v,0); v3.x = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js, v,1); v3.y = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js, v,2); v3.z = js2number(js, val); JS_FreeValue(js,val); }
{ JSValue val = JS_GetPropertyNumber(js, v,0); v3.x = js2number(js, val); }
{ JSValue val = JS_GetPropertyNumber(js, v,1); v3.y = js2number(js, val); }
{ JSValue val = JS_GetPropertyNumber(js, v,2); v3.z = js2number(js, val); }
return v3;
}
@@ -153,7 +150,7 @@ double arr_vec_length(JSContext *js,JSValue v)
double sum = 0;
for (int i = 0; i < len; i++)
{ JSValue val = JS_GetPropertyNumber(js, v, i); double num = js2number(js, val); JS_FreeValue(js,val); sum += pow(num, 2); }
{ JSValue val = JS_GetPropertyNumber(js, v, i); double num = js2number(js, val); sum += pow(num, 2); }
return sqrt(sum);
}
@@ -184,7 +181,6 @@ vec2 *js2cpvec2arr(JSContext *js,JSValue v) {
for (int i = 0; i < n; i++) {
JSValue ii = JS_GetPropertyNumber(js,v,i);
arr[i] = js2vec2(js,ii);
JS_FreeValue(js,ii);
}
return arr;

View File

@@ -284,19 +284,13 @@ static JSValue compress_bc_common(JSContext *js, JSValueConst *argv, int argc, i
JSValue height_val = JS_GetPropertyStr(js, argv[0], "height");
if (JS_IsNull(width_val) || JS_IsNull(height_val)) {
JS_FreeValue(js, width_val);
JS_FreeValue(js, height_val);
return JS_ThrowTypeError(js, "compress_%s requires width and height properties", format_name);
}
int width, height;
if (JS_ToInt32(js, &width, width_val) < 0 || JS_ToInt32(js, &height, height_val) < 0) {
JS_FreeValue(js, width_val);
JS_FreeValue(js, height_val);
return JS_ThrowTypeError(js, "width and height must be numbers");
}
JS_FreeValue(js, width_val);
JS_FreeValue(js, height_val);
if (width < 1 || height < 1)
return JS_ThrowRangeError(js, "width and height must be at least 1");
@@ -307,7 +301,6 @@ static JSValue compress_bc_common(JSContext *js, JSValueConst *argv, int argc, i
// Get pixel format
JSValue format_val = JS_GetPropertyStr(js, argv[0], "format");
SDL_PixelFormat format = js2pixelformat(js, format_val);
JS_FreeValue(js, format_val);
if (format == SDL_PIXELFORMAT_UNKNOWN)
return JS_ThrowTypeError(js, "Invalid or missing pixel format");
@@ -318,7 +311,6 @@ static JSValue compress_bc_common(JSContext *js, JSValueConst *argv, int argc, i
void *pixel_data = js_get_blob_data(js, &pixel_len, pixels_val);
if (!pixel_data || pixel_data == -1) {
JS_FreeValue(js, pixels_val);
return JS_ThrowTypeError(js, "pixels property must be an ArrayBuffer");
}
@@ -326,12 +318,10 @@ static JSValue compress_bc_common(JSContext *js, JSValueConst *argv, int argc, i
int bytes_per_pixel = SDL_BYTESPERPIXEL(format);
size_t required_size;
if (check_size_overflow(width, height, bytes_per_pixel, &required_size)) {
JS_FreeValue(js, pixels_val);
return JS_ThrowRangeError(js, "Image dimensions too large");
}
if (pixel_len < required_size) {
JS_FreeValue(js, pixels_val);
return JS_ThrowRangeError(js, "pixels buffer too small for %dx%d format (need %zu bytes, got %zu)",
width, height, required_size, pixel_len);
}
@@ -350,14 +340,12 @@ static JSValue compress_bc_common(JSContext *js, JSValueConst *argv, int argc, i
int bytes_per_block = (alpha_mode == 0) ? 8 : 16; // BC1=8, BC3=16
size_t output_size;
if (check_size_overflow(blocks_x, blocks_y, bytes_per_block, &output_size)) {
JS_FreeValue(js, pixels_val);
return JS_ThrowRangeError(js, "Output dimensions too large");
}
// Allocate output buffer
unsigned char *output = malloc(output_size);
if (!output) {
JS_FreeValue(js, pixels_val);
return JS_ThrowOutOfMemory(js);
}
@@ -365,14 +353,12 @@ static JSValue compress_bc_common(JSContext *js, JSValueConst *argv, int argc, i
size_t rgba_size;
if (check_size_overflow(width, height, 4, &rgba_size)) {
free(output);
JS_FreeValue(js, pixels_val);
return JS_ThrowRangeError(js, "RGBA buffer size too large");
}
unsigned char *rgba_data = malloc(rgba_size);
if (!rgba_data) {
free(output);
JS_FreeValue(js, pixels_val);
return JS_ThrowOutOfMemory(js);
}
@@ -383,7 +369,6 @@ static JSValue compress_bc_common(JSContext *js, JSValueConst *argv, int argc, i
SDL_PIXELFORMAT_RGBA32, rgba_data, width * 4
);
JS_FreeValue(js, pixels_val);
if (convert_result != 0) {
free(output);
@@ -461,19 +446,13 @@ static JSValue compress_bc_channels(JSContext *js, JSValueConst *argv, int argc,
JSValue height_val = JS_GetPropertyStr(js, argv[0], "height");
if (JS_IsNull(width_val) || JS_IsNull(height_val)) {
JS_FreeValue(js, width_val);
JS_FreeValue(js, height_val);
return JS_ThrowTypeError(js, "compress_%s requires width and height properties", format_name);
}
int width, height;
if (JS_ToInt32(js, &width, width_val) < 0 || JS_ToInt32(js, &height, height_val) < 0) {
JS_FreeValue(js, width_val);
JS_FreeValue(js, height_val);
return JS_ThrowTypeError(js, "width and height must be numbers");
}
JS_FreeValue(js, width_val);
JS_FreeValue(js, height_val);
if (width < 1 || height < 1)
return JS_ThrowRangeError(js, "width and height must be at least 1");
@@ -484,7 +463,6 @@ static JSValue compress_bc_channels(JSContext *js, JSValueConst *argv, int argc,
// Get pixel format
JSValue format_val = JS_GetPropertyStr(js, argv[0], "format");
SDL_PixelFormat format = js2pixelformat(js, format_val);
JS_FreeValue(js, format_val);
if (format == SDL_PIXELFORMAT_UNKNOWN)
return JS_ThrowTypeError(js, "Invalid or missing pixel format");
@@ -495,26 +473,22 @@ static JSValue compress_bc_channels(JSContext *js, JSValueConst *argv, int argc,
void *pixel_data = js_get_blob_data(js, &pixel_len, pixels_val);
if (!pixel_data || pixel_data == -1) {
JS_FreeValue(js, pixels_val);
return JS_ThrowTypeError(js, "pixels property must be an ArrayBuffer");
}
// Validate buffer size
int bytes_per_pixel = SDL_BYTESPERPIXEL(format);
if (bytes_per_pixel < num_channels) {
JS_FreeValue(js, pixels_val);
return JS_ThrowTypeError(js, "%s compression requires a format with at least %d channel(s)",
format_name, num_channels);
}
size_t required_size;
if (check_size_overflow(width, height, bytes_per_pixel, &required_size)) {
JS_FreeValue(js, pixels_val);
return JS_ThrowRangeError(js, "Image dimensions too large");
}
if (pixel_len < required_size) {
JS_FreeValue(js, pixels_val);
return JS_ThrowRangeError(js, "pixels buffer too small for %dx%d format (need %zu bytes, got %zu)",
width, height, required_size, pixel_len);
}
@@ -525,14 +499,12 @@ static JSValue compress_bc_channels(JSContext *js, JSValueConst *argv, int argc,
int bytes_per_block = (num_channels == 1) ? 8 : 16; // BC4=8, BC5=16
size_t output_size;
if (check_size_overflow(blocks_x, blocks_y, bytes_per_block, &output_size)) {
JS_FreeValue(js, pixels_val);
return JS_ThrowRangeError(js, "Output dimensions too large");
}
// Allocate output buffer
unsigned char *output = malloc(output_size);
if (!output) {
JS_FreeValue(js, pixels_val);
return JS_ThrowOutOfMemory(js);
}
@@ -540,14 +512,12 @@ static JSValue compress_bc_channels(JSContext *js, JSValueConst *argv, int argc,
size_t channel_size;
if (check_size_overflow(width, height, num_channels, &channel_size)) {
free(output);
JS_FreeValue(js, pixels_val);
return JS_ThrowRangeError(js, "Channel buffer size too large");
}
unsigned char *channel_data = malloc(channel_size);
if (!channel_data) {
free(output);
JS_FreeValue(js, pixels_val);
return JS_ThrowOutOfMemory(js);
}
@@ -564,7 +534,6 @@ static JSValue compress_bc_channels(JSContext *js, JSValueConst *argv, int argc,
}
}
JS_FreeValue(js, pixels_val);
// Compress blocks
for (int by = 0; by < blocks_y; by++) {
@@ -641,7 +610,6 @@ JSC_CCALL(surface_constructor,
if (!JS_IsNull(format_val)) {
format = js2pixelformat(js, format_val);
}
JS_FreeValue(js, format_val);
// Check for pixel data
JSValue pixels_val = JS_GetPropertyStr(js, argv[0], "pixels");
@@ -651,20 +619,17 @@ JSC_CCALL(surface_constructor,
void *raw = js_get_blob_data(js, &len, pixels_val);
if (raw == -1) {
JS_FreeValue(js, pixels_val);
return JS_EXCEPTION;
return JS_EXCEPTION;
}
if (!raw) {
JS_FreeValue(js, pixels_val);
return JS_ThrowTypeError(js, "no data");
return JS_ThrowTypeError(js, "no data");
}
int pitch;
JSValue pitch_val = JS_GetPropertyStr(js, argv[0], "pitch");
if (!JS_IsNull(pitch_val)) {
pitch = js2number(js, pitch_val);
JS_FreeValue(js, pitch_val);
} else {
// Calculate pitch based on format
int bytes_per_pixel = SDL_BYTESPERPIXEL(format);
@@ -674,19 +639,16 @@ JSC_CCALL(surface_constructor,
// Copy the pixel data
void *pixels_copy = malloc(len);
if (!pixels_copy) {
JS_FreeValue(js, pixels_val);
return JS_ThrowOutOfMemory(js);
return JS_ThrowOutOfMemory(js);
}
memcpy(pixels_copy, raw, len);
SDL_Surface *surface = SDL_CreateSurfaceFrom(width, height, format, pixels_copy, pitch);
if (!surface) {
free(pixels_copy);
JS_FreeValue(js, pixels_val);
return JS_ThrowInternalError(js, "Failed to create surface from pixels: %s", SDL_GetError());
return JS_ThrowInternalError(js, "Failed to create surface from pixels: %s", SDL_GetError());
}
JS_FreeValue(js, pixels_val);
ret = SDL_Surface2js(js, surface);
} else {
// Create blank surface
@@ -717,24 +679,17 @@ static SDL_Surface* image_to_surface(JSContext *js, JSValue img_obj)
JSValue height_val = JS_GetPropertyStr(js, img_obj, "height");
if (JS_IsNull(width_val) || JS_IsNull(height_val)) {
JS_FreeValue(js, width_val);
JS_FreeValue(js, height_val);
return NULL;
}
int width, height;
if (JS_ToInt32(js, &width, width_val) < 0 || JS_ToInt32(js, &height, height_val) < 0) {
JS_FreeValue(js, width_val);
JS_FreeValue(js, height_val);
return NULL;
}
JS_FreeValue(js, width_val);
JS_FreeValue(js, height_val);
// Get format
JSValue format_val = JS_GetPropertyStr(js, img_obj, "format");
SDL_PixelFormat format = js2pixelformat(js, format_val);
JS_FreeValue(js, format_val);
if (format == SDL_PIXELFORMAT_UNKNOWN)
format = SDL_PIXELFORMAT_RGBA32; // default
@@ -745,12 +700,10 @@ static SDL_Surface* image_to_surface(JSContext *js, JSValue img_obj)
void *pixel_data = js_get_blob_data(js, &pixel_len, pixels_val);
if (pixel_data == -1) {
JS_FreeValue(js, pixels_val);
return NULL;
}
if (!pixel_data) {
JS_FreeValue(js, pixels_val);
return NULL;
}
@@ -759,7 +712,6 @@ static SDL_Surface* image_to_surface(JSContext *js, JSValue img_obj)
JSValue pitch_val = JS_GetPropertyStr(js, img_obj, "pitch");
if (!JS_IsNull(pitch_val)) {
pitch = js2number(js, pitch_val);
JS_FreeValue(js, pitch_val);
} else {
pitch = width * SDL_BYTESPERPIXEL(format);
}
@@ -767,11 +719,9 @@ static SDL_Surface* image_to_surface(JSContext *js, JSValue img_obj)
// Create a copy of pixel data since SDL_Surface will own it
void *pixels_copy = malloc(pixel_len);
if (!pixels_copy) {
JS_FreeValue(js, pixels_val);
return NULL;
}
memcpy(pixels_copy, pixel_data, pixel_len);
JS_FreeValue(js, pixels_val);
SDL_Surface *surface = SDL_CreateSurfaceFrom(width, height, format, pixels_copy, pitch);
if (!surface) {
@@ -838,13 +788,10 @@ JSC_CCALL(surface_scale_img,
if (!JS_IsNull(height_val))
JS_ToInt32(js, &new_height, height_val);
JS_FreeValue(js, width_val);
JS_FreeValue(js, height_val);
// Get scale mode
JSValue mode_val = JS_GetPropertyStr(js, argv[1], "mode");
SDL_ScaleMode mode = js2SDL_ScaleMode(js, mode_val);
JS_FreeValue(js, mode_val);
SDL_Surface *dst = SDL_ScaleSurface(src, new_width, new_height, mode);
SDL_DestroySurface(src);
@@ -976,7 +923,6 @@ JSC_CCALL(surface_convert_generic,
// Get source format
JSValue src_format_val = JS_GetPropertyStr(js, argv[0], "format");
SDL_PixelFormat src_format = js2pixelformat(js, src_format_val);
JS_FreeValue(js, src_format_val);
if (src_format == SDL_PIXELFORMAT_UNKNOWN)
return JS_ThrowTypeError(js, "source object requires valid format");
@@ -987,7 +933,6 @@ JSC_CCALL(surface_convert_generic,
void *src_pixels = js_get_blob_data(js, &src_len, src_pixels_val);
if (src_pixels == -1) {
JS_FreeValue(js, src_pixels_val);
return JS_EXCEPTION;
}
@@ -996,7 +941,6 @@ JSC_CCALL(surface_convert_generic,
JSValue src_pitch_val = JS_GetPropertyStr(js, argv[0], "pitch");
if (!JS_IsNull(src_pitch_val)) {
src_pitch = js2number(js, src_pitch_val);
JS_FreeValue(js, src_pitch_val);
} else {
src_pitch = src_width * SDL_BYTESPERPIXEL(src_format);
}
@@ -1011,12 +955,10 @@ JSC_CCALL(surface_convert_generic,
src_colorspace = (SDL_Colorspace)colorspace_num;
}
}
JS_FreeValue(js, src_colorspace_val);
// Parse conversion object
JSValue dst_format_val = JS_GetPropertyStr(js, argv[1], "format");
SDL_PixelFormat dst_format = js2pixelformat(js, dst_format_val);
JS_FreeValue(js, dst_format_val);
if (dst_format == SDL_PIXELFORMAT_UNKNOWN)
return JS_ThrowTypeError(js, "conversion object requires valid format");
@@ -1026,7 +968,6 @@ JSC_CCALL(surface_convert_generic,
JSValue dst_pitch_val = JS_GetPropertyStr(js, argv[1], "pitch");
if (!JS_IsNull(dst_pitch_val)) {
dst_pitch = js2number(js, dst_pitch_val);
JS_FreeValue(js, dst_pitch_val);
} else {
dst_pitch = src_width * SDL_BYTESPERPIXEL(dst_format);
}
@@ -1040,13 +981,11 @@ JSC_CCALL(surface_convert_generic,
dst_colorspace = (SDL_Colorspace)colorspace_num;
}
}
JS_FreeValue(js, dst_colorspace_val);
// Calculate destination buffer size
size_t dst_size = dst_pitch * src_height;
void *dst_pixels = malloc(dst_size);
if (!dst_pixels) {
JS_FreeValue(js, src_pixels_val);
return JS_ThrowOutOfMemory(js);
}
@@ -1071,7 +1010,6 @@ JSC_CCALL(surface_convert_generic,
);
}
JS_FreeValue(js, src_pixels_val);
if (!success) {
free(dst_pixels);

47
video.c
View File

@@ -42,7 +42,6 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
if (!JS_IsNull(title_val)) {
title = JS_ToCString(js, title_val);
}
JS_FreeValue(js, title_val);
if (!title) {
return JS_ThrowTypeError(js, "Window title is required");
@@ -53,14 +52,12 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
if (!JS_IsNull(width_val)) {
width = js2number(js, width_val);
}
JS_FreeValue(js, width_val);
int height = 480;
JSValue height_val = JS_GetPropertyStr(js, opts, "height");
if (!JS_IsNull(height_val)) {
height = js2number(js, height_val);
}
JS_FreeValue(js, height_val);
// Create SDL properties object
SDL_PropertiesID props = SDL_CreateProperties();
@@ -84,7 +81,6 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, js2number(js, x_val));
}
}
JS_FreeValue(js, x_val);
JSValue y_val = JS_GetPropertyStr(js, opts, "y");
if (!JS_IsNull(y_val)) {
@@ -99,7 +95,6 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, js2number(js, y_val));
}
}
JS_FreeValue(js, y_val);
// Helper function to check and set boolean properties
#define SET_BOOL_PROP(js_name, sdl_prop) do { \
@@ -107,7 +102,6 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
if (!JS_IsNull(val)) { \
SDL_SetBooleanProperty(props, sdl_prop, JS_ToBool(js, val)); \
} \
JS_FreeValue(js, val); \
} while(0)
// Set all boolean properties directly on the SDL properties object
@@ -135,14 +129,12 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
if (!JS_IsNull(focusable_val)) {
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, JS_ToBool(js, focusable_val));
}
JS_FreeValue(js, focusable_val);
// Handle notFocusable (for backwards compatibility)
JSValue not_focusable_val = JS_GetPropertyStr(js, opts, "notFocusable");
if (!JS_IsNull(not_focusable_val)) {
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, !JS_ToBool(js, not_focusable_val));
}
JS_FreeValue(js, not_focusable_val);
#undef SET_BOOL_PROP
@@ -154,7 +146,6 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, parent);
}
}
JS_FreeValue(js, parent_val);
// Create window with properties
SDL_Window *window = SDL_CreateWindowWithProperties(props);
@@ -201,7 +192,6 @@ static JSValue js_SDL_Window_constructor(JSContext *js, JSValueConst new_target,
if (JS_ToBool(js, text_input)) {
// SDL_StartTextInput(window);
}
JS_FreeValue(js, text_input);
JS_RETURN(window_obj);
}
@@ -627,7 +617,6 @@ JSValue js_window_updateSurfaceRects(JSContext *js, JSValue self, int argc, JSVa
JSValue val = JS_GetPropertyNumber(js, argv[0], i);
rect r = js2rect(js, val);
rects[i] = (SDL_Rect){r.x, r.y, r.w, r.h};
JS_FreeValue(js, val);
}
if (!SDL_UpdateWindowSurfaceRects(w, rects, len))
@@ -685,58 +674,58 @@ JSValue js_window_set(JSContext *js, JSValue self, int argc, JSValue *argv)
JSValue val;
val = JS_GetPropertyStr(js, obj, "title");
if (!JS_IsNull(val)) { js_window_set_title(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_title(js, self, val); }
val = JS_GetPropertyStr(js, obj, "size");
if (!JS_IsNull(val)) { js_window_set_size(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_size(js, self, val); }
val = JS_GetPropertyStr(js, obj, "position");
if (!JS_IsNull(val)) { js_window_set_position(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_position(js, self, val); }
val = JS_GetPropertyStr(js, obj, "mouseGrab");
if (!JS_IsNull(val)) { js_window_set_mouseGrab(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_mouseGrab(js, self, val); }
val = JS_GetPropertyStr(js, obj, "keyboardGrab");
if (!JS_IsNull(val)) { js_window_set_keyboardGrab(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_keyboardGrab(js, self, val); }
val = JS_GetPropertyStr(js, obj, "opacity");
if (!JS_IsNull(val)) { js_window_set_opacity(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_opacity(js, self, val); }
val = JS_GetPropertyStr(js, obj, "minimumSize");
if (!JS_IsNull(val)) { js_window_set_minimumSize(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_minimumSize(js, self, val); }
val = JS_GetPropertyStr(js, obj, "maximumSize");
if (!JS_IsNull(val)) { js_window_set_maximumSize(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_maximumSize(js, self, val); }
val = JS_GetPropertyStr(js, obj, "resizable");
if (!JS_IsNull(val)) { js_window_set_resizable(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_resizable(js, self, val); }
val = JS_GetPropertyStr(js, obj, "bordered");
if (!JS_IsNull(val)) { js_window_set_bordered(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_bordered(js, self, val); }
val = JS_GetPropertyStr(js, obj, "alwaysOnTop");
if (!JS_IsNull(val)) { js_window_set_alwaysOnTop(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_alwaysOnTop(js, self, val); }
val = JS_GetPropertyStr(js, obj, "fullscreen");
if (!JS_IsNull(val)) { js_window_set_fullscreen(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_fullscreen(js, self, val); }
val = JS_GetPropertyStr(js, obj, "focusable");
if (!JS_IsNull(val)) { js_window_set_focusable(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_focusable(js, self, val); }
val = JS_GetPropertyStr(js, obj, "modal");
if (!JS_IsNull(val)) { js_window_set_modal(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_modal(js, self, val); }
val = JS_GetPropertyStr(js, obj, "visible");
if (!JS_IsNull(val)) { js_window_set_visible(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_visible(js, self, val); }
val = JS_GetPropertyStr(js, obj, "minimized");
if (!JS_IsNull(val)) { js_window_set_minimized(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_minimized(js, self, val); }
val = JS_GetPropertyStr(js, obj, "maximized");
if (!JS_IsNull(val)) { js_window_set_maximized(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_maximized(js, self, val); }
val = JS_GetPropertyStr(js, obj, "parent");
if (!JS_IsNull(val)) { js_window_set_parent(js, self, val); JS_FreeValue(js, val); }
if (!JS_IsNull(val)) { js_window_set_parent(js, self, val); }
return JS_NULL;
}