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
This commit is contained in:
Jonas Ådahl 2020-08-16 21:36:38 +02:00 committed by Georges Basile Stavracas Neto
parent 3dfe3a248d
commit a1daf0ab24
2 changed files with 34 additions and 6 deletions

View File

@ -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",

View File

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