gskvulkanrenderer: Create imagevies and framebuffers

This commit is contained in:
Benjamin Otte 2016-11-30 02:08:17 +01:00
parent 5bea4ff45e
commit 3e59b11700

View File

@ -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);
}