Message ID | 20230719014218.1700057-3-zack@kde.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Fix cursor planes with virtualized drivers | expand |
On Wednesday, July 19th, 2023 at 03:42, Zack Rusin <zack@kde.org> wrote: > From: Zack Rusin <zackr@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@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> > --- > 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; > + } Hm, it sounds a bit weird to catch this case here. Wouldn't it be a driver bug to attach the hotspot props to a plane which isn't a cursor? Wouldn't it make more sense to WARN in drm_plane_create_hotspot_properties() if a driver attempts to do so? > + 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); This is an atomic-only property, the DRM_MODE_PROP_ATOMIC flag should be passed. > + 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; > +}
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)