virtio-gpu/win32: allocate shareable 2d resources/images
Allocate pixman bits for scanouts with qemu_win32_map_alloc() so we can set a shareable handle on the associated display surface. Note: when bits are provided to pixman_image_create_bits(), you must also give the rowstride (the argument is ignored when bits is NULL) Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20230606115658.677673-11-marcandre.lureau@redhat.com>
This commit is contained in:
parent
09b4c198b8
commit
9462ff4695
@ -258,6 +258,16 @@ static uint32_t calc_image_hostmem(pixman_format_code_t pformat,
|
|||||||
return height * stride;
|
return height * stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
static void
|
||||||
|
win32_pixman_image_destroy(pixman_image_t *image, void *data)
|
||||||
|
{
|
||||||
|
HANDLE handle = data;
|
||||||
|
|
||||||
|
qemu_win32_map_free(pixman_image_get_data(image), handle, &error_warn);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
|
static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
|
||||||
struct virtio_gpu_ctrl_command *cmd)
|
struct virtio_gpu_ctrl_command *cmd)
|
||||||
{
|
{
|
||||||
@ -304,12 +314,27 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
|
|||||||
|
|
||||||
res->hostmem = calc_image_hostmem(pformat, c2d.width, c2d.height);
|
res->hostmem = calc_image_hostmem(pformat, c2d.width, c2d.height);
|
||||||
if (res->hostmem + g->hostmem < g->conf_max_hostmem) {
|
if (res->hostmem + g->hostmem < g->conf_max_hostmem) {
|
||||||
|
void *bits = NULL;
|
||||||
|
#ifdef WIN32
|
||||||
|
bits = qemu_win32_map_alloc(res->hostmem, &res->handle, &error_warn);
|
||||||
|
if (!bits) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
res->image = pixman_image_create_bits(pformat,
|
res->image = pixman_image_create_bits(pformat,
|
||||||
c2d.width,
|
c2d.width,
|
||||||
c2d.height,
|
c2d.height,
|
||||||
NULL, 0);
|
bits, res->hostmem / c2d.height);
|
||||||
|
#ifdef WIN32
|
||||||
|
if (res->image) {
|
||||||
|
pixman_image_set_destroy_function(res->image, win32_pixman_image_destroy, res->handle);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
end:
|
||||||
|
#endif
|
||||||
if (!res->image) {
|
if (!res->image) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
"%s: resource creation failed %d %d %d\n",
|
"%s: resource creation failed %d %d %d\n",
|
||||||
@ -685,6 +710,9 @@ static void virtio_gpu_do_set_scanout(VirtIOGPU *g,
|
|||||||
*error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
*error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifdef WIN32
|
||||||
|
qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, fb->offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
pixman_image_unref(rect);
|
pixman_image_unref(rect);
|
||||||
dpy_gfx_replace_surface(g->parent_obj.scanout[scanout_id].con,
|
dpy_gfx_replace_surface(g->parent_obj.scanout[scanout_id].con,
|
||||||
@ -1228,6 +1256,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
|
|||||||
struct virtio_gpu_simple_resource *res;
|
struct virtio_gpu_simple_resource *res;
|
||||||
struct virtio_gpu_scanout *scanout;
|
struct virtio_gpu_scanout *scanout;
|
||||||
uint32_t resource_id, pformat;
|
uint32_t resource_id, pformat;
|
||||||
|
void *bits = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
g->hostmem = 0;
|
g->hostmem = 0;
|
||||||
@ -1252,15 +1281,23 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
|
|||||||
g_free(res);
|
g_free(res);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res->hostmem = calc_image_hostmem(pformat, res->width, res->height);
|
||||||
|
#ifdef WIN32
|
||||||
|
bits = qemu_win32_map_alloc(res->hostmem, &res->handle, &error_warn);
|
||||||
|
if (!bits) {
|
||||||
|
g_free(res);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
res->image = pixman_image_create_bits(pformat,
|
res->image = pixman_image_create_bits(pformat,
|
||||||
res->width, res->height,
|
res->width, res->height,
|
||||||
NULL, 0);
|
bits, res->hostmem / res->height);
|
||||||
if (!res->image) {
|
if (!res->image) {
|
||||||
g_free(res);
|
g_free(res);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
res->hostmem = calc_image_hostmem(pformat, res->width, res->height);
|
|
||||||
|
|
||||||
res->addrs = g_new(uint64_t, res->iov_cnt);
|
res->addrs = g_new(uint64_t, res->iov_cnt);
|
||||||
res->iov = g_new(struct iovec, res->iov_cnt);
|
res->iov = g_new(struct iovec, res->iov_cnt);
|
||||||
@ -1321,6 +1358,9 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
|
|||||||
if (!scanout->ds) {
|
if (!scanout->ds) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
#ifdef WIN32
|
||||||
|
qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
dpy_gfx_replace_surface(scanout->con, scanout->ds);
|
dpy_gfx_replace_surface(scanout->con, scanout->ds);
|
||||||
dpy_gfx_update_full(scanout->con);
|
dpy_gfx_update_full(scanout->con);
|
||||||
|
@ -48,6 +48,9 @@ struct virtio_gpu_simple_resource {
|
|||||||
unsigned int iov_cnt;
|
unsigned int iov_cnt;
|
||||||
uint32_t scanout_bitmask;
|
uint32_t scanout_bitmask;
|
||||||
pixman_image_t *image;
|
pixman_image_t *image;
|
||||||
|
#ifdef WIN32
|
||||||
|
HANDLE handle;
|
||||||
|
#endif
|
||||||
uint64_t hostmem;
|
uint64_t hostmem;
|
||||||
|
|
||||||
uint64_t blob_size;
|
uint64_t blob_size;
|
||||||
|
Loading…
Reference in New Issue
Block a user