diff --git a/gsk/gpu/gskgpuframe.c b/gsk/gpu/gskgpuframe.c index 9464ba9151..c809ab2c9b 100644 --- a/gsk/gpu/gskgpuframe.c +++ b/gsk/gpu/gskgpuframe.c @@ -561,6 +561,7 @@ copy_texture (gpointer user_data, static void gsk_gpu_frame_record_rect (GskGpuFrame *self, GskGpuImage *target, + GdkColorState *target_color_state, const cairo_rectangle_int_t *clip, GskRenderNode *node, const graphene_rect_t *viewport) @@ -572,6 +573,7 @@ gsk_gpu_frame_record_rect (GskGpuFrame *self, gsk_gpu_node_processor_process (self, target, + target_color_state, clip, node, viewport); @@ -585,6 +587,7 @@ static void gsk_gpu_frame_record (GskGpuFrame *self, gint64 timestamp, GskGpuImage *target, + GdkColorState *target_color_state, const cairo_region_t *clip, GskRenderNode *node, const graphene_rect_t *viewport, @@ -603,13 +606,14 @@ gsk_gpu_frame_record (GskGpuFrame *self, cairo_rectangle_int_t rect; cairo_region_get_rectangle (clip, i, &rect); - gsk_gpu_frame_record_rect (self, target, &rect, node, viewport); + gsk_gpu_frame_record_rect (self, target, target_color_state, &rect, node, viewport); } } else { gsk_gpu_frame_record_rect (self, target, + target_color_state, &(cairo_rectangle_int_t) { 0, 0, gsk_gpu_image_get_width (target), @@ -656,6 +660,7 @@ void gsk_gpu_frame_render (GskGpuFrame *self, gint64 timestamp, GskGpuImage *target, + GdkColorState *target_color_state, const cairo_region_t *region, GskRenderNode *node, const graphene_rect_t *viewport, @@ -663,7 +668,7 @@ gsk_gpu_frame_render (GskGpuFrame *self, { gsk_gpu_frame_cleanup (self); - gsk_gpu_frame_record (self, timestamp, target, region, node, viewport, texture); + gsk_gpu_frame_record (self, timestamp, target, target_color_state, region, node, viewport, texture); gsk_gpu_frame_submit (self); } diff --git a/gsk/gpu/gskgpuframeprivate.h b/gsk/gpu/gskgpuframeprivate.h index 10dfbf0aa9..9e6d5bb0c9 100644 --- a/gsk/gpu/gskgpuframeprivate.h +++ b/gsk/gpu/gskgpuframeprivate.h @@ -75,6 +75,7 @@ void gsk_gpu_frame_wait (GskGpuF void gsk_gpu_frame_render (GskGpuFrame *self, gint64 timestamp, GskGpuImage *target, + GdkColorState *target_color_state, const cairo_region_t *region, GskRenderNode *node, const graphene_rect_t *viewport, diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index 765c4a5f23..779393d028 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -120,6 +120,7 @@ struct _GskGpuNodeProcessor float opacity; GskGpuGlobals pending_globals; + GdkColorState *color_state; }; #define GDK_ARRAY_NAME pattern_buffer @@ -141,6 +142,7 @@ struct _GskGpuPatternWriter guint stack; PatternBuffer buffer; + GdkColorState *color_state; }; static void gsk_gpu_node_processor_add_node (GskGpuNodeProcessor *self, @@ -153,6 +155,7 @@ gsk_gpu_node_processor_finish (GskGpuNodeProcessor *self) { g_clear_pointer (&self->modelview, gsk_transform_unref); g_clear_object (&self->desc); + g_clear_pointer (&self->color_state, gdk_color_state_unref); } static void @@ -160,6 +163,7 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self, GskGpuFrame *frame, GskGpuDescriptors *desc, GskGpuImage *target, + GdkColorState *color_state, const cairo_rectangle_int_t *clip, const graphene_rect_t *viewport) { @@ -202,6 +206,8 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self, -viewport->origin.y); self->opacity = 1.0; self->pending_globals = GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP | GSK_GPU_GLOBAL_SCISSOR | GSK_GPU_GLOBAL_BLEND; + + self->color_state = gdk_color_state_ref (color_state); } static void @@ -338,6 +344,7 @@ gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self, GskGpuFrame *frame, GdkMemoryDepth depth, const graphene_vec2_t *scale, + GdkColorState *color_state, const graphene_rect_t *viewport) { GskGpuImage *image; @@ -359,6 +366,7 @@ gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self, frame, NULL, image, + color_state, &area, viewport); @@ -384,6 +392,7 @@ gsk_gpu_node_processor_finish_draw (GskGpuNodeProcessor *self, void gsk_gpu_node_processor_process (GskGpuFrame *frame, GskGpuImage *target, + GdkColorState *target_color_state, const cairo_rectangle_int_t *clip, GskRenderNode *node, const graphene_rect_t *viewport) @@ -394,6 +403,7 @@ gsk_gpu_node_processor_process (GskGpuFrame *frame, frame, NULL, target, + target_color_state, clip, viewport); @@ -406,6 +416,7 @@ static void gsk_gpu_pattern_writer_init (GskGpuPatternWriter *self, GskGpuFrame *frame, const graphene_vec2_t *scale, + GdkColorState *color_state, const graphene_point_t *offset, const graphene_rect_t *bounds) { @@ -419,6 +430,8 @@ gsk_gpu_pattern_writer_init (GskGpuPatternWriter *self, self->scale = *scale; self->stack = 0; + self->color_state = gdk_color_state_ref (color_state); + pattern_buffer_init (&self->buffer); } @@ -546,6 +559,7 @@ gsk_gpu_pattern_writer_finish (GskGpuPatternWriter *self) pattern_buffer_clear (&self->buffer); g_assert (self->stack == 0); g_clear_object (&self->desc); + g_clear_pointer (&self->color_state, gdk_color_state_unref); } static gboolean @@ -742,6 +756,7 @@ gsk_gpu_node_processor_image_op (GskGpuNodeProcessor *self, static GskGpuImage * gsk_gpu_node_processor_create_offscreen (GskGpuFrame *frame, const graphene_vec2_t *scale, + GdkColorState *color_state, const graphene_rect_t *viewport, GskRenderNode *node) { @@ -752,6 +767,7 @@ gsk_gpu_node_processor_create_offscreen (GskGpuFrame *frame, frame, gsk_render_node_get_preferred_depth (node), scale, + color_state, viewport); if (image == NULL) return NULL; @@ -789,6 +805,7 @@ static GskGpuImage * gsk_gpu_get_node_as_image (GskGpuFrame *frame, const graphene_rect_t *clip_bounds, const graphene_vec2_t *scale, + GdkColorState *color_state, GskRenderNode *node, graphene_rect_t *out_bounds) { @@ -833,6 +850,7 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame, GSK_DEBUG (FALLBACK, "Offscreening node '%s'", g_type_name_from_instance ((GTypeInstance *) node)); result = gsk_gpu_node_processor_create_offscreen (frame, scale, + color_state, clip_bounds, node); @@ -843,6 +861,7 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame, static GskGpuImage * gsk_gpu_node_processor_ensure_image (GskGpuFrame *frame, GskGpuImage *image, + GdkColorState *color_state, GskGpuImageFlags required_flags, GskGpuImageFlags disallowed_flags) { @@ -895,6 +914,7 @@ gsk_gpu_node_processor_ensure_image (GskGpuFrame *frame, frame, NULL, copy, + color_state, &(cairo_rectangle_int_t) { 0, 0, width, height }, &rect); @@ -968,6 +988,7 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self, image = gsk_gpu_get_node_as_image (self->frame, &clip, &self->scale, + self->color_state, node, out_bounds); if (image == NULL) @@ -975,6 +996,7 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self, ensure = gsk_gpu_node_processor_ensure_image (self->frame, image, + self->color_state, required_flags, disallowed_flags); @@ -1026,6 +1048,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self, self->frame, source_depth, &self->scale, + self->color_state, &intermediate_rect); gsk_gpu_node_processor_sync_globals (&other, 0); @@ -1206,6 +1229,7 @@ gsk_gpu_node_processor_try_node_as_pattern (GskGpuNodeProcessor *self, gsk_gpu_pattern_writer_init (&writer, self->frame, &self->scale, + self->color_state, &self->offset, &clipped); @@ -1455,6 +1479,7 @@ gsk_gpu_node_processor_add_rounded_clip_node_with_mask (GskGpuNodeProcessor *sel self->frame, gsk_render_node_get_preferred_depth (node), &self->scale, + self->color_state, &clip_bounds); gsk_gpu_node_processor_sync_globals (&other, 0); gsk_gpu_rounded_color_op (other.frame, @@ -1956,6 +1981,7 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self, image = gsk_gpu_node_processor_ensure_image (self->frame, image, + self->color_state, GSK_GPU_IMAGE_MIPMAP, GSK_GPU_IMAGE_STRAIGHT_ALPHA); descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_MIPMAP_DEFAULT); @@ -2021,6 +2047,7 @@ gsk_gpu_node_processor_create_texture_pattern (GskGpuPatternWriter *self, { image = gsk_gpu_node_processor_ensure_image (self->frame, image, + self->color_state, GSK_GPU_IMAGE_MIPMAP, GSK_GPU_IMAGE_STRAIGHT_ALPHA); sampler = GSK_GPU_SAMPLER_MIPMAP_DEFAULT; @@ -2082,6 +2109,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, clip_bounds.size.height = ceilf (clip_bounds.size.height); offscreen = gsk_gpu_node_processor_create_offscreen (self->frame, graphene_vec2_one (), + self->color_state, &clip_bounds, node); descriptor = gsk_gpu_node_processor_add_image (self, offscreen, GSK_GPU_SAMPLER_DEFAULT); @@ -2119,6 +2147,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, image = gsk_gpu_node_processor_ensure_image (self->frame, image, + self->color_state, need_mipmap ? (GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_MIPMAP) : 0, GSK_GPU_IMAGE_STRAIGHT_ALPHA); @@ -2283,6 +2312,7 @@ gsk_gpu_node_processor_add_gradient_node (GskGpuNodeProcessor *self, self->frame, gsk_render_node_get_preferred_depth (node), &self->scale, + self->color_state, &bounds); other.blend = GSK_GPU_BLEND_ADD; @@ -3332,6 +3362,7 @@ gsk_gpu_node_processor_repeat_tile (GskGpuNodeProcessor *self, GSK_DEBUG (FALLBACK, "Offscreening node '%s' for tiling", g_type_name_from_instance ((GTypeInstance *) child)); image = gsk_gpu_node_processor_create_offscreen (self->frame, &self->scale, + self->color_state, &clipped_child_bounds, child); @@ -3806,17 +3837,31 @@ static void gsk_gpu_node_processor_add_color_state_node (GskGpuNodeProcessor *self, GskRenderNode *node) { - GskGpuImage *image; GskRenderNode *child; + GdkColorState *color_state; child = gsk_color_state_node_get_child (node); + color_state = gsk_color_state_node_get_color_state (node); - image = gsk_gpu_node_processor_create_offscreen (self->frame, - &self->scale, - &node->bounds, - child); + if (gdk_color_state_equal (color_state, self->color_state)) + { + gsk_gpu_node_processor_add_node (self, child); + return; + } + else + { + GskGpuImage *offscreen; - gsk_gpu_node_processor_image_op (self, image, &node->bounds, &node->bounds); + offscreen = gsk_gpu_node_processor_create_offscreen (self->frame, + &self->scale, + color_state, + &node->bounds, + child); + + gsk_gpu_node_processor_image_op (self, offscreen, &node->bounds, &node->bounds); + + g_object_unref (offscreen); + } } static void @@ -4147,6 +4192,7 @@ gsk_gpu_node_processor_create_node_pattern (GskGpuPatternWriter *self, image = gsk_gpu_get_node_as_image (self->frame, &bounds, &self->scale, + self->color_state, node, &bounds); if (image == NULL) diff --git a/gsk/gpu/gskgpunodeprocessorprivate.h b/gsk/gpu/gskgpunodeprocessorprivate.h index 1b14019e6b..ae25099482 100644 --- a/gsk/gpu/gskgpunodeprocessorprivate.h +++ b/gsk/gpu/gskgpunodeprocessorprivate.h @@ -7,6 +7,7 @@ G_BEGIN_DECLS void gsk_gpu_node_processor_process (GskGpuFrame *frame, GskGpuImage *target, + GdkColorState *target_color_state, const cairo_rectangle_int_t *clip, GskRenderNode *node, const graphene_rect_t *viewport); diff --git a/gsk/gpu/gskgpurenderer.c b/gsk/gpu/gskgpurenderer.c index 4d52693b8e..ca070bfebd 100644 --- a/gsk/gpu/gskgpurenderer.c +++ b/gsk/gpu/gskgpurenderer.c @@ -18,6 +18,7 @@ #include "gdk/gdktextureprivate.h" #include "gdk/gdktexturedownloaderprivate.h" #include "gdk/gdkdrawcontextprivate.h" +#include "gdk/gdkcolorstateprivate.h" #include @@ -261,6 +262,7 @@ gsk_gpu_renderer_fallback_render_texture (GskGpuRenderer *self, GdkTexture *texture; GdkTextureDownloader downloader; GskGpuFrame *frame; + GdkColorState *color_state; max_size = gsk_gpu_device_get_max_image_size (priv->device); depth = gsk_render_node_get_preferred_depth (root); @@ -283,6 +285,7 @@ gsk_gpu_renderer_fallback_render_texture (GskGpuRenderer *self, stride = width * bpp; size = stride * height; data = g_malloc_n (stride, height); + color_state = gdk_color_state_get_srgb (); for (y = 0; y < height; y += image_height) { @@ -299,6 +302,7 @@ gsk_gpu_renderer_fallback_render_texture (GskGpuRenderer *self, gsk_gpu_frame_render (frame, g_get_monotonic_time (), image, + color_state, NULL, root, &GRAPHENE_RECT_INIT (rounded_viewport->origin.x + x, @@ -338,6 +342,7 @@ gsk_gpu_renderer_render_texture (GskRenderer *renderer, GskGpuImage *image; GdkTexture *texture; graphene_rect_t rounded_viewport; + GdkColorState *color_state; gsk_gpu_device_maybe_gc (priv->device); @@ -351,6 +356,7 @@ gsk_gpu_renderer_render_texture (GskRenderer *renderer, gsk_render_node_get_preferred_depth (root), rounded_viewport.size.width, rounded_viewport.size.height); + color_state = gdk_color_state_get_srgb (); if (image == NULL) return gsk_gpu_renderer_fallback_render_texture (self, root, &rounded_viewport); @@ -361,6 +367,7 @@ gsk_gpu_renderer_render_texture (GskRenderer *renderer, gsk_gpu_frame_render (frame, g_get_monotonic_time (), image, + color_state, NULL, root, &rounded_viewport, @@ -388,6 +395,10 @@ gsk_gpu_renderer_render (GskRenderer *renderer, GskGpuImage *backbuffer; cairo_region_t *render_region; double scale; + GdkSurface *surface; + GdkColorState *color_state; + GskRenderNode *node; + GdkMemoryDepth depth; if (cairo_region_is_empty (region)) { @@ -395,9 +406,13 @@ gsk_gpu_renderer_render (GskRenderer *renderer, return; } - gdk_draw_context_begin_frame_full (priv->context, - gsk_render_node_get_preferred_depth (root), - region); + surface = gdk_draw_context_get_surface (priv->context); + depth = gsk_render_node_get_preferred_depth (root); + + color_state = gdk_surface_get_color_state (surface); + depth = gdk_memory_depth_merge (depth, gdk_color_state_get_min_depth (color_state)); + + gdk_draw_context_begin_frame_full (priv->context, depth, region); gsk_gpu_device_maybe_gc (priv->device); @@ -409,11 +424,17 @@ gsk_gpu_renderer_render (GskRenderer *renderer, render_region = get_render_region (self); scale = gsk_gpu_renderer_get_scale (self); + if (!gdk_color_state_is_linear (color_state)) + node = gsk_color_state_node_new (root, gdk_color_state_get_srgb_linear ()); + else + node = gsk_render_node_ref (root); + gsk_gpu_frame_render (frame, g_get_monotonic_time (), backbuffer, + color_state, render_region, - root, + node, &GRAPHENE_RECT_INIT ( 0, 0, gsk_gpu_image_get_width (backbuffer) / scale, @@ -421,6 +442,8 @@ gsk_gpu_renderer_render (GskRenderer *renderer, ), NULL); + gsk_render_node_unref (node); + gsk_gpu_device_queue_gc (priv->device); gdk_draw_context_end_frame (priv->context);