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