Compare commits

...

2 Commits

Author SHA1 Message Date
Georges Basile Stavracas Neto
bfb96bb23a gdk/vulkancontext: Don't create swapchain upfront
We now create and destroy swapchains and surfaces as needed, so no
need to create the swapchain when initializing the context.
2023-04-09 15:20:09 -03:00
Georges Basile Stavracas Neto
dbb6b81081 gdk/vulkancontext: Recreate swapchain when mapping surface
Right now, we create a VkSurface from either an X11 window, or a
Wayland wl_surface, when creating the GdkVulkanContext from a
GdkSurface.

That works when initially creating it, however, these days, hiding
a GdkSurface may destroy the wl_surface or X window too. Sadly,
GdkVulkanContext doesn't react to that, and keeps using the same
VkSurface that now points to a non-existent object.

Connect to the surface's 'notify::mapped' signal, and either destroy
the VkSurface and VkSwapchain when the surface is unmapped, or
recreate them when the surface is mapped. This ensures the VkSurface
is always pointing to a valid native surface.

Future commits may reorganize how it all fits together, but at the
very least, this commit allows us to use and test the Vulkan renderer
without crashing too often.
2023-04-09 15:19:56 -03:00

View File

@@ -424,6 +424,49 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context,
return res == VK_SUCCESS;
}
static void
surface_mapped_changed_cb (GdkSurface *surface,
GParamSpec *pspec,
GdkVulkanContext *self)
{
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (self);
if (GDK_SURFACE_IS_MAPPED (surface) && priv->swapchain == VK_NULL_HANDLE)
{
GError *error = NULL;
VkResult res;
res = GDK_VULKAN_CONTEXT_GET_CLASS (self)->create_surface (self, &priv->surface);
if (res != VK_SUCCESS)
return;
if (!gdk_vulkan_context_check_swapchain (self, &error))
{
g_warning ("%s", error->message);
g_error_free (error);
return;
}
}
else if (!GDK_SURFACE_IS_MAPPED (surface))
{
if (priv->swapchain != VK_NULL_HANDLE)
{
vkDestroySwapchainKHR (gdk_vulkan_context_get_device (self),
priv->swapchain,
NULL);
priv->swapchain = VK_NULL_HANDLE;
}
if (priv->surface != VK_NULL_HANDLE)
{
vkDestroySurfaceKHR (gdk_vulkan_context_get_instance (self),
priv->surface,
NULL);
priv->surface = VK_NULL_HANDLE;
}
}
}
static gboolean
device_supports_incremental_present (VkPhysicalDevice device)
{
@@ -645,9 +688,6 @@ gdk_vulkan_context_real_init (GInitable *initable,
priv->image_format = formats[i];
priv->has_present_region = device_supports_incremental_present (display->vk_physical_device);
if (!gdk_vulkan_context_check_swapchain (context, error))
goto out_surface;
GDK_VK_CHECK (vkCreateSemaphore, gdk_vulkan_context_get_device (context),
&(VkSemaphoreCreateInfo) {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
@@ -655,6 +695,12 @@ gdk_vulkan_context_real_init (GInitable *initable,
NULL,
&priv->draw_semaphore);
g_signal_connect_object (gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context)),
"notify::mapped",
G_CALLBACK (surface_mapped_changed_cb),
context, 0);
return TRUE;
}