From 73fb64cbb6d65709f4c47b7c2850bb6d66a8b3d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 10 Jun 2022 20:01:49 +0200 Subject: [PATCH] kms: Always handle KMS update result via callback Instead of using the "discarded" page flip callback when the "discarding" happened during actual immediate processing, communicate the same via the KMS update feedback. The "discarded" page flip callback is instead used only for when a posted page flip is discarded. In the atomic backend, this only happens on shutdown, while in the simple backend, this also happens when a asynchronous retry sequence eventually is abandoned. This allows further improvements making KMS handling fully async. Part-of: --- .../native/meta-kms-impl-device-atomic.c | 46 --------- .../native/meta-kms-impl-device-simple.c | 17 ++-- .../native/meta-kms-page-flip-private.h | 2 + src/backends/native/meta-kms.c | 8 +- src/backends/native/meta-kms.h | 6 +- src/backends/native/meta-onscreen-native.c | 98 +++++++++---------- src/backends/native/meta-renderer-native.c | 62 +++++------- 7 files changed, 88 insertions(+), 151 deletions(-) diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c index 456d742ca..d44ca5f20 100644 --- a/src/backends/native/meta-kms-impl-device-atomic.c +++ b/src/backends/native/meta-kms-impl-device-atomic.c @@ -711,43 +711,6 @@ process_page_flip_listener (MetaKmsImplDevice *impl_device, return TRUE; } -static gboolean -discard_page_flip_listener (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsPageFlipListener *listener = update_entry; - GError *commit_error = user_data; - MetaKmsPageFlipData *page_flip_data; - gpointer listener_user_data; - GDestroyNotify listener_destroy_notify; - - page_flip_data = meta_kms_page_flip_data_new (impl_device, - listener->crtc); - - meta_topic (META_DEBUG_KMS, - "[atomic] Creating transient page flip data for (%u, %s): %p", - meta_kms_crtc_get_id (listener->crtc), - meta_kms_impl_device_get_path (impl_device), - page_flip_data); - - listener_user_data = g_steal_pointer (&listener->user_data); - listener_destroy_notify = g_steal_pointer (&listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - listener->vtable, - listener->flags, - listener_user_data, - listener_destroy_notify); - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, commit_error); - - return TRUE; -} - static gboolean process_entries (MetaKmsImplDevice *impl_device, MetaKmsUpdate *update, @@ -1046,15 +1009,6 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, err: meta_topic (META_DEBUG_KMS, "[atomic] KMS update failed: %s", error->message); - process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_page_flip_listeners (update), - error, - discard_page_flip_listener, - NULL); - if (req) drmModeAtomicFree (req); diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c index 7aa39cce5..8cf683acc 100644 --- a/src/backends/native/meta-kms-impl-device-simple.c +++ b/src/backends/native/meta-kms-impl-device-simple.c @@ -1131,15 +1131,14 @@ maybe_dispatch_page_flips (MetaKmsImplDevice *impl_device, MetaKmsUpdateFlag flags, GError **error) { - g_autoptr (GList) page_flip_datas = NULL; - GList *l; + g_autolist (MetaKmsPageFlipData) page_flip_datas = NULL; page_flip_datas = generate_page_flip_datas (impl_device, update); while (page_flip_datas) { g_autoptr (GList) l = NULL; - MetaKmsPageFlipData *page_flip_data; + g_autoptr (MetaKmsPageFlipData) page_flip_data = NULL; l = page_flip_datas; page_flip_datas = g_list_remove_link (page_flip_datas, l); @@ -1166,21 +1165,17 @@ maybe_dispatch_page_flips (MetaKmsImplDevice *impl_device, *failed_planes = g_list_prepend (*failed_planes, plane_feedback); } - meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error); - goto err; } + else + { + meta_kms_page_flip_data_ref (page_flip_data); + } } return TRUE; err: - for (l = page_flip_datas; l; l = l->next) - { - MetaKmsPageFlipData *page_flip_data = l->data; - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error); - } g_list_free (page_flip_datas); return FALSE; diff --git a/src/backends/native/meta-kms-page-flip-private.h b/src/backends/native/meta-kms-page-flip-private.h index b23272ad9..93ed2d30d 100644 --- a/src/backends/native/meta-kms-page-flip-private.h +++ b/src/backends/native/meta-kms-page-flip-private.h @@ -62,4 +62,6 @@ void meta_kms_page_flip_data_take_error (MetaKmsPageFlipData *page_flip_data, void meta_kms_page_flip_data_make_symbolic (MetaKmsPageFlipData *page_flip_data); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsPageFlipData, meta_kms_page_flip_data_unref) + #endif /* META_KMS_PAGE_FLIP_H */ diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index 6c7974427..faaa87b5f 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -266,13 +266,13 @@ meta_kms_queue_result_callback (MetaKms *kms, (GDestroyNotify) meta_kms_result_listener_free); } -MetaKmsFeedback * +void meta_kms_post_pending_update_sync (MetaKms *kms, MetaKmsDevice *device, MetaKmsUpdateFlag flags) { MetaKmsUpdate *update; - MetaKmsFeedback *feedback; + g_autoptr (MetaKmsFeedback) feedback = NULL; GList *result_listeners; COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync, @@ -280,7 +280,7 @@ meta_kms_post_pending_update_sync (MetaKms *kms, update = meta_kms_take_pending_update (kms, device); if (!update) - return NULL; + return; feedback = meta_kms_device_process_update_sync (device, update, flags); @@ -289,8 +289,6 @@ meta_kms_post_pending_update_sync (MetaKms *kms, meta_kms_update_free (update); meta_kms_feedback_dispatch_result (feedback, kms, result_listeners); - - return feedback; } static gpointer diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h index 5b30d0ddf..05b22e8b9 100644 --- a/src/backends/native/meta-kms.h +++ b/src/backends/native/meta-kms.h @@ -42,9 +42,9 @@ MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms *kms, MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms, MetaKmsDevice *device); -MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms, - MetaKmsDevice *device, - MetaKmsUpdateFlag flags); +void meta_kms_post_pending_update_sync (MetaKms *kms, + MetaKmsDevice *device, + MetaKmsUpdateFlag flags); void meta_kms_discard_pending_page_flips (MetaKms *kms); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index bf2469d99..93a8d7b59 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -1017,6 +1017,35 @@ ensure_crtc_modes (CoglOnscreen *onscreen) meta_onscreen_native_set_crtc_mode (onscreen, renderer_gpu_data); } +static void +on_swap_buffer_update_result (const MetaKmsFeedback *kms_feedback, + gpointer user_data) +{ + CoglOnscreen *onscreen = COGL_ONSCREEN (user_data); + const GError *error; + CoglFrameInfo *frame_info; + + /* + * Page flipping failed, but we want to fail gracefully, so to avoid freezing + * the frame clock, emit a symbolic flip. + */ + + error = meta_kms_feedback_get_error (kms_feedback); + if (!error) + return; + + if (!g_error_matches (error, + G_IO_ERROR, + G_IO_ERROR_PERMISSION_DENIED)) + g_warning ("Page flip failed: %s", error->message); + + frame_info = cogl_onscreen_peek_head_frame_info (onscreen); + frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; + + meta_onscreen_native_notify_frame_complete (onscreen); + meta_onscreen_native_clear_next_fb (onscreen); +} + static void meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, const int *rectangles, @@ -1051,9 +1080,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, g_autoptr (MetaDrmBuffer) secondary_gpu_fb = NULL; MetaKmsCrtc *kms_crtc; MetaKmsDevice *kms_device; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *feedback_error; COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers, "Onscreen (swap-buffers)"); @@ -1136,9 +1162,19 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, if (egl_context_changed) _cogl_winsys_egl_ensure_current (cogl_display); + kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); + kms_device = meta_kms_crtc_get_device (kms_crtc); + power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); if (power_save_mode == META_POWER_SAVE_ON) { + MetaKmsUpdate *kms_update; + + kms_update = meta_kms_ensure_pending_update (kms, kms_device); + meta_kms_update_add_result_listener (kms_update, + on_swap_buffer_update_result, + onscreen_native); + ensure_crtc_modes (onscreen); meta_onscreen_native_flip_crtc (onscreen, onscreen_native->view, @@ -1158,8 +1194,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, COGL_TRACE_BEGIN_SCOPED (MetaRendererNativePostKmsUpdate, "Onscreen (post pending update)"); - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); - kms_device = meta_kms_crtc_get_device (kms_crtc); switch (renderer_gpu_data->mode) { @@ -1209,26 +1243,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_kms_crtc_get_id (kms_crtc), meta_kms_device_get_path (kms_device)); - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags); - - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - break; - case META_KMS_FEEDBACK_FAILED: - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - - feedback_error = meta_kms_feedback_get_error (kms_feedback); - if (!g_error_matches (feedback_error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", feedback_error->message); - break; - } + meta_kms_post_pending_update_sync (kms, kms_device, META_KMS_UPDATE_FLAG_NONE); + clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); } gboolean @@ -1473,10 +1489,7 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); MetaKms *kms = meta_kms_device_get_kms (kms_device); - MetaKmsUpdateFlag flags; MetaKmsUpdate *kms_update; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *error; kms_update = meta_kms_get_pending_update (kms, kms_device); if (!kms_update) @@ -1491,30 +1504,15 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE, g_object_ref (onscreen_native->view), g_object_unref); + add_onscreen_frame_info (crtc); - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, - kms_device, - flags); - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - add_onscreen_frame_info (crtc); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - break; - case META_KMS_FEEDBACK_FAILED: - add_onscreen_frame_info (crtc); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); + meta_topic (META_DEBUG_KMS, + "Posting non-primary plane update for CRTC %u (%s)", + meta_kms_crtc_get_id (kms_crtc), + meta_kms_device_get_path (kms_device)); - error = meta_kms_feedback_get_error (kms_feedback); - if (!g_error_matches (error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", error->message); - break; - } + meta_kms_post_pending_update_sync (kms, kms_device, META_KMS_UPDATE_FLAG_NONE); + clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); } static gboolean diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 756caad63..1278edf00 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -816,6 +816,20 @@ clear_detached_onscreens (MetaRendererNative *renderer_native) g_object_unref); } +static void +on_mode_sets_update_result (const MetaKmsFeedback *kms_feedback, + gpointer user_data) +{ + const GError *feedback_error; + + feedback_error = meta_kms_feedback_get_error (kms_feedback); + if (feedback_error && + !g_error_matches (feedback_error, + G_IO_ERROR, + G_IO_ERROR_PERMISSION_DENIED)) + g_warning ("Failed to post KMS update: %s", feedback_error->message); +} + void meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native) { @@ -828,9 +842,6 @@ meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native) { MetaKmsDevice *kms_device = l->data; MetaKmsUpdate *kms_update; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *feedback_error; configure_disabled_crtcs (kms_device); @@ -838,21 +849,12 @@ meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native) if (!kms_update) continue; - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags); + meta_kms_update_add_result_listener (kms_update, + on_mode_sets_update_result, + NULL); - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - break; - case META_KMS_FEEDBACK_FAILED: - feedback_error = meta_kms_feedback_get_error (kms_feedback); - if (!g_error_matches (feedback_error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", feedback_error->message); - break; - } + meta_kms_post_pending_update_sync (kms, kms_device, + META_KMS_UPDATE_FLAG_NONE); } clear_detached_onscreens (renderer_native); @@ -876,40 +878,28 @@ unset_disabled_crtcs (MetaBackend *backend, MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (META_GPU_KMS (gpu)); GList *k; - gboolean did_mode_set = FALSE; - MetaKmsUpdateFlag flags; g_autoptr (MetaKmsFeedback) kms_feedback = NULL; + MetaKmsUpdate *kms_update = NULL; for (k = meta_gpu_get_crtcs (gpu); k; k = k->next) { MetaCrtc *crtc = k->data; - MetaKmsUpdate *kms_update; if (meta_crtc_get_config (crtc)) continue; kms_update = meta_kms_ensure_pending_update (kms, kms_device); meta_crtc_kms_set_mode (META_CRTC_KMS (crtc), kms_update); - - did_mode_set = TRUE; } - if (!did_mode_set) + if (!kms_update) continue; - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, - kms_device, - flags); - if (meta_kms_feedback_get_result (kms_feedback) != - META_KMS_FEEDBACK_PASSED) - { - const GError *error = meta_kms_feedback_get_error (kms_feedback); - - if (!g_error_matches (error, G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", error->message); - } + meta_kms_update_add_result_listener (kms_update, + on_mode_sets_update_result, + NULL); + meta_kms_post_pending_update_sync (kms, kms_device, + META_KMS_UPDATE_FLAG_NONE); } }