Commit 9428088c authored by Ray Strode's avatar Ray Strode Committed by Dave Airlie

drm/qxl: reapply cursor after resetting primary

QXL associates mouse state with its primary plane.

Destroying a primary plane and putting a new one in place has the side
effect of destroying the cursor as well.

This commit changes the driver to reapply the cursor any time a new
primary is created. It achieves this by keeping a reference to the
cursor bo on the qxl_crtc struct.

This fix is very similar to

commit 4532b241 ("drm/qxl: reapply cursor after SetCrtc calls")

which got implicitly reverted as part of implementing the atomic
modeset feature.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Dave Airlie <airlied@redhat.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1512097
Fixes: 1277eed5 ("drm: qxl: Atomic phase 1: convert cursor to universal plane")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarRay Strode <rstrode@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 16c6db36
...@@ -289,6 +289,7 @@ static void qxl_crtc_destroy(struct drm_crtc *crtc) ...@@ -289,6 +289,7 @@ static void qxl_crtc_destroy(struct drm_crtc *crtc)
{ {
struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc); struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc);
qxl_bo_unref(&qxl_crtc->cursor_bo);
drm_crtc_cleanup(crtc); drm_crtc_cleanup(crtc);
kfree(qxl_crtc); kfree(qxl_crtc);
} }
...@@ -495,6 +496,53 @@ static int qxl_primary_atomic_check(struct drm_plane *plane, ...@@ -495,6 +496,53 @@ static int qxl_primary_atomic_check(struct drm_plane *plane,
return 0; return 0;
} }
static int qxl_primary_apply_cursor(struct drm_plane *plane)
{
struct drm_device *dev = plane->dev;
struct qxl_device *qdev = dev->dev_private;
struct drm_framebuffer *fb = plane->state->fb;
struct qxl_crtc *qcrtc = to_qxl_crtc(plane->state->crtc);
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 = plane->state->crtc_x + fb->hot_x;
cmd->u.set.position.y = plane->state->crtc_y + fb->hot_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 void qxl_primary_atomic_update(struct drm_plane *plane, static void qxl_primary_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state) struct drm_plane_state *old_state)
{ {
...@@ -510,6 +558,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, ...@@ -510,6 +558,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
.x2 = qfb->base.width, .x2 = qfb->base.width,
.y2 = qfb->base.height .y2 = qfb->base.height
}; };
int ret;
bool same_shadow = false; bool same_shadow = false;
if (old_state->fb) { if (old_state->fb) {
...@@ -531,6 +580,11 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, ...@@ -531,6 +580,11 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
if (!same_shadow) if (!same_shadow)
qxl_io_destroy_primary(qdev); qxl_io_destroy_primary(qdev);
bo_old->is_primary = false; bo_old->is_primary = false;
ret = qxl_primary_apply_cursor(plane);
if (ret)
DRM_ERROR(
"could not set cursor after creating primary");
} }
if (!bo->is_primary) { if (!bo->is_primary) {
...@@ -571,6 +625,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane, ...@@ -571,6 +625,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
struct drm_device *dev = plane->dev; struct drm_device *dev = plane->dev;
struct qxl_device *qdev = dev->dev_private; struct qxl_device *qdev = dev->dev_private;
struct drm_framebuffer *fb = plane->state->fb; struct drm_framebuffer *fb = plane->state->fb;
struct qxl_crtc *qcrtc = to_qxl_crtc(plane->state->crtc);
struct qxl_release *release; struct qxl_release *release;
struct qxl_cursor_cmd *cmd; struct qxl_cursor_cmd *cmd;
struct qxl_cursor *cursor; struct qxl_cursor *cursor;
...@@ -628,6 +683,10 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane, ...@@ -628,6 +683,10 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
cmd->u.set.shape = qxl_bo_physical_address(qdev, cmd->u.set.shape = qxl_bo_physical_address(qdev,
cursor_bo, 0); cursor_bo, 0);
cmd->type = QXL_CURSOR_SET; cmd->type = QXL_CURSOR_SET;
qxl_bo_unref(&qcrtc->cursor_bo);
qcrtc->cursor_bo = cursor_bo;
cursor_bo = NULL;
} else { } else {
ret = qxl_release_reserve_list(release, true); ret = qxl_release_reserve_list(release, true);
......
...@@ -111,6 +111,8 @@ struct qxl_bo_list { ...@@ -111,6 +111,8 @@ struct qxl_bo_list {
struct qxl_crtc { struct qxl_crtc {
struct drm_crtc base; struct drm_crtc base;
int index; int index;
struct qxl_bo *cursor_bo;
}; };
struct qxl_output { struct qxl_output {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment