summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ã…dahl <jadahl@gmail.com>2019-01-29 10:24:44 +0100
committerGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2019-06-20 13:31:55 +0000
commitfef5753a194d11b90b7785548ed897c9b6be6257 (patch)
treecf7971ed34b5e85d456a57209562b72b125766d1
parentf3fd7cf92bc8fda9032941257849a9db6a590d6a (diff)
downloadmutter-fef5753a194d11b90b7785548ed897c9b6be6257.tar.gz
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
-rw-r--r--src/backends/native/meta-backend-native.c29
-rw-r--r--src/backends/native/meta-backend-native.h3
-rw-r--r--src/backends/native/meta-gpu-kms.c37
-rw-r--r--src/backends/native/meta-gpu-kms.h10
-rw-r--r--src/backends/native/meta-kms-device.c185
-rw-r--r--src/backends/native/meta-kms-device.h43
-rw-r--r--src/backends/native/meta-kms-impl-device.c98
-rw-r--r--src/backends/native/meta-kms-impl-device.h46
-rw-r--r--src/backends/native/meta-kms-impl-simple.c51
-rw-r--r--src/backends/native/meta-kms-impl-simple.h32
-rw-r--r--src/backends/native/meta-kms-impl.c110
-rw-r--r--src/backends/native/meta-kms-impl.h37
-rw-r--r--src/backends/native/meta-kms-private.h43
-rw-r--r--src/backends/native/meta-kms-types.h36
-rw-r--r--src/backends/native/meta-kms.c124
-rw-r--r--src/backends/native/meta-kms.h41
-rw-r--r--src/meson.build12
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',