mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-18 17:33:43 +00:00
ACRN:DM:VGPU: virtio-gpu-flush cmds check whether one scanout_win needs to be displayed
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 And the VIRTIO_GPU_CMD_FLUSH will notify the vdisplay module to display the framebuffer related with the scanout_id. But the virtio_gpu_cmd_flush doesn't pass the scanout info.Instead it only passes the flushed_region and the resource_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. v1->v2: Use the bpp instead of hardcode 4 for offset_calculation Tracked-On: #7988 Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Reviewed-by: Peng Sun <peng.p.sun@linux.intel.com>
This commit is contained in:
parent
6d83cd17f8
commit
8b55026f9d
@ -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));
|
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
|
static void
|
||||||
virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
|
virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
|
||||||
{
|
{
|
||||||
@ -983,6 +1023,9 @@ virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
|
|||||||
struct virtio_gpu_resource_2d *r2d;
|
struct virtio_gpu_resource_2d *r2d;
|
||||||
struct surface surf;
|
struct surface surf;
|
||||||
struct virtio_gpu *gpu;
|
struct virtio_gpu *gpu;
|
||||||
|
int i;
|
||||||
|
struct virtio_gpu_scanout *gpu_scanout;
|
||||||
|
int bytes_pp;
|
||||||
|
|
||||||
gpu = cmd->gpu;
|
gpu = cmd->gpu;
|
||||||
memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
|
memcpy(&req, cmd->iov[0].iov_base, sizeof(req));
|
||||||
@ -999,24 +1042,37 @@ virtio_gpu_cmd_resource_flush(struct virtio_gpu_command *cmd)
|
|||||||
}
|
}
|
||||||
if (r2d->blob) {
|
if (r2d->blob) {
|
||||||
virtio_gpu_dmabuf_ref(r2d->dma_info);
|
virtio_gpu_dmabuf_ref(r2d->dma_info);
|
||||||
surf.dma_info.dmabuf_fd = r2d->dma_info->dmabuf_fd;
|
for (i = 0; i < gpu->scanout_num; i++) {
|
||||||
surf.surf_type = SURFACE_DMABUF;
|
if (!virtio_gpu_scanout_needs_flush(gpu, i, req.resource_id, &req.r))
|
||||||
vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
|
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;
|
resp.type = VIRTIO_GPU_RESP_OK_NODATA;
|
||||||
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
|
memcpy(cmd->iov[1].iov_base, &resp, sizeof(resp));
|
||||||
virtio_gpu_dmabuf_unref(r2d->dma_info);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pixman_image_ref(r2d->image);
|
pixman_image_ref(r2d->image);
|
||||||
surf.pixel = pixman_image_get_data(r2d->image);
|
bytes_pp = PIXMAN_FORMAT_BPP(r2d->format) / 8;
|
||||||
surf.x = req.r.x;
|
for (i = 0; i < gpu->scanout_num; i++) {
|
||||||
surf.y = req.r.y;
|
if (!virtio_gpu_scanout_needs_flush(gpu, i, req.resource_id, &req.r))
|
||||||
surf.width = r2d->width;
|
continue;
|
||||||
surf.height = r2d->height;
|
|
||||||
surf.stride = pixman_image_get_stride(r2d->image);
|
gpu_scanout = gpu->gpu_scanouts + i;
|
||||||
surf.surf_format = r2d->format;
|
surf.pixel = pixman_image_get_data(r2d->image);
|
||||||
surf.surf_type = SURFACE_PIXMAN;
|
surf.x = gpu_scanout->scanout_rect.x;
|
||||||
vdpy_surface_update(gpu->vdpy_handle, 0, &surf);
|
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 += bytes_pp * surf.x + surf.y * surf.stride;
|
||||||
|
vdpy_surface_update(gpu->vdpy_handle, i, &surf);
|
||||||
|
}
|
||||||
pixman_image_unref(r2d->image);
|
pixman_image_unref(r2d->image);
|
||||||
|
|
||||||
cmd->iolen = sizeof(resp);
|
cmd->iolen = sizeof(resp);
|
||||||
|
Loading…
Reference in New Issue
Block a user