From 6d3c3332087f19fd425f00248410dfb1e86994a6 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 26 Sep 2024 04:40:45 +0200 Subject: [PATCH] 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). --- gsk/gpu/gskgpuframe.c | 21 ++++++++ gsk/gpu/gskgpunodeprocessor.c | 79 ++++++++++++++++++++++++++++ gsk/gpu/gskgpunodeprocessorprivate.h | 5 ++ 3 files changed, 105 insertions(+) diff --git a/gsk/gpu/gskgpuframe.c b/gsk/gpu/gskgpuframe.c index 529295eec6..4d91ae700c 100644 --- a/gsk/gpu/gskgpuframe.c +++ b/gsk/gpu/gskgpuframe.c @@ -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, diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index f241606dac..aba78cef82 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -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; +} + diff --git a/gsk/gpu/gskgpunodeprocessorprivate.h b/gsk/gpu/gskgpunodeprocessorprivate.h index 26bde2f266..04e715f3d2 100644 --- a/gsk/gpu/gskgpunodeprocessorprivate.h +++ b/gsk/gpu/gskgpunodeprocessorprivate.h @@ -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