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

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>

authored by

Ray Strode and committed by
Gerd Hoffmann
4532b241 de595762

+56 -1
+55 -1
drivers/gpu/drm/qxl/qxl_display.c
··· 211 211 struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc); 212 212 213 213 drm_crtc_cleanup(crtc); 214 + qxl_bo_unref(&qxl_crtc->cursor_bo); 214 215 kfree(qxl_crtc); 215 216 } 216 217 ··· 295 294 qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); 296 295 qxl_release_fence_buffer_objects(release); 297 296 return 0; 297 + } 298 + 299 + static int qxl_crtc_apply_cursor(struct drm_crtc *crtc) 300 + { 301 + struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); 302 + struct drm_device *dev = crtc->dev; 303 + struct qxl_device *qdev = dev->dev_private; 304 + struct qxl_cursor_cmd *cmd; 305 + struct qxl_release *release; 306 + int ret = 0; 307 + 308 + if (!qcrtc->cursor_bo) 309 + return 0; 310 + 311 + ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), 312 + QXL_RELEASE_CURSOR_CMD, 313 + &release, NULL); 314 + if (ret) 315 + return ret; 316 + 317 + ret = qxl_release_list_add(release, qcrtc->cursor_bo); 318 + if (ret) 319 + goto out_free_release; 320 + 321 + ret = qxl_release_reserve_list(release, false); 322 + if (ret) 323 + goto out_free_release; 324 + 325 + cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); 326 + cmd->type = QXL_CURSOR_SET; 327 + cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x; 328 + cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y; 329 + 330 + cmd->u.set.shape = qxl_bo_physical_address(qdev, qcrtc->cursor_bo, 0); 331 + 332 + cmd->u.set.visible = 1; 333 + qxl_release_unmap(qdev, release, &cmd->release_info); 334 + 335 + qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); 336 + qxl_release_fence_buffer_objects(release); 337 + 338 + return ret; 339 + 340 + out_free_release: 341 + qxl_release_free(qdev, release); 342 + return ret; 298 343 } 299 344 300 345 static int qxl_crtc_cursor_set2(struct drm_crtc *crtc, ··· 447 400 } 448 401 drm_gem_object_unreference_unlocked(obj); 449 402 450 - qxl_bo_unref(&cursor_bo); 403 + qxl_bo_unref (&qcrtc->cursor_bo); 404 + qcrtc->cursor_bo = cursor_bo; 451 405 452 406 return ret; 453 407 ··· 703 655 bo->surf.stride, bo->surf.format); 704 656 qxl_io_create_primary(qdev, 0, bo); 705 657 bo->is_primary = true; 658 + 659 + ret = qxl_crtc_apply_cursor(crtc); 660 + if (ret) { 661 + DRM_ERROR("could not set cursor after modeset"); 662 + ret = 0; 663 + } 706 664 } 707 665 708 666 if (bo->is_primary) {
+1
drivers/gpu/drm/qxl/qxl_drv.h
··· 137 137 int cur_y; 138 138 int hot_spot_x; 139 139 int hot_spot_y; 140 + struct qxl_bo *cursor_bo; 140 141 }; 141 142 142 143 struct qxl_output {