diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c index 2f71dc0066..0e6a04bbbb 100644 --- a/gsk/gskvulkanrenderer.c +++ b/gsk/gskvulkanrenderer.c @@ -15,6 +15,14 @@ #include +typedef struct _GskVulkanTextureData GskVulkanTextureData; + +struct _GskVulkanTextureData { + GskTexture *texture; + GskVulkanImage *image; + GskVulkanRenderer *renderer; +}; + #ifdef G_ENABLE_DEBUG typedef struct { GQuark cpu_time; @@ -35,6 +43,8 @@ struct _GskVulkanRenderer GskVulkanRender *render; + GSList *textures; + #ifdef G_ENABLE_DEBUG ProfileTimers profile_timers; #endif @@ -133,6 +143,16 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer) { GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); VkDevice device; + GSList *l; + + for (l = self->textures; l; l = l->next) + { + GskVulkanTextureData *data = l->data; + + data->renderer = NULL; + gsk_texture_clear_render_data (data->texture); + } + g_clear_pointer (&self->textures, (GDestroyNotify) g_slist_free); g_clear_pointer (&self->render, gsk_vulkan_render_free); @@ -237,3 +257,56 @@ gsk_vulkan_renderer_init (GskVulkanRenderer *self) self->profile_timers.cpu_time = gsk_profiler_add_timer (profiler, "cpu-time", "CPU time", FALSE, TRUE); #endif } + +static void +gsk_vulkan_renderer_clear_texture (gpointer p) +{ + GskVulkanTextureData *data = p; + + if (data->renderer != NULL) + data->renderer->textures = g_slist_remove (data->renderer->textures, data); + + g_object_unref (data->image); + + g_slice_free (GskVulkanTextureData, data); +} + +GskVulkanImage * +gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self, + GskTexture *texture, + VkCommandBuffer command_buffer) +{ + GskVulkanTextureData *data; + cairo_surface_t *surface; + GskVulkanImage *image; + + data = gsk_texture_get_render_data (texture, self); + if (data) + return g_object_ref (data->image); + + surface = gsk_texture_download (texture); + image = gsk_vulkan_image_new_from_data (self->vulkan, + command_buffer, + cairo_image_surface_get_data (surface), + cairo_image_surface_get_width (surface), + cairo_image_surface_get_height (surface), + cairo_image_surface_get_stride (surface)); + cairo_surface_destroy (surface); + + data = g_slice_new0 (GskVulkanTextureData); + data->image = image; + data->texture = texture; + data->renderer = self; + + if (gsk_texture_set_render_data (texture, self, data, gsk_vulkan_renderer_clear_texture)) + { + g_object_ref (data->image); + self->textures = g_slist_prepend (self->textures, data); + } + else + { + g_slice_free (GskVulkanTextureData, data); + } + + return image; +} diff --git a/gsk/gskvulkanrendererprivate.h b/gsk/gskvulkanrendererprivate.h index a4a07f47cb..c3485f76b3 100644 --- a/gsk/gskvulkanrendererprivate.h +++ b/gsk/gskvulkanrendererprivate.h @@ -4,6 +4,8 @@ #include #include +#include "gsk/gskvulkanimageprivate.h" + G_BEGIN_DECLS #define GSK_TYPE_VULKAN_RENDERER (gsk_vulkan_renderer_get_type ()) @@ -19,6 +21,10 @@ typedef struct _GskVulkanRendererClass GskVulkanRendererClass; GType gsk_vulkan_renderer_get_type (void) G_GNUC_CONST; +GskVulkanImage * gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self, + GskTexture *texture, + VkCommandBuffer command_buffer); + G_END_DECLS #endif /* __GSK_VULKAN_RENDERER_PRIVATE_H__ */ diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index 8f9f12b213..1d493b152e 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -5,7 +5,7 @@ #include "gskvulkanimageprivate.h" #include "gskrendernodeprivate.h" #include "gskrenderer.h" -#include "gsktextureprivate.h" +#include "gskvulkanrendererprivate.h" typedef struct _GskVulkanRenderOp GskVulkanRenderOp; @@ -170,15 +170,10 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, case GSK_VULKAN_OP_TEXTURE: { - cairo_surface_t *surface = gsk_texture_download (gsk_render_node_get_texture (op->node)); - op->source = gsk_vulkan_image_new_from_data (self->vulkan, - command_buffer, - cairo_image_surface_get_data (surface), - cairo_image_surface_get_width (surface), - cairo_image_surface_get_height (surface), - cairo_image_surface_get_stride (surface)); + op->source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)), + gsk_render_node_get_texture (op->node), + command_buffer); gsk_vulkan_render_add_cleanup_image (render, op->source); - cairo_surface_destroy (surface); } break;