-
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
linux-kvm: Add patches to fix cursor in sway
- Loading branch information
1 parent
ee32f99
commit fb37141
Showing
11 changed files
with
1,159 additions
and
397 deletions.
There are no files selected for viewing
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
From 4e3b70da64a53784683cfcbac2deda5d6e540407 Mon Sep 17 00:00:00 2001 | ||
From: Zack Rusin <[email protected]> | ||
Date: Mon, 23 Oct 2023 09:46:05 +0200 | ||
Subject: drm: Disable the cursor plane on atomic contexts with virtualized | ||
drivers | ||
|
||
Cursor planes on virtualized drivers have special meaning and require | ||
that the clients handle them in specific ways, e.g. the cursor plane | ||
should react to the mouse movement the way a mouse cursor would be | ||
expected to and the client is required to set hotspot properties on it | ||
in order for the mouse events to be routed correctly. | ||
|
||
This breaks the contract as specified by the "universal planes". Fix it | ||
by disabling the cursor planes on virtualized drivers while adding | ||
a foundation on top of which it's possible to special case mouse cursor | ||
planes for clients that want it. | ||
|
||
Disabling the cursor planes makes some kms compositors which were broken, | ||
e.g. Weston, fallback to software cursor which works fine or at least | ||
better than currently while having no effect on others, e.g. gnome-shell | ||
or kwin, which put virtualized drivers on a deny-list when running in | ||
atomic context to make them fallback to legacy kms and avoid this issue. | ||
|
||
Signed-off-by: Zack Rusin <[email protected]> | ||
Fixes: 681e7ec73044 ("drm: Allow userspace to ask for universal plane list (v2)") | ||
Cc: <[email protected]> # v5.4+ | ||
Cc: Maarten Lankhorst <[email protected]> | ||
Cc: Maxime Ripard <[email protected]> | ||
Cc: Thomas Zimmermann <[email protected]> | ||
Cc: David Airlie <[email protected]> | ||
Cc: Daniel Vetter <[email protected]> | ||
Cc: Dave Airlie <[email protected]> | ||
Cc: Gerd Hoffmann <[email protected]> | ||
Cc: Hans de Goede <[email protected]> | ||
Cc: Gurchetan Singh <[email protected]> | ||
Cc: Chia-I Wu <[email protected]> | ||
Cc: [email protected] | ||
Cc: [email protected] | ||
Cc: [email protected] | ||
Acked-by: Pekka Paalanen <[email protected]> | ||
Reviewed-by: Javier Martinez Canillas <[email protected]> | ||
Acked-by: Simon Ser <[email protected]> | ||
Signed-off-by: Javier Martinez Canillas <[email protected]> | ||
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] | ||
--- | ||
drivers/gpu/drm/drm_plane.c | 13 +++++++++++++ | ||
drivers/gpu/drm/qxl/qxl_drv.c | 2 +- | ||
drivers/gpu/drm/vboxvideo/vbox_drv.c | 2 +- | ||
drivers/gpu/drm/virtio/virtgpu_drv.c | 2 +- | ||
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- | ||
include/drm/drm_drv.h | 9 +++++++++ | ||
include/drm/drm_file.h | 12 ++++++++++++ | ||
7 files changed, 38 insertions(+), 4 deletions(-) | ||
|
||
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c | ||
index 24e7998d1731..c6bbb0c209f4 100644 | ||
--- a/drivers/gpu/drm/drm_plane.c | ||
+++ b/drivers/gpu/drm/drm_plane.c | ||
@@ -678,6 +678,19 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, | ||
!file_priv->universal_planes) | ||
continue; | ||
|
||
+ /* | ||
+ * If we're running on a virtualized driver then, | ||
+ * unless userspace advertizes support for the | ||
+ * virtualized cursor plane, disable cursor planes | ||
+ * because they'll be broken due to missing cursor | ||
+ * hotspot info. | ||
+ */ | ||
+ if (plane->type == DRM_PLANE_TYPE_CURSOR && | ||
+ drm_core_check_feature(dev, DRIVER_CURSOR_HOTSPOT) && | ||
+ file_priv->atomic && | ||
+ !file_priv->supports_virtualized_cursor_plane) | ||
+ continue; | ||
+ | ||
if (drm_lease_held(file_priv, plane->base.id)) { | ||
if (count < plane_resp->count_planes && | ||
put_user(plane->base.id, plane_ptr + count)) | ||
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c | ||
index 46de4f171970..beee5563031a 100644 | ||
--- a/drivers/gpu/drm/qxl/qxl_drv.c | ||
+++ b/drivers/gpu/drm/qxl/qxl_drv.c | ||
@@ -285,7 +285,7 @@ static const struct drm_ioctl_desc qxl_ioctls[] = { | ||
}; | ||
|
||
static struct drm_driver qxl_driver = { | ||
- .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, | ||
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_CURSOR_HOTSPOT, | ||
|
||
.dumb_create = qxl_mode_dumb_create, | ||
.dumb_map_offset = drm_gem_ttm_dumb_map_offset, | ||
diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c b/drivers/gpu/drm/vboxvideo/vbox_drv.c | ||
index 047b95812334..cd9e66a06596 100644 | ||
--- a/drivers/gpu/drm/vboxvideo/vbox_drv.c | ||
+++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c | ||
@@ -182,7 +182,7 @@ DEFINE_DRM_GEM_FOPS(vbox_fops); | ||
|
||
static const struct drm_driver driver = { | ||
.driver_features = | ||
- DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, | ||
+ DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | DRIVER_CURSOR_HOTSPOT, | ||
|
||
.fops = &vbox_fops, | ||
.name = DRIVER_NAME, | ||
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c | ||
index 4334c7608408..f8e9abe647b9 100644 | ||
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c | ||
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c | ||
@@ -177,7 +177,7 @@ static const struct drm_driver driver = { | ||
* out via drm_device::driver_features: | ||
*/ | ||
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC | | ||
- DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE, | ||
+ DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE | DRIVER_CURSOR_HOTSPOT, | ||
.open = virtio_gpu_driver_open, | ||
.postclose = virtio_gpu_driver_postclose, | ||
|
||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | ||
index 8b24ecf60e3e..d3e308fdfd5b 100644 | ||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | ||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | ||
@@ -1611,7 +1611,7 @@ static const struct file_operations vmwgfx_driver_fops = { | ||
|
||
static const struct drm_driver driver = { | ||
.driver_features = | ||
- DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC | DRIVER_GEM, | ||
+ DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC | DRIVER_GEM | DRIVER_CURSOR_HOTSPOT, | ||
.ioctls = vmw_ioctls, | ||
.num_ioctls = ARRAY_SIZE(vmw_ioctls), | ||
.master_set = vmw_master_set, | ||
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h | ||
index e2640dc64e08..ea36aa79dca2 100644 | ||
--- a/include/drm/drm_drv.h | ||
+++ b/include/drm/drm_drv.h | ||
@@ -110,6 +110,15 @@ enum drm_driver_feature { | ||
* Driver supports user defined GPU VA bindings for GEM objects. | ||
*/ | ||
DRIVER_GEM_GPUVA = BIT(8), | ||
+ /** | ||
+ * @DRIVER_CURSOR_HOTSPOT: | ||
+ * | ||
+ * Driver supports and requires cursor hotspot information in the | ||
+ * cursor plane (e.g. cursor plane has to actually track the mouse | ||
+ * cursor and the clients are required to set hotspot in order for | ||
+ * the cursor planes to work correctly). | ||
+ */ | ||
+ DRIVER_CURSOR_HOTSPOT = BIT(9), | ||
|
||
/* IMPORTANT: Below are all the legacy flags, add new ones above. */ | ||
|
||
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h | ||
index e1b5b4282f75..8f35dcea82d3 100644 | ||
--- a/include/drm/drm_file.h | ||
+++ b/include/drm/drm_file.h | ||
@@ -226,6 +226,18 @@ struct drm_file { | ||
*/ | ||
bool is_master; | ||
|
||
+ /** | ||
+ * @supports_virtualized_cursor_plane: | ||
+ * | ||
+ * This client is capable of handling the cursor plane with the | ||
+ * restrictions imposed on it by the virtualized drivers. | ||
+ * | ||
+ * This implies that the cursor plane has to behave like a cursor | ||
+ * i.e. track cursor movement. It also requires setting of the | ||
+ * hotspot properties by the client on the cursor plane. | ||
+ */ | ||
+ bool supports_virtualized_cursor_plane; | ||
+ | ||
/** | ||
* @master: | ||
* | ||
-- | ||
cgit v1.2.3 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
From 8f7179a1027d89bf949b0b80c388a544a5e096f2 Mon Sep 17 00:00:00 2001 | ||
From: Zack Rusin <[email protected]> | ||
Date: Mon, 23 Oct 2023 09:46:06 +0200 | ||
Subject: drm/atomic: Add support for mouse hotspots | ||
|
||
Atomic modesetting code lacked support for specifying mouse cursor | ||
hotspots. The legacy kms DRM_IOCTL_MODE_CURSOR2 had support for setting | ||
the hotspot but the functionality was not implemented in the new atomic | ||
paths. | ||
|
||
Due to the lack of hotspots in the atomic paths userspace compositors | ||
completely disable atomic modesetting for drivers that require it (i.e. | ||
all paravirtualized drivers). | ||
|
||
This change adds hotspot properties to the atomic codepaths throughtout | ||
the DRM core and will allow enabling atomic modesetting for virtualized | ||
drivers in the userspace. | ||
|
||
Signed-off-by: Zack Rusin <[email protected]> | ||
Cc: Maarten Lankhorst <[email protected]> | ||
Cc: Maxime Ripard <[email protected]> | ||
Cc: Thomas Zimmermann <[email protected]> | ||
Cc: David Airlie <[email protected]> | ||
Cc: Daniel Vetter <[email protected]> | ||
Reviewed-by: Javier Martinez Canillas <[email protected]> | ||
Signed-off-by: Javier Martinez Canillas <[email protected]> | ||
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] | ||
--- | ||
drivers/gpu/drm/drm_atomic_state_helper.c | 14 +++++++++ | ||
drivers/gpu/drm/drm_atomic_uapi.c | 20 +++++++++++++ | ||
drivers/gpu/drm/drm_plane.c | 50 +++++++++++++++++++++++++++++++ | ||
include/drm/drm_plane.h | 14 +++++++++ | ||
4 files changed, 98 insertions(+) | ||
|
||
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c | ||
index 784e63d70a42..54975de44a0e 100644 | ||
--- a/drivers/gpu/drm/drm_atomic_state_helper.c | ||
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c | ||
@@ -275,6 +275,20 @@ void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state, | ||
plane_state->normalized_zpos = val; | ||
} | ||
} | ||
+ | ||
+ if (plane->hotspot_x_property) { | ||
+ if (!drm_object_property_get_default_value(&plane->base, | ||
+ plane->hotspot_x_property, | ||
+ &val)) | ||
+ plane_state->hotspot_x = val; | ||
+ } | ||
+ | ||
+ if (plane->hotspot_y_property) { | ||
+ if (!drm_object_property_get_default_value(&plane->base, | ||
+ plane->hotspot_y_property, | ||
+ &val)) | ||
+ plane_state->hotspot_y = val; | ||
+ } | ||
} | ||
EXPORT_SYMBOL(__drm_atomic_helper_plane_state_reset); | ||
|
||
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c | ||
index 116407002269..aee4a65d4959 100644 | ||
--- a/drivers/gpu/drm/drm_atomic_uapi.c | ||
+++ b/drivers/gpu/drm/drm_atomic_uapi.c | ||
@@ -593,6 +593,22 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, | ||
} else if (plane->funcs->atomic_set_property) { | ||
return plane->funcs->atomic_set_property(plane, state, | ||
property, val); | ||
+ } else if (property == plane->hotspot_x_property) { | ||
+ if (plane->type != DRM_PLANE_TYPE_CURSOR) { | ||
+ drm_dbg_atomic(plane->dev, | ||
+ "[PLANE:%d:%s] is not a cursor plane: 0x%llx\n", | ||
+ plane->base.id, plane->name, val); | ||
+ return -EINVAL; | ||
+ } | ||
+ state->hotspot_x = val; | ||
+ } else if (property == plane->hotspot_y_property) { | ||
+ if (plane->type != DRM_PLANE_TYPE_CURSOR) { | ||
+ drm_dbg_atomic(plane->dev, | ||
+ "[PLANE:%d:%s] is not a cursor plane: 0x%llx\n", | ||
+ plane->base.id, plane->name, val); | ||
+ return -EINVAL; | ||
+ } | ||
+ state->hotspot_y = val; | ||
} else { | ||
drm_dbg_atomic(plane->dev, | ||
"[PLANE:%d:%s] unknown property [PROP:%d:%s]\n", | ||
@@ -653,6 +669,10 @@ drm_atomic_plane_get_property(struct drm_plane *plane, | ||
*val = state->scaling_filter; | ||
} else if (plane->funcs->atomic_get_property) { | ||
return plane->funcs->atomic_get_property(plane, state, property, val); | ||
+ } else if (property == plane->hotspot_x_property) { | ||
+ *val = state->hotspot_x; | ||
+ } else if (property == plane->hotspot_y_property) { | ||
+ *val = state->hotspot_y; | ||
} else { | ||
drm_dbg_atomic(dev, | ||
"[PLANE:%d:%s] unknown property [PROP:%d:%s]\n", | ||
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c | ||
index c6bbb0c209f4..eaca367bdc7e 100644 | ||
--- a/drivers/gpu/drm/drm_plane.c | ||
+++ b/drivers/gpu/drm/drm_plane.c | ||
@@ -230,6 +230,47 @@ static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane | ||
return 0; | ||
} | ||
|
||
+/** | ||
+ * drm_plane_create_hotspot_properties - creates the mouse hotspot | ||
+ * properties and attaches them to the given cursor plane | ||
+ * | ||
+ * @plane: drm cursor plane | ||
+ * | ||
+ * This function enables the mouse hotspot property on a given | ||
+ * cursor plane. | ||
+ * | ||
+ * RETURNS: | ||
+ * Zero for success or -errno | ||
+ */ | ||
+static int drm_plane_create_hotspot_properties(struct drm_plane *plane) | ||
+{ | ||
+ struct drm_property *prop_x; | ||
+ struct drm_property *prop_y; | ||
+ | ||
+ drm_WARN_ON(plane->dev, | ||
+ !drm_core_check_feature(plane->dev, | ||
+ DRIVER_CURSOR_HOTSPOT)); | ||
+ | ||
+ prop_x = drm_property_create_signed_range(plane->dev, 0, "HOTSPOT_X", | ||
+ INT_MIN, INT_MAX); | ||
+ if (IS_ERR(prop_x)) | ||
+ return PTR_ERR(prop_x); | ||
+ | ||
+ prop_y = drm_property_create_signed_range(plane->dev, 0, "HOTSPOT_Y", | ||
+ INT_MIN, INT_MAX); | ||
+ if (IS_ERR(prop_y)) { | ||
+ drm_property_destroy(plane->dev, prop_x); | ||
+ return PTR_ERR(prop_y); | ||
+ } | ||
+ | ||
+ drm_object_attach_property(&plane->base, prop_x, 0); | ||
+ drm_object_attach_property(&plane->base, prop_y, 0); | ||
+ plane->hotspot_x_property = prop_x; | ||
+ plane->hotspot_y_property = prop_y; | ||
+ | ||
+ return 0; | ||
+} | ||
+ | ||
__printf(9, 0) | ||
static int __drm_universal_plane_init(struct drm_device *dev, | ||
struct drm_plane *plane, | ||
@@ -348,6 +389,10 @@ static int __drm_universal_plane_init(struct drm_device *dev, | ||
drm_object_attach_property(&plane->base, config->prop_src_w, 0); | ||
drm_object_attach_property(&plane->base, config->prop_src_h, 0); | ||
} | ||
+ if (drm_core_check_feature(dev, DRIVER_CURSOR_HOTSPOT) && | ||
+ type == DRM_PLANE_TYPE_CURSOR) { | ||
+ drm_plane_create_hotspot_properties(plane); | ||
+ } | ||
|
||
if (format_modifier_count) | ||
create_in_format_blob(dev, plane); | ||
@@ -1067,6 +1112,11 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, | ||
|
||
fb->hot_x = req->hot_x; | ||
fb->hot_y = req->hot_y; | ||
+ | ||
+ if (plane->hotspot_x_property && plane->state) | ||
+ plane->state->hotspot_x = req->hot_x; | ||
+ if (plane->hotspot_y_property && plane->state) | ||
+ plane->state->hotspot_y = req->hot_y; | ||
} else { | ||
fb = NULL; | ||
} | ||
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h | ||
index 79d62856defb..e2c671585775 100644 | ||
--- a/include/drm/drm_plane.h | ||
+++ b/include/drm/drm_plane.h | ||
@@ -116,6 +116,10 @@ struct drm_plane_state { | ||
/** @src_h: height of visible portion of plane (in 16.16) */ | ||
uint32_t src_h, src_w; | ||
|
||
+ /** @hotspot_x: x offset to mouse cursor hotspot */ | ||
+ /** @hotspot_y: y offset to mouse cursor hotspot */ | ||
+ int32_t hotspot_x, hotspot_y; | ||
+ | ||
/** | ||
* @alpha: | ||
* Opacity of the plane with 0 as completely transparent and 0xffff as | ||
@@ -748,6 +752,16 @@ struct drm_plane { | ||
* scaling. | ||
*/ | ||
struct drm_property *scaling_filter_property; | ||
+ | ||
+ /** | ||
+ * @hotspot_x_property: property to set mouse hotspot x offset. | ||
+ */ | ||
+ struct drm_property *hotspot_x_property; | ||
+ | ||
+ /** | ||
+ * @hotspot_y_property: property to set mouse hotspot y offset. | ||
+ */ | ||
+ struct drm_property *hotspot_y_property; | ||
}; | ||
|
||
#define obj_to_plane(x) container_of(x, struct drm_plane, base) | ||
-- | ||
cgit v1.2.3 | ||
|
Oops, something went wrong.