From a1daf0ab24fc4da1017485cafbf8953102cf12e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sun, 16 Aug 2020 21:36:38 +0200 Subject: [PATCH] stage-view: Don't destroy onscreen until finalizing There might be pending flip callbacks to process; we shouldn't release the buffers until we have received the callback. Fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/1378 https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1407 --- clutter/clutter/clutter-stage-view.c | 14 +++++++++++- clutter/clutter/cogl/clutter-stage-cogl.c | 26 ++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c index d02b92909..b5d99f530 100644 --- a/clutter/clutter/clutter-stage-view.c +++ b/clutter/clutter/clutter-stage-view.c @@ -1267,7 +1267,6 @@ clutter_stage_view_dispose (GObject *object) int i; g_clear_pointer (&priv->name, g_free); - g_clear_pointer (&priv->framebuffer, cogl_object_unref); g_clear_pointer (&priv->shadow.framebuffer, cogl_object_unref); for (i = 0; i < G_N_ELEMENTS (priv->shadow.dma_buf.handles); i++) @@ -1286,6 +1285,18 @@ clutter_stage_view_dispose (GObject *object) G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object); } +static void +clutter_stage_view_finalize (GObject *object) +{ + ClutterStageView *view = CLUTTER_STAGE_VIEW (object); + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + g_clear_pointer (&priv->framebuffer, cogl_object_unref); + + G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object); +} + static void clutter_stage_view_init (ClutterStageView *view) { @@ -1310,6 +1321,7 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass) object_class->set_property = clutter_stage_view_set_property; object_class->constructed = clutter_stage_view_constructed; object_class->dispose = clutter_stage_view_dispose; + object_class->finalize = clutter_stage_view_finalize; obj_props[PROP_NAME] = g_param_spec_string ("name", diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c index b53a6c16a..9baccbd0e 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -58,6 +58,8 @@ typedef struct _ClutterStageViewCoglPrivate ClutterDamageHistory *damage_history; guint notify_presented_handle_id; + + CoglFrameClosure *frame_cb_closure; } ClutterStageViewCoglPrivate; G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageViewCogl, clutter_stage_view_cogl, @@ -762,27 +764,41 @@ clutter_stage_view_cogl_dispose (GObject *object) ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (object); ClutterStageViewCoglPrivate *view_priv = clutter_stage_view_cogl_get_instance_private (view_cogl); + ClutterStageView *view = CLUTTER_STAGE_VIEW (view_cogl); g_clear_handle_id (&view_priv->notify_presented_handle_id, g_source_remove); g_clear_pointer (&view_priv->damage_history, clutter_damage_history_free); + if (view_priv->frame_cb_closure) + { + CoglFramebuffer *framebuffer; + + framebuffer = clutter_stage_view_get_onscreen (view); + cogl_onscreen_remove_frame_callback (COGL_ONSCREEN (framebuffer), + view_priv->frame_cb_closure); + view_priv->frame_cb_closure = NULL; + } + G_OBJECT_CLASS (clutter_stage_view_cogl_parent_class)->dispose (object); } static void clutter_stage_view_cogl_constructed (GObject *object) { + ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (object); + ClutterStageViewCoglPrivate *view_priv = + clutter_stage_view_cogl_get_instance_private (view_cogl); ClutterStageView *view = CLUTTER_STAGE_VIEW (view_cogl); CoglFramebuffer *framebuffer; framebuffer = clutter_stage_view_get_onscreen (view); - if (framebuffer && cogl_is_onscreen (framebuffer)) { - cogl_onscreen_add_frame_callback (COGL_ONSCREEN (framebuffer), - frame_cb, - view, - NULL); + view_priv->frame_cb_closure = + cogl_onscreen_add_frame_callback (COGL_ONSCREEN (framebuffer), + frame_cb, + view, + NULL); } G_OBJECT_CLASS (clutter_stage_view_cogl_parent_class)->constructed (object);