diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index 8f916642e..eb43a54ec 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -531,7 +531,9 @@ meta_backend_native_initable_init (GInitable *initable, native->udev = meta_udev_new (native); - native->kms = meta_kms_new (META_BACKEND (native), error); + native->kms = meta_kms_new (META_BACKEND (native), + META_KMS_FLAG_NONE, + error); if (!native->kms) return FALSE; diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c index 9084d248f..c388096d5 100644 --- a/src/backends/native/meta-kms-device.c +++ b/src/backends/native/meta-kms-device.c @@ -23,10 +23,14 @@ #include "backends/native/meta-kms-device-private.h" #include "backends/native/meta-kms-device.h" +#include +#include +#include #include #include "backends/native/meta-backend-native.h" #include "backends/native/meta-kms-impl-device-atomic.h" +#include "backends/native/meta-kms-impl-device-dummy.h" #include "backends/native/meta-kms-impl-device-simple.h" #include "backends/native/meta-kms-impl-device.h" #include "backends/native/meta-kms-impl.h" @@ -227,6 +231,7 @@ typedef struct _CreateImplDeviceData MetaKmsDevice *device; int fd; const char *path; + MetaKmsDeviceFlag flags; MetaKmsImplDevice *out_impl_device; GList *out_crtcs; @@ -236,6 +241,7 @@ typedef struct _CreateImplDeviceData GList *out_fallback_modes; char *out_driver_name; char *out_driver_description; + char *out_path; } CreateImplDeviceData; static gboolean @@ -273,17 +279,21 @@ get_driver_info (int fd, } static MetaKmsImplDevice * -meta_create_kms_impl_device (MetaKmsDevice *device, - MetaKmsImpl *impl, - int fd, - const char *path, - GError **error) +meta_create_kms_impl_device (MetaKmsDevice *device, + MetaKmsImpl *impl, + int fd, + 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 impl_fd; + g_autofree char *impl_path = NULL; + MetaKmsImplDevice *impl_device; meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl)); @@ -294,7 +304,36 @@ meta_create_kms_impl_device (MetaKmsDevice *device, } atomic_kms_enable_env = getenv ("MUTTER_DEBUG_ENABLE_ATOMIC_KMS"); - if (atomic_kms_enable_env) + + if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING) + { + g_autofree char *render_node_path = NULL; + + 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; + } + + impl_fd = open (render_node_path, O_RDWR | O_CLOEXEC, 0); + if (impl_fd == -1) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Failed to open render node '%s': %s", + render_node_path, g_strerror (errno)); + return NULL; + } + + g_message ("Adding device '%s' (from '%s', %s) using no mode setting.", + render_node_path, path, driver_name); + + impl_path = g_steal_pointer (&render_node_path); + impl_device_type = META_TYPE_KMS_IMPL_DEVICE_DUMMY; + } + else if (atomic_kms_enable_env) { if (g_strcmp0 (atomic_kms_enable_env, "1") == 0) { @@ -316,6 +355,9 @@ meta_create_kms_impl_device (MetaKmsDevice *device, atomic_kms_enable_env); } + impl_fd = dup (fd); + impl_path = g_strdup (path); + g_message ("Mode setting implementation for '%s' (%s) forced (%s).", path, driver_name, impl_device_type == META_TYPE_KMS_IMPL_DEVICE_ATOMIC ? @@ -326,6 +368,8 @@ meta_create_kms_impl_device (MetaKmsDevice *device, g_message ("Adding device '%s' (%s) using non-atomic mode setting" " (using atomic mode setting not allowed).", path, driver_name); + impl_fd = dup (fd); + impl_path = g_strdup (path); impl_device_type = META_TYPE_KMS_IMPL_DEVICE_SIMPLE; } else @@ -350,16 +394,29 @@ meta_create_kms_impl_device (MetaKmsDevice *device, path, driver_name); impl_device_type = META_TYPE_KMS_IMPL_DEVICE_SIMPLE; } + + impl_fd = dup (fd); + impl_path = g_strdup (path); } - return g_initable_new (impl_device_type, NULL, error, - "device", device, - "impl", impl, - "fd", fd, - "path", path, - "driver-name", driver_name, - "driver-description", driver_description, - NULL); + impl_device = g_initable_new (impl_device_type, NULL, error, + "device", device, + "impl", impl, + "fd", impl_fd, + "path", impl_path, + "flags", flags, + "driver-name", driver_name, + "driver-description", driver_description, + NULL); + if (!impl_device) + { + close (impl_fd); + return NULL; + } + + close (fd); + + return impl_device; } static gpointer @@ -374,6 +431,7 @@ create_impl_device_in_impl (MetaKmsImpl *impl, impl, data->fd, data->path, + data->flags, error); if (!impl_device) return FALSE; @@ -391,6 +449,7 @@ create_impl_device_in_impl (MetaKmsImpl *impl, g_strdup (meta_kms_impl_device_get_driver_name (impl_device)); data->out_driver_description = g_strdup (meta_kms_impl_device_get_driver_description (impl_device)); + data->out_path = g_strdup (meta_kms_impl_device_get_path (impl_device)); return GINT_TO_POINTER (TRUE); } @@ -408,9 +467,22 @@ meta_kms_device_new (MetaKms *kms, CreateImplDeviceData data; int fd; - fd = meta_launcher_open_restricted (launcher, path, error); - if (fd == -1) - return NULL; + if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING) + { + fd = open (path, O_RDWR | O_CLOEXEC, 0); + if (fd == -1) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Failed to open DRM device: %s", g_strerror (errno)); + return NULL; + } + } + else + { + fd = meta_launcher_open_restricted (launcher, path, error); + if (fd == -1) + return NULL; + } device = g_object_new (META_TYPE_KMS_DEVICE, NULL); device->kms = kms; @@ -419,11 +491,15 @@ meta_kms_device_new (MetaKms *kms, .device = device, .fd = fd, .path = path, + .flags = flags, }; if (!meta_kms_run_impl_task_sync (kms, create_impl_device_in_impl, &data, error)) { - meta_launcher_close_restricted (launcher, fd); + if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING) + close (fd); + else + meta_launcher_close_restricted (launcher, fd); g_object_unref (device); return NULL; } @@ -438,6 +514,8 @@ meta_kms_device_new (MetaKms *kms, device->fallback_modes = data.out_fallback_modes; device->driver_name = data.out_driver_name; device->driver_description = data.out_driver_description; + free (device->path); + device->path = data.out_path; return device; } @@ -495,7 +573,10 @@ meta_kms_device_finalize (GObject *object) } else { - meta_launcher_close_restricted (launcher, data.out_fd); + if (device->flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING) + close (data.out_fd); + else + meta_launcher_close_restricted (launcher, data.out_fd); } } G_OBJECT_CLASS (meta_kms_device_parent_class)->finalize (object); diff --git a/src/backends/native/meta-kms-impl-device-dummy.c b/src/backends/native/meta-kms-impl-device-dummy.c new file mode 100644 index 000000000..c1a0a4430 --- /dev/null +++ b/src/backends/native/meta-kms-impl-device-dummy.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2021 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-dummy.h" + +struct _MetaKmsImplDeviceDummy +{ + MetaKmsImplDevice parent; +}; + +static void +initable_iface_init (GInitableIface *iface); + +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)) + +static void +meta_kms_impl_device_dummy_discard_pending_page_flips (MetaKmsImplDevice *impl) +{ +} + +static void +meta_kms_impl_device_dummy_init (MetaKmsImplDeviceDummy *impl_device_dummy) +{ +} + +static gboolean +meta_kms_impl_device_dummy_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + return TRUE; +} + +static void +initable_iface_init (GInitableIface *iface) +{ + iface->init = meta_kms_impl_device_dummy_initable_init; +} + +static void +meta_kms_impl_device_dummy_class_init (MetaKmsImplDeviceDummyClass *klass) +{ + MetaKmsImplDeviceClass *impl_device_class = + META_KMS_IMPL_DEVICE_CLASS (klass); + + 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-dummy.h b/src/backends/native/meta-kms-impl-device-dummy.h new file mode 100644 index 000000000..9576939ad --- /dev/null +++ b/src/backends/native/meta-kms-impl-device-dummy.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 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_DUMMY_H +#define META_KMS_IMPL_DEVICE_DUMMY_H + +#include "backends/native/meta-kms-impl-device.h" + +#define META_TYPE_KMS_IMPL_DEVICE_DUMMY (meta_kms_impl_device_dummy_get_type ()) +G_DECLARE_FINAL_TYPE (MetaKmsImplDeviceDummy, meta_kms_impl_device_dummy, + META, KMS_IMPL_DEVICE_DUMMY, + MetaKmsImplDevice) + +#endif /* META_KMS_IMPL_DEVICE_DUMMY_H */ diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index f2a000fd1..d0247ef71 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -37,6 +37,7 @@ #include "backends/native/meta-kms-update.h" #include "meta-default-modes.h" +#include "meta-private-enum-types.h" enum { @@ -46,6 +47,7 @@ enum PROP_IMPL, PROP_FD, PROP_PATH, + PROP_FLAGS, PROP_DRIVER_NAME, PROP_DRIVER_DESCRIPTION, @@ -62,6 +64,7 @@ typedef struct _MetaKmsImplDevicePrivate int fd; GSource *fd_source; char *path; + MetaKmsDeviceFlag flags; char *driver_name; char *driver_description; @@ -712,6 +715,9 @@ meta_kms_impl_device_get_property (GObject *object, case PROP_PATH: g_value_set_string (value, priv->path); 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; @@ -748,6 +754,9 @@ meta_kms_impl_device_set_property (GObject *object, 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; @@ -873,6 +882,15 @@ meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_props[PROP_FLAGS] = + g_param_spec_flags ("flags", + "flags", + "KMS impl device flags", + META_TYPE_KMS_DEVICE_FLAG, + META_KMS_DEVICE_FLAG_NONE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); obj_props[PROP_DRIVER_NAME] = g_param_spec_string ("driver-name", "driver-name", diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h index cf1adc44e..01db55a40 100644 --- a/src/backends/native/meta-kms-types.h +++ b/src/backends/native/meta-kms-types.h @@ -61,6 +61,7 @@ typedef enum _MetaKmsDeviceFlag META_KMS_DEVICE_FLAG_PLATFORM_DEVICE = 1 << 1, META_KMS_DEVICE_FLAG_REQUIRES_MODIFIERS = 1 << 2, META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY = 1 << 3, + META_KMS_DEVICE_FLAG_NO_MODE_SETTING = 1 << 4, } MetaKmsDeviceFlag; typedef enum _MetaKmsPlaneType MetaKmsPlaneType; diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index ee77975bd..6514f89f6 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -158,6 +158,8 @@ struct _MetaKms { GObject parent; + MetaKmsFlags flags; + MetaBackend *backend; gulong hotplug_handler_id; @@ -614,6 +616,9 @@ meta_kms_create_device (MetaKms *kms, { MetaKmsDevice *device; + if (kms->flags & META_KMS_FLAG_NO_MODE_SETTING) + flags |= META_KMS_DEVICE_FLAG_NO_MODE_SETTING; + device = meta_kms_device_new (kms, path, flags, error); if (!device) return NULL; @@ -624,14 +629,16 @@ meta_kms_create_device (MetaKms *kms, } MetaKms * -meta_kms_new (MetaBackend *backend, - GError **error) +meta_kms_new (MetaBackend *backend, + MetaKmsFlags flags, + GError **error) { MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); MetaUdev *udev = meta_backend_native_get_udev (backend_native); MetaKms *kms; kms = g_object_new (META_TYPE_KMS, NULL); + kms->flags = flags; kms->backend = backend; kms->impl = meta_kms_impl_new (kms); if (!kms->impl) @@ -640,8 +647,12 @@ meta_kms_new (MetaBackend *backend, return NULL; } - kms->hotplug_handler_id = - g_signal_connect (udev, "hotplug", G_CALLBACK (on_udev_hotplug), kms); + if (!(flags & META_KMS_FLAG_NO_MODE_SETTING)) + { + kms->hotplug_handler_id = + g_signal_connect (udev, "hotplug", G_CALLBACK (on_udev_hotplug), kms); + } + kms->removed_handler_id = g_signal_connect (udev, "device-removed", G_CALLBACK (on_udev_device_removed), kms); diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h index 7bbd78e0c..27b4e3537 100644 --- a/src/backends/native/meta-kms.h +++ b/src/backends/native/meta-kms.h @@ -25,6 +25,12 @@ #include "backends/meta-backend-private.h" #include "backends/native/meta-kms-types.h" +typedef enum _MetaKmsFlags +{ + META_KMS_FLAG_NONE = 0, + META_KMS_FLAG_NO_MODE_SETTING = 1 << 0, +} MetaKmsFlags; + typedef enum _MetaKmsUpdateFlag { META_KMS_UPDATE_FLAG_NONE = 0, @@ -57,7 +63,8 @@ MetaKmsDevice * meta_kms_create_device (MetaKms *kms, MetaKmsDeviceFlag flags, GError **error); -MetaKms * meta_kms_new (MetaBackend *backend, - GError **error); +MetaKms * meta_kms_new (MetaBackend *backend, + MetaKmsFlags flags, + GError **error); #endif /* META_KMS_H */ diff --git a/src/meson.build b/src/meson.build index 196abf71f..6f52ab714 100644 --- a/src/meson.build +++ b/src/meson.build @@ -689,6 +689,8 @@ if have_native_backend 'backends/native/meta-kms-device.h', 'backends/native/meta-kms-impl-device-atomic.c', 'backends/native/meta-kms-impl-device-atomic.h', + 'backends/native/meta-kms-impl-device-dummy.c', + 'backends/native/meta-kms-impl-device-dummy.h', 'backends/native/meta-kms-impl-device-simple.c', 'backends/native/meta-kms-impl-device-simple.h', 'backends/native/meta-kms-impl-device.c', @@ -755,6 +757,7 @@ endif if have_native_backend mutter_private_enum_sources += [ 'backends/native/meta-backend-native-types.h', + 'backends/native/meta-kms-types.h', ] endif