From 2afe3e922344a77f42afd388ad6c2ac456b314ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 29 May 2020 20:25:07 +0200 Subject: [PATCH] clutter/stage: Add signals for different update stages Right now the stage only had a signal called 'after-paint' which was not tied to painting but updating. Change this to offer 4 signals, for the 4 different stages: * before-update - emitted in the beginning before the actual stage updating * before-paint - emitted before painting if there will be any stage painting * after-paint - emitted after painting if there was any stage painting * after-update - emitted as a last step of updating, no matter whether there were any painting or not Currently there were only one listener, that should only really have been called if there was any painting, so no changes to listeners are needed. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285 --- clutter/clutter/clutter-stage-private.h | 5 +- clutter/clutter/clutter-stage.c | 69 ++++++++++++++++++++++- clutter/clutter/cogl/clutter-stage-cogl.c | 18 +++++- 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h index 8076c3256..866731100 100644 --- a/clutter/clutter/clutter-stage-private.h +++ b/clutter/clutter/clutter-stage-private.h @@ -40,7 +40,10 @@ void clutter_stage_paint_view (ClutterStage ClutterStageView *view, const cairo_region_t *redraw_clip); -void _clutter_stage_emit_after_paint (ClutterStage *stage); +void clutter_stage_emit_before_update (ClutterStage *stage); +void clutter_stage_emit_before_paint (ClutterStage *stage); +void clutter_stage_emit_after_paint (ClutterStage *stage); +void clutter_stage_emit_after_update (ClutterStage *stage); CLUTTER_EXPORT void _clutter_stage_set_window (ClutterStage *stage, diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 7539dae95..1d08cd4fa 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -167,7 +167,10 @@ enum ACTIVATE, DEACTIVATE, DELETE_EVENT, + BEFORE_UPDATE, + BEFORE_PAINT, AFTER_PAINT, + AFTER_UPDATE, PAINT_VIEW, PRESENTED, @@ -890,11 +893,29 @@ clutter_stage_paint_view (ClutterStage *stage, } void -_clutter_stage_emit_after_paint (ClutterStage *stage) +clutter_stage_emit_before_update (ClutterStage *stage) +{ + g_signal_emit (stage, stage_signals[BEFORE_UPDATE], 0); +} + +void +clutter_stage_emit_before_paint (ClutterStage *stage) +{ + g_signal_emit (stage, stage_signals[BEFORE_PAINT], 0); +} + +void +clutter_stage_emit_after_paint (ClutterStage *stage) { g_signal_emit (stage, stage_signals[AFTER_PAINT], 0); } +void +clutter_stage_emit_after_update (ClutterStage *stage) +{ + g_signal_emit (stage, stage_signals[AFTER_UPDATE], 0); +} + static gboolean clutter_stage_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume) @@ -1438,6 +1459,8 @@ _clutter_stage_do_update (ClutterStage *stage) COGL_TRACE_BEGIN_SCOPED (ClutterStageDoUpdate, "Update"); + clutter_stage_emit_before_update (stage); + /* NB: We need to ensure we have an up to date layout *before* we * check or clear the pending redraws flag since a relayout may * queue a redraw. @@ -1445,7 +1468,10 @@ _clutter_stage_do_update (ClutterStage *stage) clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage)); if (!priv->redraw_pending) - return FALSE; + { + clutter_stage_emit_after_update (stage); + return FALSE; + } clutter_stage_update_actor_stage_views (stage); clutter_stage_maybe_finish_queue_redraws (stage); @@ -1469,6 +1495,8 @@ _clutter_stage_do_update (ClutterStage *stage) clutter_stage_update_devices (stage, devices); + clutter_stage_emit_after_update (stage); + return TRUE; } @@ -1997,6 +2025,31 @@ clutter_stage_class_init (ClutterStageClass *klass) G_TYPE_BOOLEAN, 1, CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + /** + * ClutterStage::before-update: + * @stage: the #ClutterStage + */ + stage_signals[BEFORE_UPDATE] = + g_signal_new (I_("before-update"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); + + /** + * ClutterStage::before-paint: + * @stage: the stage that received the event + * + * The ::before-paint signal is emitted before the stage is painted. + */ + stage_signals[BEFORE_PAINT] = + g_signal_new (I_("before-paint"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); /** * ClutterStage::after-paint: * @stage: the stage that received the event @@ -2015,6 +2068,18 @@ clutter_stage_class_init (ClutterStageClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 0); + /** + * ClutterStage::after-update: + * @stage: the #ClutterStage + */ + stage_signals[AFTER_UPDATE] = + g_signal_new (I_("after-update"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); + /** * ClutterStage::paint-view: * @stage: the stage that received the event diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c index 565f2f9fb..af3a6da74 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -790,11 +790,26 @@ static void clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) { ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + gboolean has_redraw_clip = FALSE; gboolean swap_event = FALSE; GList *l; COGL_TRACE_BEGIN (ClutterStageCoglRedraw, "Paint (Cogl Redraw)"); + for (l = _clutter_stage_window_get_views (stage_window); l; l = l->next) + { + ClutterStageView *view = l->data; + + if (!clutter_stage_view_has_redraw_clip (view)) + continue; + + has_redraw_clip = TRUE; + break; + } + + if (has_redraw_clip) + clutter_stage_emit_before_paint (stage_cogl->wrapper); + for (l = _clutter_stage_window_get_views (stage_window); l; l = l->next) { ClutterStageView *view = l->data; @@ -817,7 +832,8 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) } } - _clutter_stage_emit_after_paint (stage_cogl->wrapper); + if (has_redraw_clip) + clutter_stage_emit_after_paint (stage_cogl->wrapper); _clutter_stage_window_finish_frame (stage_window);