feat(window): a destructor for the native backends
A Window could be created but never destroyed: the constructor's command buffers, semaphores, fences, swapchain and Vulkan surface, and on Wayland the viewport, fractional scale, decoration, xdg toplevel, xdg surface and wl_surface stayed alive, and Device::windows kept a dangling pointer the pointer listeners still compared against. An app that hides its window and shows it again — a resident messaging app closing to a notification — needs the window to go for real. The destructor waits for the device, frees and destroys the Vulkan objects in dependency order (the swapchain before the surface), releases the Wayland objects from the cursor down to the wl_surface, flushes, and removes the window from Device::windows and the focus pointers. The decoration object the constructor used to leak is a member now. The frame callback member is left alone: wl_surface_frame_done destroys the callback it is handed and re-arms through its own local, so the member may name a freed one.
This commit is contained in:
parent
bfc5e108e5
commit
b412640fac
2 changed files with 55 additions and 5 deletions
|
|
@ -299,7 +299,7 @@ Window::Window(std::uint32_t width, std::uint32_t height) : width(width), height
|
|||
|
||||
wl_surface_commit(surface);
|
||||
|
||||
zxdg_toplevel_decoration_v1* decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(Device::manager, xdgToplevel);
|
||||
decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(Device::manager, xdgToplevel);
|
||||
zxdg_toplevel_decoration_v1_set_mode(decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||
|
||||
wpViewport = wp_viewporter_get_viewport(Device::wpViewporter, surface);
|
||||
|
|
@ -515,6 +515,52 @@ Window::Window(std::uint32_t width, std::uint32_t height) : width(width), height
|
|||
currentMousePos = {0,0};
|
||||
}
|
||||
|
||||
#ifndef CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
Window::~Window() {
|
||||
// Nothing may still run against the semaphores, fences or images below.
|
||||
if (Device::device != VK_NULL_HANDLE) vkDeviceWaitIdle(Device::device);
|
||||
if (Device::device != VK_NULL_HANDLE) {
|
||||
vkFreeCommandBuffers(Device::device, Device::commandPool, numFrames, drawCmdBuffers);
|
||||
for (std::uint8_t i = 0; i < numFrames; i++) {
|
||||
if (renderFinishedSemaphores[i]) vkDestroySemaphore(Device::device, renderFinishedSemaphores[i], nullptr);
|
||||
if (waitFences[i]) vkDestroyFence(Device::device, waitFences[i], nullptr);
|
||||
}
|
||||
for (std::uint8_t i = 0; i < numAcquireSemaphores; i++) {
|
||||
if (imageAcquiredSemaphores[i]) vkDestroySemaphore(Device::device, imageAcquiredSemaphores[i], nullptr);
|
||||
}
|
||||
if (swapChain != VK_NULL_HANDLE) vkDestroySwapchainKHR(Device::device, swapChain, nullptr);
|
||||
swapChain = VK_NULL_HANDLE;
|
||||
}
|
||||
if (vulkanSurface != VK_NULL_HANDLE) vkDestroySurfaceKHR(Device::instance, vulkanSurface, nullptr);
|
||||
vulkanSurface = VK_NULL_HANDLE;
|
||||
|
||||
#ifdef CRAFTER_GRAPHICS_WINDOW_WAYLAND
|
||||
SetDefaultCursor();
|
||||
// `cb` is not destroyed here: wl_surface_frame_done frees the callback it
|
||||
// was called with and re-arms through its own local, so the member may
|
||||
// already name a freed one.
|
||||
if (wpViewport) wp_viewport_destroy(wpViewport);
|
||||
if (wp_scale) {
|
||||
wp_fractional_scale_v1_destroy(wp_scale);
|
||||
wp_scale = nullptr;
|
||||
}
|
||||
if (decoration) zxdg_toplevel_decoration_v1_destroy(decoration);
|
||||
if (xdgToplevel) xdg_toplevel_destroy(xdgToplevel);
|
||||
if (xdgSurface) xdg_surface_destroy(xdgSurface);
|
||||
if (surface) wl_surface_destroy(surface);
|
||||
wpViewport = nullptr;
|
||||
decoration = nullptr;
|
||||
xdgToplevel = nullptr;
|
||||
xdgSurface = nullptr;
|
||||
surface = nullptr;
|
||||
wl_display_flush(Device::display);
|
||||
std::erase(Device::windows, this);
|
||||
if (Device::focusedWindow == this) Device::focusedWindow = nullptr;
|
||||
if (Device::keyboardWindow == this) Device::keyboardWindow = nullptr;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void Window::Resize(std::uint32_t newWidth, std::uint32_t newHeight) {
|
||||
// Skip degenerate resizes. Win32 minimised windows give (0, 0); Wayland
|
||||
// sometimes echoes the current size in a configure.
|
||||
|
|
|
|||
Loading…
Reference in a new issue