summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gui/gui.zig41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/gui/gui.zig b/src/gui/gui.zig
index 73f17a22..9d785b96 100644
--- a/src/gui/gui.zig
+++ b/src/gui/gui.zig
@@ -180,6 +180,12 @@ test "FreeType and HarfBuzz allocate from the gui allocator and give it all back
try std.testing.expectEqual(@as(u8, 2), shaped[4].span);
}
+/// What SDL allocates from, on its own threads as well as the render thread:
+/// the gui's gpa, through the shared C heap, which is thread-safe in every
+/// build. runNative hands everything back and calls SDL_Quit on the way out.
+var sdl_allocator: std.mem.Allocator = undefined;
+const sdl_heap = c_heap.Heap(&sdl_allocator);
+
const max_fallback_fonts = 1 + fonts.fallback_names.len;
const LoadedFallback = struct {
face: *c.UIFont,
@@ -2152,12 +2158,26 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options, attach: ?[]const u
else |_| {}
};
+ // SDL frees with whichever functions are current, so they go in before
+ // its first call, while nothing of SDL's exists yet.
+ sdl_allocator = gpa;
+ if (!c.SDL_SetMemoryFunctions(sdl_heap.malloc, sdl_heap.calloc, sdl_heap.realloc, sdl_heap.free)) {
+ log.err("SDL_SetMemoryFunctions: {s}", .{c.SDL_GetError()});
+ return error.SdlInit;
+ }
_ = c.SDL_SetHint("SDL_JOYSTICK_HIDAPI", "1"); // SDL_HINT_JOYSTICK_HIDAPI
_ = c.SDL_SetHint("SDL_JOYSTICK_HIDAPI_STEAMDECK", "1"); // ..._STEAMDECK
if (!c.SDL_Init(c.SDL_INIT_VIDEO | c.SDL_INIT_GAMEPAD)) {
log.err("SDL_Init: {s}", .{c.SDL_GetError()});
return error.SdlInit;
}
+ // SDL allocates from gpa (above), so what it still holds at exit is in a
+ // Debug build's leak report. The window, the GPU device and everything
+ // made on it go back first (the defers below run before this one). What
+ // is left is SDL 3.4.4's: its Vulkan backend never frees two 32-byte
+ // arrays per command buffer (VULKAN_INTERNAL_DestroyCommandPool; SDL's
+ // main branch frees them).
+ defer c.SDL_Quit();
var win_flags: c.SDL_WindowFlags = c.SDL_WINDOW_RESIZABLE;
if (!test_mode) win_flags |= c.SDL_WINDOW_HIGH_PIXEL_DENSITY;
// A test run renders to the capture texture; keep it off the desktop.
@@ -2171,6 +2191,7 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options, attach: ?[]const u
log.err("SDL_CreateWindow: {s}", .{c.SDL_GetError()});
return error.SdlInit;
};
+ defer c.SDL_DestroyWindow(window);
if (native_wayland) log.info("Wayland opacity: background-only transparent surface", .{});
const arrow_cursor = c.SDL_CreateCursor(&p9_arrow_set, &p9_arrow_mask, 16, 16, 1, 1);
defer if (arrow_cursor) |cursor| c.SDL_DestroyCursor(cursor);
@@ -2183,6 +2204,7 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options, attach: ?[]const u
log.err("SDL_CreateGPUDevice: {s}", .{c.SDL_GetError()});
return error.SdlInit;
};
+ defer c.SDL_DestroyGPUDevice(device);
var soft_present = false;
var soft_renderer: ?*c.SDL_Renderer = null;
const force_soft = if (env.get("PARDES_SOFT_PRESENT")) |raw|
@@ -2346,6 +2368,25 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options, attach: ?[]const u
.surface_opacity = surface_opacity,
.soft_renderer = soft_renderer,
};
+ // The pipelines, textures and buffers the Gui holds, whatever they were
+ // regrown to; the image ones are released below.
+ defer {
+ c.SDL_ReleaseGPUGraphicsPipeline(device, g.pipeline);
+ c.SDL_ReleaseGPUGraphicsPipeline(device, g.overlay_pipeline);
+ c.SDL_ReleaseGPUGraphicsPipeline(device, g.crt_pipeline);
+ c.SDL_ReleaseGPUTexture(device, g.atlas_tex);
+ c.SDL_ReleaseGPUSampler(device, g.atlas_sampler);
+ c.SDL_ReleaseGPUSampler(device, g.linear_sampler);
+ c.SDL_ReleaseGPUTransferBuffer(device, g.atlas_xfer);
+ c.SDL_ReleaseGPUBuffer(device, g.overlay_vbuf);
+ c.SDL_ReleaseGPUTransferBuffer(device, g.overlay_vxfer);
+ if (g.vbuf) |buffer| c.SDL_ReleaseGPUBuffer(device, buffer);
+ if (g.vxfer) |transfer| c.SDL_ReleaseGPUTransferBuffer(device, transfer);
+ if (g.scene_tex) |texture| c.SDL_ReleaseGPUTexture(device, texture);
+ if (g.capture_tex) |texture| c.SDL_ReleaseGPUTexture(device, texture);
+ if (g.capture_xfer) |transfer| c.SDL_ReleaseGPUTransferBuffer(device, transfer);
+ if (g.gamepad) |pad| c.SDL_CloseGamepad(pad);
+ }
setGuiFontName(&g, "Adwaita Mono");
loadFallbackFonts(&g, gpa);
defer deinitFallbackFonts(&g, gpa);