From 7c9d4b8c7c2014978f6e4b356052362c5143b9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 14 Feb 2023 20:18:26 +0100 Subject: [PATCH] kms/result-listener: Allow setting a custom main context While the default when passing NULL will be the main context of the main thread, make it possible to specify another main context, so that result handlers can be invoked on the right thread. Part-of: --- .../native/meta-cursor-renderer-native.c | 1 + src/backends/native/meta-kms-update-private.h | 4 + src/backends/native/meta-kms-update.c | 8 ++ src/backends/native/meta-kms-update.h | 2 + src/backends/native/meta-kms.c | 5 +- src/backends/native/meta-onscreen-native.c | 3 + src/backends/native/meta-renderer-native.c | 1 + src/tests/native-kms-render.c | 1 + src/tests/native-kms-updates.c | 107 ++++++++++++++++++ 9 files changed, 131 insertions(+), 1 deletion(-) diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c index f1b7459fe..f9dcee470 100644 --- a/src/backends/native/meta-cursor-renderer-native.c +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -361,6 +361,7 @@ assign_cursor_plane (MetaCursorRendererNative *native, cursor_hotspot_y); meta_kms_update_add_result_listener (kms_update, + NULL, on_kms_update_result, native); diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h index 962117a92..477b2dd53 100644 --- a/src/backends/native/meta-kms-update-private.h +++ b/src/backends/native/meta-kms-update-private.h @@ -128,6 +128,7 @@ typedef struct _MetaKmsPageFlipListener struct _MetaKmsResultListener { + GMainContext *main_context; MetaKmsResultListenerFunc func; gpointer user_data; @@ -191,8 +192,11 @@ MetaKmsCustomPageFlip * meta_kms_update_take_custom_page_flip_func (MetaKmsUpdat void meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update, MetaKmsPlane *plane); +META_EXPORT_TEST GList * meta_kms_update_take_result_listeners (MetaKmsUpdate *update); +GMainContext * meta_kms_result_listener_get_main_context (MetaKmsResultListener *listener); + void meta_kms_result_listener_set_feedback (MetaKmsResultListener *listener, MetaKmsFeedback *feedback); diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c index d7588124e..0c9cdf22b 100644 --- a/src/backends/native/meta-kms-update.c +++ b/src/backends/native/meta-kms-update.c @@ -607,6 +607,7 @@ meta_kms_plane_assignment_set_cursor_hotspot (MetaKmsPlaneAssignment *plane_assi void meta_kms_update_add_result_listener (MetaKmsUpdate *update, + GMainContext *main_context, MetaKmsResultListenerFunc func, gpointer user_data) { @@ -614,6 +615,7 @@ meta_kms_update_add_result_listener (MetaKmsUpdate *update, listener = g_new0 (MetaKmsResultListener, 1); *listener = (MetaKmsResultListener) { + .main_context = main_context, .func = func, .user_data = user_data, }; @@ -628,6 +630,12 @@ meta_kms_update_take_result_listeners (MetaKmsUpdate *update) return g_steal_pointer (&update->result_listeners); } +GMainContext * +meta_kms_result_listener_get_main_context (MetaKmsResultListener *listener) +{ + return listener->main_context; +} + void meta_kms_result_listener_set_feedback (MetaKmsResultListener *listener, MetaKmsFeedback *feedback) diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h index 8024a3f33..f98bcceaf 100644 --- a/src/backends/native/meta-kms-update.h +++ b/src/backends/native/meta-kms-update.h @@ -92,6 +92,7 @@ GList * meta_kms_feedback_get_failed_planes (const MetaKmsFeedback *feedback); const GError * meta_kms_feedback_get_error (const MetaKmsFeedback *feedback); +META_EXPORT_TEST void meta_kms_feedback_dispatch_result (MetaKmsFeedback *feedback, MetaKms *kms, GList *result_listeners); @@ -183,6 +184,7 @@ void meta_kms_plane_assignment_set_cursor_hotspot (MetaKmsPlaneAssignment *plane META_EXPORT_TEST void meta_kms_update_add_result_listener (MetaKmsUpdate *update, + GMainContext *main_context, MetaKmsResultListenerFunc func, gpointer user_data); diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index 158e34aaa..48915814a 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -169,8 +169,11 @@ void meta_kms_queue_result_callback (MetaKms *kms, MetaKmsResultListener *listener) { + GMainContext *main_context = + meta_kms_result_listener_get_main_context (listener); + meta_kms_queue_callback (kms, - NULL, + main_context, invoke_result_listener, listener, (GDestroyNotify) meta_kms_result_listener_free); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 850fadf6d..a7e463bb5 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -1171,6 +1171,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, + NULL, on_swap_buffer_update_result, onscreen_native); @@ -1389,6 +1390,7 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, + NULL, on_scanout_update_result, onscreen_native); @@ -1542,6 +1544,7 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, } meta_kms_update_add_result_listener (kms_update, + NULL, on_finish_frame_update_result, onscreen_native); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 4da361e2b..10fb7bbba 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -865,6 +865,7 @@ post_mode_set_updates (MetaRendererNative *renderer_native) g_hash_table_iter_steal (&iter); meta_kms_update_add_result_listener (kms_update, + NULL, on_mode_sets_update_result, NULL); diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c index 1557b764e..b19035237 100644 --- a/src/tests/native-kms-render.c +++ b/src/tests/native-kms-render.c @@ -376,6 +376,7 @@ on_scanout_fallback_before_paint (ClutterStage *stage, kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, + NULL, on_scanout_fallback_result, test); test->scanout_fallback.scanout_failed_view = stage_view; diff --git a/src/tests/native-kms-updates.c b/src/tests/native-kms-updates.c index 3ce063d74..6f09b0143 100644 --- a/src/tests/native-kms-updates.c +++ b/src/tests/native-kms-updates.c @@ -22,6 +22,7 @@ #include +#include "backends/native/meta-backend-native.h" #include "backends/native/meta-kms-connector.h" #include "backends/native/meta-kms-crtc.h" #include "backends/native/meta-kms-device.h" @@ -744,6 +745,110 @@ meta_test_kms_update_off_thread_page_flip (void) g_mutex_clear (&data.init_mutex); } +typedef struct +{ + GMutex init_mutex; + GCond init_cond; + gboolean initialized; + + GMainContext *thread_main_context; + GMainLoop *thread_loop; + GThread *thread; + + GMainLoop *main_thread_loop; +} CallbackData; + +static gpointer +off_thread_callback_thread_func (gpointer user_data) +{ + CallbackData *data = user_data; + MetaBackend *backend = meta_context_get_backend (test_context); + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); + MetaKms *kms = meta_backend_native_get_kms (backend_native); + + meta_thread_register_callback_context (META_THREAD (kms), + data->thread_main_context); + + data->thread_loop = g_main_loop_new (data->thread_main_context, FALSE); + + g_mutex_lock (&data->init_mutex); + data->initialized = TRUE; + g_cond_signal (&data->init_cond); + g_mutex_unlock (&data->init_mutex); + + g_assert (data->thread == g_thread_self ()); + + g_main_loop_run (data->thread_loop); + g_main_loop_unref (data->thread_loop); + + meta_thread_unregister_callback_context (META_THREAD (kms), + data->thread_main_context); + + return GINT_TO_POINTER (TRUE); +} + +static void +on_main_thread_result (const MetaKmsFeedback *feedback, + gpointer user_data) +{ + CallbackData *data = user_data; + + g_main_loop_quit (data->main_thread_loop); +} + +static void +on_callback_thread_result (const MetaKmsFeedback *feedback, + gpointer user_data) +{ + CallbackData *data = user_data; + + g_main_loop_quit (data->thread_loop); +} + +static void +meta_test_kms_update_feedback (void) +{ + CallbackData data = {}; + MetaKmsDevice *device; + MetaKmsUpdate *update; + g_autoptr (MetaDrmBuffer) buffer = NULL; + g_autoptr (MetaKmsFeedback) kms_feedback = NULL; + + data.main_thread_loop = g_main_loop_new (NULL, FALSE); + + g_mutex_init (&data.init_mutex); + g_cond_init (&data.init_cond); + g_mutex_lock (&data.init_mutex); + data.thread_main_context = g_main_context_new (); + data.thread = g_thread_new ("Callback test thread", + off_thread_callback_thread_func, + &data); + while (!data.initialized) + g_cond_wait (&data.init_cond, &data.init_mutex); + g_mutex_unlock (&data.init_mutex); + + device = meta_get_test_kms_device (test_context); + update = meta_kms_update_new (device); + populate_update (update, &buffer, POPULATE_UPDATE_FLAG_MODE); + + meta_kms_update_add_result_listener (update, NULL, + on_main_thread_result, + &data); + meta_kms_update_add_result_listener (update, data.thread_main_context, + on_callback_thread_result, + &data); + + kms_feedback = meta_kms_device_process_update_sync (device, update, + META_KMS_UPDATE_FLAG_NONE); + + g_main_loop_run (data.main_thread_loop); + + g_assert_cmpint (GPOINTER_TO_INT (g_thread_join (data.thread)), ==, TRUE); + g_main_context_unref (data.thread_main_context); + g_mutex_clear (&data.init_mutex); + g_cond_clear (&data.init_cond); +} + static void init_tests (void) { @@ -761,6 +866,8 @@ init_tests (void) meta_test_kms_update_merge); g_test_add_func ("/backends/native/kms/update/off-thread-page-flip", meta_test_kms_update_off_thread_page_flip); + g_test_add_func ("/backends/native/kms/update/feedback", + meta_test_kms_update_feedback); } int