[PATCH 4/8] ACRN:DM:VGPU: Handle the virtio-gpu-cmds based on scanout_id in cmd_request


Zhao, Yakui
 

The scanout_id is included in the below virtio-gpu-cmd request.
VIRTIO_GPU_GET_EDID
VIRTIO_GPU_SET_SCANOUT
VIRTIO_GPU_SET_SCANOUT_BLOB

So the scanout_id and scanout_rect should be handled correctly.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
devicemodel/hw/pci/virtio/virtio_gpu.c | 88 ++++++++++++++++++++------
1 file changed, 67 insertions(+), 21 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 768e188d2..aa955ba23 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -564,11 +564,17 @@ virtio_gpu_cmd_get_edid(struct virtio_gpu_command *cmd)
memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
cmd->iolen = sizeof(resp);
memset(&resp, 0, sizeof(resp));
+ virtio_gpu_update_resp_fence(&cmd->hdr, &resp.hdr);
+ if (req.scanout >= gpu->scanout_num) {
+ pr_err("%s: Incorrect scanout_id %d\n", req.scanout);
+ resp.hdr.type = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+ memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
+ return;
+ }
/* Only one EDID block is enough */
resp.size = 128;
resp.hdr.type = VIRTIO_GPU_RESP_OK_EDID;
- virtio_gpu_update_resp_fence(&cmd->hdr, &resp.hdr);
- vdpy_get_edid(gpu->vdpy_handle, 0, resp.edid, resp.size);
+ vdpy_get_edid(gpu->vdpy_handle, req.scanout, resp.edid, resp.size);
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
}

@@ -578,18 +584,21 @@ virtio_gpu_cmd_get_display_info(struct virtio_gpu_command *cmd)
struct virtio_gpu_resp_display_info resp;
struct display_info info;
struct virtio_gpu *gpu;
+ int i;

gpu = cmd->gpu;
cmd->iolen = sizeof(resp);
memset(&resp, 0, sizeof(resp));
- vdpy_get_display_info(gpu->vdpy_handle, 0, &info);
resp.hdr.type = VIRTIO_GPU_RESP_OK_DISPLAY_INFO;
virtio_gpu_update_resp_fence(&cmd->hdr, &resp.hdr);
- resp.pmodes[0].enabled = 1;
- resp.pmodes[0].r.x = info.xoff;
- resp.pmodes[0].r.y = info.yoff;
- resp.pmodes[0].r.width = info.width;
- resp.pmodes[0].r.height = info.height;
+ for (i = 0; i < gpu->scanout_num; i++) {
+ vdpy_get_display_info(gpu->vdpy_handle, i, &info);
+ resp.pmodes[i].enabled = 1;
+ resp.pmodes[i].r.x = info.xoff;
+ resp.pmodes[i].r.y = info.yoff;
+ resp.pmodes[i].r.width = info.width;
+ resp.pmodes[i].r.height = info.height;
+ }
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
}

@@ -640,6 +649,40 @@ virtio_gpu_get_pixman_format(uint32_t format)
}
}

+static void
+virtio_gpu_update_scanout(struct virtio_gpu *gpu, int scanout_id, int resource_id,
+ struct virtio_gpu_rect *scan_rect)
+{
+ struct virtio_gpu_scanout *gpu_scanout;
+ struct virtio_gpu_resource_2d *r2d;
+
+ /* as it is already checked, this is not checked again */
+ gpu_scanout = gpu->gpu_scanouts + scanout_id;
+ if (gpu_scanout->dma_buf) {
+ virtio_gpu_dmabuf_unref(gpu_scanout->dma_buf);
+ gpu_scanout->dma_buf = NULL;
+ }
+ if (gpu_scanout->cur_img) {
+ pixman_image_unref(gpu_scanout->cur_img);
+ gpu_scanout->cur_img = NULL;
+ }
+ gpu_scanout->resource_id = resource_id;
+ r2d = virtio_gpu_find_resource_2d(gpu, resource_id);
+ if (r2d) {
+ gpu_scanout->active = true;
+ if (r2d->blob) {
+ virtio_gpu_dmabuf_ref(r2d->dma_info);
+ gpu_scanout->dma_buf = r2d->dma_info;
+ } else {
+ pixman_image_ref(r2d->image);
+ gpu_scanout->cur_img = r2d->image;
+ }
+ } else {
+ gpu_scanout->active = false;
+ }
+ memcpy(&gpu_scanout->scanout_rect, scan_rect, sizeof(*scan_rect));
+}
+
static void
virtio_gpu_cmd_resource_create_2d(struct virtio_gpu_command *cmd)
{
@@ -812,7 +855,8 @@ virtio_gpu_cmd_set_scanout(struct virtio_gpu_command *cmd)

r2d = virtio_gpu_find_resource_2d(gpu, req.resource_id);
if ((req.resource_id == 0) || (r2d == NULL)) {
- vdpy_surface_set(gpu->vdpy_handle, 0, NULL);
+ virtio_gpu_update_scanout(gpu, req.scanout_id, 0, &req.r);
+ vdpy_surface_set(gpu->vdpy_handle, req.scanout_id, NULL);
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
return;
@@ -827,16 +871,17 @@ virtio_gpu_cmd_set_scanout(struct virtio_gpu_command *cmd)
__func__);
resp.type = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
} else {
+ virtio_gpu_update_scanout(gpu, req.scanout_id, req.resource_id, &req.r);
pixman_image_ref(r2d->image);
surf.pixel = pixman_image_get_data(r2d->image);
- surf.x = 0;
- surf.y = 0;
- surf.width = r2d->width;
- surf.height = r2d->height;
+ surf.x = req.r.x;
+ surf.y = req.r.y;
+ surf.width = req.r.width;
+ surf.height = req.r.height;
surf.stride = pixman_image_get_stride(r2d->image);
surf.surf_format = r2d->format;
surf.surf_type = SURFACE_PIXMAN;
- vdpy_surface_set(gpu->vdpy_handle, 0, &surf);
+ vdpy_surface_set(gpu->vdpy_handle, req.scanout_id, &surf);
pixman_image_unref(r2d->image);
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
}
@@ -1172,9 +1217,10 @@ virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_command *cmd)
gpu_scanout = gpu->gpu_scanouts + req.scanout_id;
gpu_scanout->scanout_id = req.scanout_id;
if (req.resource_id == 0) {
+ virtio_gpu_update_scanout(gpu, req.scanout_id, 0, &req.r);
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
- vdpy_surface_set(gpu->vdpy_handle, 0, NULL);
+ vdpy_surface_set(gpu->vdpy_handle, req.scanout_id, NULL);
return;
}
r2d = virtio_gpu_find_resource_2d(cmd->gpu, req.resource_id);
@@ -1183,18 +1229,18 @@ virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_command *cmd)
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
return;
}
-
if (r2d->blob == false) {
/* Maybe the resource is not blob, fallback to set_scanout */
virtio_gpu_cmd_set_scanout(cmd);
return;
}

+ virtio_gpu_update_scanout(gpu, req.scanout_id, req.resource_id, &req.r);
virtio_gpu_dmabuf_ref(r2d->dma_info);
- surf.width = req.width;
- surf.height = req.height;
- surf.x = 0;
- surf.y = 0;
+ surf.width = req.r.width;
+ surf.height = req.r.height;
+ surf.x = req.r.x;
+ surf.y = req.r.y;
surf.stride = req.strides[0];
surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
surf.surf_type = SURFACE_DMABUF;
@@ -1218,7 +1264,7 @@ virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_command *cmd)
break;
}
surf.dma_info.surf_fourcc = drm_fourcc;
- vdpy_surface_set(gpu->vdpy_handle, 0, &surf);
+ vdpy_surface_set(gpu->vdpy_handle, req.scanout_id, &surf);
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
virtio_gpu_dmabuf_unref(r2d->dma_info);
--
2.25.1

Join acrn-dev@lists.projectacrn.org to automatically receive all group messages.