Date   

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

Zhao, Yakui
 

On 2022/8/8 14:59, Sun Peng wrote:
On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
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
[Sun, Peng] The scanout_id is included in the below virtio-gpu
operation requests.
- VIRTIO_GPU_GET_EDID
- VIRTIO_GPU_SET_SCANOUT
- VIRTIO_GPU_SET_SCANOUT_BLOB

So the scanout_id and scanout_rect should be handled correctly.
Thanks for the review.

It will be updated in next version.

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);
[Sun, Peng] pr_err("%s: Invalid scanout_id %d\n"
+               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);


Re: [PATCH 8/8] ACRN:DM:VGPU: Return the parsed scanout_num to virtio_gpu in Guest_VM

Sun, Peng
 

On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
Return the parsed scanout_num to guest_vm so that the guest_vm can
configure multi-display.

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

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 42d07e053..3601a10b3 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -1619,11 +1619,11 @@ virtio_gpu_init(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
                        BACKEND_VBSU);
 
        gpu->scanout_num = 1;
-       gpu->vdpy_handle = vdpy_init(NULL);
+       gpu->vdpy_handle = vdpy_init(&gpu->scanout_num);
[Sun, Peng] I think it is better 2/8 and 8/8 should be combinded as one
patch.
        gpu->base.mtx = &gpu->mtx;
        gpu->base.device_caps = VIRTIO_GPU_S_HOSTCAPS;
 
-       if (gpu->scanout_num < 0) {
+       if ((gpu->scanout_num < 0) || (gpu->scanout_num > 2)) {
                pr_err("%s: return incorrect scanout num %d\n", gpu-
scanout_num);
                return -1;
        }
@@ -1685,7 +1685,7 @@ virtio_gpu_init(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
        /* prepare the config space */
        gpu->cfg.events_read = 0;
        gpu->cfg.events_clear = 0;
-       gpu->cfg.num_scanouts = 1;
+       gpu->cfg.num_scanouts = gpu->scanout_num;
        gpu->cfg.num_capsets = 0;
 
        /* config the device id and vendor id according to spec */
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


Re: [PATCH 3/8] ACRN:DM:VGPU: Add virtio_gpu_scanout structure to handle virtio-gpu-cmds correctly

Zhao, Yakui
 

On 2022/8/8 14:52, Sun Peng wrote:
On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
Now it only supports one scanout panel for virtio-gpu. So the
[Sun, Peng] Now it only supports one scanout for virtio-gpu.
scanout_id is ignored in
course of handling virtio-gpu-cmd. In order to handle the
[Sun, Peng] course of handling virtio-gpu commands.
virtio-gpu-cmds correctly, it
adds the virtio_gpu_scanout structure so that it can record the
scanout info.
This will be updated in next version.


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

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index cf3d20823..768e188d2 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -348,6 +348,16 @@ enum vga_thread_status {
        VGA_THREAD_EOL = 0,
        VGA_THREAD_RUNNING
 };
+
+struct virtio_gpu_scanout {
+       int scanout_id;
+       uint32_t resource_id;
+       struct virtio_gpu_rect scanout_rect;
+       pixman_image_t *cur_img;
[Sun, Peng] What is the mean of cur_img? Cursor or Current?
It is current. This indicates the image used by the scanout when
it uses the VIRTIO_GPU_SET_SCANOUT cmd.

+       struct dma_buf_info *dma_buf;
+       bool active;
[Sun, Peng] I think is_active is better.
Sure. It will be changed in next version.

+};
+
 /*
  * Per-device struct
  */
@@ -366,6 +376,8 @@ struct virtio_gpu {
        int32_t vga_thread_status;
        uint8_t edid[VIRTIO_GPU_EDID_SIZE];
        bool is_blob_supported;
+       int scanout_num;
+       struct virtio_gpu_scanout *gpu_scanouts;
 };
 struct virtio_gpu_command {
@@ -782,12 +794,22 @@ virtio_gpu_cmd_set_scanout(struct
virtio_gpu_command *cmd)
        struct virtio_gpu_ctrl_hdr resp;
        struct surface surf;
        struct virtio_gpu *gpu;
+       struct virtio_gpu_scanout *gpu_scanout;
        gpu = cmd->gpu;
        memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
        memset(&resp, 0, sizeof(resp));
        virtio_gpu_update_resp_fence(&cmd->hdr, &resp);
+       if (req.scanout_id >= gpu->scanout_num) {
+               pr_err("%s: Incorrect scanout_id %d\n",
req.scanout_id);
[Sun, Peng] pr_err("%s: Invalid scanout_id
OK. It will be updated in next version.

+               resp.type = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+               memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
+               return;
+       }
+       gpu_scanout = gpu->gpu_scanouts + req.scanout_id;
+       gpu_scanout->scanout_id = req.scanout_id;
+
        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);
@@ -1130,6 +1152,7 @@ virtio_gpu_cmd_set_scanout_blob(struct
virtio_gpu_command *cmd)
        struct surface surf;
        uint32_t drm_fourcc;
        struct virtio_gpu *gpu;
+       struct virtio_gpu_scanout *gpu_scanout;
        gpu = cmd->gpu;
        memset(&surf, 0, sizeof(surf));
@@ -1140,6 +1163,14 @@ virtio_gpu_cmd_set_scanout_blob(struct
virtio_gpu_command *cmd)
        if (cmd->gpu->vga.enable) {
                cmd->gpu->vga.enable = false;
        }
+       if (req.scanout_id >= gpu->scanout_num) {
+               pr_err("%s: Incorrect scanout_id %d\n",
req.scanout_id);
[Sun, Peng] Also "Invalid scanout_id" here.
+               resp.type = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+               memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp,
sizeof(resp));
+               return;
+       }
+       gpu_scanout = gpu->gpu_scanouts + req.scanout_id;
+       gpu_scanout->scanout_id = req.scanout_id;
        if (req.resource_id == 0) {
                resp.type = VIRTIO_GPU_RESP_OK_NODATA;
                memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp,
sizeof(resp));
@@ -1485,10 +1516,22 @@ virtio_gpu_init(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
                        gpu->vq,
                        BACKEND_VBSU);
+       gpu->scanout_num = 1;
        gpu->vdpy_handle = vdpy_init(NULL);
[Sun, Peng] I think this patch shouldn't be 3/8 patch. Because in 2/8
patch, vdpy_init() should return the supported number of vscreens.
The patch 2/8 still returns the fixed number of vscreen.
Currently it is still 1.
Before the virtio-gpu BE doesn't handle the scanout_info correctly, it is still assumed that only one scanout is supported for guest.
Only after the virtio-gpu BE can handle the scanout_info correctly, it will return the supported num of vscreens.

        gpu->base.mtx = &gpu->mtx;
        gpu->base.device_caps = VIRTIO_GPU_S_HOSTCAPS;
+       if (gpu->scanout_num < 0) {
+               pr_err("%s: return incorrect scanout num %d\n", gpu-
scanout_num);
[Sun, Peng] pr_err("%s: Invalid scanout num %d, never should be
here!\n",
gpu->scanout_num);
+               return -1;
+       }
+       gpu->gpu_scanouts = calloc(gpu->scanout_num, sizeof(struct
virtio_gpu_scanout));
+       if (gpu->gpu_scanouts == NULL) {
+               pr_err("%s: out of memory for gpu_scanouts\n",
__func__);
+               free(gpu);
+               return -1;
+       }
+
        if (vm_allow_dmabuf(gpu->base.dev->vmctx)) {
                FILE *fp;
                char buf[16];
@@ -1643,6 +1686,7 @@ virtio_gpu_deinit(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
 {
        struct virtio_gpu *gpu;
        struct virtio_gpu_resource_2d *r2d;
+       int i;
        gpu = (struct virtio_gpu *)dev->arg;
        gpu->vga.enable = false;
@@ -1661,6 +1705,25 @@ virtio_gpu_deinit(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
                gpu->vga.gc = NULL;
        }
+       for (i=0; i < gpu->scanout_num; i++) {
+               struct virtio_gpu_scanout *gpu_scanout;
+
+               gpu_scanout = gpu->gpu_scanouts + i;
+               if (gpu_scanout && gpu_scanout->active) {
+                       if (gpu_scanout->cur_img) {
+                               pixman_image_unref(gpu_scanout-
cur_img);
+                               gpu_scanout->cur_img = NULL;
+                       }
+                       if (gpu_scanout->dma_buf) {
+                               virtio_gpu_dmabuf_unref(gpu_scanout-
dma_buf);
+                               gpu_scanout->dma_buf = NULL;
+                       }
+                       gpu_scanout->active = false;
+               }
+       }
+       free(gpu->gpu_scanouts);
+       gpu->gpu_scanouts = NULL;
+
        pthread_mutex_destroy(&gpu->vga_thread_mtx);
        while (LIST_FIRST(&gpu->r2d_list)) {
                r2d = LIST_FIRST(&gpu->r2d_list);


Re: [PATCH 7/8] ACRN:DM:VGPU: Calibrate the offset in dmabuf/pixman_image to display the scanout_window

Sun, Peng
 

On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
Sometimes the virtio_gpu in guest_vm doesn't pass the zero coord_x/y
for the
displayed framebuffer. In such case the offset should be calibrated
for pixman_image/dmabuf
so that it can display the image from the correct image.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
 devicemodel/hw/pci/virtio/virtio_gpu.c | 2 ++
 devicemodel/hw/vdisplay_sdl.c          | 2 +-
 devicemodel/include/vdisplay.h         | 1 +
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 81ea82889..42d07e053 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -881,6 +881,7 @@ virtio_gpu_cmd_set_scanout(struct
virtio_gpu_command *cmd)
                surf.stride = pixman_image_get_stride(r2d->image);
                surf.surf_format = r2d->format;
                surf.surf_type = SURFACE_PIXMAN;
+               surf.pixel += 4 * (surf.x + surf.y * surf.stride);
[Sun, Peng] I think we should use bpp instead of hard code to 4, in
case the surf_format is not ARGB.
                vdpy_surface_set(gpu->vdpy_handle, req.scanout_id,
&surf);
                pixman_image_unref(r2d->image);
                resp.type = VIRTIO_GPU_RESP_OK_NODATA;
@@ -1298,6 +1299,7 @@ virtio_gpu_cmd_set_scanout_blob(struct
virtio_gpu_command *cmd)
        surf.stride = req.strides[0];
        surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
        surf.surf_type = SURFACE_DMABUF;
+       surf.dma_info.dmabuf_offset = req.offsets[0] + 4 * (surf.x +
surf.y * surf.stride);
[Sun, Peng] I think we should use bpp instead of hard code to 4, in
case the surf_format is not ARGB.
        switch (req.format) {
        case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM:
                drm_fourcc = DRM_FORMAT_XRGB8888;
diff --git a/devicemodel/hw/vdisplay_sdl.c
b/devicemodel/hw/vdisplay_sdl.c
index 65fd78d93..12140d6be 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -700,7 +700,7 @@ vdpy_surface_set(int handle, int scanout_id,
struct surface *surf)
                attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
                attrs[i++] = surf->stride;
                attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
-               attrs[i++] = 0;
+               attrs[i++] = surf->dma_info.dmabuf_offset;
                attrs[i++] = EGL_NONE;
 
                egl_img = gl_ops->eglCreateImageKHR(vdpy.eglDisplay,
diff --git a/devicemodel/include/vdisplay.h
b/devicemodel/include/vdisplay.h
index c1214a461..e24a4c625 100644
--- a/devicemodel/include/vdisplay.h
+++ b/devicemodel/include/vdisplay.h
@@ -67,6 +67,7 @@ struct surface {
        struct  {
                int dmabuf_fd;
                uint32_t surf_fourcc;
+               uint32_t dmabuf_offset;
        } dma_info;
 };
 
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


Re: [PATCH 6/8] ACRN:DM:VGPU: virtio-gpu-flush cmds check whether one scanout_win needs to be displayed

Sun, Peng
 

On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
The virtio-gpu display will be handled by the below cmd sequence:
1. Virtio_GPU_CMD_CREATE_RESOURCE
2. VIRTIO_GPU_CMD_SET_SCANOUT/SET_SCANOUT_BLOB
3. VIRTIO_GPU_CMD_FLUSH

The virtio_gpu_cmd_flush doesn't pass the scanout info.Instead it
only passes the
flushed_region and the resouce_id. So it needs to check whether the
scanout_region
is covered by the flushed_region and then decide whether the
scanout_win needs
to be displayed.

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

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index f33809eee..81ea82889 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -975,6 +975,46 @@ virtio_gpu_cmd_transfer_to_host_2d(struct
virtio_gpu_command *cmd)
        memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
 }
 
+static bool
+virtio_gpu_scanout_needs_flush(struct virtio_gpu *gpu,
+                             int scanout_id,
+                             int resource_id,
+                             struct virtio_gpu_rect *flush_rect)
+{
+       struct virtio_gpu_scanout *gpu_scanout;
+       pixman_region16_t flush_region, final_region, scanout_region;
+
+       /* the scanout_id is already checked. So it is ignored in
this function */
+       gpu_scanout = gpu->gpu_scanouts + scanout_id;
+
+       /* if the different resource_id is used, flush can be skipped
*/
+       if (resource_id != gpu_scanout->resource_id)
+               return false;
+
+       pixman_region_init(&final_region);
+       pixman_region_init_rect(&scanout_region,
+                               gpu_scanout->scanout_rect.x,
+                               gpu_scanout->scanout_rect.y,
+                               gpu_scanout->scanout_rect.width,
+                               gpu_scanout->scanout_rect.height);
+       pixman_region_init_rect(&flush_region,
+                               flush_rect->x, flush_rect->y,
+                               flush_rect->width, flush_rect-
height);
+
+       /* Check intersect region to determine whether scanout_region
+        * needs to be flushed.
+        */
+       pixman_region_intersect(&final_region, &scanout_region,
&flush_region);
+
+       /* if intersection_region is empty, it means that the
scanout_region is not
+        * covered by the flushed_region. And it is unnecessary to
update
+        */
+       if (pixman_region_not_empty(&final_region))
+               return true;
+       else
+               return false;
+}
+
 static void
 virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
 {
@@ -983,6 +1023,8 @@ virtio_gpu_cmd_resource_flush(struct
virtio_gpu_command *cmd)
        struct virtio_gpu_resource_2d *r2d;
        struct surface surf;
        struct virtio_gpu *gpu;
+       int i;
+       struct virtio_gpu_scanout *gpu_scanout;
 
        gpu = cmd->gpu;
        memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
@@ -999,24 +1041,36 @@ virtio_gpu_cmd_resource_flush(struct
virtio_gpu_command *cmd)
        }
        if (r2d->blob) {
                virtio_gpu_dmabuf_ref(r2d->dma_info);
-               surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
-               surf.surf_type = SURFACE_DMABUF;
-               vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
+               for (i = 0; i < gpu->scanout_num; i++) {
+                       if (!virtio_gpu_scanout_needs_flush(gpu, i,
req.resource_id, &req.r))
+                               continue;
+
+                       surf.dma_info.dmabuf_fd = r2d->dma_info-
dmabuf_fd;
+                       surf.surf_type = SURFACE_DMABUF;
+                       vdpy_surface_update(gpu->vdpy_handle, i,
&surf);
+               }
+               virtio_gpu_dmabuf_unref(r2d->dma_info);
                resp.type = VIRTIO_GPU_RESP_OK_NODATA;
                memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
-               virtio_gpu_dmabuf_unref(r2d->dma_info);
                return;
        }
        pixman_image_ref(r2d->image);
-       surf.pixel = pixman_image_get_data(r2d->image);
-       surf.x = req.r.x;
-       surf.y = req.r.y;
-       surf.width = r2d->width;
-       surf.height = r2d->height;
-       surf.stride = pixman_image_get_stride(r2d->image);
-       surf.surf_format = r2d->format;
-       surf.surf_type = SURFACE_PIXMAN;
-       vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
+       for (i = 0; i < gpu->scanout_num; i++) {
+               if (!virtio_gpu_scanout_needs_flush(gpu, i,
req.resource_id, &req.r))
+                       continue;
+
+               gpu_scanout = gpu->gpu_scanouts + i;
+               surf.pixel = pixman_image_get_data(r2d->image);
+               surf.x = gpu_scanout->scanout_rect.x;
+               surf.y = gpu_scanout->scanout_rect.y;
+               surf.width = gpu_scanout->scanout_rect.width;
+               surf.height = gpu_scanout->scanout_rect.height;
+               surf.stride = pixman_image_get_stride(r2d->image);
+               surf.surf_format = r2d->format;
+               surf.surf_type = SURFACE_PIXMAN;
+               surf.pixel += 4 * (surf.x + surf.y * surf.stride);
[Sun Peng] I thnk we should use bpp, not hard code to 4 in case the
surface format is not ARGB.
+               vdpy_surface_update(gpu->vdpy_handle, i, &surf);
+       }
        pixman_image_unref(r2d->image);
 
        cmd->iolen = sizeof(resp);
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


Re: [PATCH 2/8] ACRN:DM:VDisplay: vdpy_init connection returns the supported number of window

Zhao, Yakui
 

On 2022/8/8 14:37, Sun, Peng wrote:
On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
Vdisplay module will create the gui_window based on the virtio-gpu
parameter. When it tries
[Sun, Peng] Vdisplay module will create the gui_window(vScreen) based
on the virtio-gpu parameter. When virtio-gpu device tries
to establish the connection with vdisplay module, it will return the
supported number of window.
[Sun, Peng] return the number of vscreen.
Then the virtio-gpu device can initialize the correct info for the
guest_vm.
Thanks for the review.
It will be updated in next version.

BTW: The number is fixed to 1.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
 devicemodel/hw/pci/virtio/virtio_gpu.c | 2 +-
 devicemodel/hw/vdisplay_sdl.c          | 4 +++-
 devicemodel/include/vdisplay.h         | 2 +-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 2f8c4362e..cf3d20823 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -1485,7 +1485,7 @@ virtio_gpu_init(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
                        gpu->vq,
                        BACKEND_VBSU);
-       gpu->vdpy_handle = vdpy_init();
+       gpu->vdpy_handle = vdpy_init(NULL);
        gpu->base.mtx = &gpu->mtx;
        gpu->base.device_caps = VIRTIO_GPU_S_HOSTCAPS;
diff --git a/devicemodel/hw/vdisplay_sdl.c
b/devicemodel/hw/vdisplay_sdl.c
index 567a2de6f..65fd78d93 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -1069,7 +1069,7 @@ bool vdpy_submit_bh(int handle, struct
vdpy_display_bh *bh_task)
 }
 int
-vdpy_init()
+vdpy_init(int *supported_wins)
[Sun, Peng] +vdpy_init(int *num_vsceens)
 {
        int err, count;
@@ -1100,6 +1100,8 @@ vdpy_init()
        }
        vdpy.s.n_connect++;
+       if (supported_wins)
+               *supported_wins = 1;
        return vdpy.s.n_connect;
 }
diff --git a/devicemodel/include/vdisplay.h
b/devicemodel/include/vdisplay.h
index fc0e91b46..c1214a461 100644
--- a/devicemodel/include/vdisplay.h
+++ b/devicemodel/include/vdisplay.h
@@ -85,7 +85,7 @@ struct cursor {
 int vdpy_parse_cmd_option(const char *opts);
 int gfx_ui_init();
-int vdpy_init();
+int vdpy_init(int *supported_wins);
 void vdpy_get_display_info(int handle, int scanout_id, struct
display_info *info);
 void vdpy_surface_set(int handle, int scanout_id, struct surface
*surf);
 void vdpy_surface_update(int handle, int scanout_id, struct surface
*surf);


Re: [PATCH 5/8] ACRN:DM:VGPU: Handle the scanout_id for cursor virtio-gpu-cmd

Sun, Peng
 

On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
The virtio-gpu in guest_vm also passes the scanout_id for cursor
operation.
And this scanout_id should be handled in course of handling cursor
cmds.
[Sun, Peng] commands.

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

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index aa955ba23..f33809eee 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -1389,7 +1389,7 @@ virtio_gpu_cmd_update_cursor(struct
virtio_gpu_command *cmd)
                cur.height = r2d->height;
                pixman_image_ref(r2d->image);
                cur.data = pixman_image_get_data(r2d->image);
-               vdpy_cursor_define(gpu->vdpy_handle, 0, &cur);
+               vdpy_cursor_define(gpu->vdpy_handle,
req.pos.scanout_id, &cur);
                pixman_image_unref(r2d->image);
        }
 }
@@ -1402,7 +1402,7 @@ virtio_gpu_cmd_move_cursor(struct
virtio_gpu_command *cmd)
 
        gpu = cmd->gpu;
        memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
-       vdpy_cursor_move(gpu->vdpy_handle, 0, req.pos.x, req.pos.y);
+       vdpy_cursor_move(gpu->vdpy_handle, req.pos.scanout_id,
req.pos.x, req.pos.y);
 }
 
 static void
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


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

Sun, Peng
 

On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
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
[Sun, Peng] The scanout_id is included in the below virtio-gpu
operation requests.
- 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);
[Sun, Peng] pr_err("%s: Invalid scanout_id %d\n"
+               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);
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


Re: [PATCH 3/8] ACRN:DM:VGPU: Add virtio_gpu_scanout structure to handle virtio-gpu-cmds correctly

Sun, Peng
 

On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
Now it only supports one scanout panel for virtio-gpu. So the
[Sun, Peng] Now it only supports one scanout for virtio-gpu.
scanout_id is ignored in
course of handling virtio-gpu-cmd. In order to handle the
[Sun, Peng] course of handling virtio-gpu commands.
virtio-gpu-cmds correctly, it
adds the virtio_gpu_scanout structure so that it can record the
scanout info.

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

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index cf3d20823..768e188d2 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -348,6 +348,16 @@ enum vga_thread_status {
        VGA_THREAD_EOL = 0,
        VGA_THREAD_RUNNING
 };
+
+struct virtio_gpu_scanout {
+       int scanout_id;
+       uint32_t resource_id;
+       struct virtio_gpu_rect scanout_rect;
+       pixman_image_t *cur_img;
[Sun, Peng] What is the mean of cur_img? Cursor or Current?
+       struct dma_buf_info *dma_buf;
+       bool active;
[Sun, Peng] I think is_active is better.
+};
+
 /*
  * Per-device struct
  */
@@ -366,6 +376,8 @@ struct virtio_gpu {
        int32_t vga_thread_status;
        uint8_t edid[VIRTIO_GPU_EDID_SIZE];
        bool is_blob_supported;
+       int scanout_num;
+       struct virtio_gpu_scanout *gpu_scanouts;
 };
 
 struct virtio_gpu_command {
@@ -782,12 +794,22 @@ virtio_gpu_cmd_set_scanout(struct
virtio_gpu_command *cmd)
        struct virtio_gpu_ctrl_hdr resp;
        struct surface surf;
        struct virtio_gpu *gpu;
+       struct virtio_gpu_scanout *gpu_scanout;
 
        gpu = cmd->gpu;
        memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
        memset(&resp, 0, sizeof(resp));
        virtio_gpu_update_resp_fence(&cmd->hdr, &resp);
 
+       if (req.scanout_id >= gpu->scanout_num) {
+               pr_err("%s: Incorrect scanout_id %d\n",
req.scanout_id);
[Sun, Peng] pr_err("%s: Invalid scanout_id
+               resp.type = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+               memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
+               return;
+       }
+       gpu_scanout = gpu->gpu_scanouts + req.scanout_id;
+       gpu_scanout->scanout_id = req.scanout_id;
+
        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);
@@ -1130,6 +1152,7 @@ virtio_gpu_cmd_set_scanout_blob(struct
virtio_gpu_command *cmd)
        struct surface surf;
        uint32_t drm_fourcc;
        struct virtio_gpu *gpu;
+       struct virtio_gpu_scanout *gpu_scanout;
 
        gpu = cmd->gpu;
        memset(&surf, 0, sizeof(surf));
@@ -1140,6 +1163,14 @@ virtio_gpu_cmd_set_scanout_blob(struct
virtio_gpu_command *cmd)
        if (cmd->gpu->vga.enable) {
                cmd->gpu->vga.enable = false;
        }
+       if (req.scanout_id >= gpu->scanout_num) {
+               pr_err("%s: Incorrect scanout_id %d\n",
req.scanout_id);
[Sun, Peng] Also "Invalid scanout_id" here.
+               resp.type = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+               memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp,
sizeof(resp));
+               return;
+       }
+       gpu_scanout = gpu->gpu_scanouts + req.scanout_id;
+       gpu_scanout->scanout_id = req.scanout_id;
        if (req.resource_id == 0) {
                resp.type = VIRTIO_GPU_RESP_OK_NODATA;
                memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp,
sizeof(resp));
@@ -1485,10 +1516,22 @@ virtio_gpu_init(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
                        gpu->vq,
                        BACKEND_VBSU);
 
+       gpu->scanout_num = 1;
        gpu->vdpy_handle = vdpy_init(NULL);
[Sun, Peng] I think this patch shouldn't be 3/8 patch. Because in 2/8
patch, vdpy_init() should return the supported number of vscreens.
        gpu->base.mtx = &gpu->mtx;
        gpu->base.device_caps = VIRTIO_GPU_S_HOSTCAPS;
 
+       if (gpu->scanout_num < 0) {
+               pr_err("%s: return incorrect scanout num %d\n", gpu-
scanout_num);
[Sun, Peng] pr_err("%s: Invalid scanout num %d, never should be
here!\n",
gpu->scanout_num);
+               return -1;
+       }
+       gpu->gpu_scanouts = calloc(gpu->scanout_num, sizeof(struct
virtio_gpu_scanout));
+       if (gpu->gpu_scanouts == NULL) {
+               pr_err("%s: out of memory for gpu_scanouts\n",
__func__);
+               free(gpu);
+               return -1;
+       }
+
        if (vm_allow_dmabuf(gpu->base.dev->vmctx)) {
                FILE *fp;
                char buf[16];
@@ -1643,6 +1686,7 @@ virtio_gpu_deinit(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
 {
        struct virtio_gpu *gpu;
        struct virtio_gpu_resource_2d *r2d;
+       int i;
 
        gpu = (struct virtio_gpu *)dev->arg;
        gpu->vga.enable = false;
@@ -1661,6 +1705,25 @@ virtio_gpu_deinit(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
                gpu->vga.gc = NULL;
        }
 
+       for (i=0; i < gpu->scanout_num; i++) {
+               struct virtio_gpu_scanout *gpu_scanout;
+
+               gpu_scanout = gpu->gpu_scanouts + i;
+               if (gpu_scanout && gpu_scanout->active) {
+                       if (gpu_scanout->cur_img) {
+                               pixman_image_unref(gpu_scanout-
cur_img);
+                               gpu_scanout->cur_img = NULL;
+                       }
+                       if (gpu_scanout->dma_buf) {
+                               virtio_gpu_dmabuf_unref(gpu_scanout-
dma_buf);
+                               gpu_scanout->dma_buf = NULL;
+                       }
+                       gpu_scanout->active = false;
+               }
+       }
+       free(gpu->gpu_scanouts);
+       gpu->gpu_scanouts = NULL;
+
        pthread_mutex_destroy(&gpu->vga_thread_mtx);
        while (LIST_FIRST(&gpu->r2d_list)) {
                r2d = LIST_FIRST(&gpu->r2d_list);
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


Re: [PATCH 2/8] ACRN:DM:VDisplay: vdpy_init connection returns the supported number of window

Sun, Peng
 

On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
Vdisplay module will create the gui_window based on the virtio-gpu
parameter. When it tries
[Sun, Peng] Vdisplay module will create the gui_window(vScreen) based
on the virtio-gpu parameter. When virtio-gpu device tries
to establish the connection with vdisplay module, it will return the
supported number of window.
[Sun, Peng] return the number of vscreen.
Then the virtio-gpu device can initialize the correct info for the
guest_vm.

BTW: The number is fixed to 1.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
 devicemodel/hw/pci/virtio/virtio_gpu.c | 2 +-
 devicemodel/hw/vdisplay_sdl.c          | 4 +++-
 devicemodel/include/vdisplay.h         | 2 +-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 2f8c4362e..cf3d20823 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -1485,7 +1485,7 @@ virtio_gpu_init(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
                        gpu->vq,
                        BACKEND_VBSU);
 
-       gpu->vdpy_handle = vdpy_init();
+       gpu->vdpy_handle = vdpy_init(NULL);
        gpu->base.mtx = &gpu->mtx;
        gpu->base.device_caps = VIRTIO_GPU_S_HOSTCAPS;
 
diff --git a/devicemodel/hw/vdisplay_sdl.c
b/devicemodel/hw/vdisplay_sdl.c
index 567a2de6f..65fd78d93 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -1069,7 +1069,7 @@ bool vdpy_submit_bh(int handle, struct
vdpy_display_bh *bh_task)
 }
 
 int
-vdpy_init()
+vdpy_init(int *supported_wins)
[Sun, Peng] +vdpy_init(int *num_vsceens)
 {
        int err, count;
 
@@ -1100,6 +1100,8 @@ vdpy_init()
        }
 
        vdpy.s.n_connect++;
+       if (supported_wins)
+               *supported_wins = 1;
        return vdpy.s.n_connect;
 }
 
diff --git a/devicemodel/include/vdisplay.h
b/devicemodel/include/vdisplay.h
index fc0e91b46..c1214a461 100644
--- a/devicemodel/include/vdisplay.h
+++ b/devicemodel/include/vdisplay.h
@@ -85,7 +85,7 @@ struct cursor {
 
 int vdpy_parse_cmd_option(const char *opts);
 int gfx_ui_init();
-int vdpy_init();
+int vdpy_init(int *supported_wins);
 void vdpy_get_display_info(int handle, int scanout_id, struct
display_info *info);
 void vdpy_surface_set(int handle, int scanout_id, struct surface
*surf);
 void vdpy_surface_update(int handle, int scanout_id, struct surface
*surf);
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


Re: [PATCH 1/8] ACRN:DM:VDISPLAY: Refine display API to support multi scanout_window

Sun, Peng
 

LGTM.
Reviewed-by: Sun Peng <peng.p.sun@...>

On Mon, 2022-08-08 at 14:13 +0800, Zhao, Yakui wrote:
Currenly it can support only one display_win. When virtio-gpu wants
to display
the framebuffer from Guest_vm, it will render it into the default
win. In order
to support multi-window, the scanout_id is added for display API.
After display API is refined, the vdisplay and virtio-gpu can support
the multi-win
independently.

BTW: Now the scanout_id is not implemented in vdisplay module and the
virtio-gpu always
passes the zero. It will be implemeneted in the later patches.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
 devicemodel/hw/pci/virtio/virtio_gpu.c | 28 +++++++++++++-----------
--
 devicemodel/hw/vdisplay_sdl.c          | 12 +++++------
 devicemodel/include/vdisplay.h         | 12 +++++------
 3 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c
b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 4ba219bc1..2f8c4362e 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -556,7 +556,7 @@ virtio_gpu_cmd_get_edid(struct virtio_gpu_command
*cmd)
        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, resp.edid, resp.size);
+       vdpy_get_edid(gpu->vdpy_handle, 0, resp.edid, resp.size);
        memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
 }
 
@@ -570,7 +570,7 @@ virtio_gpu_cmd_get_display_info(struct
virtio_gpu_command *cmd)
        gpu = cmd->gpu;
        cmd->iolen = sizeof(resp);
        memset(&resp, 0, sizeof(resp));
-       vdpy_get_display_info(gpu->vdpy_handle, &info);
+       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;
@@ -790,7 +790,7 @@ 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, NULL);
+               vdpy_surface_set(gpu->vdpy_handle, 0, NULL);
                resp.type = VIRTIO_GPU_RESP_OK_NODATA;
                memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
                return;
@@ -814,7 +814,7 @@ virtio_gpu_cmd_set_scanout(struct
virtio_gpu_command *cmd)
                surf.stride = pixman_image_get_stride(r2d->image);
                surf.surf_format = r2d->format;
                surf.surf_type = SURFACE_PIXMAN;
-               vdpy_surface_set(gpu->vdpy_handle, &surf);
+               vdpy_surface_set(gpu->vdpy_handle, 0, &surf);
                pixman_image_unref(r2d->image);
                resp.type = VIRTIO_GPU_RESP_OK_NODATA;
        }
@@ -934,7 +934,7 @@ virtio_gpu_cmd_resource_flush(struct
virtio_gpu_command *cmd)
                virtio_gpu_dmabuf_ref(r2d->dma_info);
                surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
                surf.surf_type = SURFACE_DMABUF;
-               vdpy_surface_update(gpu->vdpy_handle, &surf);
+               vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
                resp.type = VIRTIO_GPU_RESP_OK_NODATA;
                memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
                virtio_gpu_dmabuf_unref(r2d->dma_info);
@@ -949,7 +949,7 @@ virtio_gpu_cmd_resource_flush(struct
virtio_gpu_command *cmd)
        surf.stride = pixman_image_get_stride(r2d->image);
        surf.surf_format = r2d->format;
        surf.surf_type = SURFACE_PIXMAN;
-       vdpy_surface_update(gpu->vdpy_handle, &surf);
+       vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
        pixman_image_unref(r2d->image);
 
        cmd->iolen = sizeof(resp);
@@ -1143,7 +1143,7 @@ virtio_gpu_cmd_set_scanout_blob(struct
virtio_gpu_command *cmd)
        if (req.resource_id == 0) {
                resp.type = VIRTIO_GPU_RESP_OK_NODATA;
                memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp,
sizeof(resp));
-               vdpy_surface_set(gpu->vdpy_handle, NULL);
+               vdpy_surface_set(gpu->vdpy_handle, 0, NULL);
                return;
        }
        r2d = virtio_gpu_find_resource_2d(cmd->gpu, req.resource_id);
@@ -1187,7 +1187,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, &surf);
+       vdpy_surface_set(gpu->vdpy_handle, 0, &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);
@@ -1312,7 +1312,7 @@ virtio_gpu_cmd_update_cursor(struct
virtio_gpu_command *cmd)
                cur.height = r2d->height;
                pixman_image_ref(r2d->image);
                cur.data = pixman_image_get_data(r2d->image);
-               vdpy_cursor_define(gpu->vdpy_handle, &cur);
+               vdpy_cursor_define(gpu->vdpy_handle, 0, &cur);
                pixman_image_unref(r2d->image);
        }
 }
@@ -1325,7 +1325,7 @@ virtio_gpu_cmd_move_cursor(struct
virtio_gpu_command *cmd)
 
        gpu = cmd->gpu;
        memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
-       vdpy_cursor_move(gpu->vdpy_handle, req.pos.x, req.pos.y);
+       vdpy_cursor_move(gpu->vdpy_handle, 0, req.pos.x, req.pos.y);
 }
 
 static void
@@ -1397,10 +1397,10 @@ virtio_gpu_vga_bh(void *param)
                gpu->vga.surf.pixel = gpu->vga.gc->gc_image->data;
                gpu->vga.surf.surf_format = PIXMAN_a8r8g8b8;
                gpu->vga.surf.surf_type = SURFACE_PIXMAN;
-               vdpy_surface_set(gpu->vdpy_handle, &gpu->vga.surf);
+               vdpy_surface_set(gpu->vdpy_handle, 0, &gpu-
vga.surf);
        }
 
-       vdpy_surface_update(gpu->vdpy_handle, &gpu->vga.surf);
+       vdpy_surface_update(gpu->vdpy_handle, 0, &gpu->vga.surf);
 }
 
 static void *
@@ -1553,7 +1553,7 @@ virtio_gpu_init(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
        pci_set_cfgdata16(dev, PCIR_SUBVEND_0, VIRTIO_VENDOR);
 
        LIST_INIT(&gpu->r2d_list);
-       vdpy_get_display_info(gpu->vdpy_handle, &info);
+       vdpy_get_display_info(gpu->vdpy_handle, 0, &info);
 
        /*** PCI Config BARs setup ***/
        /** BAR0: VGA framebuffer **/
@@ -1566,7 +1566,7 @@ virtio_gpu_init(struct vmctx *ctx, struct
pci_vdev *dev, char *opts)
 
        /** BAR2: VGA & Virtio Modern regs **/
        /* EDID data blob [0x000~0x3ff] */
-       vdpy_get_edid(gpu->vdpy_handle, gpu->edid,
VIRTIO_GPU_EDID_SIZE);
+       vdpy_get_edid(gpu->vdpy_handle, 0, gpu->edid,
VIRTIO_GPU_EDID_SIZE);
        /* VGA ioports regs [0x400~0x41f] */
        gpu->vga.gc = gc_init(info.width, info.height, ctx->fb_base);
        gpu->vga.dev = vga_init(gpu->vga.gc, 0);
diff --git a/devicemodel/hw/vdisplay_sdl.c
b/devicemodel/hw/vdisplay_sdl.c
index 21ceb2325..567a2de6f 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -510,7 +510,7 @@ vdpy_edid_generate(uint8_t *edid, size_t size,
struct edid_info *info)
 }
 
 void
-vdpy_get_edid(int handle, uint8_t *edid, size_t size)
+vdpy_get_edid(int handle, int scanout_id, uint8_t *edid, size_t
size)
 {
        struct edid_info edid_info;
 
@@ -534,7 +534,7 @@ vdpy_get_edid(int handle, uint8_t *edid, size_t
size)
 }
 
 void
-vdpy_get_display_info(int handle, struct display_info *info)
+vdpy_get_display_info(int handle, int scanout_id, struct
display_info *info)
 {
        if (handle == vdpy.s.n_connect) {
                info->xoff = vdpy.info.xoff;
@@ -582,7 +582,7 @@ sdl_gl_display_init(void)
 }
 
 void
-vdpy_surface_set(int handle, struct surface *surf)
+vdpy_surface_set(int handle, int scanout_id, struct surface *surf)
 {
        pixman_image_t *src_img;
        int format;
@@ -749,7 +749,7 @@ vdpy_cursor_position_transformation(struct
display *vdpy, SDL_Rect *rect)
 }
 
 void
-vdpy_surface_update(int handle, struct surface *surf)
+vdpy_surface_update(int handle, int scanout_id, struct surface
*surf)
 {
        SDL_Rect cursor_rect;
 
@@ -792,7 +792,7 @@ vdpy_surface_update(int handle, struct surface
*surf)
 }
 
 void
-vdpy_cursor_define(int handle, struct cursor *cur)
+vdpy_cursor_define(int handle, int scanout_id, struct cursor *cur)
 {
        if (handle != vdpy.s.n_connect) {
                return;
@@ -826,7 +826,7 @@ vdpy_cursor_define(int handle, struct cursor
*cur)
 }
 
 void
-vdpy_cursor_move(int handle, uint32_t x, uint32_t y)
+vdpy_cursor_move(int handle, int scanout_id, uint32_t x, uint32_t y)
 {
        if (handle != vdpy.s.n_connect) {
                return;
diff --git a/devicemodel/include/vdisplay.h
b/devicemodel/include/vdisplay.h
index 99506469b..fc0e91b46 100644
--- a/devicemodel/include/vdisplay.h
+++ b/devicemodel/include/vdisplay.h
@@ -86,13 +86,13 @@ struct cursor {
 int vdpy_parse_cmd_option(const char *opts);
 int gfx_ui_init();
 int vdpy_init();
-void vdpy_get_display_info(int handle, struct display_info *info);
-void vdpy_surface_set(int handle, struct surface *surf);
-void vdpy_surface_update(int handle, struct surface *surf);
+void vdpy_get_display_info(int handle, int scanout_id, struct
display_info *info);
+void vdpy_surface_set(int handle, int scanout_id, struct surface
*surf);
+void vdpy_surface_update(int handle, int scanout_id, struct surface
*surf);
 bool vdpy_submit_bh(int handle, struct vdpy_display_bh *bh);
-void vdpy_get_edid(int handle, uint8_t *edid, size_t size);
-void vdpy_cursor_define(int handle, struct cursor *cur);
-void vdpy_cursor_move(int handle, uint32_t x, uint32_t y);
+void vdpy_get_edid(int handle, int scanout_id, uint8_t *edid, size_t
size);
+void vdpy_cursor_define(int handle, int scanout_id, struct cursor
*cur);
+void vdpy_cursor_move(int handle, int scanout_id, uint32_t x,
uint32_t y);
 int vdpy_deinit(int handle);
 void gfx_ui_deinit();
--
Sun Peng <peng.p.sun@...>
SSE/ACRN Upstream


[PATCH v2] misc: add assert to check the vBDF conflict

chenli.wei
 

From: Chenli Wei <chenli.wei@...>

The current ACRN-Configurator just check the conflict of user setting.
have not check the conflict with native PCI device's bdf.

This patch add an assert to check the above conflict.

v1-->v2:
1 check the Service VM only

Tracked-On: #6690
Signed-off-by: Chenli Wei <chenli.wei@...>
---
misc/config_tools/schema/checks/vbdf_assignment.xsd | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/misc/config_tools/schema/checks/vbdf_assignment.xsd b/misc/config_tools/schema/checks/vbdf_assignment.xsd
index fde14c2b7..5fd777e68 100644
--- a/misc/config_tools/schema/checks/vbdf_assignment.xsd
+++ b/misc/config_tools/schema/checks/vbdf_assignment.xsd
@@ -14,4 +14,14 @@
</xs:annotation>
</xs:assert>

+
+ <xs:assert test="every $root in /acrn-config satisfies
+ every $vm in $root/vm[./load_order/text()='SERVICE_VM'] satisfies
+ every $vbdf in $root/hv//vuart_connection[type='pci']/endpoint[vm_name=$vm/name]/vbdf/text() | $root/hv//IVSHMEM_VM[VM_NAME=$vm/name]/VBDF/text() satisfies
+ string-length(substring-after(/acrn-config//PCI_DEVICE/text(), $vbdf)) = 0">
+ <xs:annotation acrn:severity="error" acrn:report-on="$root/hv//vuart_connection[type='pci']/endpoint[vm_name=$vm/name and vbdf=$vbdf] | $root/hv//IVSHMEM_VM[VM_NAME=$vm/name and VBDF=$vbdf]">
+ <xs:documentation>VM "{$vm/name}" virtual UART controllers or IVSHMEM interfaces using BDF {$vbdf} conflict with native PCI device. Adjust the BDF of those devices to be unique.</xs:documentation>
+ </xs:annotation>
+ </xs:assert>
+
</xs:schema>
--
2.25.1


[PATCH 8/8] ACRN:DM:VGPU: Return the parsed scanout_num to virtio_gpu in Guest_VM

Zhao, Yakui
 

Return the parsed scanout_num to guest_vm so that the guest_vm can configure multi-display.

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

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 42d07e053..3601a10b3 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -1619,11 +1619,11 @@ virtio_gpu_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
BACKEND_VBSU);

gpu->scanout_num = 1;
- gpu->vdpy_handle = vdpy_init(NULL);
+ gpu->vdpy_handle = vdpy_init(&gpu->scanout_num);
gpu->base.mtx = &gpu->mtx;
gpu->base.device_caps = VIRTIO_GPU_S_HOSTCAPS;

- if (gpu->scanout_num < 0) {
+ if ((gpu->scanout_num < 0) || (gpu->scanout_num > 2)) {
pr_err("%s: return incorrect scanout num %d\n", gpu->scanout_num);
return -1;
}
@@ -1685,7 +1685,7 @@ virtio_gpu_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
/* prepare the config space */
gpu->cfg.events_read = 0;
gpu->cfg.events_clear = 0;
- gpu->cfg.num_scanouts = 1;
+ gpu->cfg.num_scanouts = gpu->scanout_num;
gpu->cfg.num_capsets = 0;

/* config the device id and vendor id according to spec */
--
2.25.1


[PATCH 7/8] ACRN:DM:VGPU: Calibrate the offset in dmabuf/pixman_image to display the scanout_window

Zhao, Yakui
 

Sometimes the virtio_gpu in guest_vm doesn't pass the zero coord_x/y for the
displayed framebuffer. In such case the offset should be calibrated for pixman_image/dmabuf
so that it can display the image from the correct image.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
devicemodel/hw/pci/virtio/virtio_gpu.c | 2 ++
devicemodel/hw/vdisplay_sdl.c | 2 +-
devicemodel/include/vdisplay.h | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 81ea82889..42d07e053 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -881,6 +881,7 @@ virtio_gpu_cmd_set_scanout(struct virtio_gpu_command *cmd)
surf.stride = pixman_image_get_stride(r2d->image);
surf.surf_format = r2d->format;
surf.surf_type = SURFACE_PIXMAN;
+ surf.pixel += 4 * (surf.x + surf.y * surf.stride);
vdpy_surface_set(gpu->vdpy_handle, req.scanout_id, &surf);
pixman_image_unref(r2d->image);
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
@@ -1298,6 +1299,7 @@ virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_command *cmd)
surf.stride = req.strides[0];
surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
surf.surf_type = SURFACE_DMABUF;
+ surf.dma_info.dmabuf_offset = req.offsets[0] + 4 * (surf.x + surf.y * surf.stride);
switch (req.format) {
case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM:
drm_fourcc = DRM_FORMAT_XRGB8888;
diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index 65fd78d93..12140d6be 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -700,7 +700,7 @@ vdpy_surface_set(int handle, int scanout_id, struct surface *surf)
attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
attrs[i++] = surf->stride;
attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
- attrs[i++] = 0;
+ attrs[i++] = surf->dma_info.dmabuf_offset;
attrs[i++] = EGL_NONE;

egl_img = gl_ops->eglCreateImageKHR(vdpy.eglDisplay,
diff --git a/devicemodel/include/vdisplay.h b/devicemodel/include/vdisplay.h
index c1214a461..e24a4c625 100644
--- a/devicemodel/include/vdisplay.h
+++ b/devicemodel/include/vdisplay.h
@@ -67,6 +67,7 @@ struct surface {
struct {
int dmabuf_fd;
uint32_t surf_fourcc;
+ uint32_t dmabuf_offset;
} dma_info;
};

--
2.25.1


[PATCH 6/8] ACRN:DM:VGPU: virtio-gpu-flush cmds check whether one scanout_win needs to be displayed

Zhao, Yakui
 

The virtio-gpu display will be handled by the below cmd sequence:
1. Virtio_GPU_CMD_CREATE_RESOURCE
2. VIRTIO_GPU_CMD_SET_SCANOUT/SET_SCANOUT_BLOB
3. VIRTIO_GPU_CMD_FLUSH

The virtio_gpu_cmd_flush doesn't pass the scanout info.Instead it only passes the
flushed_region and the resouce_id. So it needs to check whether the scanout_region
is covered by the flushed_region and then decide whether the scanout_win needs
to be displayed.

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

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c b/devicemodel/hw/pci/virtio/virtio_gpu.c
index f33809eee..81ea82889 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -975,6 +975,46 @@ virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_command *cmd)
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
}

+static bool
+virtio_gpu_scanout_needs_flush(struct virtio_gpu *gpu,
+ int scanout_id,
+ int resource_id,
+ struct virtio_gpu_rect *flush_rect)
+{
+ struct virtio_gpu_scanout *gpu_scanout;
+ pixman_region16_t flush_region, final_region, scanout_region;
+
+ /* the scanout_id is already checked. So it is ignored in this function */
+ gpu_scanout = gpu->gpu_scanouts + scanout_id;
+
+ /* if the different resource_id is used, flush can be skipped */
+ if (resource_id != gpu_scanout->resource_id)
+ return false;
+
+ pixman_region_init(&final_region);
+ pixman_region_init_rect(&scanout_region,
+ gpu_scanout->scanout_rect.x,
+ gpu_scanout->scanout_rect.y,
+ gpu_scanout->scanout_rect.width,
+ gpu_scanout->scanout_rect.height);
+ pixman_region_init_rect(&flush_region,
+ flush_rect->x, flush_rect->y,
+ flush_rect->width, flush_rect->height);
+
+ /* Check intersect region to determine whether scanout_region
+ * needs to be flushed.
+ */
+ pixman_region_intersect(&final_region, &scanout_region, &flush_region);
+
+ /* if intersection_region is empty, it means that the scanout_region is not
+ * covered by the flushed_region. And it is unnecessary to update
+ */
+ if (pixman_region_not_empty(&final_region))
+ return true;
+ else
+ return false;
+}
+
static void
virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
{
@@ -983,6 +1023,8 @@ virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
struct virtio_gpu_resource_2d *r2d;
struct surface surf;
struct virtio_gpu *gpu;
+ int i;
+ struct virtio_gpu_scanout *gpu_scanout;

gpu = cmd->gpu;
memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
@@ -999,24 +1041,36 @@ virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
}
if (r2d->blob) {
virtio_gpu_dmabuf_ref(r2d->dma_info);
- surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
- surf.surf_type = SURFACE_DMABUF;
- vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
+ for (i = 0; i < gpu->scanout_num; i++) {
+ if (!virtio_gpu_scanout_needs_flush(gpu, i, req.resource_id, &req.r))
+ continue;
+
+ surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
+ surf.surf_type = SURFACE_DMABUF;
+ vdpy_surface_update(gpu->vdpy_handle, i, &surf);
+ }
+ virtio_gpu_dmabuf_unref(r2d->dma_info);
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
- virtio_gpu_dmabuf_unref(r2d->dma_info);
return;
}
pixman_image_ref(r2d->image);
- surf.pixel = pixman_image_get_data(r2d->image);
- surf.x = req.r.x;
- surf.y = req.r.y;
- surf.width = r2d->width;
- surf.height = r2d->height;
- surf.stride = pixman_image_get_stride(r2d->image);
- surf.surf_format = r2d->format;
- surf.surf_type = SURFACE_PIXMAN;
- vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
+ for (i = 0; i < gpu->scanout_num; i++) {
+ if (!virtio_gpu_scanout_needs_flush(gpu, i, req.resource_id, &req.r))
+ continue;
+
+ gpu_scanout = gpu->gpu_scanouts + i;
+ surf.pixel = pixman_image_get_data(r2d->image);
+ surf.x = gpu_scanout->scanout_rect.x;
+ surf.y = gpu_scanout->scanout_rect.y;
+ surf.width = gpu_scanout->scanout_rect.width;
+ surf.height = gpu_scanout->scanout_rect.height;
+ surf.stride = pixman_image_get_stride(r2d->image);
+ surf.surf_format = r2d->format;
+ surf.surf_type = SURFACE_PIXMAN;
+ surf.pixel += 4 * (surf.x + surf.y * surf.stride);
+ vdpy_surface_update(gpu->vdpy_handle, i, &surf);
+ }
pixman_image_unref(r2d->image);

cmd->iolen = sizeof(resp);
--
2.25.1


[PATCH 5/8] ACRN:DM:VGPU: Handle the scanout_id for cursor virtio-gpu-cmd

Zhao, Yakui
 

The virtio-gpu in guest_vm also passes the scanout_id for cursor operation.
And this scanout_id should be handled in course of handling cursor cmds.

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

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c b/devicemodel/hw/pci/virtio/virtio_gpu.c
index aa955ba23..f33809eee 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -1389,7 +1389,7 @@ virtio_gpu_cmd_update_cursor(struct virtio_gpu_command *cmd)
cur.height = r2d->height;
pixman_image_ref(r2d->image);
cur.data = pixman_image_get_data(r2d->image);
- vdpy_cursor_define(gpu->vdpy_handle, 0, &cur);
+ vdpy_cursor_define(gpu->vdpy_handle, req.pos.scanout_id, &cur);
pixman_image_unref(r2d->image);
}
}
@@ -1402,7 +1402,7 @@ virtio_gpu_cmd_move_cursor(struct virtio_gpu_command *cmd)

gpu = cmd->gpu;
memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
- vdpy_cursor_move(gpu->vdpy_handle, 0, req.pos.x, req.pos.y);
+ vdpy_cursor_move(gpu->vdpy_handle, req.pos.scanout_id, req.pos.x, req.pos.y);
}

static void
--
2.25.1


[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


[PATCH 3/8] ACRN:DM:VGPU: Add virtio_gpu_scanout structure to handle virtio-gpu-cmds correctly

Zhao, Yakui
 

Now it only supports one scanout panel for virtio-gpu. So the scanout_id is ignored in
course of handling virtio-gpu-cmd. In order to handle the virtio-gpu-cmds correctly, it
adds the virtio_gpu_scanout structure so that it can record the scanout info.

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

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c b/devicemodel/hw/pci/virtio/virtio_gpu.c
index cf3d20823..768e188d2 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -348,6 +348,16 @@ enum vga_thread_status {
VGA_THREAD_EOL = 0,
VGA_THREAD_RUNNING
};
+
+struct virtio_gpu_scanout {
+ int scanout_id;
+ uint32_t resource_id;
+ struct virtio_gpu_rect scanout_rect;
+ pixman_image_t *cur_img;
+ struct dma_buf_info *dma_buf;
+ bool active;
+};
+
/*
* Per-device struct
*/
@@ -366,6 +376,8 @@ struct virtio_gpu {
int32_t vga_thread_status;
uint8_t edid[VIRTIO_GPU_EDID_SIZE];
bool is_blob_supported;
+ int scanout_num;
+ struct virtio_gpu_scanout *gpu_scanouts;
};

struct virtio_gpu_command {
@@ -782,12 +794,22 @@ virtio_gpu_cmd_set_scanout(struct virtio_gpu_command *cmd)
struct virtio_gpu_ctrl_hdr resp;
struct surface surf;
struct virtio_gpu *gpu;
+ struct virtio_gpu_scanout *gpu_scanout;

gpu = cmd->gpu;
memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
memset(&resp, 0, sizeof(resp));
virtio_gpu_update_resp_fence(&cmd->hdr, &resp);

+ if (req.scanout_id >= gpu->scanout_num) {
+ pr_err("%s: Incorrect scanout_id %d\n", req.scanout_id);
+ resp.type = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+ memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
+ return;
+ }
+ gpu_scanout = gpu->gpu_scanouts + req.scanout_id;
+ gpu_scanout->scanout_id = req.scanout_id;
+
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);
@@ -1130,6 +1152,7 @@ virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_command *cmd)
struct surface surf;
uint32_t drm_fourcc;
struct virtio_gpu *gpu;
+ struct virtio_gpu_scanout *gpu_scanout;

gpu = cmd->gpu;
memset(&surf, 0, sizeof(surf));
@@ -1140,6 +1163,14 @@ virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_command *cmd)
if (cmd->gpu->vga.enable) {
cmd->gpu->vga.enable = false;
}
+ if (req.scanout_id >= gpu->scanout_num) {
+ pr_err("%s: Incorrect scanout_id %d\n", req.scanout_id);
+ resp.type = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+ memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
+ return;
+ }
+ gpu_scanout = gpu->gpu_scanouts + req.scanout_id;
+ gpu_scanout->scanout_id = req.scanout_id;
if (req.resource_id == 0) {
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
@@ -1485,10 +1516,22 @@ virtio_gpu_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
gpu->vq,
BACKEND_VBSU);

+ gpu->scanout_num = 1;
gpu->vdpy_handle = vdpy_init(NULL);
gpu->base.mtx = &gpu->mtx;
gpu->base.device_caps = VIRTIO_GPU_S_HOSTCAPS;

+ if (gpu->scanout_num < 0) {
+ pr_err("%s: return incorrect scanout num %d\n", gpu->scanout_num);
+ return -1;
+ }
+ gpu->gpu_scanouts = calloc(gpu->scanout_num, sizeof(struct virtio_gpu_scanout));
+ if (gpu->gpu_scanouts == NULL) {
+ pr_err("%s: out of memory for gpu_scanouts\n", __func__);
+ free(gpu);
+ return -1;
+ }
+
if (vm_allow_dmabuf(gpu->base.dev->vmctx)) {
FILE *fp;
char buf[16];
@@ -1643,6 +1686,7 @@ virtio_gpu_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
{
struct virtio_gpu *gpu;
struct virtio_gpu_resource_2d *r2d;
+ int i;

gpu = (struct virtio_gpu *)dev->arg;
gpu->vga.enable = false;
@@ -1661,6 +1705,25 @@ virtio_gpu_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
gpu->vga.gc = NULL;
}

+ for (i=0; i < gpu->scanout_num; i++) {
+ struct virtio_gpu_scanout *gpu_scanout;
+
+ gpu_scanout = gpu->gpu_scanouts + i;
+ if (gpu_scanout && gpu_scanout->active) {
+ if (gpu_scanout->cur_img) {
+ pixman_image_unref(gpu_scanout->cur_img);
+ gpu_scanout->cur_img = NULL;
+ }
+ if (gpu_scanout->dma_buf) {
+ virtio_gpu_dmabuf_unref(gpu_scanout->dma_buf);
+ gpu_scanout->dma_buf = NULL;
+ }
+ gpu_scanout->active = false;
+ }
+ }
+ free(gpu->gpu_scanouts);
+ gpu->gpu_scanouts = NULL;
+
pthread_mutex_destroy(&gpu->vga_thread_mtx);
while (LIST_FIRST(&gpu->r2d_list)) {
r2d = LIST_FIRST(&gpu->r2d_list);
--
2.25.1


[PATCH 2/8] ACRN:DM:VDisplay: vdpy_init connection returns the supported number of window

Zhao, Yakui
 

Vdisplay module will create the gui_window based on the virtio-gpu parameter. When it tries
to establish the connection with vdisplay module, it will return the supported number of window.
Then the virtio-gpu device can initialize the correct info for the guest_vm.

BTW: The number is fixed to 1.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
devicemodel/hw/pci/virtio/virtio_gpu.c | 2 +-
devicemodel/hw/vdisplay_sdl.c | 4 +++-
devicemodel/include/vdisplay.h | 2 +-
3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 2f8c4362e..cf3d20823 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -1485,7 +1485,7 @@ virtio_gpu_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
gpu->vq,
BACKEND_VBSU);

- gpu->vdpy_handle = vdpy_init();
+ gpu->vdpy_handle = vdpy_init(NULL);
gpu->base.mtx = &gpu->mtx;
gpu->base.device_caps = VIRTIO_GPU_S_HOSTCAPS;

diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index 567a2de6f..65fd78d93 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -1069,7 +1069,7 @@ bool vdpy_submit_bh(int handle, struct vdpy_display_bh *bh_task)
}

int
-vdpy_init()
+vdpy_init(int *supported_wins)
{
int err, count;

@@ -1100,6 +1100,8 @@ vdpy_init()
}

vdpy.s.n_connect++;
+ if (supported_wins)
+ *supported_wins = 1;
return vdpy.s.n_connect;
}

diff --git a/devicemodel/include/vdisplay.h b/devicemodel/include/vdisplay.h
index fc0e91b46..c1214a461 100644
--- a/devicemodel/include/vdisplay.h
+++ b/devicemodel/include/vdisplay.h
@@ -85,7 +85,7 @@ struct cursor {

int vdpy_parse_cmd_option(const char *opts);
int gfx_ui_init();
-int vdpy_init();
+int vdpy_init(int *supported_wins);
void vdpy_get_display_info(int handle, int scanout_id, struct display_info *info);
void vdpy_surface_set(int handle, int scanout_id, struct surface *surf);
void vdpy_surface_update(int handle, int scanout_id, struct surface *surf);
--
2.25.1


[PATCH 1/8] ACRN:DM:VDISPLAY: Refine display API to support multi scanout_window

Zhao, Yakui
 

Currenly it can support only one display_win. When virtio-gpu wants to display
the framebuffer from Guest_vm, it will render it into the default win. In order
to support multi-window, the scanout_id is added for display API.
After display API is refined, the vdisplay and virtio-gpu can support the multi-win
independently.

BTW: Now the scanout_id is not implemented in vdisplay module and the virtio-gpu always
passes the zero. It will be implemeneted in the later patches.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
devicemodel/hw/pci/virtio/virtio_gpu.c | 28 +++++++++++++-------------
devicemodel/hw/vdisplay_sdl.c | 12 +++++------
devicemodel/include/vdisplay.h | 12 +++++------
3 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c b/devicemodel/hw/pci/virtio/virtio_gpu.c
index 4ba219bc1..2f8c4362e 100644
--- a/devicemodel/hw/pci/virtio/virtio_gpu.c
+++ b/devicemodel/hw/pci/virtio/virtio_gpu.c
@@ -556,7 +556,7 @@ virtio_gpu_cmd_get_edid(struct virtio_gpu_command *cmd)
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, resp.edid, resp.size);
+ vdpy_get_edid(gpu->vdpy_handle, 0, resp.edid, resp.size);
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
}

@@ -570,7 +570,7 @@ virtio_gpu_cmd_get_display_info(struct virtio_gpu_command *cmd)
gpu = cmd->gpu;
cmd->iolen = sizeof(resp);
memset(&resp, 0, sizeof(resp));
- vdpy_get_display_info(gpu->vdpy_handle, &info);
+ 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;
@@ -790,7 +790,7 @@ 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, NULL);
+ vdpy_surface_set(gpu->vdpy_handle, 0, NULL);
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
return;
@@ -814,7 +814,7 @@ virtio_gpu_cmd_set_scanout(struct virtio_gpu_command *cmd)
surf.stride = pixman_image_get_stride(r2d->image);
surf.surf_format = r2d->format;
surf.surf_type = SURFACE_PIXMAN;
- vdpy_surface_set(gpu->vdpy_handle, &surf);
+ vdpy_surface_set(gpu->vdpy_handle, 0, &surf);
pixman_image_unref(r2d->image);
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
}
@@ -934,7 +934,7 @@ virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
virtio_gpu_dmabuf_ref(r2d->dma_info);
surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
surf.surf_type = SURFACE_DMABUF;
- vdpy_surface_update(gpu->vdpy_handle, &surf);
+ vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
virtio_gpu_dmabuf_unref(r2d->dma_info);
@@ -949,7 +949,7 @@ virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
surf.stride = pixman_image_get_stride(r2d->image);
surf.surf_format = r2d->format;
surf.surf_type = SURFACE_PIXMAN;
- vdpy_surface_update(gpu->vdpy_handle, &surf);
+ vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
pixman_image_unref(r2d->image);

cmd->iolen = sizeof(resp);
@@ -1143,7 +1143,7 @@ virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_command *cmd)
if (req.resource_id == 0) {
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
memcpy(cmd->iov[cmd->iovcnt - 1].iov_base, &resp, sizeof(resp));
- vdpy_surface_set(gpu->vdpy_handle, NULL);
+ vdpy_surface_set(gpu->vdpy_handle, 0, NULL);
return;
}
r2d = virtio_gpu_find_resource_2d(cmd->gpu, req.resource_id);
@@ -1187,7 +1187,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, &surf);
+ vdpy_surface_set(gpu->vdpy_handle, 0, &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);
@@ -1312,7 +1312,7 @@ virtio_gpu_cmd_update_cursor(struct virtio_gpu_command *cmd)
cur.height = r2d->height;
pixman_image_ref(r2d->image);
cur.data = pixman_image_get_data(r2d->image);
- vdpy_cursor_define(gpu->vdpy_handle, &cur);
+ vdpy_cursor_define(gpu->vdpy_handle, 0, &cur);
pixman_image_unref(r2d->image);
}
}
@@ -1325,7 +1325,7 @@ virtio_gpu_cmd_move_cursor(struct virtio_gpu_command *cmd)

gpu = cmd->gpu;
memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
- vdpy_cursor_move(gpu->vdpy_handle, req.pos.x, req.pos.y);
+ vdpy_cursor_move(gpu->vdpy_handle, 0, req.pos.x, req.pos.y);
}

static void
@@ -1397,10 +1397,10 @@ virtio_gpu_vga_bh(void *param)
gpu->vga.surf.pixel = gpu->vga.gc->gc_image->data;
gpu->vga.surf.surf_format = PIXMAN_a8r8g8b8;
gpu->vga.surf.surf_type = SURFACE_PIXMAN;
- vdpy_surface_set(gpu->vdpy_handle, &gpu->vga.surf);
+ vdpy_surface_set(gpu->vdpy_handle, 0, &gpu->vga.surf);
}

- vdpy_surface_update(gpu->vdpy_handle, &gpu->vga.surf);
+ vdpy_surface_update(gpu->vdpy_handle, 0, &gpu->vga.surf);
}

static void *
@@ -1553,7 +1553,7 @@ virtio_gpu_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
pci_set_cfgdata16(dev, PCIR_SUBVEND_0, VIRTIO_VENDOR);

LIST_INIT(&gpu->r2d_list);
- vdpy_get_display_info(gpu->vdpy_handle, &info);
+ vdpy_get_display_info(gpu->vdpy_handle, 0, &info);

/*** PCI Config BARs setup ***/
/** BAR0: VGA framebuffer **/
@@ -1566,7 +1566,7 @@ virtio_gpu_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)

/** BAR2: VGA & Virtio Modern regs **/
/* EDID data blob [0x000~0x3ff] */
- vdpy_get_edid(gpu->vdpy_handle, gpu->edid, VIRTIO_GPU_EDID_SIZE);
+ vdpy_get_edid(gpu->vdpy_handle, 0, gpu->edid, VIRTIO_GPU_EDID_SIZE);
/* VGA ioports regs [0x400~0x41f] */
gpu->vga.gc = gc_init(info.width, info.height, ctx->fb_base);
gpu->vga.dev = vga_init(gpu->vga.gc, 0);
diff --git a/devicemodel/hw/vdisplay_sdl.c b/devicemodel/hw/vdisplay_sdl.c
index 21ceb2325..567a2de6f 100644
--- a/devicemodel/hw/vdisplay_sdl.c
+++ b/devicemodel/hw/vdisplay_sdl.c
@@ -510,7 +510,7 @@ vdpy_edid_generate(uint8_t *edid, size_t size, struct edid_info *info)
}

void
-vdpy_get_edid(int handle, uint8_t *edid, size_t size)
+vdpy_get_edid(int handle, int scanout_id, uint8_t *edid, size_t size)
{
struct edid_info edid_info;

@@ -534,7 +534,7 @@ vdpy_get_edid(int handle, uint8_t *edid, size_t size)
}

void
-vdpy_get_display_info(int handle, struct display_info *info)
+vdpy_get_display_info(int handle, int scanout_id, struct display_info *info)
{
if (handle == vdpy.s.n_connect) {
info->xoff = vdpy.info.xoff;
@@ -582,7 +582,7 @@ sdl_gl_display_init(void)
}

void
-vdpy_surface_set(int handle, struct surface *surf)
+vdpy_surface_set(int handle, int scanout_id, struct surface *surf)
{
pixman_image_t *src_img;
int format;
@@ -749,7 +749,7 @@ vdpy_cursor_position_transformation(struct display *vdpy, SDL_Rect *rect)
}

void
-vdpy_surface_update(int handle, struct surface *surf)
+vdpy_surface_update(int handle, int scanout_id, struct surface *surf)
{
SDL_Rect cursor_rect;

@@ -792,7 +792,7 @@ vdpy_surface_update(int handle, struct surface *surf)
}

void
-vdpy_cursor_define(int handle, struct cursor *cur)
+vdpy_cursor_define(int handle, int scanout_id, struct cursor *cur)
{
if (handle != vdpy.s.n_connect) {
return;
@@ -826,7 +826,7 @@ vdpy_cursor_define(int handle, struct cursor *cur)
}

void
-vdpy_cursor_move(int handle, uint32_t x, uint32_t y)
+vdpy_cursor_move(int handle, int scanout_id, uint32_t x, uint32_t y)
{
if (handle != vdpy.s.n_connect) {
return;
diff --git a/devicemodel/include/vdisplay.h b/devicemodel/include/vdisplay.h
index 99506469b..fc0e91b46 100644
--- a/devicemodel/include/vdisplay.h
+++ b/devicemodel/include/vdisplay.h
@@ -86,13 +86,13 @@ struct cursor {
int vdpy_parse_cmd_option(const char *opts);
int gfx_ui_init();
int vdpy_init();
-void vdpy_get_display_info(int handle, struct display_info *info);
-void vdpy_surface_set(int handle, struct surface *surf);
-void vdpy_surface_update(int handle, struct surface *surf);
+void vdpy_get_display_info(int handle, int scanout_id, struct display_info *info);
+void vdpy_surface_set(int handle, int scanout_id, struct surface *surf);
+void vdpy_surface_update(int handle, int scanout_id, struct surface *surf);
bool vdpy_submit_bh(int handle, struct vdpy_display_bh *bh);
-void vdpy_get_edid(int handle, uint8_t *edid, size_t size);
-void vdpy_cursor_define(int handle, struct cursor *cur);
-void vdpy_cursor_move(int handle, uint32_t x, uint32_t y);
+void vdpy_get_edid(int handle, int scanout_id, uint8_t *edid, size_t size);
+void vdpy_cursor_define(int handle, int scanout_id, struct cursor *cur);
+void vdpy_cursor_move(int handle, int scanout_id, uint32_t x, uint32_t y);
int vdpy_deinit(int handle);
void gfx_ui_deinit();

--
2.25.1

861 - 880 of 37344