diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gui/gui.zig | 41 |
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); |
