diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c index 32fefcd548..f51806fd14 100644 --- a/gsk/gskvulkanrenderer.c +++ b/gsk/gskvulkanrenderer.c @@ -8,6 +8,8 @@ #include "gskrendernodeprivate.h" #include "gsktextureprivate.h" +typedef struct _GskVulkanTarget GskVulkanTarget; + #ifdef G_ENABLE_DEBUG typedef struct { GQuark cpu_time; @@ -20,6 +22,11 @@ struct _GskVulkanRenderer GskRenderer parent_instance; GdkVulkanContext *vulkan; + + guint n_targets; + GskVulkanTarget **targets; + VkRenderPass render_pass; + #ifdef G_ENABLE_DEBUG ProfileTimers profile_timers; #endif @@ -32,10 +39,132 @@ struct _GskVulkanRendererClass G_DEFINE_TYPE (GskVulkanRenderer, gsk_vulkan_renderer, GSK_TYPE_RENDERER) +struct _GskVulkanTarget { + VkImage image; + VkImageView image_view; + VkFramebuffer framebuffer; +}; + +static inline VkResult +gsk_vulkan_handle_result (VkResult res, + const char *called_function) +{ + if (res != VK_SUCCESS) + { + GSK_NOTE (VULKAN,g_printerr ("%s(): %s (%d)\n", called_function, gdk_vulkan_strerror (res), res)); + } + return res; +} + +#define GSK_VK_CHECK(func, ...) gsk_vulkan_handle_result (func (__VA_ARGS__), G_STRINGIFY (func)) + +static GskVulkanTarget * +gsk_vulkan_target_new_for_image (GskVulkanRenderer *self, + VkImage image) +{ + GskVulkanTarget *target; + GdkWindow *window; + VkDevice device; + + device = gdk_vulkan_context_get_device (self->vulkan); + window = gdk_draw_context_get_window (GDK_DRAW_CONTEXT (self->vulkan)); + + target = g_slice_new0 (GskVulkanTarget); + + target->image = image; + + GSK_VK_CHECK (vkCreateImageView, device, + &(VkImageViewCreateInfo) { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = target->image, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = gdk_vulkan_context_get_image_format (self->vulkan), + .components = { + .r = VK_COMPONENT_SWIZZLE_R, + .g = VK_COMPONENT_SWIZZLE_G, + .b = VK_COMPONENT_SWIZZLE_B, + .a = VK_COMPONENT_SWIZZLE_A, + }, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }, + NULL, + &target->image_view); + GSK_VK_CHECK (vkCreateFramebuffer, device, + &(VkFramebufferCreateInfo) { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .renderPass = self->render_pass, + .attachmentCount = 1, + .pAttachments = &target->image_view, + .width = gdk_window_get_width (window), + .height = gdk_window_get_height (window), + .layers = 1 + }, + NULL, + &target->framebuffer); + + return target; +} + +static void +gsk_vulkan_target_free (GskVulkanRenderer *self, + GskVulkanTarget *target) +{ + VkDevice device; + + device = gdk_vulkan_context_get_device (self->vulkan); + + vkDestroyFramebuffer (device, + target->framebuffer, + NULL); + vkDestroyImageView (device, + target->image_view, + NULL); + + g_slice_free (GskVulkanTarget, target); +} + +static void +gsk_vulkan_renderer_free_targets (GskVulkanRenderer *self) +{ + guint i; + + for (i = 0; i < self->n_targets; i++) + { + gsk_vulkan_target_free (self, self->targets[i]); + } + + g_clear_pointer (&self->targets, g_free); + self->n_targets = 0; +} + +static void +gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context, + GskVulkanRenderer *self) +{ + guint i; + + gsk_vulkan_renderer_free_targets (self); + + self->n_targets = gdk_vulkan_context_get_n_images (context); + self->targets = g_new (GskVulkanTarget *, self->n_targets); + + for (i = 0; i < self->n_targets; i++) + { + self->targets[i] = gsk_vulkan_target_new_for_image (self, + gdk_vulkan_context_get_image (context, i)); + } +} + static gboolean gsk_vulkan_renderer_realize (GskRenderer *renderer, - GdkWindow *window, - GError **error) + GdkWindow *window, + GError **error) { GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); @@ -43,6 +172,12 @@ gsk_vulkan_renderer_realize (GskRenderer *renderer, if (self->vulkan == NULL) return FALSE; + g_signal_connect (self->vulkan, + "images-updated", + G_CALLBACK (gsk_vulkan_renderer_update_images_cb), + self); + gsk_vulkan_renderer_update_images_cb (self->vulkan, self); + return TRUE; } @@ -51,6 +186,10 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer) { GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); + gsk_vulkan_renderer_free_targets (self); + g_signal_handlers_disconnect_by_func(self->vulkan, + gsk_vulkan_renderer_update_images_cb, + self); g_clear_object (&self->vulkan); }