[mutter] backends/native: Add basic KMS abstraction building blocks



commit fef5753a194d11b90b7785548ed897c9b6be6257
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Tue Jan 29 10:24:44 2019 +0100

    backends/native: Add basic KMS abstraction building blocks
    
    The intention with KMS abstraction is to hide away accessing the drm
    functions behind an API that allows us to have different kind of KMS
    implementations, including legacy non-atomic and atomic. The intention
    is also that the code interacting with the drm device should be able to
    be run in a different thread than the main thread. This means that we
    need to make sure that all drm*() API usage must only occur from within
    tasks that eventually can be run in the dedicated thread.
    
    The idea here is that MetaKms provides a outward facing API other places
    of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is
    an internal implementation that only gets interacted with via "tasks"
    posted via the MetaKms object. These tasks will in the future
    potentially be run on the dedicated KMS thread. Initially, we don't
    create any new threads.
    
    Likewise, MetaKmsDevice is a outward facing representation of a KMS
    device, while MetaKmsImplDevice is the corresponding implementation,
    which only runs from within the MetaKmsImpl tasks.
    
    This commit only moves opening and closing the device to this new API,
    while leaking the fd outside of the impl enclosure, effectively making
    the isolation for drm*() calls pointless. This, however, is necessary to
    allow gradual porting of drm interaction, and eventually the file
    descriptor in MetaGpuKms will be removed. For now, it's harmless, since
    everything still run in the main thread.
    
    https://gitlab.gnome.org/GNOME/mutter/issues/548
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/525

 src/backends/native/meta-backend-native.c  |  29 ++++-
 src/backends/native/meta-backend-native.h  |   3 +
 src/backends/native/meta-gpu-kms.c         |  37 +++---
 src/backends/native/meta-gpu-kms.h         |  10 +-
 src/backends/native/meta-kms-device.c      | 185 +++++++++++++++++++++++++++++
 src/backends/native/meta-kms-device.h      |  43 +++++++
 src/backends/native/meta-kms-impl-device.c |  98 +++++++++++++++
 src/backends/native/meta-kms-impl-device.h |  46 +++++++
 src/backends/native/meta-kms-impl-simple.c |  51 ++++++++
 src/backends/native/meta-kms-impl-simple.h |  32 +++++
 src/backends/native/meta-kms-impl.c        | 110 +++++++++++++++++
 src/backends/native/meta-kms-impl.h        |  37 ++++++
 src/backends/native/meta-kms-private.h     |  43 +++++++
 src/backends/native/meta-kms-types.h       |  36 ++++++
 src/backends/native/meta-kms.c             | 124 +++++++++++++++++++
 src/backends/native/meta-kms.h             |  41 +++++++
 src/meson.build                            |  12 ++
 17 files changed, 903 insertions(+), 34 deletions(-)
---
diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c
index 262ab9a0a..f34437e6d 100644
--- a/src/backends/native/meta-backend-native.c
+++ b/src/backends/native/meta-backend-native.c
@@ -51,6 +51,8 @@
 #include "backends/native/meta-clutter-backend-native.h"
 #include "backends/native/meta-cursor-renderer-native.h"
 #include "backends/native/meta-input-settings-native.h"
+#include "backends/native/meta-kms.h"
+#include "backends/native/meta-kms-device.h"
 #include "backends/native/meta-launcher.h"
 #include "backends/native/meta-monitor-manager-kms.h"
 #include "backends/native/meta-renderer-native.h"
@@ -65,6 +67,7 @@ struct _MetaBackendNative
 
   MetaLauncher *launcher;
   MetaUdev *udev;
+  MetaKms *kms;
   MetaBarrierManagerNative *barrier_manager;
 
   guint udev_device_added_handler_id;
@@ -91,6 +94,7 @@ meta_backend_native_finalize (GObject *object)
     disconnect_udev_device_added_handler (native);
 
   g_clear_object (&native->udev);
+  g_clear_object (&native->kms);
   meta_launcher_free (native->launcher);
 
   G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
@@ -523,17 +527,24 @@ create_gpu_from_udev_device (MetaBackendNative  *native,
                              GUdevDevice        *device,
                              GError            **error)
 {
-  MetaGpuKmsFlag flags = META_GPU_KMS_FLAG_NONE;
+  MetaKmsDeviceFlag flags = META_KMS_DEVICE_FLAG_NONE;
   const char *device_path;
+  MetaKmsDevice *kms_device;
 
   if (meta_is_udev_device_platform_device (device))
-    flags |= META_GPU_KMS_FLAG_PLATFORM_DEVICE;
+    flags |= META_KMS_DEVICE_FLAG_PLATFORM_DEVICE;
 
   if (meta_is_udev_device_boot_vga (device))
-    flags |= META_GPU_KMS_FLAG_BOOT_VGA;
+    flags |= META_KMS_DEVICE_FLAG_BOOT_VGA;
 
   device_path = g_udev_device_get_device_file (device);
-  return meta_gpu_kms_new (native, device_path, flags, error);
+
+  kms_device = meta_kms_create_device (native->kms, device_path, flags,
+                                       error);
+  if (!kms_device)
+    return NULL;
+
+  return meta_gpu_kms_new (native, kms_device, error);
 }
 
 static void
@@ -661,6 +672,10 @@ meta_backend_native_initable_init (GInitable     *initable,
   native->udev = meta_udev_new (native);
   native->barrier_manager = meta_barrier_manager_native_new ();
 
+  native->kms = meta_kms_new (META_BACKEND (native), error);
+  if (!native->kms)
+    return FALSE;
+
   if (!init_gpus (native, error))
     return FALSE;
 
@@ -722,6 +737,12 @@ meta_backend_native_get_udev (MetaBackendNative *native)
   return native->udev;
 }
 
+MetaKms *
+meta_backend_native_get_kms (MetaBackendNative *native)
+{
+  return native->kms;
+}
+
 gboolean
 meta_activate_vt (int vt, GError **error)
 {
diff --git a/src/backends/native/meta-backend-native.h b/src/backends/native/meta-backend-native.h
index 28b0856a3..b389652b2 100644
--- a/src/backends/native/meta-backend-native.h
+++ b/src/backends/native/meta-backend-native.h
@@ -27,6 +27,7 @@
 
 #include "backends/meta-backend-private.h"
 #include "backends/native/meta-clutter-backend-native.h"
+#include "backends/native/meta-kms-types.h"
 #include "backends/native/meta-launcher.h"
 #include "backends/native/meta-udev.h"
 
@@ -44,4 +45,6 @@ MetaLauncher * meta_backend_native_get_launcher (MetaBackendNative *native);
 
 MetaUdev * meta_backend_native_get_udev (MetaBackendNative *native);
 
+MetaKms * meta_backend_native_get_kms (MetaBackendNative *native);
+
 #endif /* META_BACKEND_NATIVE_H */
diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
index 133d5d2ae..0128f767f 100644
--- a/src/backends/native/meta-gpu-kms.c
+++ b/src/backends/native/meta-gpu-kms.c
@@ -37,6 +37,8 @@
 #include "backends/meta-output.h"
 #include "backends/native/meta-backend-native.h"
 #include "backends/native/meta-crtc-kms.h"
+#include "backends/native/meta-kms-device.h"
+#include "backends/native/meta-kms.h"
 #include "backends/native/meta-launcher.h"
 #include "backends/native/meta-output-kms.h"
 
@@ -61,9 +63,10 @@ struct _MetaGpuKms
 {
   MetaGpu parent;
 
+  MetaKmsDevice *kms_device;
+
   uint32_t id;
   int fd;
-  char *file_path;
   GSource *source;
 
   clockid_t clock_id;
@@ -72,8 +75,6 @@ struct _MetaGpuKms
   unsigned int n_connectors;
 
   gboolean resources_init_failed_before;
-
-  MetaGpuKmsFlag flags;
 };
 
 G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU)
@@ -397,7 +398,7 @@ meta_gpu_kms_get_id (MetaGpuKms *gpu_kms)
 const char *
 meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms)
 {
-  return gpu_kms->file_path;
+  return meta_kms_device_get_path (gpu_kms->kms_device);
 }
 
 int64_t
@@ -428,13 +429,19 @@ meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms,
 gboolean
 meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms)
 {
-  return !!(gpu_kms->flags & META_GPU_KMS_FLAG_BOOT_VGA);
+  MetaKmsDeviceFlag flags;
+
+  flags = meta_kms_device_get_flags (gpu_kms->kms_device);
+  return !!(flags & META_KMS_DEVICE_FLAG_BOOT_VGA);
 }
 
 gboolean
 meta_gpu_kms_is_platform_device (MetaGpuKms *gpu_kms)
 {
-  return !!(gpu_kms->flags & META_GPU_KMS_FLAG_PLATFORM_DEVICE);
+  MetaKmsDeviceFlag flags;
+
+  flags = meta_kms_device_get_flags (gpu_kms->kms_device);
+  return !!(flags & META_KMS_DEVICE_FLAG_PLATFORM_DEVICE);
 }
 
 static void
@@ -869,27 +876,22 @@ meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms)
 
 MetaGpuKms *
 meta_gpu_kms_new (MetaBackendNative  *backend_native,
-                  const char         *kms_file_path,
-                  MetaGpuKmsFlag      flags,
+                  MetaKmsDevice      *kms_device,
                   GError            **error)
 {
-  MetaLauncher *launcher = meta_backend_native_get_launcher (backend_native);
   GSource *source;
   MetaKmsSource *kms_source;
   MetaGpuKms *gpu_kms;
   int kms_fd;
 
-  kms_fd = meta_launcher_open_restricted (launcher, kms_file_path, error);
-  if (kms_fd == -1)
-    return NULL;
+  kms_fd = meta_kms_device_leak_fd (kms_device);
 
   gpu_kms = g_object_new (META_TYPE_GPU_KMS,
                           "backend", backend_native,
                           NULL);
 
-  gpu_kms->flags = flags;
+  gpu_kms->kms_device = kms_device;
   gpu_kms->fd = kms_fd;
-  gpu_kms->file_path = g_strdup (kms_file_path);
 
   drmSetClientCap (gpu_kms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
 
@@ -912,13 +914,6 @@ static void
 meta_gpu_kms_finalize (GObject *object)
 {
   MetaGpuKms *gpu_kms = META_GPU_KMS (object);
-  MetaBackend *backend = meta_gpu_get_backend (META_GPU (gpu_kms));
-  MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
-  MetaLauncher *launcher = meta_backend_native_get_launcher (backend_native);
-
-  if (gpu_kms->fd != -1)
-    meta_launcher_close_restricted (launcher, gpu_kms->fd);
-  g_clear_pointer (&gpu_kms->file_path, g_free);
 
   g_source_destroy (gpu_kms->source);
 
diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h
index e62befd93..16c6117a0 100644
--- a/src/backends/native/meta-gpu-kms.h
+++ b/src/backends/native/meta-gpu-kms.h
@@ -44,16 +44,8 @@ typedef struct _MetaKmsResources
 
 typedef void (*MetaKmsFlipCallback) (void *user_data);
 
-typedef enum _MetaGpuKmsFlag
-{
-  META_GPU_KMS_FLAG_NONE =                  0,
-  META_GPU_KMS_FLAG_BOOT_VGA =        (1 << 0),
-  META_GPU_KMS_FLAG_PLATFORM_DEVICE = (1 << 1),
-} MetaGpuKmsFlag;
-
 MetaGpuKms * meta_gpu_kms_new (MetaBackendNative  *backend_native,
-                               const char         *kms_file_path,
-                               MetaGpuKmsFlag      flags,
+                               MetaKmsDevice      *kms_device,
                                GError            **error);
 
 gboolean meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms,
diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c
new file mode 100644
index 000000000..cdfef0b4c
--- /dev/null
+++ b/src/backends/native/meta-kms-device.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2019 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "backends/native/meta-kms-device.h"
+
+#include "backends/native/meta-backend-native.h"
+#include "backends/native/meta-kms-impl-device.h"
+#include "backends/native/meta-kms-impl.h"
+#include "backends/native/meta-kms-private.h"
+
+struct _MetaKmsDevice
+{
+  GObject parent;
+
+  MetaKms *kms;
+
+  MetaKmsImplDevice *impl_device;
+
+  MetaKmsDeviceFlag flags;
+  char *path;
+};
+
+G_DEFINE_TYPE (MetaKmsDevice, meta_kms_device, G_TYPE_OBJECT);
+
+int
+meta_kms_device_leak_fd (MetaKmsDevice *device)
+{
+  return meta_kms_impl_device_leak_fd (device->impl_device);
+}
+
+const char *
+meta_kms_device_get_path (MetaKmsDevice *device)
+{
+  return device->path;
+}
+
+MetaKmsDeviceFlag
+meta_kms_device_get_flags (MetaKmsDevice *device)
+{
+  return device->flags;
+}
+
+typedef struct _CreateImplDeviceData
+{
+  MetaKmsDevice *device;
+  int fd;
+
+  MetaKmsImplDevice *out_impl_device;
+} CreateImplDeviceData;
+
+static gboolean
+create_impl_device_in_impl (MetaKmsImpl  *impl,
+                            gpointer      user_data,
+                            GError      **error)
+{
+  CreateImplDeviceData *data = user_data;
+  MetaKmsImplDevice *impl_device;
+
+  impl_device = meta_kms_impl_device_new (data->device, impl, data->fd);
+
+  data->out_impl_device = impl_device;
+
+  return TRUE;
+}
+
+MetaKmsDevice *
+meta_kms_device_new (MetaKms            *kms,
+                     const char         *path,
+                     MetaKmsDeviceFlag   flags,
+                     GError            **error)
+{
+  MetaBackend *backend = meta_kms_get_backend (kms);
+  MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
+  MetaLauncher *launcher = meta_backend_native_get_launcher (backend_native);
+  MetaKmsDevice *device;
+  CreateImplDeviceData data;
+  int fd;
+
+  fd = meta_launcher_open_restricted (launcher, path, error);
+  if (fd == -1)
+    return NULL;
+
+  device = g_object_new (META_TYPE_KMS_DEVICE, NULL);
+
+  data = (CreateImplDeviceData) {
+    .device = device,
+    .fd = fd,
+  };
+  if (!meta_kms_run_impl_task_sync (kms, create_impl_device_in_impl, &data,
+                                    error))
+    {
+      meta_launcher_close_restricted (launcher, fd);
+      g_object_unref (device);
+      return NULL;
+    }
+
+  device->kms = kms;
+  device->impl_device = data.out_impl_device;
+  device->flags = flags;
+  device->path = g_strdup (path);
+
+  return device;
+}
+
+typedef struct _FreeImplDeviceData
+{
+  MetaKmsImplDevice *impl_device;
+
+  int out_fd;
+} FreeImplDeviceData;
+
+static gboolean
+free_impl_device_in_impl (MetaKmsImpl  *impl,
+                          gpointer      user_data,
+                          GError      **error)
+{
+  FreeImplDeviceData *data = user_data;
+  MetaKmsImplDevice *impl_device = data->impl_device;
+  int fd;
+
+  fd = meta_kms_impl_device_close (impl_device);
+  g_object_unref (impl_device);
+
+  data->out_fd = fd;
+
+  return TRUE;
+}
+
+static void
+meta_kms_device_finalize (GObject *object)
+{
+  MetaKmsDevice *device = META_KMS_DEVICE (object);
+  MetaBackend *backend = meta_kms_get_backend (device->kms);
+  MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
+  MetaLauncher *launcher = meta_backend_native_get_launcher (backend_native);
+  FreeImplDeviceData data;
+  GError *error = NULL;
+
+  data = (FreeImplDeviceData) {
+    .impl_device = device->impl_device,
+  };
+  if (!meta_kms_run_impl_task_sync (device->kms, free_impl_device_in_impl, &data,
+                                   &error))
+    {
+      g_warning ("Failed to close KMS impl device: %s", error->message);
+      g_error_free (error);
+    }
+  else
+    {
+      meta_launcher_close_restricted (launcher, data.out_fd);
+    }
+
+  G_OBJECT_CLASS (meta_kms_device_parent_class)->finalize (object);
+}
+
+static void
+meta_kms_device_init (MetaKmsDevice *device)
+{
+}
+
+static void
+meta_kms_device_class_init (MetaKmsDeviceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_kms_device_finalize;
+}
diff --git a/src/backends/native/meta-kms-device.h b/src/backends/native/meta-kms-device.h
new file mode 100644
index 000000000..9972f1318
--- /dev/null
+++ b/src/backends/native/meta-kms-device.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_KMS_DEVICE_H
+#define META_KMS_DEVICE_H
+
+#include <glib-object.h>
+
+#include "backends/native/meta-kms-types.h"
+
+#define META_TYPE_KMS_DEVICE (meta_kms_device_get_type ())
+G_DECLARE_FINAL_TYPE (MetaKmsDevice, meta_kms_device,
+                      META, KMS_DEVICE,
+                      GObject)
+
+int meta_kms_device_leak_fd (MetaKmsDevice *device);
+
+const char * meta_kms_device_get_path (MetaKmsDevice *device);
+
+MetaKmsDeviceFlag meta_kms_device_get_flags (MetaKmsDevice *device);
+
+MetaKmsDevice * meta_kms_device_new (MetaKms            *kms,
+                                     const char         *path,
+                                     MetaKmsDeviceFlag   flags,
+                                     GError            **error);
+
+#endif /* META_KMS_DEVICE_H */
diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c
new file mode 100644
index 000000000..6727bb024
--- /dev/null
+++ b/src/backends/native/meta-kms-impl-device.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "backends/native/meta-kms-impl-device.h"
+
+#include "backends/native/meta-kms-impl.h"
+#include "backends/native/meta-kms-private.h"
+
+struct _MetaKmsImplDevice
+{
+  GObject parent;
+
+  MetaKmsDevice *device;
+  MetaKmsImpl *impl;
+
+  int fd;
+};
+
+G_DEFINE_TYPE (MetaKmsImplDevice, meta_kms_impl_device, G_TYPE_OBJECT)
+
+MetaKmsDevice *
+meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device)
+{
+  return impl_device->device;
+}
+
+MetaKmsImplDevice *
+meta_kms_impl_device_new (MetaKmsDevice *device,
+                          MetaKmsImpl   *impl,
+                          int            fd)
+{
+  MetaKmsImplDevice *impl_device;
+
+  meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl));
+
+  impl_device = g_object_new (META_TYPE_KMS_IMPL_DEVICE, NULL);
+  impl_device->device = device;
+  impl_device->impl = impl;
+  impl_device->fd = fd;
+
+  return impl_device;
+}
+
+int
+meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device)
+{
+  meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl_device->impl));
+
+  return impl_device->fd;
+}
+
+int
+meta_kms_impl_device_leak_fd (MetaKmsImplDevice *impl_device)
+{
+  return impl_device->fd;
+}
+
+int
+meta_kms_impl_device_close (MetaKmsImplDevice *impl_device)
+{
+  int fd;
+
+  meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl_device->impl));
+
+  fd = impl_device->fd;
+  impl_device->fd = -1;
+
+  return fd;
+}
+
+static void
+meta_kms_impl_device_init (MetaKmsImplDevice *device)
+{
+}
+
+static void
+meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass)
+{
+}
+
diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h
new file mode 100644
index 000000000..3c316d82d
--- /dev/null
+++ b/src/backends/native/meta-kms-impl-device.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_KMS_IMPL_DEVICE_H
+#define META_KMS_IMPL_DEVICE_H
+
+#include <glib-object.h>
+#include <stdint.h>
+
+#include "backends/native/meta-kms-device.h"
+#include "backends/native/meta-kms-types.h"
+
+#define META_TYPE_KMS_IMPL_DEVICE (meta_kms_impl_device_get_type ())
+G_DECLARE_FINAL_TYPE (MetaKmsImplDevice, meta_kms_impl_device,
+                      META, KMS_IMPL_DEVICE,
+                      GObject)
+
+MetaKmsDevice * meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device);
+
+int meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device);
+
+int meta_kms_impl_device_leak_fd (MetaKmsImplDevice *impl_device);
+
+int meta_kms_impl_device_close (MetaKmsImplDevice *impl_device);
+
+MetaKmsImplDevice * meta_kms_impl_device_new (MetaKmsDevice *device,
+                                              MetaKmsImpl   *kms_impl,
+                                              int            fd);
+
+#endif /* META_KMS_IMPL_DEVICE_H */
diff --git a/src/backends/native/meta-kms-impl-simple.c b/src/backends/native/meta-kms-impl-simple.c
new file mode 100644
index 000000000..6432cbb7a
--- /dev/null
+++ b/src/backends/native/meta-kms-impl-simple.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018-2019 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "backends/native/meta-kms-impl-simple.h"
+
+#include <gbm.h>
+
+struct _MetaKmsImplSimple
+{
+  MetaKmsImpl parent;
+};
+
+G_DEFINE_TYPE (MetaKmsImplSimple, meta_kms_impl_simple,
+               META_TYPE_KMS_IMPL)
+
+MetaKmsImplSimple *
+meta_kms_impl_simple_new (MetaKms  *kms,
+                          GError  **error)
+{
+  return g_object_new (META_TYPE_KMS_IMPL_SIMPLE,
+                       "kms", kms,
+                       NULL);
+}
+
+static void
+meta_kms_impl_simple_init (MetaKmsImplSimple *impl_simple)
+{
+}
+
+static void
+meta_kms_impl_simple_class_init (MetaKmsImplSimpleClass *klass)
+{
+}
diff --git a/src/backends/native/meta-kms-impl-simple.h b/src/backends/native/meta-kms-impl-simple.h
new file mode 100644
index 000000000..e2cf6296e
--- /dev/null
+++ b/src/backends/native/meta-kms-impl-simple.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_KMS_IMPL_SIMPLE_H
+#define META_KMS_IMPL_SIMPLE_H
+
+#include "backends/native/meta-kms-impl.h"
+
+#define META_TYPE_KMS_IMPL_SIMPLE meta_kms_impl_simple_get_type ()
+G_DECLARE_FINAL_TYPE (MetaKmsImplSimple, meta_kms_impl_simple,
+                      META, KMS_IMPL_SIMPLE, MetaKmsImpl)
+
+MetaKmsImplSimple * meta_kms_impl_simple_new (MetaKms  *kms,
+                                              GError  **error);
+
+#endif /* META_KMS_IMPL_SIMPLE_H */
diff --git a/src/backends/native/meta-kms-impl.c b/src/backends/native/meta-kms-impl.c
new file mode 100644
index 000000000..b6f9c2509
--- /dev/null
+++ b/src/backends/native/meta-kms-impl.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "backends/native/meta-kms-impl.h"
+
+enum
+{
+  PROP_0,
+
+  PROP_KMS,
+};
+
+typedef struct _MetaKmsImplPrivate
+{
+  MetaKms *kms;
+} MetaKmsImplPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaKmsImpl, meta_kms_impl, G_TYPE_OBJECT)
+
+MetaKms *
+meta_kms_impl_get_kms (MetaKmsImpl *impl)
+{
+  MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl);
+
+  return priv->kms;
+}
+
+static void
+meta_kms_impl_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  MetaKmsImpl *impl = META_KMS_IMPL (object);
+  MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl);
+
+  switch (prop_id)
+    {
+    case PROP_KMS:
+      priv->kms = g_value_get_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+meta_kms_impl_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+  MetaKmsImpl *impl = META_KMS_IMPL (object);
+  MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl);
+
+  switch (prop_id)
+    {
+    case PROP_KMS:
+      g_value_set_object (value, priv->kms);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+meta_kms_impl_init (MetaKmsImpl *kms_impl)
+{
+}
+
+static void
+meta_kms_impl_class_init (MetaKmsImplClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GParamSpec *pspec;
+
+  object_class->set_property = meta_kms_impl_set_property;
+  object_class->get_property = meta_kms_impl_get_property;
+
+  pspec = g_param_spec_object ("kms",
+                               "kms",
+                               "MetaKms",
+                               META_TYPE_KMS,
+                               G_PARAM_READWRITE |
+                               G_PARAM_STATIC_STRINGS |
+                               G_PARAM_CONSTRUCT_ONLY);
+  g_object_class_install_property (object_class,
+                                   PROP_KMS,
+                                   pspec);
+}
diff --git a/src/backends/native/meta-kms-impl.h b/src/backends/native/meta-kms-impl.h
new file mode 100644
index 000000000..fa774af17
--- /dev/null
+++ b/src/backends/native/meta-kms-impl.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_KMS_IMPL_H
+#define META_KMS_IMPL_H
+
+#include "backends/native/meta-kms-impl-device.h"
+#include "backends/native/meta-kms.h"
+
+#define META_TYPE_KMS_IMPL (meta_kms_impl_get_type ())
+G_DECLARE_DERIVABLE_TYPE (MetaKmsImpl, meta_kms_impl,
+                          META, KMS_IMPL, GObject)
+
+struct _MetaKmsImplClass
+{
+  GObjectClass parent_class;
+};
+
+MetaKms * meta_kms_impl_get_kms (MetaKmsImpl *impl);
+
+#endif /* META_KMS_IMPL_H */
diff --git a/src/backends/native/meta-kms-private.h b/src/backends/native/meta-kms-private.h
new file mode 100644
index 000000000..da59d7431
--- /dev/null
+++ b/src/backends/native/meta-kms-private.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_KMS_PRIVATE_H
+#define META_KMS_PRIVATE_H
+
+#include "backends/native/meta-kms.h"
+
+#include "backends/native/meta-kms-types.h"
+
+typedef gboolean (* MetaKmsImplTaskFunc) (MetaKmsImpl  *impl,
+                                          gpointer      user_data,
+                                          GError      **error);
+
+gboolean meta_kms_run_impl_task_sync (MetaKms              *kms,
+                                      MetaKmsImplTaskFunc   func,
+                                      gpointer              user_data,
+                                      GError              **error);
+
+gboolean meta_kms_in_impl_task (MetaKms *kms);
+
+#define meta_assert_in_kms_impl(kms) \
+  g_assert (meta_kms_in_impl_task (kms))
+#define meta_assert_not_in_kms_impl(kms) \
+  g_assert (!meta_kms_in_impl_task (kms))
+
+#endif /* META_KMS_PRIVATE_H */
diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h
new file mode 100644
index 000000000..43337eff2
--- /dev/null
+++ b/src/backends/native/meta-kms-types.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_KMS_IMPL_TYPES_H
+#define META_KMS_IMPL_TYPES_H
+
+typedef struct _MetaKms MetaKms;
+typedef struct _MetaKmsDevice MetaKmsDevice;
+
+typedef struct _MetaKmsImpl MetaKmsImpl;
+typedef struct _MetaKmsImplDevice MetaKmsImplDevice;
+
+typedef enum _MetaKmsDeviceFlag
+{
+  META_KMS_DEVICE_FLAG_NONE = 0,
+  META_KMS_DEVICE_FLAG_BOOT_VGA = 1 << 0,
+  META_KMS_DEVICE_FLAG_PLATFORM_DEVICE = 1 << 1,
+} MetaKmsDeviceFlag;
+
+#endif /* META_KMS_IMPL_TYPES_H */
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
new file mode 100644
index 000000000..40ce2e8ea
--- /dev/null
+++ b/src/backends/native/meta-kms.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2018 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "backends/native/meta-kms-private.h"
+
+#include "backends/native/meta-kms-impl.h"
+#include "backends/native/meta-kms-impl-simple.h"
+
+struct _MetaKms
+{
+  GObject parent;
+
+  MetaBackend *backend;
+
+  MetaKmsImpl *impl;
+  gboolean in_impl_task;
+
+  GList *devices;
+};
+
+G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT)
+
+gboolean
+meta_kms_run_impl_task_sync (MetaKms              *kms,
+                             MetaKmsImplTaskFunc   func,
+                             gpointer              user_data,
+                             GError              **error)
+{
+  gboolean ret;
+
+  kms->in_impl_task = TRUE;
+  ret = func (kms->impl, user_data, error);
+  kms->in_impl_task = FALSE;
+
+  return ret;
+}
+
+gboolean
+meta_kms_in_impl_task (MetaKms *kms)
+{
+  return kms->in_impl_task;
+}
+
+MetaBackend *
+meta_kms_get_backend (MetaKms *kms)
+{
+  return kms->backend;
+}
+
+MetaKmsDevice *
+meta_kms_create_device (MetaKms            *kms,
+                        const char         *path,
+                        MetaKmsDeviceFlag   flags,
+                        GError            **error)
+{
+  MetaKmsDevice *device;
+
+  device = meta_kms_device_new (kms, path, flags, error);
+  if (!device)
+    return NULL;
+
+  kms->devices = g_list_append (kms->devices, device);
+
+  return device;
+}
+
+MetaKms *
+meta_kms_new (MetaBackend  *backend,
+              GError      **error)
+{
+  MetaKms *kms;
+
+  kms = g_object_new (META_TYPE_KMS, NULL);
+  kms->backend = backend;
+  kms->impl = META_KMS_IMPL (meta_kms_impl_simple_new (kms, error));
+  if (!kms->impl)
+    {
+      g_object_unref (kms);
+      return NULL;
+    }
+
+  return kms;
+}
+
+static void
+meta_kms_finalize (GObject *object)
+{
+  MetaKms *kms = META_KMS (object);
+
+  g_list_free_full (kms->devices, g_object_unref);
+
+  G_OBJECT_CLASS (meta_kms_parent_class)->finalize (object);
+}
+
+static void
+meta_kms_init (MetaKms *kms)
+{
+}
+
+static void
+meta_kms_class_init (MetaKmsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_kms_finalize;
+}
diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h
new file mode 100644
index 000000000..7c4073256
--- /dev/null
+++ b/src/backends/native/meta-kms.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_KMS_H
+#define META_KMS_H
+
+#include <glib-object.h>
+
+#include "backends/meta-backend-private.h"
+#include "backends/native/meta-kms-types.h"
+
+#define META_TYPE_KMS (meta_kms_get_type ())
+G_DECLARE_FINAL_TYPE (MetaKms, meta_kms, META, KMS, GObject)
+
+MetaBackend * meta_kms_get_backend (MetaKms *kms);
+
+MetaKmsDevice * meta_kms_create_device (MetaKms            *kms,
+                                        const char         *path,
+                                        MetaKmsDeviceFlag   flags,
+                                        GError            **error);
+
+MetaKms * meta_kms_new (MetaBackend  *backend,
+                        GError      **error);
+
+#endif /* META_KMS_H */
diff --git a/src/meson.build b/src/meson.build
index 22516d868..f4f27b32e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -595,6 +595,18 @@ if have_native_backend
     'backends/native/meta-output-kms.c',
     'backends/native/meta-output-kms.h',
     'backends/native/meta-renderer-native.c',
+    'backends/native/meta-kms-device.c',
+    'backends/native/meta-kms-device.h',
+    'backends/native/meta-kms-impl-device.c',
+    'backends/native/meta-kms-impl-device.h',
+    'backends/native/meta-kms-impl-simple.c',
+    'backends/native/meta-kms-impl-simple.h',
+    'backends/native/meta-kms-impl.c',
+    'backends/native/meta-kms-impl.h',
+    'backends/native/meta-kms-private.h',
+    'backends/native/meta-kms-types.h',
+    'backends/native/meta-kms.c',
+    'backends/native/meta-kms.h',
     'backends/native/meta-renderer-native-gles3.c',
     'backends/native/meta-renderer-native-gles3.h',
     'backends/native/meta-renderer-native.h',



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