[mutter] kms: Add API to post callbacks out of the impl context



commit 2bbd2e55637430f011a35161e397f88b9dffd3c7
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Sun Mar 10 13:36:34 2019 +0100

    kms: Add API to post callbacks out of the impl context
    
    While the current impl context is in the same thread as the main
    context, the separation still exists, and to post callbacks from the
    impl context, it must pass MetaKms to make sure the callback is invoked
    in the right context.
    
    https://gitlab.gnome.org/GNOME/mutter/issues/548
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/525

 src/backends/native/meta-kms-private.h |  8 +++++
 src/backends/native/meta-kms.c         | 66 ++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+)
---
diff --git a/src/backends/native/meta-kms-private.h b/src/backends/native/meta-kms-private.h
index da59d7431..8c0ce9425 100644
--- a/src/backends/native/meta-kms-private.h
+++ b/src/backends/native/meta-kms-private.h
@@ -24,10 +24,18 @@
 
 #include "backends/native/meta-kms-types.h"
 
+typedef void (* MetaKmsCallback) (MetaKms  *kms,
+                                  gpointer  user_data);
+
 typedef gboolean (* MetaKmsImplTaskFunc) (MetaKmsImpl  *impl,
                                           gpointer      user_data,
                                           GError      **error);
 
+void meta_kms_queue_callback (MetaKms         *kms,
+                              MetaKmsCallback  callback,
+                              gpointer         user_data,
+                              GDestroyNotify   user_data_destroy);
+
 gboolean meta_kms_run_impl_task_sync (MetaKms              *kms,
                                       MetaKmsImplTaskFunc   func,
                                       gpointer              user_data,
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
index 4fd9c5ee4..408b9f5a2 100644
--- a/src/backends/native/meta-kms.c
+++ b/src/backends/native/meta-kms.c
@@ -27,6 +27,13 @@
 #include "backends/native/meta-kms-impl-simple.h"
 #include "backends/native/meta-udev.h"
 
+typedef struct _MetaKmsCallbackData
+{
+  MetaKmsCallback callback;
+  gpointer user_data;
+  GDestroyNotify user_data_destroy;
+} MetaKmsCallbackData;
+
 struct _MetaKms
 {
   GObject parent;
@@ -39,10 +46,62 @@ struct _MetaKms
   gboolean in_impl_task;
 
   GList *devices;
+
+  GList *pending_callbacks;
+  guint callback_source_id;
 };
 
 G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT)
 
+static void
+meta_kms_callback_data_free (MetaKmsCallbackData *callback_data)
+{
+  if (callback_data->user_data_destroy)
+    callback_data->user_data_destroy (callback_data->user_data);
+  g_slice_free (MetaKmsCallbackData, callback_data);
+}
+
+static gboolean
+callback_idle (gpointer user_data)
+{
+  MetaKms *kms = user_data;
+  GList *l;
+
+  for (l = kms->pending_callbacks; l; l = l->next)
+    {
+      MetaKmsCallbackData *callback_data = l->data;
+
+      callback_data->callback (kms, callback_data->user_data);
+      meta_kms_callback_data_free (callback_data);
+    }
+
+  g_list_free (kms->pending_callbacks);
+  kms->pending_callbacks = NULL;
+
+  kms->callback_source_id = 0;
+  return G_SOURCE_REMOVE;
+}
+
+void
+meta_kms_queue_callback (MetaKms         *kms,
+                         MetaKmsCallback  callback,
+                         gpointer         user_data,
+                         GDestroyNotify   user_data_destroy)
+{
+  MetaKmsCallbackData *callback_data;
+
+  callback_data = g_slice_new0 (MetaKmsCallbackData);
+  *callback_data = (MetaKmsCallbackData) {
+    .callback = callback,
+    .user_data = user_data,
+    .user_data_destroy = user_data_destroy,
+  };
+  kms->pending_callbacks = g_list_append (kms->pending_callbacks,
+                                          callback_data);
+  if (!kms->callback_source_id)
+    kms->callback_source_id = g_idle_add (callback_idle, kms);
+}
+
 gboolean
 meta_kms_run_impl_task_sync (MetaKms              *kms,
                              MetaKmsImplTaskFunc   func,
@@ -155,6 +214,13 @@ meta_kms_finalize (GObject *object)
   MetaKms *kms = META_KMS (object);
   MetaBackendNative *backend_native = META_BACKEND_NATIVE (kms->backend);
   MetaUdev *udev = meta_backend_native_get_udev (backend_native);
+  GList *l;
+
+  for (l = kms->pending_callbacks; l; l = l->next)
+    meta_kms_callback_data_free (l->data);
+  g_list_free (kms->pending_callbacks);
+
+  g_clear_handle_id (&kms->callback_source_id, g_source_remove);
 
   g_list_free_full (kms->devices, g_object_unref);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]