From 325efe707827d0e0f11d849e950930537bf7f1fb Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 30 Nov 2016 00:54:48 +0100 Subject: vulkan: Expose the swapchain images in public API --- gdk/gdkvulkancontext.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++--- gdk/gdkvulkancontext.h | 5 +++ 2 files changed, 90 insertions(+), 5 deletions(-) diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index af485b4e79..03cbbfecd7 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -36,10 +36,21 @@ struct _GdkVulkanContextPrivate { int swapchain_width, swapchain_height; VkSwapchainKHR swapchain; + + guint n_images; + VkImage *images; +}; + +enum { + IMAGES_UPDATED, + + LAST_SIGNAL }; G_DEFINE_QUARK (gdk-vulkan-error-quark, gdk_vulkan_error) +static guint signals[LAST_SIGNAL] = { 0 }; + static void gdk_vulkan_context_initable_init (GInitableIface *iface); G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkVulkanContext, gdk_vulkan_context, GDK_TYPE_DRAW_CONTEXT, @@ -111,6 +122,9 @@ gdk_vulkan_context_dispose (GObject *gobject) GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context); GdkDisplay *display; + g_clear_pointer (&priv->images, g_free); + priv->n_images = 0; + if (priv->swapchain != VK_NULL_HANDLE) { vkDestroySwapchainKHR (gdk_vulkan_context_get_device (context), @@ -141,6 +155,23 @@ gdk_vulkan_context_class_init (GdkVulkanContextClass *klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->dispose = gdk_vulkan_context_dispose; + + /** + * GdkVulkanContext::images-updated: + * @context: the object on which the signal is emitted + * + * This signal is emitted when the images managed by this context have + * changed. Usually this means that the swapchain had to be recreated, + * for example in response to a change of the window size. + */ + signals[IMAGES_UPDATED] = + g_signal_new (g_intern_static_string ("images-updated"), + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void @@ -158,11 +189,14 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context, VkCompositeAlphaFlagBitsKHR composite_alpha; VkSwapchainKHR new_swapchain; VkResult res; + VkDevice device; if (gdk_window_get_width (window) == priv->swapchain_width && gdk_window_get_height (window) == priv->swapchain_height) return TRUE; + device = gdk_vulkan_context_get_device (context); + res = GDK_VK_CHECK (vkGetPhysicalDeviceSurfaceCapabilitiesKHR, gdk_vulkan_context_get_physical_device (context), priv->surface, &capabilities); @@ -188,7 +222,7 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context, composite_alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; } - res = GDK_VK_CHECK (vkCreateSwapchainKHR, gdk_vulkan_context_get_device (context), + res = GDK_VK_CHECK (vkCreateSwapchainKHR, device, &(VkSwapchainCreateInfoKHR) { .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, .pNext = NULL, @@ -215,15 +249,29 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context, &new_swapchain); if (priv->swapchain != VK_NULL_HANDLE) - vkDestroySwapchainKHR (gdk_vulkan_context_get_device (context), - priv->swapchain, - NULL); + { + vkDestroySwapchainKHR (device, + priv->swapchain, + NULL); + g_clear_pointer (&priv->images, g_free); + priv->n_images = 0; + } if (res == VK_SUCCESS) { priv->swapchain_width = gdk_window_get_width (window); priv->swapchain_height = gdk_window_get_height (window); priv->swapchain = new_swapchain; + + GDK_VK_CHECK (vkGetSwapchainImagesKHR, device, + priv->swapchain, + &priv->n_images, + NULL); + priv->images = g_new (VkImage, priv->n_images); + GDK_VK_CHECK (vkGetSwapchainImagesKHR, device, + priv->swapchain, + &priv->n_images, + priv->images); } else { @@ -235,7 +283,9 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context, return FALSE; } - return TRUE; + g_signal_emit (context, signals[IMAGES_UPDATED], 0); + + return res == VK_SUCCESS; } static gboolean @@ -367,6 +417,28 @@ gdk_vulkan_context_get_image_format (GdkVulkanContext *context) return priv->image_format.format; } +guint +gdk_vulkan_context_get_n_images (GdkVulkanContext *context) +{ + GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context); + + g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), 0); + + return priv->n_images; +} + +VkImage +gdk_vulkan_context_get_image (GdkVulkanContext *context, + guint id) +{ + GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context); + + g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), VK_NULL_HANDLE); + g_return_val_if_fail (id < priv->n_images, VK_NULL_HANDLE); + + return priv->images[id]; +} + static gboolean gdk_display_create_vulkan_device (GdkDisplay *display, GError **error) @@ -672,6 +744,14 @@ gdk_display_unref_vulkan (GdkDisplay *display) static void gdk_vulkan_context_class_init (GdkVulkanContextClass *klass) { + signals[IMAGES_UPDATED] = + g_signal_new (g_intern_static_string ("images-updated"), + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void diff --git a/gdk/gdkvulkancontext.h b/gdk/gdkvulkancontext.h index d4b078903b..2690048e85 100644 --- a/gdk/gdkvulkancontext.h +++ b/gdk/gdkvulkancontext.h @@ -63,6 +63,11 @@ GDK_AVAILABLE_IN_3_90 uint32_t gdk_vulkan_context_get_queue_family_index (GdkVulkanContext *context); GDK_AVAILABLE_IN_3_90 VkFormat gdk_vulkan_context_get_image_format (GdkVulkanContext *context); +GDK_AVAILABLE_IN_3_90 +guint gdk_vulkan_context_get_n_images (GdkVulkanContext *context); +GDK_AVAILABLE_IN_3_90 +VkImage gdk_vulkan_context_get_image (GdkVulkanContext *context, + guint id); #endif /* GDK_WINDOWING_VULKAN */ -- cgit v1.2.1