mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-16 00:16:12 +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));
|
||||
}
|
||||
|
||||
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,9 @@ 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;
|
||||
int bytes_pp;
|
||||
|
||||
gpu = cmd->gpu;
|
||||
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) {
|
||||
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);
|
||||
bytes_pp = PIXMAN_FORMAT_BPP(r2d->format) / 8;
|
||||
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 += bytes_pp * surf.x + surf.y * surf.stride;
|
||||
vdpy_surface_update(gpu->vdpy_handle, i, &surf);
|
||||
}
|
||||
pixman_image_unref(r2d->image);
|
||||
|
||||
cmd->iolen = sizeof(resp);
|
||||
|
Loading…
Reference in New Issue
Block a user