[Spice-devel] [PATCH v2 10/11] drm/qxl: rework cursor plane

Thomas Zimmermann tzimmermann at suse.de
Thu Feb 18 08:02:58 UTC 2021


Hi

Am 17.02.21 um 13:32 schrieb Gerd Hoffmann:
> 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.

I'm still trying to wrap my head around the qxl cursor code.

Getting vmap out of the commit tail is good, but I feel like this isn't 
going in the right direction overall.

In ast, these helper functions were only good when converting the drvier 
to atomic modesetting. So I removed them in the latst patchset and did 
all the updates in the plane helpers directly.

For cursor_bo itself, it seems to be transitional state that is only 
used during the plane update and crtc update . It should probably be 
stored in a plane-state structure.

Some of the primary plane's functions seem to deal with cursor handling. 
What's the role of the primary plane in cursor handling?

For now, I suggest to merge patch 1 to 8 and 11; and move the cursor 
patches into a new patchset. I'd like ot hear Daniel's opinion on this. 
Do you have further plans here?

If you absolutely want patches 9 and 10, I'd rubber-stamp an A-b on them.

Best regards
Thomas

> 
> Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
> ---
>   drivers/gpu/drm/qxl/qxl_display.c | 248 ++++++++++++++++--------------
>   1 file changed, 133 insertions(+), 115 deletions(-)
> 
> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> index b315d7484e21..4a3d272e8d6c 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -476,12 +476,11 @@ static int qxl_primary_atomic_check(struct drm_plane *plane,
>   	return qxl_check_framebuffer(qdev, bo);
>   }
>   
> -static int qxl_primary_apply_cursor(struct drm_plane *plane)
> +static int qxl_primary_apply_cursor(struct qxl_device *qdev,
> +				    struct drm_plane_state *plane_state)
>   {
> -	struct drm_device *dev = plane->dev;
> -	struct qxl_device *qdev = to_qxl(dev);
> -	struct drm_framebuffer *fb = plane->state->fb;
> -	struct qxl_crtc *qcrtc = to_qxl_crtc(plane->state->crtc);
> +	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;
> @@ -505,8 +504,8 @@ static int qxl_primary_apply_cursor(struct drm_plane *plane)
>   
>   	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.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);
>   
> @@ -523,6 +522,113 @@ static int qxl_primary_apply_cursor(struct drm_plane *plane)
>   	return ret;
>   }
>   
> +static int qxl_primary_move_cursor(struct qxl_device *qdev,
> +				   struct drm_plane_state *plane_state)
> +{
> +	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_reserve_list(release, true);
> +	if (ret) {
> +		qxl_release_free(qdev, release);
> +		return ret;
> +	}
> +
> +	cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
> +	cmd->type = QXL_CURSOR_MOVE;
> +	cmd->u.position.x = plane_state->crtc_x + fb->hot_x;
> +	cmd->u.position.y = plane_state->crtc_y + fb->hot_y;
> +	qxl_release_unmap(qdev, release, &cmd->release_info);
> +
> +	qxl_release_fence_buffer_objects(release);
> +	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
> +	return ret;
> +}
> +
> +static struct qxl_bo *qxl_create_cursor(struct qxl_device *qdev,
> +					struct qxl_bo *user_bo,
> +					int hot_x, int hot_y)
> +{
> +	static const u32 size = 64 * 64 * 4;
> +	struct qxl_bo *cursor_bo;
> +	struct dma_buf_map cursor_map;
> +	struct dma_buf_map user_map;
> +	struct qxl_cursor cursor;
> +	int ret;
> +
> +	if (!user_bo)
> +		return NULL;
> +
> +	ret = qxl_bo_create(qdev, sizeof(struct qxl_cursor) + size,
> +			    false, true, QXL_GEM_DOMAIN_VRAM, 1,
> +			    NULL, &cursor_bo);
> +	if (ret)
> +		goto err;
> +
> +	ret = qxl_bo_vmap(cursor_bo, &cursor_map);
> +	if (ret)
> +		goto err_unref;
> +
> +	ret = qxl_bo_vmap(user_bo, &user_map);
> +	if (ret)
> +		goto err_unmap;
> +
> +	cursor.header.unique = 0;
> +	cursor.header.type = SPICE_CURSOR_TYPE_ALPHA;
> +	cursor.header.width = 64;
> +	cursor.header.height = 64;
> +	cursor.header.hot_spot_x = hot_x;
> +	cursor.header.hot_spot_y = hot_y;
> +	cursor.data_size = size;
> +	cursor.chunk.next_chunk = 0;
> +	cursor.chunk.prev_chunk = 0;
> +	cursor.chunk.data_size = size;
> +	if (cursor_map.is_iomem) {
> +		memcpy_toio(cursor_map.vaddr_iomem,
> +			    &cursor, sizeof(cursor));
> +		memcpy_toio(cursor_map.vaddr_iomem + sizeof(cursor),
> +			    user_map.vaddr, size);
> +	} else {
> +		memcpy(cursor_map.vaddr,
> +		       &cursor, sizeof(cursor));
> +		memcpy(cursor_map.vaddr + sizeof(cursor),
> +		       user_map.vaddr, size);
> +	}
> +
> +	qxl_bo_vunmap(user_bo);
> +	qxl_bo_vunmap(cursor_bo);
> +	return cursor_bo;
> +
> +err_unmap:
> +	qxl_bo_vunmap(cursor_bo);
> +err_unref:
> +	qxl_bo_unpin(cursor_bo);
> +	qxl_bo_unref(&cursor_bo);
> +err:
> +	return NULL;
> +}
> +
> +static void qxl_free_cursor(struct qxl_bo *cursor_bo)
> +{
> +	if (!cursor_bo)
> +		return;
> +
> +	qxl_bo_unpin(cursor_bo);
> +	qxl_bo_unref(&cursor_bo);
> +}
> +
>   static void qxl_primary_atomic_update(struct drm_plane *plane,
>   				      struct drm_plane_state *old_state)
>   {
> @@ -543,7 +649,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
>   		if (qdev->primary_bo)
>   			qxl_io_destroy_primary(qdev);
>   		qxl_io_create_primary(qdev, primary);
> -		qxl_primary_apply_cursor(plane);
> +		qxl_primary_apply_cursor(qdev, plane->state);
>   	}
>   
>   	if (bo->is_dumb)
> @@ -574,124 +680,21 @@ static void qxl_primary_atomic_disable(struct drm_plane *plane,
>   static void qxl_cursor_atomic_update(struct drm_plane *plane,
>   				     struct drm_plane_state *old_state)
>   {
> -	struct drm_device *dev = plane->dev;
> -	struct qxl_device *qdev = to_qxl(dev);
> +	struct qxl_device *qdev = to_qxl(plane->dev);
>   	struct drm_framebuffer *fb = plane->state->fb;
> -	struct qxl_crtc *qcrtc = to_qxl_crtc(plane->state->crtc);
> -	struct qxl_release *release;
> -	struct qxl_cursor_cmd *cmd;
> -	struct qxl_cursor *cursor;
> -	struct drm_gem_object *obj;
> -	struct qxl_bo *cursor_bo = NULL, *user_bo = NULL, *old_cursor_bo = NULL;
> -	int ret;
> -	struct dma_buf_map user_map;
> -	struct dma_buf_map cursor_map;
> -	void *user_ptr;
> -	int size = 64*64*4;
> -
> -	ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
> -					 QXL_RELEASE_CURSOR_CMD,
> -					 &release, NULL);
> -	if (ret)
> -		return;
>   
>   	if (fb != old_state->fb) {
> -		obj = fb->obj[0];
> -		user_bo = gem_to_qxl_bo(obj);
> -
> -		/* pinning is done in the prepare/cleanup framevbuffer */
> -		ret = qxl_bo_vmap_locked(user_bo, &user_map);
> -		if (ret)
> -			goto out_free_release;
> -		user_ptr = user_map.vaddr; /* TODO: Use mapping abstraction properly */
> -
> -		ret = qxl_alloc_bo_reserved(qdev, release,
> -					    sizeof(struct qxl_cursor) + size,
> -					    &cursor_bo);
> -		if (ret)
> -			goto out_kunmap;
> -
> -		ret = qxl_bo_pin(cursor_bo);
> -		if (ret)
> -			goto out_free_bo;
> -
> -		ret = qxl_release_reserve_list(release, true);
> -		if (ret)
> -			goto out_unpin;
> -
> -		ret = qxl_bo_vmap_locked(cursor_bo, &cursor_map);
> -		if (ret)
> -			goto out_backoff;
> -		if (cursor_map.is_iomem) /* TODO: Use mapping abstraction properly */
> -			cursor = (struct qxl_cursor __force *)cursor_map.vaddr_iomem;
> -		else
> -			cursor = (struct qxl_cursor *)cursor_map.vaddr;
> -
> -		cursor->header.unique = 0;
> -		cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
> -		cursor->header.width = 64;
> -		cursor->header.height = 64;
> -		cursor->header.hot_spot_x = fb->hot_x;
> -		cursor->header.hot_spot_y = fb->hot_y;
> -		cursor->data_size = size;
> -		cursor->chunk.next_chunk = 0;
> -		cursor->chunk.prev_chunk = 0;
> -		cursor->chunk.data_size = size;
> -		memcpy(cursor->chunk.data, user_ptr, size);
> -		qxl_bo_vunmap_locked(cursor_bo);
> -		qxl_bo_vunmap_locked(user_bo);
> -
> -		cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
> -		cmd->u.set.visible = 1;
> -		cmd->u.set.shape = qxl_bo_physical_address(qdev,
> -							   cursor_bo, 0);
> -		cmd->type = QXL_CURSOR_SET;
> -
> -		old_cursor_bo = qcrtc->cursor_bo;
> -		qcrtc->cursor_bo = cursor_bo;
> -		cursor_bo = NULL;
> +		qxl_primary_apply_cursor(qdev, plane->state);
>   	} else {
> -
> -		ret = qxl_release_reserve_list(release, true);
> -		if (ret)
> -			goto out_free_release;
> -
> -		cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
> -		cmd->type = QXL_CURSOR_MOVE;
> +		qxl_primary_move_cursor(qdev, plane->state);
>   	}
> -
> -	cmd->u.position.x = plane->state->crtc_x + fb->hot_x;
> -	cmd->u.position.y = plane->state->crtc_y + fb->hot_y;
> -
> -	qxl_release_unmap(qdev, release, &cmd->release_info);
> -	qxl_release_fence_buffer_objects(release);
> -	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
> -
> -	if (old_cursor_bo != NULL)
> -		qxl_bo_unpin(old_cursor_bo);
> -	qxl_bo_unref(&old_cursor_bo);
> -	qxl_bo_unref(&cursor_bo);
> -
> -	return;
> -
> -out_backoff:
> -	qxl_release_backoff_reserve_list(release);
> -out_unpin:
> -	qxl_bo_unpin(cursor_bo);
> -out_free_bo:
> -	qxl_bo_unref(&cursor_bo);
> -out_kunmap:
> -	qxl_bo_vunmap_locked(user_bo);
> -out_free_release:
> -	qxl_release_free(qdev, release);
> -	return;
> -
>   }
>   
>   static void qxl_cursor_atomic_disable(struct drm_plane *plane,
>   				      struct drm_plane_state *old_state)
>   {
>   	struct qxl_device *qdev = to_qxl(plane->dev);
> +	struct qxl_crtc *qcrtc;
>   	struct qxl_release *release;
>   	struct qxl_cursor_cmd *cmd;
>   	int ret;
> @@ -714,6 +717,10 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
>   
>   	qxl_release_fence_buffer_objects(release);
>   	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
> +
> +	qcrtc = to_qxl_crtc(old_state->crtc);
> +	qxl_free_cursor(qcrtc->cursor_bo);
> +	qcrtc->cursor_bo = NULL;
>   }
>   
>   static void qxl_update_dumb_head(struct qxl_device *qdev,
> @@ -822,6 +829,17 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
>   		qxl_prepare_shadow(qdev, user_bo, new_state->crtc->index);
>   	}
>   
> +	if (plane->type == DRM_PLANE_TYPE_CURSOR &&
> +	    plane->state->fb != new_state->fb) {
> +		struct qxl_crtc *qcrtc = to_qxl_crtc(new_state->crtc);
> +		struct qxl_bo *old_cursor_bo = qcrtc->cursor_bo;
> +
> +		qcrtc->cursor_bo = qxl_create_cursor(qdev, user_bo,
> +						     new_state->fb->hot_x,
> +						     new_state->fb->hot_y);
> +		qxl_free_cursor(old_cursor_bo);
> +	}
> +
>   	return qxl_bo_pin(user_bo);
>   }
>   
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/spice-devel/attachments/20210218/de724b00/attachment-0001.sig>


More information about the Spice-devel mailing list