vulkan: Expose the swapchain images in public API

This commit is contained in:
Benjamin Otte 2016-11-30 00:54:48 +01:00
parent a753f047df
commit 325efe7078
2 changed files with 90 additions and 5 deletions

View File

@ -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

View File

@ -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 */