gpu: Add a gsk_gpu_download_into_op()
... and use it for the dmabuf downloader Splits the download op into 2 separate ops: One for downloading textures and one for downloading into preallocated memory. The download into memory is the fallback for the texture downloading op, so they need to share code. But keeping them separate ensures that the different codepaths for dmabuf download and render_texture() don't get mixed up in weird ways that potentially call into each other. By passing the emory down into the op we can also avoid an extra memcpy which can lead to quite large speedups for big textures.
This commit is contained in:
@@ -37,10 +37,8 @@ struct _GskGpuDownloadOp
|
||||
GdkColorState *color_state;
|
||||
gboolean allow_dmabuf;
|
||||
GdkGpuDownloadOpCreateFunc create_func;
|
||||
GskGpuDownloadFunc func;
|
||||
gpointer user_data;
|
||||
GdkTexture **texture;
|
||||
|
||||
GdkTexture *texture;
|
||||
GskGpuBuffer *buffer;
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
VkSemaphore vk_semaphore;
|
||||
@@ -55,9 +53,6 @@ gsk_gpu_download_op_finish (GskGpuOp *op)
|
||||
if (self->create_func)
|
||||
self->create_func (self);
|
||||
|
||||
self->func (self->user_data, self->texture);
|
||||
|
||||
g_object_unref (self->texture);
|
||||
g_object_unref (self->image);
|
||||
g_clear_object (&self->buffer);
|
||||
}
|
||||
@@ -160,8 +155,8 @@ gsk_gpu_download_op_vk_sync_semaphore (GskGpuDownloadOp *self)
|
||||
int fd, sync_file_fd;
|
||||
|
||||
/* Don't look at where I store my variables plz */
|
||||
display = gdk_dmabuf_texture_get_display (GDK_DMABUF_TEXTURE (self->texture));
|
||||
fd = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (self->texture))->planes[0].fd;
|
||||
display = gdk_dmabuf_texture_get_display (GDK_DMABUF_TEXTURE (*self->texture));
|
||||
fd = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (*self->texture))->planes[0].fd;
|
||||
func_vkGetSemaphoreFdKHR = (PFN_vkGetSemaphoreFdKHR) vkGetDeviceProcAddr (display->vk_device, "vkGetSemaphoreFdKHR");
|
||||
|
||||
/* vkGetSemaphoreFdKHR implicitly resets the semaphore.
|
||||
@@ -206,7 +201,7 @@ gsk_gpu_download_op_vk_create (GskGpuDownloadOp *self)
|
||||
gdk_memory_texture_builder_set_bytes (builder, bytes);
|
||||
gdk_memory_texture_builder_set_stride (builder, stride);
|
||||
gdk_memory_texture_builder_set_color_state (builder, self->color_state);
|
||||
self->texture = gdk_memory_texture_builder_build (builder);
|
||||
*self->texture = gdk_memory_texture_builder_build (builder);
|
||||
|
||||
g_object_unref (builder);
|
||||
g_bytes_unref (bytes);
|
||||
@@ -219,19 +214,18 @@ gsk_gpu_download_op_vk_command (GskGpuOp *op,
|
||||
GskVulkanCommandState *state)
|
||||
{
|
||||
GskGpuDownloadOp *self = (GskGpuDownloadOp *) op;
|
||||
gsize width, height, stride;
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
if (self->allow_dmabuf)
|
||||
self->texture = gsk_vulkan_image_to_dmabuf_texture (GSK_VULKAN_IMAGE (self->image),
|
||||
*self->texture = gsk_vulkan_image_to_dmabuf_texture (GSK_VULKAN_IMAGE (self->image),
|
||||
self->color_state);
|
||||
if (self->texture)
|
||||
if (*self->texture)
|
||||
{
|
||||
GskGpuDevice *device = gsk_gpu_frame_get_device (frame);
|
||||
GskGpuCache *cache = gsk_gpu_device_get_cache (device);
|
||||
VkDevice vk_device = gsk_vulkan_device_get_vk_device (GSK_VULKAN_DEVICE (device));
|
||||
|
||||
gsk_gpu_cache_cache_texture_image (cache, self->texture, self->image, NULL);
|
||||
gsk_gpu_cache_cache_texture_image (cache, *self->texture, self->image, NULL);
|
||||
|
||||
if (gsk_vulkan_device_has_feature (GSK_VULKAN_DEVICE (device), GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT))
|
||||
{
|
||||
@@ -339,11 +333,11 @@ gsk_gpu_download_op_gl_command (GskGpuOp *op,
|
||||
gdk_dmabuf_texture_builder_set_height (db, gsk_gpu_image_get_height (self->image));
|
||||
gdk_dmabuf_texture_builder_set_color_state (db, self->color_state);
|
||||
|
||||
self->texture = gdk_dmabuf_texture_builder_build (db, release_dmabuf_texture, texture, NULL);
|
||||
*self->texture = gdk_dmabuf_texture_builder_build (db, release_dmabuf_texture, texture, NULL);
|
||||
|
||||
g_object_unref (db);
|
||||
|
||||
if (self->texture)
|
||||
if (*self->texture)
|
||||
return op->next;
|
||||
|
||||
gdk_dmabuf_close_fds (&texture->dmabuf);
|
||||
@@ -369,11 +363,11 @@ gsk_gpu_download_op_gl_command (GskGpuOp *op,
|
||||
gdk_gl_texture_builder_set_height (builder, gsk_gpu_image_get_height (self->image));
|
||||
gdk_gl_texture_builder_set_sync (builder, data->sync);
|
||||
|
||||
self->texture = gdk_gl_texture_builder_build (builder,
|
||||
gsk_gl_texture_data_free,
|
||||
data);
|
||||
*self->texture = gdk_gl_texture_builder_build (builder,
|
||||
gsk_gl_texture_data_free,
|
||||
data);
|
||||
|
||||
gsk_gpu_image_toggle_ref_texture (self->image, self->texture);
|
||||
gsk_gpu_image_toggle_ref_texture (self->image, *self->texture);
|
||||
gsk_gl_image_steal_texture_ownership (GSK_GL_IMAGE (self->image));
|
||||
|
||||
g_object_unref (builder);
|
||||
@@ -396,17 +390,158 @@ void
|
||||
gsk_gpu_download_op (GskGpuFrame *frame,
|
||||
GskGpuImage *image,
|
||||
GdkColorState *color_state,
|
||||
gboolean allow_dmabuf,
|
||||
GskGpuDownloadFunc func,
|
||||
gpointer user_data)
|
||||
GdkTexture **out_texture)
|
||||
{
|
||||
GskGpuDownloadOp *self;
|
||||
|
||||
g_assert (out_texture != NULL && *out_texture == NULL);
|
||||
|
||||
self = (GskGpuDownloadOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_DOWNLOAD_OP_CLASS);
|
||||
|
||||
self->image = g_object_ref (image);
|
||||
self->color_state = gdk_color_state_ref (color_state);
|
||||
self->allow_dmabuf = allow_dmabuf;
|
||||
self->func = func,
|
||||
self->user_data = user_data;
|
||||
self->texture = out_texture;
|
||||
}
|
||||
|
||||
typedef struct _GskGpuDownloadIntoOp GskGpuDownloadIntoOp;
|
||||
|
||||
typedef void (* GdkGpuDownloadIntoOpCreateFunc) (GskGpuDownloadIntoOp *);
|
||||
|
||||
struct _GskGpuDownloadIntoOp
|
||||
{
|
||||
GskGpuOp op;
|
||||
|
||||
GdkGpuDownloadIntoOpCreateFunc create_func;
|
||||
GskGpuBuffer *buffer;
|
||||
|
||||
GskGpuImage *image;
|
||||
GdkColorState *image_color_state;
|
||||
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_gpu_download_into_op_finish (GskGpuOp *op)
|
||||
{
|
||||
GskGpuDownloadIntoOp *self = (GskGpuDownloadIntoOp *) op;
|
||||
|
||||
if (self->create_func)
|
||||
self->create_func (self);
|
||||
|
||||
g_object_unref (self->image);
|
||||
gdk_color_state_unref (self->image_color_state);
|
||||
gdk_color_state_unref (self->color_state);
|
||||
g_clear_object (&self->buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_download_into_op_print (GskGpuOp *op,
|
||||
GskGpuFrame *frame,
|
||||
GString *string,
|
||||
guint indent)
|
||||
{
|
||||
GskGpuDownloadIntoOp *self = (GskGpuDownloadIntoOp *) op;
|
||||
|
||||
gsk_gpu_print_op (string, indent, "download-into");
|
||||
gsk_gpu_print_image (string, self->image);
|
||||
g_string_append_printf (string, "%s ", gdk_color_state_get_name (self->image_color_state));
|
||||
g_string_append_printf (string, "%s ", gdk_memory_format_get_name (self->format));
|
||||
g_string_append_printf (string, "%s ", gdk_color_state_get_name (self->color_state));
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
static void
|
||||
gsk_gpu_download_into_op_vk_create (GskGpuDownloadIntoOp *self)
|
||||
{
|
||||
guchar *data;
|
||||
GdkMemoryFormat format;
|
||||
gsize width, height;
|
||||
|
||||
data = gsk_gpu_buffer_map (self->buffer);
|
||||
format = gsk_gpu_image_get_format (self->image);
|
||||
width = gsk_gpu_image_get_width (self->image);
|
||||
height = gsk_gpu_image_get_height (self->image);
|
||||
|
||||
gdk_memory_convert (self->data,
|
||||
self->stride,
|
||||
self->format,
|
||||
self->color_state,
|
||||
data,
|
||||
width * gdk_memory_format_bytes_per_pixel (format),
|
||||
format,
|
||||
self->image_color_state,
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
static GskGpuOp *
|
||||
gsk_gpu_download_into_op_vk_command (GskGpuOp *op,
|
||||
GskGpuFrame *frame,
|
||||
GskVulkanCommandState *state)
|
||||
{
|
||||
GskGpuDownloadIntoOp *self = (GskGpuDownloadIntoOp *) op;
|
||||
|
||||
self->buffer = gsk_gpu_download_vk_start (frame, state, self->image);
|
||||
self->create_func = gsk_gpu_download_into_op_vk_create;
|
||||
|
||||
return op->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
static GskGpuOp *
|
||||
gsk_gpu_download_into_op_gl_command (GskGpuOp *op,
|
||||
GskGpuFrame *frame,
|
||||
GskGLCommandState *state)
|
||||
{
|
||||
GskGpuDownloadIntoOp *self = (GskGpuDownloadIntoOp *) op;
|
||||
|
||||
gdk_gl_context_download (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
|
||||
gsk_gl_image_get_texture_id (GSK_GL_IMAGE (self->image)),
|
||||
gsk_gpu_image_get_format (self->image),
|
||||
self->image_color_state,
|
||||
self->data,
|
||||
self->stride,
|
||||
self->format,
|
||||
self->color_state,
|
||||
gsk_gpu_image_get_width (self->image),
|
||||
gsk_gpu_image_get_height (self->image));
|
||||
|
||||
return op->next;
|
||||
}
|
||||
|
||||
static const GskGpuOpClass GSK_GPU_DOWNLOAD_INTO_OP_CLASS = {
|
||||
GSK_GPU_OP_SIZE (GskGpuDownloadIntoOp),
|
||||
GSK_GPU_STAGE_COMMAND,
|
||||
gsk_gpu_download_into_op_finish,
|
||||
gsk_gpu_download_into_op_print,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
gsk_gpu_download_into_op_vk_command,
|
||||
#endif
|
||||
gsk_gpu_download_into_op_gl_command
|
||||
};
|
||||
|
||||
void
|
||||
gsk_gpu_download_into_op (GskGpuFrame *frame,
|
||||
GskGpuImage *image,
|
||||
GdkColorState *image_color_state,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GskGpuDownloadIntoOp *self;
|
||||
|
||||
self = (GskGpuDownloadIntoOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_DOWNLOAD_INTO_OP_CLASS);
|
||||
|
||||
self->image = g_object_ref (image);
|
||||
self->image_color_state = gdk_color_state_ref (image_color_state);
|
||||
self->format = format;
|
||||
self->color_state = gdk_color_state_ref (color_state);
|
||||
self->data = data;
|
||||
self->stride = stride;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,15 +4,17 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef void (* GskGpuDownloadFunc) (gpointer user_data,
|
||||
GdkTexture *texture);
|
||||
|
||||
void gsk_gpu_download_op (GskGpuFrame *frame,
|
||||
GskGpuImage *image,
|
||||
GdkColorState *color_state,
|
||||
gboolean allow_dmabuf,
|
||||
GskGpuDownloadFunc func,
|
||||
gpointer user_data);
|
||||
GdkTexture **out_texture);
|
||||
void gsk_gpu_download_into_op (GskGpuFrame *frame,
|
||||
GskGpuImage *image,
|
||||
GdkColorState *image_color_state,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -651,15 +651,6 @@ gsk_gpu_frame_wait (GskGpuFrame *self)
|
||||
gsk_gpu_frame_cleanup (self);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_texture (gpointer user_data,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
GdkTexture **target = (GdkTexture **) user_data;
|
||||
|
||||
*target = g_object_ref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_frame_record (GskGpuFrame *self,
|
||||
gint64 timestamp,
|
||||
@@ -679,7 +670,7 @@ gsk_gpu_frame_record (GskGpuFrame *self,
|
||||
gsk_gpu_node_processor_process (self, target, target_color_state, clip, node, viewport, pass_type);
|
||||
|
||||
if (texture)
|
||||
gsk_gpu_download_op (self, target, target_color_state, TRUE, copy_texture, texture);
|
||||
gsk_gpu_download_op (self, target, target_color_state, texture);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -732,32 +723,6 @@ gsk_gpu_frame_render (GskGpuFrame *self,
|
||||
gsk_gpu_frame_submit (self, pass_type);
|
||||
}
|
||||
|
||||
typedef struct _Download Download;
|
||||
|
||||
struct _Download
|
||||
{
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
};
|
||||
|
||||
static void
|
||||
do_download (gpointer user_data,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
Download *download = user_data;
|
||||
GdkTextureDownloader downloader;
|
||||
|
||||
gdk_texture_downloader_init (&downloader, texture);
|
||||
gdk_texture_downloader_set_format (&downloader, download->format);
|
||||
gdk_texture_downloader_set_color_state (&downloader, download->color_state);
|
||||
gdk_texture_downloader_download_into (&downloader, download->data, download->stride);
|
||||
gdk_texture_downloader_finish (&downloader);
|
||||
|
||||
g_free (download);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_frame_download_texture (GskGpuFrame *self,
|
||||
gint64 timestamp,
|
||||
@@ -785,17 +750,13 @@ gsk_gpu_frame_download_texture (GskGpuFrame *self,
|
||||
|
||||
gsk_gpu_frame_cleanup (self);
|
||||
|
||||
gsk_gpu_download_op (self,
|
||||
image,
|
||||
gdk_texture_get_color_state (texture),
|
||||
FALSE,
|
||||
do_download,
|
||||
g_memdup2 (&(Download) {
|
||||
.format = format,
|
||||
.color_state = color_state,
|
||||
.data = data,
|
||||
.stride = stride
|
||||
}, sizeof (Download)));
|
||||
gsk_gpu_download_into_op (self,
|
||||
image,
|
||||
gdk_texture_get_color_state (texture),
|
||||
format,
|
||||
color_state,
|
||||
data,
|
||||
stride);
|
||||
|
||||
gsk_gpu_frame_submit (self, GSK_RENDER_PASS_EXPORT);
|
||||
g_object_unref (image);
|
||||
|
||||
Reference in New Issue
Block a user