From 3076cd9a47ee712043ad44848563749678b9845a Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 17 Jun 2024 15:56:38 -0400 Subject: [PATCH] gpu: Convert textures to the right color state Add function to convert an image from one color state to another, and call it whenever we upload a texture. --- gsk/gpu/gskgpunodeprocessor.c | 109 ++++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 6 deletions(-) diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index 4f2d864a03..e82bc49e2c 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -10,6 +10,7 @@ #include "gskgpubluropprivate.h" #include "gskgpuclearopprivate.h" #include "gskgpuclipprivate.h" +#include "gskgpucolorconvertopprivate.h" #include "gskgpucolorizeopprivate.h" #include "gskgpucolormatrixopprivate.h" #include "gskgpucoloropprivate.h" @@ -44,6 +45,7 @@ #include "gdk/gdkrgbaprivate.h" #include "gdk/gdksubsurfaceprivate.h" +#include "gdk/gdkcolorstateprivate.h" /* the epsilon we allow pixels to be off due to rounding errors. * Chosen rather randomly. @@ -389,6 +391,72 @@ gsk_gpu_node_processor_finish_draw (GskGpuNodeProcessor *self, gsk_gpu_node_processor_finish (self); } +static GskGpuImage * +gsk_gpu_color_convert (GskGpuFrame *frame, + GskGpuImage *image, + GdkColorState *from, + GdkColorState *to) +{ + GskGpuNodeProcessor other; + int width, height; + GdkMemoryDepth depth; + GskGpuImage *copy; + guint32 descriptor; + graphene_rect_t rect; + + if (gdk_color_state_equal (from, to)) + return image; + + width = gsk_gpu_image_get_width (image); + height = gsk_gpu_image_get_height (image); + depth = gdk_memory_format_get_depth (gsk_gpu_image_get_format (image)); + depth = gdk_memory_depth_merge (depth, gdk_color_state_get_min_depth (from)); + depth = gdk_memory_depth_merge (depth, gdk_color_state_get_min_depth (to)); + rect = GRAPHENE_RECT_INIT (0, 0, width, height); + + copy = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (frame), + FALSE, + depth, + width, height); + + gsk_gpu_node_processor_init (&other, + frame, + NULL, + copy, + to, + &(cairo_rectangle_int_t) { 0, 0, width, height }, + &rect); + + gsk_gpu_render_pass_begin_op (other.frame, + copy, + &(cairo_rectangle_int_t) { 0, 0, width, height }, + GSK_RENDER_PASS_OFFSCREEN); + + descriptor = gsk_gpu_node_processor_add_image (&other, image, GSK_GPU_SAMPLER_DEFAULT); + + gsk_gpu_node_processor_sync_globals (&other, 0); + + gsk_gpu_color_convert_op (frame, + GSK_GPU_SHADER_CLIP_NONE, + from, + to, + other.desc, + descriptor, + &rect, + &other.offset, + &rect); + + gsk_gpu_render_pass_end_op (other.frame, + copy, + GSK_RENDER_PASS_OFFSCREEN); + + gsk_gpu_node_processor_finish (&other); + + g_object_unref (image); + + return copy; +} + void gsk_gpu_node_processor_process (GskGpuFrame *frame, GskGpuImage *target, @@ -820,9 +888,19 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame, GdkTexture *texture = gsk_texture_node_get_texture (node); GskGpuDevice *device = gsk_gpu_frame_get_device (frame); gint64 timestamp = gsk_gpu_frame_get_timestamp (frame); - result = gsk_gpu_device_lookup_texture_image (device, texture, gdk_texture_get_color_state (texture), timestamp); + + result = gsk_gpu_device_lookup_texture_image (device, texture, color_state, timestamp); if (result == NULL) - result = gsk_gpu_frame_upload_texture (frame, FALSE, texture, &image_color_state); + { + result = gsk_gpu_frame_upload_texture (frame, FALSE, texture, &image_color_state); + + if (result && + !gdk_color_state_equal (image_color_state, color_state)) + { + result = gsk_gpu_color_convert (frame, result, image_color_state, color_state); + gsk_gpu_device_cache_texture_image (device, texture, timestamp, result, color_state); + } + } if (result) { @@ -840,6 +918,8 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame, gsk_render_node_ref (node), (GDestroyNotify) gsk_render_node_unref); + result = gsk_gpu_color_convert (frame, result, GDK_COLOR_STATE_SRGB, color_state); + g_object_ref (result); *out_bounds = *clip_bounds; @@ -1010,7 +1090,7 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self, gsk_texture_node_get_texture (node), gsk_gpu_frame_get_timestamp (self->frame), ensure, - gdk_texture_get_color_state (gsk_texture_node_get_texture (node))); + self->color_state); } return ensure; @@ -1961,7 +2041,7 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self, texture = gsk_texture_node_get_texture (node); timestamp = gsk_gpu_frame_get_timestamp (self->frame); - image = gsk_gpu_device_lookup_texture_image (device, texture, gdk_texture_get_color_state (texture), timestamp); + image = gsk_gpu_device_lookup_texture_image (device, texture, self->color_state, timestamp); if (image == NULL) { image = gsk_gpu_frame_upload_texture (self->frame, FALSE, texture, &image_color_state); @@ -1974,6 +2054,12 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self, gsk_gpu_node_processor_add_fallback_node (self, node); return; } + + if (!gdk_color_state_equal (image_color_state, self->color_state)) + { + image = gsk_gpu_color_convert (self->frame, image, image_color_state, self->color_state); + gsk_gpu_device_cache_texture_image (device, texture, timestamp, image, self->color_state); + } } if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) && @@ -2037,12 +2123,18 @@ gsk_gpu_node_processor_create_texture_pattern (GskGpuPatternWriter *self, texture = gsk_texture_node_get_texture (node); timestamp = gsk_gpu_frame_get_timestamp (self->frame); - image = gsk_gpu_device_lookup_texture_image (device, texture, gdk_texture_get_color_state (texture), timestamp); + image = gsk_gpu_device_lookup_texture_image (device, texture, self->color_state, timestamp); if (image == NULL) { image = gsk_gpu_frame_upload_texture (self->frame, FALSE, texture, &image_color_state); if (image == NULL) return FALSE; + + if (!gdk_color_state_equal (image_color_state, self->color_state)) + { + image = gsk_gpu_color_convert (self->frame, image, image_color_state, self->color_state); + gsk_gpu_device_cache_texture_image (device, texture, timestamp, image, self->color_state); + } } if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) && @@ -2135,7 +2227,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, timestamp = gsk_gpu_frame_get_timestamp (self->frame); need_mipmap = scaling_filter == GSK_SCALING_FILTER_TRILINEAR; - image = gsk_gpu_device_lookup_texture_image (device, texture, gdk_texture_get_color_state (texture), timestamp); + image = gsk_gpu_device_lookup_texture_image (device, texture, self->color_state, timestamp); if (image == NULL) { image = gsk_gpu_frame_upload_texture (self->frame, need_mipmap, texture, &image_color_state); @@ -2148,6 +2240,11 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, gsk_gpu_node_processor_add_fallback_node (self, node); return; } + if (!gdk_color_state_equal (image_color_state, self->color_state)) + { + image = gsk_gpu_color_convert (self->frame, image, image_color_state, self->color_state); + gsk_gpu_device_cache_texture_image (device, texture, timestamp, image, self->color_state); + } } image = gsk_gpu_node_processor_ensure_image (self->frame,