From 27f798b6d014fa6f336dd4ceb1fcf6d587b44594 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Wed, 1 Jun 2022 22:01:45 -0400 Subject: [PATCH] kms/impl-device/atomic: Implement mouse cursor hotspots DRM's kms atomic code was updated to include an API to set the mouse cursor hotspot. This has historically been missing in the atomic kms which meant that the virtualized drivers which require mouse cursor hotspot info to properly render had to be put on a deny list and had to fallback to the legacy DRM kms code. Implement the new hotspot API by checking whether the device supports hotspot properties and if it does set them on the cursor plane. This enables atomic kms on all virtualized drivers for kernels where mouse cursor hotspots are in drm core. Part-of: --- .../native/meta-kms-impl-device-atomic.c | 67 +++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c index df153213f..5ea36de2a 100644 --- a/src/backends/native/meta-kms-impl-device-atomic.c +++ b/src/backends/native/meta-kms-impl-device-atomic.c @@ -48,6 +48,16 @@ static GInitableIface *initable_parent_iface; static void initable_iface_init (GInitableIface *iface); +/* + * Fallback while the patch updating the uAPI header has not landed. + * Should be removed afterward. + * Clients which do set cursor hotspot and treat the cursor plane + * like a mouse cursor should set this property. + */ +#ifndef DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT +#define DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT 6 +#endif + G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceAtomic, meta_kms_impl_device_atomic, META_TYPE_KMS_IMPL_DEVICE, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, @@ -1234,6 +1244,20 @@ meta_kms_impl_device_atomic_finalize (GObject *object) G_OBJECT_CLASS (meta_kms_impl_device_atomic_parent_class)->finalize (object); } +static gboolean +requires_hotspots (const char *driver_name) +{ + const char *atomic_driver_hotspots[] = { + "qxl", + "vboxvideo", + "virtio_gpu", + "vmwgfx", + NULL, + }; + + return g_strv_contains (atomic_driver_hotspots, driver_name); +} + static MetaDeviceFile * meta_kms_impl_device_atomic_open_device_file (MetaKmsImplDevice *impl_device, const char *path, @@ -1284,14 +1308,30 @@ meta_kms_impl_device_atomic_open_device_file (MetaKmsImplDevice *impl_device, return g_steal_pointer (&device_file); } +static gboolean +has_cursor_hotspot_properties (MetaKmsImplDevice *impl_device) +{ + GList *planes; + GList *l; + + planes = meta_kms_impl_device_peek_planes (impl_device); + for (l = planes; l; l = l->next) + { + MetaKmsPlane *plane = l->data; + + if (meta_kms_plane_get_plane_type (plane) != META_KMS_PLANE_TYPE_CURSOR) + continue; + + return meta_kms_plane_supports_cursor_hotspot (plane); + } + + return FALSE; +} + static gboolean is_atomic_allowed (const char *driver_name) { const char *atomic_driver_deny_list[] = { - "qxl", - "vmwgfx", - "vboxvideo", - "virtio_gpu", "xlnx", NULL, }; @@ -1319,6 +1359,25 @@ meta_kms_impl_device_atomic_initable_init (GInitable *initable, if (!meta_kms_impl_device_init_mode_setting (impl_device, error)) return FALSE; + if (requires_hotspots (meta_kms_impl_device_get_driver_name (impl_device))) + { + if (drmSetClientCap (meta_kms_impl_device_get_fd (impl_device), + DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT, 1) != 0) + { + g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED, + "Kernel has no support for virtual cursor plane on %s", + meta_kms_impl_device_get_driver_name (impl_device)); + return FALSE; + } + if (!has_cursor_hotspot_properties (impl_device)) + { + g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED, + "Plane cursor with hotspot properties is missing on %s", + meta_kms_impl_device_get_driver_name (impl_device)); + 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));