gpu: Actually ensure a downloadable dmabuf

For some formats, we could not download the dmabuf directly - in
particular YUV formats.
For those, do a copy on the GPU into the correct format.

While we're at it, also check the desired format and colorstate and if
they don't match, do the conversion on the GPU instead of using
gdk_memory_convert().
Reserve the CPU conversion for situations where the GPU doesn't support
the final format - like for example G8A8 (or often also RGB16).
This commit is contained in:
Benjamin Otte
2024-09-26 04:40:45 +02:00
parent 62c3923e5a
commit 6d3c333208
3 changed files with 105 additions and 0 deletions

View File

@@ -761,6 +761,27 @@ gsk_gpu_frame_download_texture (GskGpuFrame *self,
gsk_gpu_frame_cleanup (self);
if (gsk_gpu_image_get_format (image) != format ||
image_cs != color_state)
{
GskGpuImage *converted;
converted = gsk_gpu_node_processor_convert_image (self,
format,
color_state,
image,
image_cs);
if (converted == NULL)
{
g_critical ("Conversion into readable format failed");
g_object_unref (image);
return;
}
g_object_unref (image);
image = converted;
image_cs = color_state;
}
gsk_gpu_download_into_op (self,
image,
image_cs,

View File

@@ -4404,3 +4404,82 @@ gsk_gpu_node_processor_process (GskGpuFrame *frame,
cairo_region_destroy (clip);
}
GskGpuImage *
gsk_gpu_node_processor_convert_image (GskGpuFrame *frame,
GdkMemoryFormat target_format,
GdkColorState *target_color_state,
GskGpuImage *image,
GdkColorState *image_color_state)
{
GskGpuNodeProcessor self;
GskGpuImage *converted, *intermediate = NULL;
gsize width, height;
width = gsk_gpu_image_get_width (image);
height = gsk_gpu_image_get_height (image);
converted = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (frame),
FALSE,
target_format,
gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_SRGB,
width,
height);
if (converted == NULL)
return NULL;
/* We need to go via an intermediate colorstate */
if (!GDK_IS_DEFAULT_COLOR_STATE (image_color_state) &&
!GDK_IS_DEFAULT_COLOR_STATE (target_color_state))
{
GdkColorState *ccs = gdk_color_state_get_rendering_color_state (image_color_state);
intermediate = gsk_gpu_copy_image (frame, ccs, image, image_color_state, FALSE);
if (intermediate == NULL)
return NULL;
image = intermediate;
image_color_state = ccs;
}
gsk_gpu_node_processor_init (&self,
frame,
converted,
target_color_state,
&(cairo_rectangle_int_t) { 0, 0, width, height },
&GRAPHENE_RECT_INIT (0, 0, width, height));
gsk_gpu_render_pass_begin_op (frame,
converted,
&(cairo_rectangle_int_t) { 0, 0, width, height },
GSK_GPU_LOAD_OP_DONT_CARE,
NULL,
GSK_RENDER_PASS_OFFSCREEN);
gsk_gpu_node_processor_sync_globals (&self, 0);
if (GDK_IS_DEFAULT_COLOR_STATE (target_color_state))
{
gsk_gpu_node_processor_image_op (&self,
image,
image_color_state,
GSK_GPU_SAMPLER_DEFAULT,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_RECT_INIT (0, 0, width, height));
}
else
{
gsk_gpu_node_processor_convert_to (&self,
image,
image_color_state,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_RECT_INIT (0, 0, width, height));
}
gsk_gpu_render_pass_end_op (self.frame,
converted,
GSK_RENDER_PASS_OFFSCREEN);
gsk_gpu_node_processor_finish (&self);
g_clear_object (&intermediate);
return converted;
}

View File

@@ -12,5 +12,10 @@ void gsk_gpu_node_processor_process (GskGpuF
GskRenderNode *node,
const graphene_rect_t *viewport,
GskRenderPassType pass_type);
GskGpuImage * gsk_gpu_node_processor_convert_image (GskGpuFrame *frame,
GdkMemoryFormat target_format,
GdkColorState *target_color_state,
GskGpuImage *image,
GdkColorState *image_color_state);
G_END_DECLS