summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/qxl
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2016-09-09 11:09:05 -0400
committerGerd Hoffmann <kraxel@redhat.com>2016-09-20 14:25:37 +0200
commit4532b241a4b7b0ca372a80baf900ce4ea2015412 (patch)
tree8233bd477d8df9b782de4c7d87682a1665c1df59 /drivers/gpu/drm/qxl
parentde59576293f82ee285ef5edb31f7169c84403368 (diff)
drm/qxl: reapply cursor after SetCrtc calls
The qxl driver currently destroys and recreates the qxl "primary" any time the first crtc is set. A side-effect of destroying the primary is mouse state associated with the crtc is lost, which leads to disappearing mouse cursors on wayland sessions. This commit changes the driver to reapply the cursor any time SetCrtc is called. It achieves this by keeping a reference to the cursor bo on the qxl_crtc struct. Signed-off-by: Ray Strode <rstrode@redhat.com> Message-id: 1473433745-11016-1-git-send-email-halfline@gmail.com https://bugzilla.redhat.com/show_bug.cgi?id=1200901 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/qxl')
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c56
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h1
2 files changed, 56 insertions, 1 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 3aef12742a53..a61c0d460ec2 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -211,6 +211,7 @@ static void qxl_crtc_destroy(struct drm_crtc *crtc)
struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc);
drm_crtc_cleanup(crtc);
+ qxl_bo_unref(&qxl_crtc->cursor_bo);
kfree(qxl_crtc);
}
@@ -296,6 +297,52 @@ qxl_hide_cursor(struct qxl_device *qdev)
return 0;
}
+static int qxl_crtc_apply_cursor(struct drm_crtc *crtc)
+{
+ struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct qxl_device *qdev = dev->dev_private;
+ struct qxl_cursor_cmd *cmd;
+ struct qxl_release *release;
+ int ret = 0;
+
+ if (!qcrtc->cursor_bo)
+ return 0;
+
+ ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
+ QXL_RELEASE_CURSOR_CMD,
+ &release, NULL);
+ if (ret)
+ return ret;
+
+ ret = qxl_release_list_add(release, qcrtc->cursor_bo);
+ if (ret)
+ goto out_free_release;
+
+ ret = qxl_release_reserve_list(release, false);
+ if (ret)
+ goto out_free_release;
+
+ cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
+ cmd->type = QXL_CURSOR_SET;
+ cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
+ cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
+
+ cmd->u.set.shape = qxl_bo_physical_address(qdev, qcrtc->cursor_bo, 0);
+
+ cmd->u.set.visible = 1;
+ qxl_release_unmap(qdev, release, &cmd->release_info);
+
+ qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+ qxl_release_fence_buffer_objects(release);
+
+ return ret;
+
+out_free_release:
+ qxl_release_free(qdev, release);
+ return ret;
+}
+
static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
struct drm_file *file_priv,
uint32_t handle,
@@ -400,7 +447,8 @@ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
}
drm_gem_object_unreference_unlocked(obj);
- qxl_bo_unref(&cursor_bo);
+ qxl_bo_unref (&qcrtc->cursor_bo);
+ qcrtc->cursor_bo = cursor_bo;
return ret;
@@ -655,6 +703,12 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
bo->surf.stride, bo->surf.format);
qxl_io_create_primary(qdev, 0, bo);
bo->is_primary = true;
+
+ ret = qxl_crtc_apply_cursor(crtc);
+ if (ret) {
+ DRM_ERROR("could not set cursor after modeset");
+ ret = 0;
+ }
}
if (bo->is_primary) {
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 8e633caa4078..5f3e5ad99de7 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -137,6 +137,7 @@ struct qxl_crtc {
int cur_y;
int hot_spot_x;
int hot_spot_y;
+ struct qxl_bo *cursor_bo;
};
struct qxl_output {