Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: add hotspot support for cursors.

So it looks like for virtual hw cursors on QXL we need to inform
the "hw" device what the cursor hotspot parameters are. This
makes sense if you think the host has to draw the cursor and interpret
clicks from it. However the current modesetting interface doesn't support
passing the hotspot information from userspace.

This implements a new cursor ioctl, that takes the hotspot info as well,
userspace can try calling the new interface and if it gets -ENOSYS it means
its on an older kernel and can just fallback.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>

+49 -6
+29 -6
drivers/gpu/drm/drm_crtc.c
··· 2178 2178 return ret; 2179 2179 } 2180 2180 2181 - int drm_mode_cursor_ioctl(struct drm_device *dev, 2182 - void *data, struct drm_file *file_priv) 2181 + static int drm_mode_cursor_common(struct drm_device *dev, 2182 + struct drm_mode_cursor2 *req, 2183 + struct drm_file *file_priv) 2183 2184 { 2184 - struct drm_mode_cursor *req = data; 2185 2185 struct drm_mode_object *obj; 2186 2186 struct drm_crtc *crtc; 2187 2187 int ret = 0; ··· 2201 2201 2202 2202 mutex_lock(&crtc->mutex); 2203 2203 if (req->flags & DRM_MODE_CURSOR_BO) { 2204 - if (!crtc->funcs->cursor_set) { 2204 + if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { 2205 2205 ret = -ENXIO; 2206 2206 goto out; 2207 2207 } 2208 2208 /* Turns off the cursor if handle is 0 */ 2209 - ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, 2210 - req->width, req->height); 2209 + if (crtc->funcs->cursor_set2) 2210 + ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle, 2211 + req->width, req->height, req->hot_x, req->hot_y); 2212 + else 2213 + ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, 2214 + req->width, req->height); 2211 2215 } 2212 2216 2213 2217 if (req->flags & DRM_MODE_CURSOR_MOVE) { ··· 2226 2222 mutex_unlock(&crtc->mutex); 2227 2223 2228 2224 return ret; 2225 + 2226 + } 2227 + int drm_mode_cursor_ioctl(struct drm_device *dev, 2228 + void *data, struct drm_file *file_priv) 2229 + { 2230 + struct drm_mode_cursor *req = data; 2231 + struct drm_mode_cursor2 new_req; 2232 + 2233 + memcpy(&new_req, req, sizeof(struct drm_mode_cursor)); 2234 + new_req.hot_x = new_req.hot_y = 0; 2235 + 2236 + return drm_mode_cursor_common(dev, &new_req, file_priv); 2237 + } 2238 + 2239 + int drm_mode_cursor2_ioctl(struct drm_device *dev, 2240 + void *data, struct drm_file *file_priv) 2241 + { 2242 + struct drm_mode_cursor2 *req = data; 2243 + return drm_mode_cursor_common(dev, req, file_priv); 2229 2244 } 2230 2245 2231 2246 /* Original addfb only supported RGB formats, so figure out which one */
+1
drivers/gpu/drm/drm_drv.c
··· 166 166 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 167 167 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), 168 168 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 169 + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 169 170 }; 170 171 171 172 #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
+5
include/drm/drm_crtc.h
··· 339 339 /* cursor controls */ 340 340 int (*cursor_set)(struct drm_crtc *crtc, struct drm_file *file_priv, 341 341 uint32_t handle, uint32_t width, uint32_t height); 342 + int (*cursor_set2)(struct drm_crtc *crtc, struct drm_file *file_priv, 343 + uint32_t handle, uint32_t width, uint32_t height, 344 + int32_t hot_x, int32_t hot_y); 342 345 int (*cursor_move)(struct drm_crtc *crtc, int x, int y); 343 346 344 347 /* Set gamma on the CRTC */ ··· 1020 1017 extern int drm_mode_setplane(struct drm_device *dev, 1021 1018 void *data, struct drm_file *file_priv); 1022 1019 extern int drm_mode_cursor_ioctl(struct drm_device *dev, 1020 + void *data, struct drm_file *file_priv); 1021 + extern int drm_mode_cursor2_ioctl(struct drm_device *dev, 1023 1022 void *data, struct drm_file *file_priv); 1024 1023 extern int drm_mode_addfb(struct drm_device *dev, 1025 1024 void *data, struct drm_file *file_priv);
+1
include/uapi/drm/drm.h
··· 732 732 #define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) 733 733 #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) 734 734 #define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) 735 + #define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) 735 736 736 737 /** 737 738 * Device specific ioctls should only be in their respective headers
+13
include/uapi/drm/drm_mode.h
··· 388 388 __u32 handle; 389 389 }; 390 390 391 + struct drm_mode_cursor2 { 392 + __u32 flags; 393 + __u32 crtc_id; 394 + __s32 x; 395 + __s32 y; 396 + __u32 width; 397 + __u32 height; 398 + /* driver specific handle */ 399 + __u32 handle; 400 + __s32 hot_x; 401 + __s32 hot_y; 402 + }; 403 + 391 404 struct drm_mode_crtc_lut { 392 405 __u32 crtc_id; 393 406 __u32 gamma_size;