From b275af95b72bb641c7e5eacab6fcd121491e462e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 9 Nov 2023 13:03:55 +0800 Subject: [PATCH] clutter/paint-context: Add content and target color state tracking The initial target color state is the color state of the stage view being painted to. If we're painting to an arbitrary framebuffer, it's currently hard coded to sRGB/electrical. The content color state is not set on construction, but when starting to paint, it's set to the color state of the stage itself. Whenever an actor is painted, it'll set the color state to the color state of itself. The intention is that offscreen rendering pushes a target color state that causes painting to it to not necessarily be in the stage view color state. Pass color state with offscreen framebuffer, as this avoids hard coding sRGB in the lower level bits of paint contexts. It's still practically hard coded, only that it's derived from somewhere else (e.g. the stage or window actor). Nothing is actually using this yet, but will eventually. Part-of: --- clutter/clutter/clutter-actor.c | 7 +- .../clutter/clutter-paint-context-private.h | 5 + clutter/clutter/clutter-paint-context.c | 92 ++++++++++++++++++- clutter/clutter/clutter-paint-context.h | 20 +++- clutter/clutter/clutter-stage.c | 11 ++- src/compositor/meta-window-actor.c | 6 +- 6 files changed, 131 insertions(+), 10 deletions(-) diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index acd7a2c80..6a88b495e 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -3460,6 +3460,8 @@ clutter_actor_paint (ClutterActor *self, } #endif + clutter_paint_context_push_color_state (paint_context, priv->color_state); + actor_node = clutter_actor_node_new (self, -1); root_node = clutter_paint_node_ref (actor_node); @@ -3574,7 +3576,7 @@ clutter_actor_paint (ClutterActor *self, if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)) _clutter_actor_paint_cull_result (self, success, result, actor_node); else if (result == CLUTTER_CULL_RESULT_OUT && success) - return; + goto out; } if (priv->effects == NULL) @@ -3593,6 +3595,9 @@ clutter_actor_paint (ClutterActor *self, * unless a new redraw was queued up. */ priv->is_dirty = priv->propagated_one_redraw; + +out: + clutter_paint_context_pop_color_state (paint_context); } /** diff --git a/clutter/clutter/clutter-paint-context-private.h b/clutter/clutter/clutter-paint-context-private.h index b13ed2958..ac711800d 100644 --- a/clutter/clutter/clutter-paint-context-private.h +++ b/clutter/clutter/clutter-paint-context-private.h @@ -34,3 +34,8 @@ clutter_paint_context_get_clip_frusta (ClutterPaintContext *paint_context); void clutter_paint_context_assign_frame (ClutterPaintContext *paint_context, ClutterFrame *frame); + +void clutter_paint_context_push_target_color_state (ClutterPaintContext *paint_context, + ClutterColorState *color_state); + +void clutter_paint_context_pop_target_color_state (ClutterPaintContext *paint_context); diff --git a/clutter/clutter/clutter-paint-context.c b/clutter/clutter/clutter-paint-context.c index 9a1a644c2..88a4a4c87 100644 --- a/clutter/clutter/clutter-paint-context.c +++ b/clutter/clutter/clutter-paint-context.c @@ -18,7 +18,10 @@ #include "config.h" #include "clutter/clutter-paint-context-private.h" + +#include "clutter/clutter-color-state.h" #include "clutter/clutter-frame.h" +#include "clutter/clutter-stage-view-private.h" struct _ClutterPaintContext { @@ -33,6 +36,11 @@ struct _ClutterPaintContext MtkRegion *redraw_clip; GArray *clip_frusta; + + GList *target_color_states; + GList *color_states; + + ClutterColorState *framebuffer_color_state; }; G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context, @@ -46,6 +54,7 @@ clutter_paint_context_new_for_view (ClutterStageView *view, ClutterPaintFlag paint_flags) { ClutterPaintContext *paint_context; + ClutterColorState *target_color_state; CoglFramebuffer *framebuffer; paint_context = g_new0 (ClutterPaintContext, 1); @@ -54,6 +63,12 @@ clutter_paint_context_new_for_view (ClutterStageView *view, paint_context->redraw_clip = mtk_region_copy (redraw_clip); paint_context->clip_frusta = g_array_ref (clip_frusta); paint_context->paint_flags = paint_flags; + g_set_object (&paint_context->framebuffer_color_state, + clutter_stage_view_get_color_state (view)); + + target_color_state = paint_context->framebuffer_color_state; + clutter_paint_context_push_target_color_state (paint_context, + target_color_state); framebuffer = clutter_stage_view_get_framebuffer (view); clutter_paint_context_push_framebuffer (paint_context, framebuffer); @@ -65,15 +80,22 @@ clutter_paint_context_new_for_view (ClutterStageView *view, * clutter_paint_context_new_for_framebuffer: (skip) */ ClutterPaintContext * -clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer, - const MtkRegion *redraw_clip, - ClutterPaintFlag paint_flags) +clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer, + const MtkRegion *redraw_clip, + ClutterPaintFlag paint_flags, + ClutterColorState *color_state) { ClutterPaintContext *paint_context; + ClutterColorState *target_color_state; paint_context = g_new0 (ClutterPaintContext, 1); g_ref_count_init (&paint_context->ref_count); paint_context->paint_flags = paint_flags; + g_set_object (&paint_context->framebuffer_color_state, color_state); + + target_color_state = paint_context->framebuffer_color_state; + clutter_paint_context_push_target_color_state (paint_context, + target_color_state); if (redraw_clip) paint_context->redraw_clip = mtk_region_copy (redraw_clip); @@ -93,6 +115,14 @@ clutter_paint_context_ref (ClutterPaintContext *paint_context) static void clutter_paint_context_dispose (ClutterPaintContext *paint_context) { + if (paint_context->framebuffer_color_state) + { + clutter_paint_context_pop_target_color_state (paint_context); + g_clear_object (&paint_context->framebuffer_color_state); + } + + g_warn_if_fail (!paint_context->color_states); + g_warn_if_fail (!paint_context->target_color_states); g_list_free_full (paint_context->framebuffers, g_object_unref); paint_context->framebuffers = NULL; g_clear_pointer (&paint_context->redraw_clip, mtk_region_unref); @@ -229,3 +259,59 @@ clutter_paint_context_get_frame (ClutterPaintContext *paint_context) { return paint_context->frame; } + +void +clutter_paint_context_push_target_color_state (ClutterPaintContext *paint_context, + ClutterColorState *color_state) +{ + paint_context->target_color_states = + g_list_prepend (paint_context->target_color_states, color_state); +} + +void +clutter_paint_context_pop_target_color_state (ClutterPaintContext *paint_context) +{ + g_return_if_fail (paint_context->target_color_states); + + paint_context->target_color_states = + g_list_delete_link (paint_context->target_color_states, + paint_context->target_color_states); +} + +void +clutter_paint_context_push_color_state (ClutterPaintContext *paint_context, + ClutterColorState *color_state) +{ + paint_context->color_states = g_list_prepend (paint_context->color_states, + color_state); +} + +void +clutter_paint_context_pop_color_state (ClutterPaintContext *paint_context) +{ + g_return_if_fail (paint_context->color_states); + + paint_context->color_states = + g_list_delete_link (paint_context->color_states, + paint_context->color_states); +} + +/** + * clutter_paint_context_get_target_color_state: (skip) + */ +ClutterColorState * +clutter_paint_context_get_target_color_state (ClutterPaintContext *paint_context) +{ + return CLUTTER_COLOR_STATE (paint_context->target_color_states->data); +} + +/** + * clutter_paint_context_get_color_state: (skip) + */ +ClutterColorState * +clutter_paint_context_get_color_state (ClutterPaintContext *paint_context) +{ + g_return_val_if_fail (paint_context->color_states, NULL); + + return CLUTTER_COLOR_STATE (paint_context->color_states->data); +} diff --git a/clutter/clutter/clutter-paint-context.h b/clutter/clutter/clutter-paint-context.h index 9a9e66588..321c86ee4 100644 --- a/clutter/clutter/clutter-paint-context.h +++ b/clutter/clutter/clutter-paint-context.h @@ -42,9 +42,10 @@ CLUTTER_EXPORT GType clutter_paint_context_get_type (void); CLUTTER_EXPORT -ClutterPaintContext * clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer, - const MtkRegion *redraw_clip, - ClutterPaintFlag paint_flags); +ClutterPaintContext * clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer, + const MtkRegion *redraw_clip, + ClutterPaintFlag paint_flags, + ClutterColorState *color_state); CLUTTER_EXPORT ClutterPaintContext * clutter_paint_context_ref (ClutterPaintContext *paint_context); @@ -77,4 +78,17 @@ ClutterPaintFlag clutter_paint_context_get_paint_flags (ClutterPaintContext *pai CLUTTER_EXPORT ClutterFrame * clutter_paint_context_get_frame (ClutterPaintContext *paint_context); +CLUTTER_EXPORT +void clutter_paint_context_push_color_state (ClutterPaintContext *paint_context, + ClutterColorState *color_state); + +CLUTTER_EXPORT +void clutter_paint_context_pop_color_state (ClutterPaintContext *paint_context); + +CLUTTER_EXPORT +ClutterColorState * clutter_paint_context_get_target_color_state (ClutterPaintContext *paint_context); + +CLUTTER_EXPORT +ClutterColorState * clutter_paint_context_get_color_state (ClutterPaintContext *paint_context); + G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintContext, clutter_paint_context_unref) diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index a6bc89983..ada20d39c 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -455,11 +455,16 @@ clutter_stage_do_paint_view (ClutterStage *stage, fb = clutter_stage_view_get_framebuffer (view); + clutter_paint_context_push_color_state (paint_context, + clutter_actor_get_color_state (CLUTTER_ACTOR (stage))); + root_node = clutter_root_node_new (fb, &bg_color, COGL_BUFFER_BIT_DEPTH); clutter_paint_node_set_static_name (root_node, "Stage (root)"); clutter_paint_node_paint (root_node, paint_context); clutter_paint_node_unref (root_node); + clutter_paint_context_pop_color_state (paint_context); + clutter_actor_paint (CLUTTER_ACTOR (stage), paint_context); clutter_paint_context_destroy (paint_context); } @@ -2668,6 +2673,7 @@ clutter_stage_paint_to_framebuffer (ClutterStage *stage, ClutterStagePrivate *priv = clutter_stage_get_instance_private (stage); ClutterPaintContext *paint_context; g_autoptr (MtkRegion) redraw_clip = NULL; + ClutterColorState *color_state; COGL_TRACE_BEGIN_SCOPED (PaintToFramebuffer, "Clutter::Stage::paint_to_framebuffer()"); @@ -2681,10 +2687,13 @@ clutter_stage_paint_to_framebuffer (ClutterStage *stage, } redraw_clip = mtk_region_create_rectangle (rect); + color_state = + clutter_actor_get_color_state (CLUTTER_ACTOR (stage)); paint_context = clutter_paint_context_new_for_framebuffer (framebuffer, redraw_clip, - paint_flags); + paint_flags, + color_state); cogl_framebuffer_push_matrix (framebuffer); cogl_framebuffer_set_projection_matrix (framebuffer, &priv->projection); diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index e0826251c..6be7c0535 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -1481,7 +1481,8 @@ meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window, paint_context = clutter_paint_context_new_for_framebuffer (framebuffer, NULL, - CLUTTER_PAINT_FLAG_NONE); + CLUTTER_PAINT_FLAG_NONE, + clutter_actor_get_color_state (actor)); clutter_actor_paint (actor, paint_context); clutter_paint_context_destroy (paint_context); @@ -1614,7 +1615,8 @@ create_framebuffer_from_window_actor (MetaWindowActor *self, paint_context = clutter_paint_context_new_for_framebuffer (framebuffer, NULL, - CLUTTER_PAINT_FLAG_NONE); + CLUTTER_PAINT_FLAG_NONE, + clutter_actor_get_color_state (actor)); clutter_actor_paint (actor, paint_context); clutter_paint_context_destroy (paint_context);