diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2023-06-28 08:42:32 +0200 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2023-06-28 08:42:32 +0200 |
commit | b111569da9f82fdf05df03184836a4564adef599 (patch) | |
tree | ae450dcb6d62df40d10456b44e597281c739e5b2 /hw | |
parent | 4329d049d5b8d4af71c6b399d64a6d1b98856318 (diff) | |
parent | de1f8ce0abb8c43d1e6a00c31c6d24dfe0505b92 (diff) | |
download | qemu-b111569da9f82fdf05df03184836a4564adef599.zip qemu-b111569da9f82fdf05df03184836a4564adef599.tar.gz qemu-b111569da9f82fdf05df03184836a4564adef599.tar.bz2 |
Merge tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging
wef
# -----BEGIN PGP SIGNATURE-----
#
# iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmSa+6McHG1hcmNhbmRy
# ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5YxfD/46nwpTCTWWdKdTeo5p
# OUdrF0rfHFqu4FN3OWHbfRxZCO/AdHL+UZ52owV4+5bJJI5uOnXwYKpkrwKYBrFd
# H8Bll7NitzA41rw4AQa0GeaQYCPJ99OOfnhbRI5Aep2NG2DfX5PK4RWnfqYw8LD1
# TiHtRv2lWnX9EyMjnEh93C+n17OfquP5Ew3ozZNQJ0+SiJ3CvsUn6hEqxOA8OdyX
# lj6l00CASQA2BxW+zjXjJKvRakCV4gfdvrL9eMf4eu0UopzET7ombBJGPnYVsrDU
# /4R7b0JgGM4iOpXFxK4Ng6myP28vPdOEJAU/OJLH+oMRz1caohS+0Ijl2KviUCex
# SGpb9plxqI7fI2QQt+1CxAlXADSW7oV1zV0/tLkKl/n5+MF3HJ/5qR3tefLhYu1p
# 2LpfbPMKGQ9V3+5Z/UvWx6GQYP1iBRm5THPLn+HSDMSqLmt6yp5cOTwP3KTx1Zlc
# JfpBtekT2Cgs54nnCcfnXa6/EPo4uR7cMFzrgXdSacPz/GssMVa1c2mNUYkgYEYU
# PeyDWZG2Rt/70y+CFDPBpKWEQVICnf7Ha43oj4BtGTqqUFeuZClMTTtZ5poSg3ir
# FcRNJ5zSWg2KhHIQ9TQKxIAwrxxVBY0AiQleNRyDzx+YGAuBBadO6i5eCqqpGgOa
# QRVBsP33Pg/QD1JdxN9GSSEh0w==
# =cR6x
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 27 Jun 2023 05:09:23 PM CEST
# gpg: using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg: issuer "marcandre.lureau@redhat.com"
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full]
# gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full]
* tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu: (33 commits)
ui/dbus: use shared D3D11 Texture2D when possible
virtio-gpu-virgl: use D3D11_SHARE_TEXTURE when available
ui: add optional d3d texture pointer to scanout texture
ui/egl: query ANGLE d3d device
virtio-gpu-virgl: teach it to get the QEMU EGL display
ui/dbus: add some GL traces
ui/dbus: add GL support on win32
ui: add egl_fb_read_rect()
ui/egl: default to GLES on windows
ui: add egl-headless support on win32
ui/dbus: use shared memory when possible on win32
virtio-gpu/win32: allocate shareable 2d resources/images
console/win32: allocate shareable display surface
ui/dbus: introduce "Interfaces" properties
tests: make dbus-display-test work on win32
qtest: add qtest_pid()
ui/dbus: win32 support
scripts: add a XML preprocessor script
ui/dbus: compile without gio/gunixfdlist.h
ui/egl: fix make_context_current() callback return value
...
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/display/virtio-gpu-udmabuf.c | 3 | ||||
-rw-r--r-- | hw/display/virtio-gpu-virgl.c | 43 | ||||
-rw-r--r-- | hw/display/virtio-gpu.c | 99 |
3 files changed, 118 insertions, 27 deletions
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index 69e2cf0..ef1a740 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -132,7 +132,8 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res) void *pdata = NULL; res->dmabuf_fd = -1; - if (res->iov_cnt == 1) { + if (res->iov_cnt == 1 && + res->iov[0].iov_len < 4096) { pdata = res->iov[0].iov_base; } else { virtio_gpu_create_udmabuf(res); diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c index 1c47603..8bb7a2c 100644 --- a/hw/display/virtio-gpu-virgl.c +++ b/hw/display/virtio-gpu-virgl.c @@ -18,9 +18,17 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-gpu.h" +#include "ui/egl-helpers.h" + #include <virglrenderer.h> -static struct virgl_renderer_callbacks virtio_gpu_3d_cbs; +#if VIRGL_RENDERER_CALLBACKS_VERSION >= 4 +static void * +virgl_get_egl_display(G_GNUC_UNUSED void *cookie) +{ + return qemu_egl_display; +} +#endif static void virgl_cmd_create_resource_2d(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd) @@ -145,7 +153,6 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd) { struct virtio_gpu_set_scanout ss; - struct virgl_renderer_resource_info info; int ret; VIRTIO_GPU_FILL_CMD(ss); @@ -160,10 +167,20 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g, } g->parent_obj.enable = 1; - memset(&info, 0, sizeof(info)); - if (ss.resource_id && ss.r.width && ss.r.height) { + struct virgl_renderer_resource_info info; + void *d3d_tex2d = NULL; + +#ifdef HAVE_VIRGL_D3D_INFO_EXT + struct virgl_renderer_resource_info_ext ext; + memset(&ext, 0, sizeof(ext)); + ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext); + info = ext.base; + d3d_tex2d = ext.d3d_tex2d; +#else + memset(&info, 0, sizeof(info)); ret = virgl_renderer_resource_get_info(ss.resource_id, &info); +#endif if (ret == -1) { qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n", @@ -178,7 +195,8 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g, g->parent_obj.scanout[ss.scanout_id].con, info.tex_id, info.flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, info.width, info.height, - ss.r.x, ss.r.y, ss.r.width, ss.r.height); + ss.r.x, ss.r.y, ss.r.width, ss.r.height, + d3d_tex2d); } else { dpy_gfx_replace_surface( g->parent_obj.scanout[ss.scanout_id].con, NULL); @@ -607,8 +625,21 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g) int virtio_gpu_virgl_init(VirtIOGPU *g) { int ret; + uint32_t flags = 0; + +#if VIRGL_RENDERER_CALLBACKS_VERSION >= 4 + if (qemu_egl_display) { + virtio_gpu_3d_cbs.version = 4; + virtio_gpu_3d_cbs.get_egl_display = virgl_get_egl_display; + } +#endif +#ifdef VIRGL_RENDERER_D3D11_SHARE_TEXTURE + if (qemu_egl_angle_d3d) { + flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE; + } +#endif - ret = virgl_renderer_init(g, 0, &virtio_gpu_3d_cbs); + ret = virgl_renderer_init(g, flags, &virtio_gpu_3d_cbs); if (ret != 0) { error_report("virgl could not be initialized: %d", ret); return ret; diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 66cddd9..347e17d 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -258,6 +258,16 @@ static uint32_t calc_image_hostmem(pixman_format_code_t pformat, 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, 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); 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, c2d.width, 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) { qemu_log_mask(LOG_GUEST_ERROR, "%s: resource creation failed %d %d %d\n", @@ -438,11 +463,11 @@ static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd) { struct virtio_gpu_simple_resource *res; - int h; + int h, bpp; uint32_t src_offset, dst_offset, stride; - int bpp; pixman_format_code_t format; struct virtio_gpu_transfer_to_host_2d t2d; + void *img_data; VIRTIO_GPU_FILL_CMD(t2d); virtio_gpu_t2d_bswap(&t2d); @@ -471,23 +496,23 @@ static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g, format = pixman_image_get_format(res->image); bpp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8); stride = pixman_image_get_stride(res->image); + img_data = pixman_image_get_data(res->image); - if (t2d.offset || t2d.r.x || t2d.r.y || - t2d.r.width != pixman_image_get_width(res->image)) { - void *img_data = pixman_image_get_data(res->image); + if (t2d.r.x || t2d.r.width != pixman_image_get_width(res->image)) { for (h = 0; h < t2d.r.height; h++) { src_offset = t2d.offset + stride * h; dst_offset = (t2d.r.y + h) * stride + (t2d.r.x * bpp); iov_to_buf(res->iov, res->iov_cnt, src_offset, - (uint8_t *)img_data - + dst_offset, t2d.r.width * bpp); + (uint8_t *)img_data + dst_offset, + t2d.r.width * bpp); } } else { - iov_to_buf(res->iov, res->iov_cnt, 0, - pixman_image_get_data(res->image), - pixman_image_get_stride(res->image) - * pixman_image_get_height(res->image)); + src_offset = t2d.offset; + dst_offset = t2d.r.y * stride + t2d.r.x * bpp; + iov_to_buf(res->iov, res->iov_cnt, src_offset, + (uint8_t *)img_data + dst_offset, + stride * t2d.r.height); } } @@ -498,6 +523,8 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g, struct virtio_gpu_resource_flush rf; struct virtio_gpu_scanout *scanout; pixman_region16_t flush_region; + bool within_bounds = false; + bool update_submitted = false; int i; VIRTIO_GPU_FILL_CMD(rf); @@ -518,13 +545,28 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g, rf.r.x < scanout->x + scanout->width && rf.r.x + rf.r.width >= scanout->x && rf.r.y < scanout->y + scanout->height && - rf.r.y + rf.r.height >= scanout->y && - console_has_gl(scanout->con)) { - dpy_gl_update(scanout->con, 0, 0, scanout->width, - scanout->height); + rf.r.y + rf.r.height >= scanout->y) { + within_bounds = true; + + if (console_has_gl(scanout->con)) { + dpy_gl_update(scanout->con, 0, 0, scanout->width, + scanout->height); + update_submitted = true; + } } } - return; + + if (update_submitted) { + return; + } + if (!within_bounds) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: flush bounds outside scanouts" + " bounds for flush %d: %d %d %d %d\n", + __func__, rf.resource_id, rf.r.x, rf.r.y, + rf.r.width, rf.r.height); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + return; + } } if (!res->blob && @@ -634,8 +676,10 @@ static void virtio_gpu_do_set_scanout(VirtIOGPU *g, if (console_has_gl(scanout->con)) { if (!virtio_gpu_update_dmabuf(g, scanout_id, res, fb, r)) { virtio_gpu_update_scanout(g, scanout_id, res, r); - return; + } else { + *error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY; } + return; } data = res->blob; @@ -666,6 +710,9 @@ static void virtio_gpu_do_set_scanout(VirtIOGPU *g, *error = VIRTIO_GPU_RESP_ERR_UNSPEC; return; } +#ifdef WIN32 + qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, fb->offset); +#endif pixman_image_unref(rect); dpy_gfx_replace_surface(g->parent_obj.scanout[scanout_id].con, @@ -1209,6 +1256,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, struct virtio_gpu_simple_resource *res; struct virtio_gpu_scanout *scanout; uint32_t resource_id, pformat; + void *bits = NULL; int i; g->hostmem = 0; @@ -1233,15 +1281,23 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, g_free(res); 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->width, res->height, - NULL, 0); + bits, res->hostmem / res->height); if (!res->image) { g_free(res); return -EINVAL; } - res->hostmem = calc_image_hostmem(pformat, res->width, res->height); res->addrs = g_new(uint64_t, res->iov_cnt); res->iov = g_new(struct iovec, res->iov_cnt); @@ -1302,6 +1358,9 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, if (!scanout->ds) { 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_update_full(scanout->con); |