Skip to content

Commit b4b27f0

Browse files
committed
drm/qxl: rework cursor plane
Add helper functions to create and move the cursor. Create the cursor_bo in prepare_fb callback, in the atomic_commit callback we only send the update command to the host. Signed-off-by: Gerd Hoffmann <[email protected]> Acked-by: Thomas Zimmermann <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent ab422b0 commit b4b27f0

File tree

1 file changed

+133
-115
lines changed

1 file changed

+133
-115
lines changed

drivers/gpu/drm/qxl/qxl_display.c

Lines changed: 133 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -476,12 +476,11 @@ static int qxl_primary_atomic_check(struct drm_plane *plane,
476476
return qxl_check_framebuffer(qdev, bo);
477477
}
478478

479-
static int qxl_primary_apply_cursor(struct drm_plane *plane)
479+
static int qxl_primary_apply_cursor(struct qxl_device *qdev,
480+
struct drm_plane_state *plane_state)
480481
{
481-
struct drm_device *dev = plane->dev;
482-
struct qxl_device *qdev = to_qxl(dev);
483-
struct drm_framebuffer *fb = plane->state->fb;
484-
struct qxl_crtc *qcrtc = to_qxl_crtc(plane->state->crtc);
482+
struct drm_framebuffer *fb = plane_state->fb;
483+
struct qxl_crtc *qcrtc = to_qxl_crtc(plane_state->crtc);
485484
struct qxl_cursor_cmd *cmd;
486485
struct qxl_release *release;
487486
int ret = 0;
@@ -505,8 +504,8 @@ static int qxl_primary_apply_cursor(struct drm_plane *plane)
505504

506505
cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
507506
cmd->type = QXL_CURSOR_SET;
508-
cmd->u.set.position.x = plane->state->crtc_x + fb->hot_x;
509-
cmd->u.set.position.y = plane->state->crtc_y + fb->hot_y;
507+
cmd->u.set.position.x = plane_state->crtc_x + fb->hot_x;
508+
cmd->u.set.position.y = plane_state->crtc_y + fb->hot_y;
510509

511510
cmd->u.set.shape = qxl_bo_physical_address(qdev, qcrtc->cursor_bo, 0);
512511

@@ -523,6 +522,113 @@ static int qxl_primary_apply_cursor(struct drm_plane *plane)
523522
return ret;
524523
}
525524

525+
static int qxl_primary_move_cursor(struct qxl_device *qdev,
526+
struct drm_plane_state *plane_state)
527+
{
528+
struct drm_framebuffer *fb = plane_state->fb;
529+
struct qxl_crtc *qcrtc = to_qxl_crtc(plane_state->crtc);
530+
struct qxl_cursor_cmd *cmd;
531+
struct qxl_release *release;
532+
int ret = 0;
533+
534+
if (!qcrtc->cursor_bo)
535+
return 0;
536+
537+
ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
538+
QXL_RELEASE_CURSOR_CMD,
539+
&release, NULL);
540+
if (ret)
541+
return ret;
542+
543+
ret = qxl_release_reserve_list(release, true);
544+
if (ret) {
545+
qxl_release_free(qdev, release);
546+
return ret;
547+
}
548+
549+
cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
550+
cmd->type = QXL_CURSOR_MOVE;
551+
cmd->u.position.x = plane_state->crtc_x + fb->hot_x;
552+
cmd->u.position.y = plane_state->crtc_y + fb->hot_y;
553+
qxl_release_unmap(qdev, release, &cmd->release_info);
554+
555+
qxl_release_fence_buffer_objects(release);
556+
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
557+
return ret;
558+
}
559+
560+
static struct qxl_bo *qxl_create_cursor(struct qxl_device *qdev,
561+
struct qxl_bo *user_bo,
562+
int hot_x, int hot_y)
563+
{
564+
static const u32 size = 64 * 64 * 4;
565+
struct qxl_bo *cursor_bo;
566+
struct dma_buf_map cursor_map;
567+
struct dma_buf_map user_map;
568+
struct qxl_cursor cursor;
569+
int ret;
570+
571+
if (!user_bo)
572+
return NULL;
573+
574+
ret = qxl_bo_create(qdev, sizeof(struct qxl_cursor) + size,
575+
false, true, QXL_GEM_DOMAIN_VRAM, 1,
576+
NULL, &cursor_bo);
577+
if (ret)
578+
goto err;
579+
580+
ret = qxl_bo_vmap(cursor_bo, &cursor_map);
581+
if (ret)
582+
goto err_unref;
583+
584+
ret = qxl_bo_vmap(user_bo, &user_map);
585+
if (ret)
586+
goto err_unmap;
587+
588+
cursor.header.unique = 0;
589+
cursor.header.type = SPICE_CURSOR_TYPE_ALPHA;
590+
cursor.header.width = 64;
591+
cursor.header.height = 64;
592+
cursor.header.hot_spot_x = hot_x;
593+
cursor.header.hot_spot_y = hot_y;
594+
cursor.data_size = size;
595+
cursor.chunk.next_chunk = 0;
596+
cursor.chunk.prev_chunk = 0;
597+
cursor.chunk.data_size = size;
598+
if (cursor_map.is_iomem) {
599+
memcpy_toio(cursor_map.vaddr_iomem,
600+
&cursor, sizeof(cursor));
601+
memcpy_toio(cursor_map.vaddr_iomem + sizeof(cursor),
602+
user_map.vaddr, size);
603+
} else {
604+
memcpy(cursor_map.vaddr,
605+
&cursor, sizeof(cursor));
606+
memcpy(cursor_map.vaddr + sizeof(cursor),
607+
user_map.vaddr, size);
608+
}
609+
610+
qxl_bo_vunmap(user_bo);
611+
qxl_bo_vunmap(cursor_bo);
612+
return cursor_bo;
613+
614+
err_unmap:
615+
qxl_bo_vunmap(cursor_bo);
616+
err_unref:
617+
qxl_bo_unpin(cursor_bo);
618+
qxl_bo_unref(&cursor_bo);
619+
err:
620+
return NULL;
621+
}
622+
623+
static void qxl_free_cursor(struct qxl_bo *cursor_bo)
624+
{
625+
if (!cursor_bo)
626+
return;
627+
628+
qxl_bo_unpin(cursor_bo);
629+
qxl_bo_unref(&cursor_bo);
630+
}
631+
526632
static void qxl_primary_atomic_update(struct drm_plane *plane,
527633
struct drm_plane_state *old_state)
528634
{
@@ -543,7 +649,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
543649
if (qdev->primary_bo)
544650
qxl_io_destroy_primary(qdev);
545651
qxl_io_create_primary(qdev, primary);
546-
qxl_primary_apply_cursor(plane);
652+
qxl_primary_apply_cursor(qdev, plane->state);
547653
}
548654

549655
if (bo->is_dumb)
@@ -574,124 +680,21 @@ static void qxl_primary_atomic_disable(struct drm_plane *plane,
574680
static void qxl_cursor_atomic_update(struct drm_plane *plane,
575681
struct drm_plane_state *old_state)
576682
{
577-
struct drm_device *dev = plane->dev;
578-
struct qxl_device *qdev = to_qxl(dev);
683+
struct qxl_device *qdev = to_qxl(plane->dev);
579684
struct drm_framebuffer *fb = plane->state->fb;
580-
struct qxl_crtc *qcrtc = to_qxl_crtc(plane->state->crtc);
581-
struct qxl_release *release;
582-
struct qxl_cursor_cmd *cmd;
583-
struct qxl_cursor *cursor;
584-
struct drm_gem_object *obj;
585-
struct qxl_bo *cursor_bo = NULL, *user_bo = NULL, *old_cursor_bo = NULL;
586-
int ret;
587-
struct dma_buf_map user_map;
588-
struct dma_buf_map cursor_map;
589-
void *user_ptr;
590-
int size = 64*64*4;
591-
592-
ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
593-
QXL_RELEASE_CURSOR_CMD,
594-
&release, NULL);
595-
if (ret)
596-
return;
597685

598686
if (fb != old_state->fb) {
599-
obj = fb->obj[0];
600-
user_bo = gem_to_qxl_bo(obj);
601-
602-
/* pinning is done in the prepare/cleanup framevbuffer */
603-
ret = qxl_bo_vmap_locked(user_bo, &user_map);
604-
if (ret)
605-
goto out_free_release;
606-
user_ptr = user_map.vaddr; /* TODO: Use mapping abstraction properly */
607-
608-
ret = qxl_alloc_bo_reserved(qdev, release,
609-
sizeof(struct qxl_cursor) + size,
610-
&cursor_bo);
611-
if (ret)
612-
goto out_kunmap;
613-
614-
ret = qxl_bo_pin(cursor_bo);
615-
if (ret)
616-
goto out_free_bo;
617-
618-
ret = qxl_release_reserve_list(release, true);
619-
if (ret)
620-
goto out_unpin;
621-
622-
ret = qxl_bo_vmap_locked(cursor_bo, &cursor_map);
623-
if (ret)
624-
goto out_backoff;
625-
if (cursor_map.is_iomem) /* TODO: Use mapping abstraction properly */
626-
cursor = (struct qxl_cursor __force *)cursor_map.vaddr_iomem;
627-
else
628-
cursor = (struct qxl_cursor *)cursor_map.vaddr;
629-
630-
cursor->header.unique = 0;
631-
cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
632-
cursor->header.width = 64;
633-
cursor->header.height = 64;
634-
cursor->header.hot_spot_x = fb->hot_x;
635-
cursor->header.hot_spot_y = fb->hot_y;
636-
cursor->data_size = size;
637-
cursor->chunk.next_chunk = 0;
638-
cursor->chunk.prev_chunk = 0;
639-
cursor->chunk.data_size = size;
640-
memcpy(cursor->chunk.data, user_ptr, size);
641-
qxl_bo_vunmap_locked(cursor_bo);
642-
qxl_bo_vunmap_locked(user_bo);
643-
644-
cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
645-
cmd->u.set.visible = 1;
646-
cmd->u.set.shape = qxl_bo_physical_address(qdev,
647-
cursor_bo, 0);
648-
cmd->type = QXL_CURSOR_SET;
649-
650-
old_cursor_bo = qcrtc->cursor_bo;
651-
qcrtc->cursor_bo = cursor_bo;
652-
cursor_bo = NULL;
687+
qxl_primary_apply_cursor(qdev, plane->state);
653688
} else {
654-
655-
ret = qxl_release_reserve_list(release, true);
656-
if (ret)
657-
goto out_free_release;
658-
659-
cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
660-
cmd->type = QXL_CURSOR_MOVE;
689+
qxl_primary_move_cursor(qdev, plane->state);
661690
}
662-
663-
cmd->u.position.x = plane->state->crtc_x + fb->hot_x;
664-
cmd->u.position.y = plane->state->crtc_y + fb->hot_y;
665-
666-
qxl_release_unmap(qdev, release, &cmd->release_info);
667-
qxl_release_fence_buffer_objects(release);
668-
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
669-
670-
if (old_cursor_bo != NULL)
671-
qxl_bo_unpin(old_cursor_bo);
672-
qxl_bo_unref(&old_cursor_bo);
673-
qxl_bo_unref(&cursor_bo);
674-
675-
return;
676-
677-
out_backoff:
678-
qxl_release_backoff_reserve_list(release);
679-
out_unpin:
680-
qxl_bo_unpin(cursor_bo);
681-
out_free_bo:
682-
qxl_bo_unref(&cursor_bo);
683-
out_kunmap:
684-
qxl_bo_vunmap_locked(user_bo);
685-
out_free_release:
686-
qxl_release_free(qdev, release);
687-
return;
688-
689691
}
690692

691693
static void qxl_cursor_atomic_disable(struct drm_plane *plane,
692694
struct drm_plane_state *old_state)
693695
{
694696
struct qxl_device *qdev = to_qxl(plane->dev);
697+
struct qxl_crtc *qcrtc;
695698
struct qxl_release *release;
696699
struct qxl_cursor_cmd *cmd;
697700
int ret;
@@ -714,6 +717,10 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
714717

715718
qxl_release_fence_buffer_objects(release);
716719
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
720+
721+
qcrtc = to_qxl_crtc(old_state->crtc);
722+
qxl_free_cursor(qcrtc->cursor_bo);
723+
qcrtc->cursor_bo = NULL;
717724
}
718725

719726
static void qxl_update_dumb_head(struct qxl_device *qdev,
@@ -822,6 +829,17 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
822829
qxl_prepare_shadow(qdev, user_bo, new_state->crtc->index);
823830
}
824831

832+
if (plane->type == DRM_PLANE_TYPE_CURSOR &&
833+
plane->state->fb != new_state->fb) {
834+
struct qxl_crtc *qcrtc = to_qxl_crtc(new_state->crtc);
835+
struct qxl_bo *old_cursor_bo = qcrtc->cursor_bo;
836+
837+
qcrtc->cursor_bo = qxl_create_cursor(qdev, user_bo,
838+
new_state->fb->hot_x,
839+
new_state->fb->hot_y);
840+
qxl_free_cursor(old_cursor_bo);
841+
}
842+
825843
return qxl_bo_pin(user_bo);
826844
}
827845

0 commit comments

Comments
 (0)