81f5f8b
From f2a2b3496b6024a5df546f0aedd60705b896a464 Mon Sep 17 00:00:00 2001
81f5f8b
From: Dave Airlie <airlied@redhat.com>
81f5f8b
Date: Thu, 20 Jun 2013 11:48:52 +1000
81f5f8b
Subject: [PATCH 2/5] drm: add hotspot support for cursors.
81f5f8b
81f5f8b
So it looks like for virtual hw cursors on QXL we need to inform
81f5f8b
the "hw" device what the cursor hotspot parameters are. This
81f5f8b
makes sense if you think the host has to draw the cursor and interpret
81f5f8b
clicks from it. However the current modesetting interface doesn't support
81f5f8b
passing the hotspot information from userspace.
81f5f8b
81f5f8b
This implements a new cursor ioctl, that takes the hotspot info as well,
81f5f8b
userspace can try calling the new interface and if it gets -ENOSYS it means
81f5f8b
its on an older kernel and can just fallback.
81f5f8b
81f5f8b
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
81f5f8b
Signed-off-by: Dave Airlie <airlied@redhat.com>
81f5f8b
---
81f5f8b
 drivers/gpu/drm/drm_crtc.c  | 35 +++++++++++++++++++++++++++++------
81f5f8b
 drivers/gpu/drm/drm_drv.c   |  1 +
81f5f8b
 include/drm/drm_crtc.h      |  5 +++++
81f5f8b
 include/uapi/drm/drm.h      |  1 +
81f5f8b
 include/uapi/drm/drm_mode.h | 13 +++++++++++++
81f5f8b
 5 files changed, 49 insertions(+), 6 deletions(-)
81f5f8b
81f5f8b
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
81f5f8b
index dd64a06..21e71a8 100644
81f5f8b
--- a/drivers/gpu/drm/drm_crtc.c
81f5f8b
+++ b/drivers/gpu/drm/drm_crtc.c
81f5f8b
@@ -2202,10 +2202,10 @@ out:
81f5f8b
 	return ret;
81f5f8b
 }
81f5f8b
 
81f5f8b
-int drm_mode_cursor_ioctl(struct drm_device *dev,
81f5f8b
-			void *data, struct drm_file *file_priv)
81f5f8b
+static int drm_mode_cursor_common(struct drm_device *dev,
81f5f8b
+				  struct drm_mode_cursor2 *req,
81f5f8b
+				  struct drm_file *file_priv)
81f5f8b
 {
81f5f8b
-	struct drm_mode_cursor *req = data;
81f5f8b
 	struct drm_mode_object *obj;
81f5f8b
 	struct drm_crtc *crtc;
81f5f8b
 	int ret = 0;
81f5f8b
@@ -2225,13 +2225,17 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
81f5f8b
 
81f5f8b
 	mutex_lock(&crtc->mutex);
81f5f8b
 	if (req->flags & DRM_MODE_CURSOR_BO) {
81f5f8b
-		if (!crtc->funcs->cursor_set) {
81f5f8b
+		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
81f5f8b
 			ret = -ENXIO;
81f5f8b
 			goto out;
81f5f8b
 		}
81f5f8b
 		/* Turns off the cursor if handle is 0 */
81f5f8b
-		ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
81f5f8b
-					      req->width, req->height);
81f5f8b
+		if (crtc->funcs->cursor_set2)
81f5f8b
+			ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
81f5f8b
+						      req->width, req->height, req->hot_x, req->hot_y);
81f5f8b
+		else
81f5f8b
+			ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
81f5f8b
+						      req->width, req->height);
81f5f8b
 	}
81f5f8b
 
81f5f8b
 	if (req->flags & DRM_MODE_CURSOR_MOVE) {
81f5f8b
@@ -2246,6 +2250,25 @@ out:
81f5f8b
 	mutex_unlock(&crtc->mutex);
81f5f8b
 
81f5f8b
 	return ret;
81f5f8b
+
81f5f8b
+}
81f5f8b
+int drm_mode_cursor_ioctl(struct drm_device *dev,
81f5f8b
+			void *data, struct drm_file *file_priv)
81f5f8b
+{
81f5f8b
+	struct drm_mode_cursor *req = data;
81f5f8b
+	struct drm_mode_cursor2 new_req;
81f5f8b
+
81f5f8b
+	memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
81f5f8b
+	new_req.hot_x = new_req.hot_y = 0;
81f5f8b
+
81f5f8b
+	return drm_mode_cursor_common(dev, &new_req, file_priv);
81f5f8b
+}
81f5f8b
+
81f5f8b
+int drm_mode_cursor2_ioctl(struct drm_device *dev,
81f5f8b
+			   void *data, struct drm_file *file_priv)
81f5f8b
+{
81f5f8b
+	struct drm_mode_cursor2 *req = data;
81f5f8b
+	return drm_mode_cursor_common(dev, req, file_priv);
81f5f8b
 }
81f5f8b
 
81f5f8b
 /* Original addfb only supported RGB formats, so figure out which one */
81f5f8b
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
81f5f8b
index 25f91cd..cb4470b 100644
81f5f8b
--- a/drivers/gpu/drm/drm_drv.c
81f5f8b
+++ b/drivers/gpu/drm/drm_drv.c
81f5f8b
@@ -166,6 +166,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
81f5f8b
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
81f5f8b
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
81f5f8b
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
81f5f8b
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
81f5f8b
 };
81f5f8b
 
81f5f8b
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
81f5f8b
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
81f5f8b
index e3e0d65..eba931b 100644
81f5f8b
--- a/include/drm/drm_crtc.h
81f5f8b
+++ b/include/drm/drm_crtc.h
81f5f8b
@@ -339,6 +339,9 @@ struct drm_crtc_funcs {
81f5f8b
 	/* cursor controls */
81f5f8b
 	int (*cursor_set)(struct drm_crtc *crtc, struct drm_file *file_priv,
81f5f8b
 			  uint32_t handle, uint32_t width, uint32_t height);
81f5f8b
+	int (*cursor_set2)(struct drm_crtc *crtc, struct drm_file *file_priv,
81f5f8b
+			   uint32_t handle, uint32_t width, uint32_t height,
81f5f8b
+			   int32_t hot_x, int32_t hot_y);
81f5f8b
 	int (*cursor_move)(struct drm_crtc *crtc, int x, int y);
81f5f8b
 
81f5f8b
 	/* Set gamma on the CRTC */
81f5f8b
@@ -1025,6 +1028,8 @@ extern int drm_mode_setplane(struct drm_device *dev,
81f5f8b
 			       void *data, struct drm_file *file_priv);
81f5f8b
 extern int drm_mode_cursor_ioctl(struct drm_device *dev,
81f5f8b
 				void *data, struct drm_file *file_priv);
81f5f8b
+extern int drm_mode_cursor2_ioctl(struct drm_device *dev,
81f5f8b
+				void *data, struct drm_file *file_priv);
81f5f8b
 extern int drm_mode_addfb(struct drm_device *dev,
81f5f8b
 			  void *data, struct drm_file *file_priv);
81f5f8b
 extern int drm_mode_addfb2(struct drm_device *dev,
81f5f8b
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
81f5f8b
index 8d1e2bb..5182a2d 100644
81f5f8b
--- a/include/uapi/drm/drm.h
81f5f8b
+++ b/include/uapi/drm/drm.h
81f5f8b
@@ -732,6 +732,7 @@ struct drm_prime_handle {
81f5f8b
 #define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
81f5f8b
 #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES	DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
81f5f8b
 #define DRM_IOCTL_MODE_OBJ_SETPROPERTY	DRM_IOWR(0xBA, struct drm_mode_obj_set_property)
81f5f8b
+#define DRM_IOCTL_MODE_CURSOR2		DRM_IOWR(0xBB, struct drm_mode_cursor2)
81f5f8b
 
81f5f8b
 /**
81f5f8b
  * Device specific ioctls should only be in their respective headers
81f5f8b
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
81f5f8b
index 3d6301b..ecde539 100644
81f5f8b
--- a/include/uapi/drm/drm_mode.h
81f5f8b
+++ b/include/uapi/drm/drm_mode.h
81f5f8b
@@ -388,6 +388,19 @@ struct drm_mode_cursor {
81f5f8b
 	__u32 handle;
81f5f8b
 };
81f5f8b
 
81f5f8b
+struct drm_mode_cursor2 {
81f5f8b
+	__u32 flags;
81f5f8b
+	__u32 crtc_id;
81f5f8b
+	__s32 x;
81f5f8b
+	__s32 y;
81f5f8b
+	__u32 width;
81f5f8b
+	__u32 height;
81f5f8b
+	/* driver specific handle */
81f5f8b
+	__u32 handle;
81f5f8b
+	__s32 hot_x;
81f5f8b
+	__s32 hot_y;
81f5f8b
+};
81f5f8b
+
81f5f8b
 struct drm_mode_crtc_lut {
81f5f8b
 	__u32 crtc_id;
81f5f8b
 	__u32 gamma_size;
81f5f8b
-- 
81f5f8b
1.8.3.1
81f5f8b