[PATCH v4 2/8] drm/atomic: Add support for mouse hotspots

Pekka Paalanen ppaalanen at gmail.com
Wed Jun 28 07:54:24 UTC 2023


On Wed, 28 Jun 2023 10:41:06 +0300
Pekka Paalanen <ppaalanen at gmail.com> wrote:

> On Wed, 28 Jun 2023 01:21:27 -0400
> Zack Rusin <zack at kde.org> wrote:
> 
> > From: Zack Rusin <zackr at vmware.com>
> > 
> > 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 at vmware.com>
> > Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> > Cc: Maxime Ripard <mripard at kernel.org>
> > Cc: Thomas Zimmermann <tzimmermann at suse.de>
> > Cc: David Airlie <airlied at linux.ie>
> > Cc: Daniel Vetter <daniel at ffwll.ch>
> > Reviewed-by: Javier Martinez Canillas <javierm at redhat.com>  
> 
> Hi Zack,
> 
> I still do not see any UAPI docs for the new properties in this patch?

If you are wondering what there could be to write about, maybe this can
give a good mindset:

Let's assume that I am a Wayland compositor developer who has never used
"hotspots" with KMS UAPI before. As I have never tested anything in a
VM, I have no idea why the kernel would ever want to know about cursor
hotspots. Display hardware never does anything with that, it just puts
the cursor plane where I tell it to and composes a single image to be
sent to the sink. The virtual driver VKMS does the same. To me, a
cursor plane is just another universal plane that may have weird
stacking order, pixel format, and size limitations.

Ideally the doc for HOTSPOT_X and HOTSPOT_Y documents not only their
possible existence and allowed/expected values, but also the reasons
to have them and what they are used for, and that if the properties
are exposed they are mandatory to program in order to use the plane.


Thanks,
pq

> > ---
> >  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 98d3b10c08ae..07a7b3f18df2 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 51291983ea44..74e62f90a1ad 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)  
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20230628/ef7f0752/attachment-0001.sig>


More information about the dri-devel mailing list