From 588c0a456afd19f0f1eaa2b7db718ae089049a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 23 Oct 2020 10:21:54 +0200 Subject: [PATCH] renderer/native: Keep onscreens alive until after the next mode set Destroying an onscreen destroyes the gbm_surface, the gbm_bo's, and the fb_id's. Doing this (drmModeRmFB() of the fb_id specifically), may on some hw implicitly disable the CRTC of the plane that framebuffer was assigned to. This would cause following atomic commit that attempts to disable the CRTC to fail as disabling an already disabled CRTC is not allowed. It'd also mean we'd always disable the plane before having finished next mode set, leaving it monitor content potentially empty when not really necessary. Solve this by keeping the CoglOnscreens (thus the gbm_surface, gbm_bo and fb_id) alive until the following global mode set has completed, i.e. the new state has been fully committed and applied. Part-of: --- src/backends/native/meta-renderer-native.c | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 281091f3e..5c3fe4980 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -203,6 +203,8 @@ struct _MetaRendererNative gboolean pending_mode_set; guint mode_set_failed_feedback_source_id; + GList *kept_alive_onscreens; + GList *power_save_page_flip_onscreens; guint power_save_page_flip_source_id; }; @@ -1997,6 +1999,14 @@ configure_disabled_crtcs (MetaGpu *gpu, } } +static void +clear_kept_alive_onscreens (MetaRendererNative *renderer_native) +{ + g_list_free_full (renderer_native->kept_alive_onscreens, + g_object_unref); + renderer_native->kept_alive_onscreens = NULL; +} + static void meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native) { @@ -2035,6 +2045,8 @@ meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native) } } + clear_kept_alive_onscreens (renderer_native); + if (failed_views) { DispatchFailedModeSetViews *data; @@ -3272,6 +3284,25 @@ meta_renderer_native_create_view (MetaRenderer *renderer, return view; } +static void +keep_current_onscreens_alive (MetaRenderer *renderer) +{ + MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); + GList *views; + GList *l; + + views = meta_renderer_get_views (renderer); + for (l = views; l; l = l->next) + { + ClutterStageView *stage_view = l->data; + CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (stage_view); + + renderer_native->kept_alive_onscreens = + g_list_prepend (renderer_native->kept_alive_onscreens, + g_object_ref (onscreen)); + } +} + static void meta_renderer_native_rebuild_views (MetaRenderer *renderer) { @@ -3283,6 +3314,8 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) meta_kms_discard_pending_page_flips (kms); + keep_current_onscreens_alive (renderer); + parent_renderer_class->rebuild_views (renderer); meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer)); @@ -4100,6 +4133,8 @@ meta_renderer_native_finalize (GObject *object) { MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object); + clear_kept_alive_onscreens (renderer_native); + if (renderer_native->power_save_page_flip_onscreens) { g_list_free_full (renderer_native->power_save_page_flip_onscreens,