]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
drm/atomic: Add support for mouse hotspots
authorZack Rusin <zackr@vmware.com>
Mon, 23 Oct 2023 07:46:06 +0000 (09:46 +0200)
committerJavier Martinez Canillas <javierm@redhat.com>
Fri, 24 Nov 2023 10:57:56 +0000 (11:57 +0100)
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 <zackr@vmware.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231023074613.41327-3-aesteve@redhat.com
drivers/gpu/drm/drm_atomic_state_helper.c
drivers/gpu/drm/drm_atomic_uapi.c
drivers/gpu/drm/drm_plane.c
include/drm/drm_plane.h

index 784e63d70a421ea0272e64e1abd5b4ee113b45dc..54975de44a0e34f5fb3d6f29e39d6c5bd865ace9 100644 (file)
@@ -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);
 
index 116407002269688e759b4c82c4e737b874ddbd7e..aee4a65d495910081157d8f937ec86e38b5b4719 100644 (file)
@@ -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",
index c6bbb0c209f47f95510d820514584308836df776..eaca367bdc7e7b7313d12dd7c8d4a3fecd6ac12f 100644 (file)
@@ -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;
                }
index 79d62856defbf781c81c2c7f19365d3f2da56457..e2c671585775b6f4dcd4b9aae4c3451e7efc981a 100644 (file)
@@ -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)