1
0
Fork 0

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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3433>
This commit is contained in:
Jonas Ådahl 2023-11-09 13:03:55 +08:00 committed by Sebastian Wick
parent 1a52108c17
commit b275af95b7
6 changed files with 131 additions and 10 deletions

View file

@ -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);
}
/**

View file

@ -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);

View file

@ -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);
}

View file

@ -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)

View file

@ -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);

View file

@ -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);