aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-06-28 08:42:32 +0200
committerRichard Henderson <richard.henderson@linaro.org>2023-06-28 08:42:32 +0200
commitb111569da9f82fdf05df03184836a4564adef599 (patch)
treeae450dcb6d62df40d10456b44e597281c739e5b2 /hw
parent4329d049d5b8d4af71c6b399d64a6d1b98856318 (diff)
parentde1f8ce0abb8c43d1e6a00c31c6d24dfe0505b92 (diff)
downloadqemu-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.c3
-rw-r--r--hw/display/virtio-gpu-virgl.c43
-rw-r--r--hw/display/virtio-gpu.c99
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);