summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-07-11 15:10:06 +1000
committerDave Airlie <airlied@redhat.com>2013-09-03 15:10:48 +1000
commit07eaaae1b2002d3d2b8149777e7ff5f558bb9434 (patch)
tree095bf2e87197bff8fa96fa9bb5dbc13e68ef548a
parent27c23c8d7fc442532a955555fbc1f520fb583a53 (diff)
virgl: add cursor support
-rw-r--r--drivers/gpu/drm/virgl/virgl_display.c63
-rw-r--r--drivers/gpu/drm/virgl/virgl_drv.h10
-rw-r--r--drivers/gpu/drm/virgl/virgl_ioctl.c21
-rw-r--r--include/uapi/drm/virgl_drm.h10
4 files changed, 102 insertions, 2 deletions
diff --git a/drivers/gpu/drm/virgl/virgl_display.c b/drivers/gpu/drm/virgl/virgl_display.c
index 6d0454f7445f..7c382b1dac25 100644
--- a/drivers/gpu/drm/virgl/virgl_display.c
+++ b/drivers/gpu/drm/virgl/virgl_display.c
@@ -88,7 +88,7 @@ static void virgl_crtc_destroy(struct drm_crtc *crtc)
static void
virgl_hide_cursor(struct virgl_device *qdev)
{
-
+ iowrite32(0, qdev->ioaddr + VIRTIO_VIRGL_CURSOR_ID);
}
static int virgl_crtc_cursor_set(struct drm_crtc *crtc,
@@ -97,12 +97,71 @@ static int virgl_crtc_cursor_set(struct drm_crtc *crtc,
uint32_t width,
uint32_t height)
{
- return 0;
+ struct virgl_device *qdev = crtc->dev->dev_private;
+ struct drm_gem_object *gobj = NULL;
+ struct virgl_bo *qobj = NULL;
+ int ret = 0;
+ if (handle == 0) {
+ virgl_hide_cursor(qdev);
+ return 0;
+ }
+
+ /* lookup the cursor */
+ gobj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+ if (gobj == NULL)
+ return -ENOENT;
+
+ qobj = gem_to_virgl_bo(gobj);
+
+ if (!qobj->res_handle) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ {
+ struct virgl_command *cmd_p;
+ struct virgl_vbuffer *vbuf;
+ uint32_t offset = 0;
+
+ cmd_p = virgl_alloc_cmd(qdev, qobj, false, &offset, 0, &vbuf);
+ if (IS_ERR(cmd_p)) {
+ printk("failed to allocate cmd for transfer\n");
+ return -EINVAL;
+ }
+
+ cmd_p->type = VIRGL_TRANSFER_PUT;
+ cmd_p->u.transfer_put.res_handle = qobj->res_handle;
+
+ cmd_p->u.transfer_put.dst_box.x = 0;
+ cmd_p->u.transfer_put.dst_box.y = 0;
+ cmd_p->u.transfer_put.dst_box.z = 0;
+ cmd_p->u.transfer_put.dst_box.w = 64;
+ cmd_p->u.transfer_put.dst_box.h = 64;
+ cmd_p->u.transfer_put.dst_box.d = 1;
+
+ cmd_p->u.transfer_put.dst_level = 0;
+ cmd_p->u.transfer_put.src_stride = 0;
+
+ cmd_p->u.transfer_put.data = offset;
+ cmd_p->u.transfer_put.transfer_flags = 0;
+
+ virgl_queue_cmd_buf(qdev, vbuf);
+ }
+
+ iowrite32(qobj->res_handle, qdev->ioaddr + VIRTIO_VIRGL_CURSOR_ID);
+ iowrite32(0, qdev->ioaddr + VIRTIO_VIRGL_CURSOR_HOT_X_Y);
+
+out:
+ drm_gem_object_unreference_unlocked(gobj);
+ return ret;
}
static int virgl_crtc_cursor_move(struct drm_crtc *crtc,
int x, int y)
{
+ struct virgl_device *qdev = crtc->dev->dev_private;
+ iowrite32(x, qdev->ioaddr + VIRTIO_VIRGL_CURSOR_CUR_X);
+ iowrite32(y, qdev->ioaddr + VIRTIO_VIRGL_CURSOR_CUR_Y);
return 0;
}
diff --git a/drivers/gpu/drm/virgl/virgl_drv.h b/drivers/gpu/drm/virgl/virgl_drv.h
index 959751812bb4..5a9deccd19f8 100644
--- a/drivers/gpu/drm/virgl/virgl_drv.h
+++ b/drivers/gpu/drm/virgl/virgl_drv.h
@@ -376,4 +376,14 @@ u32 virgl_fence_read(struct virgl_device *qdev);
void virgl_dequeue_work_func(struct work_struct *work);
int virgl_resource_unref(struct virgl_device *qdev, uint32_t res_handle);
+
+/* 32-bit cursor resource id - 0 = disable cursor */
+#define VIRTIO_VIRGL_FENCE_ID 20
+#define VIRTIO_VIRGL_CURSOR_ID 24
+/* cursor hotspot info */
+#define VIRTIO_VIRGL_CURSOR_HOT_X_Y 28
+/* current cursor position */
+#define VIRTIO_VIRGL_CURSOR_CUR_X 32
+#define VIRTIO_VIRGL_CURSOR_CUR_Y 36
+
#endif
diff --git a/drivers/gpu/drm/virgl/virgl_ioctl.c b/drivers/gpu/drm/virgl/virgl_ioctl.c
index f926f0c15c41..836b82612869 100644
--- a/drivers/gpu/drm/virgl/virgl_ioctl.c
+++ b/drivers/gpu/drm/virgl/virgl_ioctl.c
@@ -281,6 +281,25 @@ static int virgl_wait_ioctl(struct drm_device *dev, void *data,
return ret;
}
+static int virgl_cursor_link_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_virgl_cursor_link *args = data;
+ struct drm_gem_object *gobj = NULL;
+ struct virgl_bo *qobj = NULL;
+
+ gobj = drm_gem_object_lookup(dev, file, args->bo_handle);
+ if (gobj == NULL)
+ return -ENOENT;
+
+ qobj = gem_to_virgl_bo(gobj);
+
+ qobj->res_handle = args->res_handle;
+ drm_gem_object_unreference_unlocked(gobj);
+
+ return 0;
+}
+
struct drm_ioctl_desc virgl_ioctls[] = {
DRM_IOCTL_DEF_DRV(VIRGL_ALLOC, virgl_alloc_ioctl, DRM_AUTH|DRM_UNLOCKED),
@@ -302,6 +321,8 @@ struct drm_ioctl_desc virgl_ioctls[] = {
DRM_IOCTL_DEF_DRV(VIRGL_WAIT, virgl_wait_ioctl, DRM_AUTH|DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(VIRGL_CURSOR_LINK, virgl_cursor_link_ioctl, DRM_AUTH|DRM_UNLOCKED),
+
};
int virgl_max_ioctls = DRM_ARRAY_SIZE(virgl_ioctls);
diff --git a/include/uapi/drm/virgl_drm.h b/include/uapi/drm/virgl_drm.h
index faf704dcf9de..f7b4c92dc15c 100644
--- a/include/uapi/drm/virgl_drm.h
+++ b/include/uapi/drm/virgl_drm.h
@@ -43,6 +43,7 @@
#define DRM_VIRGL_TRANSFER_GET 0x06
#define DRM_VIRGL_TRANSFER_PUT 0x07
#define DRM_VIRGL_WAIT 0x08
+#define DRM_VIRGL_CURSOR_LINK 0x09
struct drm_virgl_alloc {
uint32_t size;
@@ -116,6 +117,11 @@ struct drm_virgl_3d_wait {
uint32_t flags;
};
+struct drm_virgl_cursor_link {
+ uint32_t bo_handle;
+ uint32_t res_handle;
+};
+
#define DRM_IOCTL_VIRGL_ALLOC \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRGL_ALLOC, struct drm_virgl_alloc)
@@ -149,4 +155,8 @@ struct drm_virgl_3d_wait {
#define DRM_IOCTL_VIRGL_WAIT \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRGL_WAIT, \
struct drm_virgl_3d_wait)
+
+#define DRM_IOCTL_VIRGL_CURSOR_LINK \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRGL_CURSOR_LINK, \
+ struct drm_virgl_cursor_link)
#endif