[mutter] kms: Have the device impl open device files themself



commit e6421dc5da9d6e452d7d887f71f425f16157d7ec
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Tue Apr 6 12:14:24 2021 +0200

    kms: Have the device impl open device files themself
    
    This changes the way the KMS backends load; if we're headless, we always
    use the dummy one and fail otherwise; in other cases, we first try the
    atomic backend, and if that fails, fall back on the simple one.
    
    The aim for this is to have the impl device open and close the device
    when needed, using the device pool directly.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1828>

 src/backends/native/meta-kms-device.c             | 201 +++++-----------------
 src/backends/native/meta-kms-impl-device-atomic.c |  78 ++++++++-
 src/backends/native/meta-kms-impl-device-dummy.c  |  64 ++++++-
 src/backends/native/meta-kms-impl-device-simple.c |  30 ++++
 src/backends/native/meta-kms-impl-device.c        | 115 +++++++------
 src/backends/native/meta-kms-impl-device.h        |  14 ++
 6 files changed, 289 insertions(+), 213 deletions(-)
---
diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c
index 6fe8cc2a1e..4f0793ece2 100644
--- a/src/backends/native/meta-kms-device.c
+++ b/src/backends/native/meta-kms-device.c
@@ -230,7 +230,6 @@ meta_kms_device_add_fake_plane_in_impl (MetaKmsDevice    *device,
 typedef struct _CreateImplDeviceData
 {
   MetaKmsDevice *device;
-  MetaDeviceFile *device_file;
   const char *path;
   MetaKmsDeviceFlag flags;
 
@@ -245,170 +244,70 @@ typedef struct _CreateImplDeviceData
   char *out_path;
 } CreateImplDeviceData;
 
-static gboolean
-is_atomic_allowed (const char *driver_name)
+static const char *
+impl_device_type_to_string (GType type)
 {
-  const char *atomic_driver_deny_list[] = {
-    "qxl",
-    "vmwgfx",
-    "vboxvideo",
-    "nvidia-drm",
-    NULL,
-  };
-
-  return !g_strv_contains (atomic_driver_deny_list, driver_name);
-}
-
-static gboolean
-get_driver_info (int    fd,
-                 char **name,
-                 char **description)
-{
-  drmVersion *drm_version;
-
-  drm_version = drmGetVersion (fd);
-  if (!drm_version)
-    return FALSE;
-
-  *name = g_strndup (drm_version->name,
-                     drm_version->name_len);
-  *description = g_strndup (drm_version->desc,
-                            drm_version->desc_len);
-  drmFreeVersion (drm_version);
-
-  return TRUE;
+  if (type == META_TYPE_KMS_IMPL_DEVICE_ATOMIC)
+    return "atomic modesetting";
+  else if (type == META_TYPE_KMS_IMPL_DEVICE_SIMPLE)
+    return "legacy modesetting";
+  else if (type == META_TYPE_KMS_IMPL_DEVICE_DUMMY)
+    return "no modesetting";
+  g_assert_not_reached();
 }
 
 static MetaKmsImplDevice *
 meta_create_kms_impl_device (MetaKmsDevice      *device,
                              MetaKmsImpl        *impl,
-                             MetaDeviceFile     *device_file,
                              const char         *path,
                              MetaKmsDeviceFlag   flags,
                              GError            **error)
 {
-  GType impl_device_type;
-  gboolean supports_atomic_mode_setting;
-  g_autofree char *driver_name = NULL;
-  g_autofree char *driver_description = NULL;
-  const char *atomic_kms_enable_env;
-  int fd;
-  g_autoptr (MetaDeviceFile) impl_device_file = NULL;
-  MetaKmsImplDevice *impl_device;
-
   meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl));
 
-  fd = meta_device_file_get_fd (device_file);
-  if (!get_driver_info (fd, &driver_name, &driver_description))
-    {
-      driver_name = g_strdup ("unknown");
-      driver_description = g_strdup ("Unknown");
-    }
-
-  atomic_kms_enable_env = getenv ("MUTTER_DEBUG_ENABLE_ATOMIC_KMS");
-
   if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING)
     {
-      g_autofree char *render_node_path = NULL;
-      MetaDevicePool *device_pool;
-
-      render_node_path = drmGetRenderDeviceNameFromFd (fd);
-      if (!render_node_path)
-        {
-          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                       "Couldn't find render node device for '%s' (%s)",
-                       path, driver_name);
-          return NULL;
-        }
-
-      device_pool = meta_device_file_get_pool (device_file);
-
-      impl_device_file = meta_device_pool_open (device_pool, render_node_path,
-                                                META_DEVICE_FILE_FLAG_NONE,
-                                                error);
-      if (!impl_device_file)
-        return NULL;
-
-      g_message ("Adding device '%s' (from '%s', %s) using no mode setting.",
-                 render_node_path, path, driver_name);
-
-      impl_device_type = META_TYPE_KMS_IMPL_DEVICE_DUMMY;
-    }
-  else if (atomic_kms_enable_env)
-    {
-      if (g_strcmp0 (atomic_kms_enable_env, "1") == 0)
-        {
-          impl_device_type = META_TYPE_KMS_IMPL_DEVICE_ATOMIC;
-          if (drmSetClientCap (fd, DRM_CLIENT_CAP_ATOMIC, 1) != 0)
-            {
-              g_error ("Failed to force atomic mode setting on '%s' (%s).",
-                       path, driver_name);
-            }
-        }
-      else if (g_strcmp0 (atomic_kms_enable_env, "0") == 0)
-        {
-          impl_device_type = META_TYPE_KMS_IMPL_DEVICE_SIMPLE;
-        }
-      else
-        {
-          g_error ("Invalid value '%s' for MUTTER_DEBUG_ENABLE_ATOMIC_KMS, "
-                   "bailing.",
-                   atomic_kms_enable_env);
-        }
-
-      impl_device_file = meta_device_file_acquire (device_file);
-
-      g_message ("Mode setting implementation for '%s' (%s) forced (%s).",
-                 path, driver_name,
-                 impl_device_type == META_TYPE_KMS_IMPL_DEVICE_ATOMIC ?
-                   "atomic" : "non-atomic");
-    }
-  else if (!is_atomic_allowed (driver_name))
-    {
-      g_message ("Adding device '%s' (%s) using non-atomic mode setting"
-                 " (using atomic mode setting not allowed).",
-                 path, driver_name);
-      impl_device_file = meta_device_file_acquire (device_file);
-      impl_device_type = META_TYPE_KMS_IMPL_DEVICE_SIMPLE;
+      return g_initable_new (META_TYPE_KMS_IMPL_DEVICE_DUMMY,
+                             NULL, error,
+                             "device", device,
+                             "impl", impl,
+                             "path", path,
+                             "flags", flags,
+                             NULL);
     }
   else
     {
-      int ret;
+      GType impl_device_types[] = {
+        META_TYPE_KMS_IMPL_DEVICE_ATOMIC,
+        META_TYPE_KMS_IMPL_DEVICE_SIMPLE,
+      };
+      int i;
 
-      ret = drmSetClientCap (fd, DRM_CLIENT_CAP_ATOMIC, 1);
-      if (ret == 0)
-        supports_atomic_mode_setting = TRUE;
-      else
-        supports_atomic_mode_setting = FALSE;
-
-      if (supports_atomic_mode_setting)
-        {
-          g_message ("Adding device '%s' (%s) using atomic mode setting.",
-                     path, driver_name);
-          impl_device_type = META_TYPE_KMS_IMPL_DEVICE_ATOMIC;
-        }
-      else
+      for (i = 0; i < G_N_ELEMENTS (impl_device_types); i++)
         {
-          g_message ("Adding device '%s' (%s) using non-atomic mode setting.",
-                     path, driver_name);
-          impl_device_type = META_TYPE_KMS_IMPL_DEVICE_SIMPLE;
+          MetaKmsImplDevice *impl_device;
+          g_autoptr (GError) local_error = NULL;
+
+          impl_device = g_initable_new (impl_device_types[i],
+                                        NULL, &local_error,
+                                        "device", device,
+                                        "impl", impl,
+                                        "path", path,
+                                        "flags", flags,
+                                        NULL);
+          if (impl_device)
+            return impl_device;
+
+          if (local_error->domain != META_KMS_ERROR)
+            {
+              g_warning ("Failed to open %s backend: %s",
+                         impl_device_type_to_string (impl_device_types[i]),
+                         local_error->message);
+            }
         }
 
-      impl_device_file = meta_device_file_acquire (device_file);
+      return NULL;
     }
-
-  impl_device = g_initable_new (impl_device_type, NULL, error,
-                                "device", device,
-                                "impl", impl,
-                                "device-file", impl_device_file,
-                                "flags", flags,
-                                "driver-name", driver_name,
-                                "driver-description", driver_description,
-                                NULL);
-  if (!impl_device)
-    return NULL;
-
-  return impl_device;
 }
 
 static gpointer
@@ -421,7 +320,6 @@ create_impl_device_in_impl (MetaKmsImpl  *impl,
 
   impl_device = meta_create_kms_impl_device (data->device,
                                              impl,
-                                             data->device_file,
                                              data->path,
                                              data->flags,
                                              error);
@@ -452,29 +350,14 @@ meta_kms_device_new (MetaKms            *kms,
                      MetaKmsDeviceFlag   flags,
                      GError            **error)
 {
-  MetaBackend *backend = meta_kms_get_backend (kms);
-  MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
-  MetaDevicePool *device_pool =
-    meta_backend_native_get_device_pool (backend_native);
   MetaKmsDevice *device;
   CreateImplDeviceData data;
-  g_autoptr (MetaDeviceFile) device_file = NULL;
-  MetaDeviceFileFlags device_file_flags;
-
-  device_file_flags = META_DEVICE_FILE_FLAG_NONE;
-  if (!(flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING))
-    device_file_flags |= META_DEVICE_FILE_FLAG_TAKE_CONTROL;
-
-  device_file = meta_device_pool_open (device_pool, path, flags, error);
-  if (!device_file)
-    return NULL;
 
   device = g_object_new (META_TYPE_KMS_DEVICE, NULL);
   device->kms = kms;
 
   data = (CreateImplDeviceData) {
     .device = device,
-    .device_file = device_file,
     .path = path,
     .flags = flags,
   };
diff --git a/src/backends/native/meta-kms-impl-device-atomic.c 
b/src/backends/native/meta-kms-impl-device-atomic.c
index 4115b9b05d..4fdf60f280 100644
--- a/src/backends/native/meta-kms-impl-device-atomic.c
+++ b/src/backends/native/meta-kms-impl-device-atomic.c
@@ -21,6 +21,7 @@
 
 #include "backends/native/meta-kms-impl-device-atomic.h"
 
+#include "backends/native/meta-backend-native-private.h"
 #include "backends/native/meta-kms-connector-private.h"
 #include "backends/native/meta-kms-crtc-private.h"
 #include "backends/native/meta-kms-device-private.h"
@@ -44,6 +45,8 @@ struct _MetaKmsImplDeviceAtomic
   GHashTable *page_flip_datas;
 };
 
+static GInitableIface *initable_parent_iface;
+
 static void
 initable_iface_init (GInitableIface *iface);
 
@@ -1039,14 +1042,83 @@ meta_kms_impl_device_atomic_finalize (GObject *object)
   G_OBJECT_CLASS (meta_kms_impl_device_atomic_parent_class)->finalize (object);
 }
 
+static MetaDeviceFile *
+meta_kms_impl_device_atomic_open_device_file (MetaKmsImplDevice  *impl_device,
+                                              const char         *path,
+                                              GError            **error)
+{
+  MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
+  MetaKms *kms = meta_kms_device_get_kms (device);
+  MetaBackend *backend = meta_kms_get_backend (kms);
+  MetaDevicePool *device_pool =
+    meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend));
+  g_autoptr (MetaDeviceFile) device_file = NULL;
+
+  device_file = meta_device_pool_open (device_pool, path,
+                                       META_DEVICE_FILE_FLAG_TAKE_CONTROL,
+                                       error);
+  if (!device_file)
+    return NULL;
+
+  if (drmSetClientCap (meta_device_file_get_fd (device_file),
+                       DRM_CLIENT_CAP_ATOMIC, 1) != 0)
+    {
+      g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED,
+                   "DRM_CLIENT_CAP_ATOMIC not supported");
+      return NULL;
+    }
+
+  return g_steal_pointer (&device_file);
+}
+
+static gboolean
+is_atomic_allowed (const char *driver_name)
+{
+  const char *atomic_driver_deny_list[] = {
+    "qxl",
+    "vmwgfx",
+    "vboxvideo",
+    "nvidia-drm",
+    NULL,
+  };
+
+  return !g_strv_contains (atomic_driver_deny_list, driver_name);
+}
+
 static gboolean
 meta_kms_impl_device_atomic_initable_init (GInitable     *initable,
                                            GCancellable  *cancellable,
                                            GError       **error)
 {
   MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable);
+  const char *atomic_kms_enable_env;
+
+  atomic_kms_enable_env = getenv ("MUTTER_DEBUG_ENABLE_ATOMIC_KMS");
+  if (atomic_kms_enable_env && g_strcmp0 (atomic_kms_enable_env, "1") != 0)
+    {
+      g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_USER_INHIBITED,
+                   "Atomic mode setting disable via env var");
+      return FALSE;
+    }
+
+  if (!initable_parent_iface->init (initable, cancellable, error))
+    return FALSE;
 
-  return meta_kms_impl_device_init_mode_setting (impl_device, error);
+  if (!is_atomic_allowed (meta_kms_impl_device_get_driver_name (impl_device)))
+    {
+      g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_DENY_LISTED,
+                   "Atomic mode setting disable via driver deny list");
+      return FALSE;
+    }
+
+  if (!meta_kms_impl_device_init_mode_setting (impl_device, error))
+    return FALSE;
+
+  g_message ("Added device '%s' (%s) using atomic mode setting.",
+             meta_kms_impl_device_get_path (impl_device),
+             meta_kms_impl_device_get_driver_name (impl_device));
+
+  return TRUE;
 }
 
 static void
@@ -1058,6 +1130,8 @@ meta_kms_impl_device_atomic_init (MetaKmsImplDeviceAtomic *impl_device_atomic)
 static void
 initable_iface_init (GInitableIface *iface)
 {
+  initable_parent_iface = g_type_interface_peek_parent (iface);
+
   iface->init = meta_kms_impl_device_atomic_initable_init;
 }
 
@@ -1070,6 +1144,8 @@ meta_kms_impl_device_atomic_class_init (MetaKmsImplDeviceAtomicClass *klass)
 
   object_class->finalize = meta_kms_impl_device_atomic_finalize;
 
+  impl_device_class->open_device_file =
+    meta_kms_impl_device_atomic_open_device_file;
   impl_device_class->setup_drm_event_context =
     meta_kms_impl_device_atomic_setup_drm_event_context;
   impl_device_class->process_update =
diff --git a/src/backends/native/meta-kms-impl-device-dummy.c 
b/src/backends/native/meta-kms-impl-device-dummy.c
index 22e326c329..02583bbebe 100644
--- a/src/backends/native/meta-kms-impl-device-dummy.c
+++ b/src/backends/native/meta-kms-impl-device-dummy.c
@@ -21,15 +21,21 @@
 
 #include "backends/native/meta-kms-impl-device-dummy.h"
 
+#include "backends/native/meta-backend-native-private.h"
+#include "backends/native/meta-kms.h"
+
 struct _MetaKmsImplDeviceDummy
 {
   MetaKmsImplDevice parent;
 };
 
+static GInitableIface *initable_parent_iface;
+
 static void
 initable_iface_init (GInitableIface *iface);
 
-G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceDummy, meta_kms_impl_device_dummy,
+G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceDummy,
+                         meta_kms_impl_device_dummy,
                          META_TYPE_KMS_IMPL_DEVICE,
                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
                                                 initable_iface_init))
@@ -39,9 +45,43 @@ meta_kms_impl_device_dummy_discard_pending_page_flips (MetaKmsImplDevice *impl_d
 {
 }
 
-static void
-meta_kms_impl_device_dummy_init (MetaKmsImplDeviceDummy *impl_device_dummy)
+static MetaDeviceFile *
+meta_kms_impl_device_dummy_open_device_file (MetaKmsImplDevice  *impl_device,
+                                             const char         *path,
+                                             GError            **error)
 {
+  MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
+  MetaKms *kms = meta_kms_device_get_kms (device);
+  MetaBackend *backend = meta_kms_get_backend (kms);
+  MetaDevicePool *device_pool =
+    meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend));
+  g_autoptr (MetaDeviceFile) device_file = NULL;
+  int fd;
+  g_autofree char *render_node_path = NULL;
+
+  device_file = meta_device_pool_open (device_pool, path,
+                                       META_DEVICE_FILE_FLAG_NONE,
+                                       error);
+  if (!device_file)
+    return NULL;
+
+  fd = meta_device_file_get_fd (device_file);
+  render_node_path = drmGetRenderDeviceNameFromFd (fd);
+  if (!render_node_path)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Couldn't find render node device for '%s' (%s)",
+                   meta_kms_impl_device_get_path (impl_device),
+                   meta_kms_impl_device_get_driver_name (impl_device));
+      return NULL;
+    }
+
+  meta_topic (META_DEBUG_KMS, "Found render node '%s' from '%s'",
+              render_node_path, path);
+
+  return meta_device_pool_open (device_pool, render_node_path,
+                                META_DEVICE_FILE_FLAG_NONE,
+                                error);
 }
 
 static gboolean
@@ -49,21 +89,39 @@ meta_kms_impl_device_dummy_initable_init (GInitable     *initable,
                                           GCancellable  *cancellable,
                                           GError       **error)
 {
+  MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable);
+
+  if (!initable_parent_iface->init (initable, cancellable, error))
+    return FALSE;
+
+  g_message ("Added device '%s' (%s) using no mode setting.",
+             meta_kms_impl_device_get_path (impl_device),
+             meta_kms_impl_device_get_driver_name (impl_device));
+
   return TRUE;
 }
 
 static void
 initable_iface_init (GInitableIface *iface)
 {
+  initable_parent_iface = g_type_interface_peek_parent (iface);
+
   iface->init = meta_kms_impl_device_dummy_initable_init;
 }
 
+static void
+meta_kms_impl_device_dummy_init (MetaKmsImplDeviceDummy *impl_device_dummy)
+{
+}
+
 static void
 meta_kms_impl_device_dummy_class_init (MetaKmsImplDeviceDummyClass *klass)
 {
   MetaKmsImplDeviceClass *impl_device_class =
     META_KMS_IMPL_DEVICE_CLASS (klass);
 
+  impl_device_class->open_device_file =
+    meta_kms_impl_device_dummy_open_device_file;
   impl_device_class->discard_pending_page_flips =
     meta_kms_impl_device_dummy_discard_pending_page_flips;
 }
diff --git a/src/backends/native/meta-kms-impl-device-simple.c 
b/src/backends/native/meta-kms-impl-device-simple.c
index 7e8a49413e..02f87b62c7 100644
--- a/src/backends/native/meta-kms-impl-device-simple.c
+++ b/src/backends/native/meta-kms-impl-device-simple.c
@@ -21,6 +21,7 @@
 
 #include "backends/native/meta-kms-impl-device-simple.h"
 
+#include "backends/native/meta-backend-native-private.h"
 #include "backends/native/meta-drm-buffer-gbm.h"
 #include "backends/native/meta-kms-connector-private.h"
 #include "backends/native/meta-kms-crtc-private.h"
@@ -60,6 +61,8 @@ struct _MetaKmsImplDeviceSimple
   GHashTable *cached_mode_sets;
 };
 
+static GInitableIface *initable_parent_iface;
+
 static void
 initable_iface_init (GInitableIface *iface);
 
@@ -1534,6 +1537,22 @@ meta_kms_impl_device_simple_finalize (GObject *object)
   G_OBJECT_CLASS (meta_kms_impl_device_simple_parent_class)->finalize (object);
 }
 
+static MetaDeviceFile *
+meta_kms_impl_device_simple_open_device_file (MetaKmsImplDevice  *impl_device,
+                                              const char         *path,
+                                              GError            **error)
+{
+  MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
+  MetaKms *kms = meta_kms_device_get_kms (device);
+  MetaBackend *backend = meta_kms_get_backend (kms);
+  MetaDevicePool *device_pool =
+    meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend));
+
+  return meta_device_pool_open (device_pool, path,
+                                META_DEVICE_FILE_FLAG_TAKE_CONTROL,
+                                error);
+}
+
 static gboolean
 meta_kms_impl_device_simple_initable_init (GInitable     *initable,
                                            GCancellable  *cancellable,
@@ -1545,6 +1564,9 @@ meta_kms_impl_device_simple_initable_init (GInitable     *initable,
   MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
   GList *l;
 
+  if (!initable_parent_iface->init (initable, cancellable, error))
+    return FALSE;
+
   if (!meta_kms_impl_device_init_mode_setting (impl_device, error))
     return FALSE;
 
@@ -1573,6 +1595,10 @@ meta_kms_impl_device_simple_initable_init (GInitable     *initable,
                                               crtc);
     }
 
+  g_message ("Added device '%s' (%s) using non-atomic mode setting.",
+             meta_kms_impl_device_get_path (impl_device),
+             meta_kms_impl_device_get_driver_name (impl_device));
+
   return TRUE;
 }
 
@@ -1584,6 +1610,8 @@ meta_kms_impl_device_simple_init (MetaKmsImplDeviceSimple *impl_device_simple)
 static void
 initable_iface_init (GInitableIface *iface)
 {
+  initable_parent_iface = g_type_interface_peek_parent (iface);
+
   iface->init = meta_kms_impl_device_simple_initable_init;
 }
 
@@ -1596,6 +1624,8 @@ meta_kms_impl_device_simple_class_init (MetaKmsImplDeviceSimpleClass *klass)
 
   object_class->finalize = meta_kms_impl_device_simple_finalize;
 
+  impl_device_class->open_device_file =
+    meta_kms_impl_device_simple_open_device_file;
   impl_device_class->setup_drm_event_context =
     meta_kms_impl_device_simple_setup_drm_event_context;
   impl_device_class->process_update =
diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c
index ee8b91e64b..40cf8c41f2 100644
--- a/src/backends/native/meta-kms-impl-device.c
+++ b/src/backends/native/meta-kms-impl-device.c
@@ -47,10 +47,8 @@ enum
 
   PROP_DEVICE,
   PROP_IMPL,
-  PROP_DEVICE_FILE,
+  PROP_PATH,
   PROP_FLAGS,
-  PROP_DRIVER_NAME,
-  PROP_DRIVER_DESCRIPTION,
 
   N_PROPS
 };
@@ -79,9 +77,16 @@ typedef struct _MetaKmsImplDevicePrivate
   GList *fallback_modes;
 } MetaKmsImplDevicePrivate;
 
+static void
+initable_iface_init (GInitableIface *iface);
+
 G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDevice, meta_kms_impl_device,
                          G_TYPE_OBJECT,
-                         G_ADD_PRIVATE (MetaKmsImplDevice))
+                         G_ADD_PRIVATE (MetaKmsImplDevice)
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+                                                initable_iface_init))
+
+G_DEFINE_QUARK (-meta-kms-error-quark, meta_kms_error)
 
 MetaKmsDevice *
 meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device)
@@ -711,18 +716,9 @@ meta_kms_impl_device_get_property (GObject    *object,
     case PROP_IMPL:
       g_value_set_object (value, priv->impl);
       break;
-    case PROP_DEVICE_FILE:
-      g_value_set_pointer (value, priv->device_file);
-      break;
     case PROP_FLAGS:
       g_value_set_flags (value, priv->flags);
       break;
-    case PROP_DRIVER_NAME:
-      g_value_set_string (value, priv->driver_name);
-      break;
-    case PROP_DRIVER_DESCRIPTION:
-      g_value_set_string (value, priv->driver_name);
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -747,19 +743,12 @@ meta_kms_impl_device_set_property (GObject      *object,
     case PROP_IMPL:
       priv->impl = g_value_get_object (value);
       break;
-    case PROP_DEVICE_FILE:
-      priv->device_file =
-        meta_device_file_acquire (g_value_get_pointer (value));
+    case PROP_PATH:
+      priv->path = g_value_dup_string (value);
       break;
     case PROP_FLAGS:
       priv->flags = g_value_get_flags (value);
       break;
-    case PROP_DRIVER_NAME:
-      priv->driver_name = g_value_dup_string (value);
-      break;
-    case PROP_DRIVER_DESCRIPTION:
-      priv->driver_description = g_value_dup_string (value);
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -849,16 +838,52 @@ meta_kms_impl_device_prepare_shutdown (MetaKmsImplDevice *impl_device)
     klass->prepare_shutdown (impl_device);
 }
 
-static void
-meta_kms_impl_device_constructed (GObject *object)
+static gboolean
+get_driver_info (int    fd,
+                 char **name,
+                 char **description)
 {
-  MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (object);
+  drmVersion *drm_version;
+
+  drm_version = drmGetVersion (fd);
+  if (!drm_version)
+    return FALSE;
+
+  *name = g_strndup (drm_version->name,
+                     drm_version->name_len);
+  *description = g_strndup (drm_version->desc,
+                            drm_version->desc_len);
+  drmFreeVersion (drm_version);
+
+  return TRUE;
+}
+
+static gboolean
+meta_kms_impl_device_initable_init (GInitable     *initable,
+                                    GCancellable  *cancellable,
+                                    GError       **error)
+{
+  MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable);
   MetaKmsImplDevicePrivate *priv =
     meta_kms_impl_device_get_instance_private (impl_device);
+  MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
+  int fd;
+
+  priv->device_file = klass->open_device_file (impl_device, priv->path, error);
+  if (!priv->device_file)
+    return FALSE;
 
+  g_clear_pointer (&priv->path, g_free);
   priv->path = g_strdup (meta_device_file_get_path (priv->device_file));
 
-  G_OBJECT_CLASS (meta_kms_impl_device_parent_class)->constructed (object);
+  fd = meta_device_file_get_fd (priv->device_file);
+  if (!get_driver_info (fd, &priv->driver_name, &priv->driver_description))
+    {
+      priv->driver_name = g_strdup ("unknown");
+      priv->driver_description = g_strdup ("Unknown");
+    }
+
+  return TRUE;
 }
 
 static void
@@ -866,6 +891,12 @@ meta_kms_impl_device_init (MetaKmsImplDevice *impl_device)
 {
 }
 
+static void
+initable_iface_init (GInitableIface *iface)
+{
+  iface->init = meta_kms_impl_device_initable_init;
+}
+
 static void
 meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass)
 {
@@ -873,7 +904,6 @@ meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass)
 
   object_class->get_property = meta_kms_impl_device_get_property;
   object_class->set_property = meta_kms_impl_device_set_property;
-  object_class->constructed = meta_kms_impl_device_constructed;
   object_class->finalize = meta_kms_impl_device_finalize;
 
   obj_props[PROP_DEVICE] =
@@ -892,13 +922,14 @@ meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass)
                          G_PARAM_READWRITE |
                          G_PARAM_CONSTRUCT_ONLY |
                          G_PARAM_STATIC_STRINGS);
-  obj_props[PROP_DEVICE_FILE] =
-    g_param_spec_pointer ("device-file",
-                          "device-file",
-                          "Device file",
-                          G_PARAM_READWRITE |
-                          G_PARAM_CONSTRUCT_ONLY |
-                          G_PARAM_STATIC_STRINGS);
+  obj_props[PROP_PATH] =
+    g_param_spec_string ("path",
+                         "path",
+                         "Device path",
+                         NULL,
+                         G_PARAM_WRITABLE |
+                         G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
   obj_props[PROP_FLAGS] =
     g_param_spec_flags ("flags",
                         "flags",
@@ -908,21 +939,5 @@ meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass)
                         G_PARAM_READWRITE |
                         G_PARAM_CONSTRUCT_ONLY |
                         G_PARAM_STATIC_STRINGS);
-  obj_props[PROP_DRIVER_NAME] =
-    g_param_spec_string ("driver-name",
-                         "driver-name",
-                         "DRM device driver name",
-                         NULL,
-                         G_PARAM_READWRITE |
-                         G_PARAM_CONSTRUCT_ONLY |
-                         G_PARAM_STATIC_STRINGS);
-  obj_props[PROP_DRIVER_DESCRIPTION] =
-    g_param_spec_string ("driver-description",
-                         "driver-description",
-                         "DRM device driver description",
-                         NULL,
-                         G_PARAM_READWRITE |
-                         G_PARAM_CONSTRUCT_ONLY |
-                         G_PARAM_STATIC_STRINGS);
   g_object_class_install_properties (object_class, N_PROPS, obj_props);
 }
diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h
index df0c92bf63..3136ccfd88 100644
--- a/src/backends/native/meta-kms-impl-device.h
+++ b/src/backends/native/meta-kms-impl-device.h
@@ -25,6 +25,7 @@
 #include <xf86drm.h>
 #include <xf86drmMode.h>
 
+#include "backends/native/meta-device-pool.h"
 #include "backends/native/meta-kms-device.h"
 #include "backends/native/meta-kms-page-flip-private.h"
 #include "backends/native/meta-kms-types.h"
@@ -62,6 +63,9 @@ struct _MetaKmsImplDeviceClass
 {
   GObjectClass parent_class;
 
+  MetaDeviceFile * (* open_device_file) (MetaKmsImplDevice  *impl_device,
+                                         const char         *path,
+                                         GError            **error);
   void (* setup_drm_event_context) (MetaKmsImplDevice *impl_device,
                                     drmEventContext   *drm_event_context);
   MetaKmsFeedback * (* process_update) (MetaKmsImplDevice *impl_device,
@@ -73,6 +77,16 @@ struct _MetaKmsImplDeviceClass
   void (* prepare_shutdown) (MetaKmsImplDevice *impl_device);
 };
 
+enum
+{
+  META_KMS_ERROR_USER_INHIBITED,
+  META_KMS_ERROR_DENY_LISTED,
+  META_KMS_ERROR_NOT_SUPPORTED,
+};
+
+#define META_KMS_ERROR meta_kms_error_quark ()
+GQuark meta_kms_error_quark (void);
+
 MetaKmsDevice * meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device);
 
 GList * meta_kms_impl_device_copy_connectors (MetaKmsImplDevice *impl_device);


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