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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This commit is contained in:
Jonas Ådahl 2023-02-14 20:18:26 +01:00
parent 1e0367bf08
commit 7c9d4b8c7c
9 changed files with 131 additions and 1 deletions

View File

@ -361,6 +361,7 @@ assign_cursor_plane (MetaCursorRendererNative *native,
cursor_hotspot_y); cursor_hotspot_y);
meta_kms_update_add_result_listener (kms_update, meta_kms_update_add_result_listener (kms_update,
NULL,
on_kms_update_result, on_kms_update_result,
native); native);

View File

@ -128,6 +128,7 @@ typedef struct _MetaKmsPageFlipListener
struct _MetaKmsResultListener struct _MetaKmsResultListener
{ {
GMainContext *main_context;
MetaKmsResultListenerFunc func; MetaKmsResultListenerFunc func;
gpointer user_data; 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, void meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update,
MetaKmsPlane *plane); MetaKmsPlane *plane);
META_EXPORT_TEST
GList * meta_kms_update_take_result_listeners (MetaKmsUpdate *update); 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, void meta_kms_result_listener_set_feedback (MetaKmsResultListener *listener,
MetaKmsFeedback *feedback); MetaKmsFeedback *feedback);

View File

@ -607,6 +607,7 @@ meta_kms_plane_assignment_set_cursor_hotspot (MetaKmsPlaneAssignment *plane_assi
void void
meta_kms_update_add_result_listener (MetaKmsUpdate *update, meta_kms_update_add_result_listener (MetaKmsUpdate *update,
GMainContext *main_context,
MetaKmsResultListenerFunc func, MetaKmsResultListenerFunc func,
gpointer user_data) gpointer user_data)
{ {
@ -614,6 +615,7 @@ meta_kms_update_add_result_listener (MetaKmsUpdate *update,
listener = g_new0 (MetaKmsResultListener, 1); listener = g_new0 (MetaKmsResultListener, 1);
*listener = (MetaKmsResultListener) { *listener = (MetaKmsResultListener) {
.main_context = main_context,
.func = func, .func = func,
.user_data = user_data, .user_data = user_data,
}; };
@ -628,6 +630,12 @@ meta_kms_update_take_result_listeners (MetaKmsUpdate *update)
return g_steal_pointer (&update->result_listeners); return g_steal_pointer (&update->result_listeners);
} }
GMainContext *
meta_kms_result_listener_get_main_context (MetaKmsResultListener *listener)
{
return listener->main_context;
}
void void
meta_kms_result_listener_set_feedback (MetaKmsResultListener *listener, meta_kms_result_listener_set_feedback (MetaKmsResultListener *listener,
MetaKmsFeedback *feedback) MetaKmsFeedback *feedback)

View File

@ -92,6 +92,7 @@ GList * meta_kms_feedback_get_failed_planes (const MetaKmsFeedback *feedback);
const GError * meta_kms_feedback_get_error (const MetaKmsFeedback *feedback); const GError * meta_kms_feedback_get_error (const MetaKmsFeedback *feedback);
META_EXPORT_TEST
void meta_kms_feedback_dispatch_result (MetaKmsFeedback *feedback, void meta_kms_feedback_dispatch_result (MetaKmsFeedback *feedback,
MetaKms *kms, MetaKms *kms,
GList *result_listeners); GList *result_listeners);
@ -183,6 +184,7 @@ void meta_kms_plane_assignment_set_cursor_hotspot (MetaKmsPlaneAssignment *plane
META_EXPORT_TEST META_EXPORT_TEST
void meta_kms_update_add_result_listener (MetaKmsUpdate *update, void meta_kms_update_add_result_listener (MetaKmsUpdate *update,
GMainContext *main_context,
MetaKmsResultListenerFunc func, MetaKmsResultListenerFunc func,
gpointer user_data); gpointer user_data);

View File

@ -169,8 +169,11 @@ void
meta_kms_queue_result_callback (MetaKms *kms, meta_kms_queue_result_callback (MetaKms *kms,
MetaKmsResultListener *listener) MetaKmsResultListener *listener)
{ {
GMainContext *main_context =
meta_kms_result_listener_get_main_context (listener);
meta_kms_queue_callback (kms, meta_kms_queue_callback (kms,
NULL, main_context,
invoke_result_listener, invoke_result_listener,
listener, listener,
(GDestroyNotify) meta_kms_result_listener_free); (GDestroyNotify) meta_kms_result_listener_free);

View File

@ -1171,6 +1171,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_update = meta_frame_native_ensure_kms_update (frame_native,
kms_device); kms_device);
meta_kms_update_add_result_listener (kms_update, meta_kms_update_add_result_listener (kms_update,
NULL,
on_swap_buffer_update_result, on_swap_buffer_update_result,
onscreen_native); 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); kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device);
meta_kms_update_add_result_listener (kms_update, meta_kms_update_add_result_listener (kms_update,
NULL,
on_scanout_update_result, on_scanout_update_result,
onscreen_native); onscreen_native);
@ -1542,6 +1544,7 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
} }
meta_kms_update_add_result_listener (kms_update, meta_kms_update_add_result_listener (kms_update,
NULL,
on_finish_frame_update_result, on_finish_frame_update_result,
onscreen_native); onscreen_native);

View File

@ -865,6 +865,7 @@ post_mode_set_updates (MetaRendererNative *renderer_native)
g_hash_table_iter_steal (&iter); g_hash_table_iter_steal (&iter);
meta_kms_update_add_result_listener (kms_update, meta_kms_update_add_result_listener (kms_update,
NULL,
on_mode_sets_update_result, on_mode_sets_update_result,
NULL); NULL);

View File

@ -376,6 +376,7 @@ on_scanout_fallback_before_paint (ClutterStage *stage,
kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device);
meta_kms_update_add_result_listener (kms_update, meta_kms_update_add_result_listener (kms_update,
NULL,
on_scanout_fallback_result, test); on_scanout_fallback_result, test);
test->scanout_fallback.scanout_failed_view = stage_view; test->scanout_fallback.scanout_failed_view = stage_view;

View File

@ -22,6 +22,7 @@
#include <dlfcn.h> #include <dlfcn.h>
#include "backends/native/meta-backend-native.h"
#include "backends/native/meta-kms-connector.h" #include "backends/native/meta-kms-connector.h"
#include "backends/native/meta-kms-crtc.h" #include "backends/native/meta-kms-crtc.h"
#include "backends/native/meta-kms-device.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); 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 static void
init_tests (void) init_tests (void)
{ {
@ -761,6 +866,8 @@ init_tests (void)
meta_test_kms_update_merge); meta_test_kms_update_merge);
g_test_add_func ("/backends/native/kms/update/off-thread-page-flip", g_test_add_func ("/backends/native/kms/update/off-thread-page-flip",
meta_test_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 int