aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-11-05 11:42:06 -0400
committerRichard Henderson <richard.henderson@linaro.org>2021-11-05 11:42:06 -0400
commitc39deb218178d1fb814dd2138ceff4b541a03d85 (patch)
tree843478391dfc3bae3991d5bd83c7a1bc1aeff004
parente4d96a7eb83146c936d88182c8dee9ba899bb6bb (diff)
parent1350ff156b25be65c599ecca9957ce6726c6d383 (diff)
downloadqemu-c39deb218178d1fb814dd2138ceff4b541a03d85.zip
qemu-c39deb218178d1fb814dd2138ceff4b541a03d85.tar.gz
qemu-c39deb218178d1fb814dd2138ceff4b541a03d85.tar.bz2
Merge remote-tracking branch 'remotes/kraxel/tags/egl-20211105-pull-request' into staging
gtk: a collection of egl fixes. # gpg: Signature made Fri 05 Nov 2021 07:30:21 AM EDT # gpg: using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] * remotes/kraxel/tags/egl-20211105-pull-request: ui/gtk-egl: blitting partial guest fb to the proper scanout surface ui/gtk: gd_draw_event returns FALSE when no cairo surface is bound ui/gtk-egl: guest fb texture needs to be regenerated when reinitializing egl ui/gtk-egl: make sure the right context is set as the current ui/gtk-egl: un-tab and re-tab should destroy egl surface and context virtio-gpu: splitting one extended mode guest fb into n-scanouts Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--hw/display/virtio-gpu-udmabuf-stubs.c3
-rw-r--r--hw/display/virtio-gpu-udmabuf.c22
-rw-r--r--hw/display/virtio-gpu.c4
-rw-r--r--include/hw/virtio/virtio-gpu.h5
-rw-r--r--include/ui/console.h4
-rw-r--r--ui/egl-helpers.c25
-rw-r--r--ui/gtk-egl.c10
-rw-r--r--ui/gtk.c23
8 files changed, 79 insertions, 17 deletions
diff --git a/hw/display/virtio-gpu-udmabuf-stubs.c b/hw/display/virtio-gpu-udmabuf-stubs.c
index 81f6614..f692e13 100644
--- a/hw/display/virtio-gpu-udmabuf-stubs.c
+++ b/hw/display/virtio-gpu-udmabuf-stubs.c
@@ -20,7 +20,8 @@ void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res)
int virtio_gpu_update_dmabuf(VirtIOGPU *g,
uint32_t scanout_id,
struct virtio_gpu_simple_resource *res,
- struct virtio_gpu_framebuffer *fb)
+ struct virtio_gpu_framebuffer *fb,
+ struct virtio_gpu_rect *r)
{
/* nothing (stub) */
return 0;
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index 60ea7f8..1597921 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -171,7 +171,8 @@ static VGPUDMABuf
*virtio_gpu_create_dmabuf(VirtIOGPU *g,
uint32_t scanout_id,
struct virtio_gpu_simple_resource *res,
- struct virtio_gpu_framebuffer *fb)
+ struct virtio_gpu_framebuffer *fb,
+ struct virtio_gpu_rect *r)
{
VGPUDMABuf *dmabuf;
@@ -183,6 +184,10 @@ static VGPUDMABuf
dmabuf->buf.width = fb->width;
dmabuf->buf.height = fb->height;
dmabuf->buf.stride = fb->stride;
+ dmabuf->buf.x = r->x;
+ dmabuf->buf.y = r->y;
+ dmabuf->buf.scanout_width = r->width;
+ dmabuf->buf.scanout_height = r->height;
dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
dmabuf->buf.fd = res->dmabuf_fd;
dmabuf->buf.allow_fences = true;
@@ -196,24 +201,25 @@ static VGPUDMABuf
int virtio_gpu_update_dmabuf(VirtIOGPU *g,
uint32_t scanout_id,
struct virtio_gpu_simple_resource *res,
- struct virtio_gpu_framebuffer *fb)
+ struct virtio_gpu_framebuffer *fb,
+ struct virtio_gpu_rect *r)
{
struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[scanout_id];
VGPUDMABuf *new_primary, *old_primary = NULL;
- new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb);
+ new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r);
if (!new_primary) {
return -EINVAL;
}
- if (g->dmabuf.primary) {
- old_primary = g->dmabuf.primary;
+ if (g->dmabuf.primary[scanout_id]) {
+ old_primary = g->dmabuf.primary[scanout_id];
}
- g->dmabuf.primary = new_primary;
+ g->dmabuf.primary[scanout_id] = new_primary;
qemu_console_resize(scanout->con,
- new_primary->buf.width,
- new_primary->buf.height);
+ new_primary->buf.scanout_width,
+ new_primary->buf.scanout_height);
dpy_gl_scanout_dmabuf(scanout->con, &new_primary->buf);
if (old_primary) {
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 182e086..d78b970 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -517,9 +517,9 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
console_has_gl(scanout->con)) {
dpy_gl_update(scanout->con, 0, 0, scanout->width,
scanout->height);
- return;
}
}
+ return;
}
if (!res->blob &&
@@ -627,7 +627,7 @@ static void virtio_gpu_do_set_scanout(VirtIOGPU *g,
if (res->blob) {
if (console_has_gl(scanout->con)) {
- if (!virtio_gpu_update_dmabuf(g, scanout_id, res, fb)) {
+ if (!virtio_gpu_update_dmabuf(g, scanout_id, res, fb, r)) {
virtio_gpu_update_scanout(g, scanout_id, res, r);
return;
}
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 24c6628..acfba7c 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -187,7 +187,7 @@ struct VirtIOGPU {
struct {
QTAILQ_HEAD(, VGPUDMABuf) bufs;
- VGPUDMABuf *primary;
+ VGPUDMABuf *primary[VIRTIO_GPU_MAX_SCANOUTS];
} dmabuf;
};
@@ -273,7 +273,8 @@ void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res);
int virtio_gpu_update_dmabuf(VirtIOGPU *g,
uint32_t scanout_id,
struct virtio_gpu_simple_resource *res,
- struct virtio_gpu_framebuffer *fb);
+ struct virtio_gpu_framebuffer *fb,
+ struct virtio_gpu_rect *r);
/* virtio-gpu-3d.c */
void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
diff --git a/include/ui/console.h b/include/ui/console.h
index b6bedc5..6d67892 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -167,6 +167,10 @@ typedef struct QemuDmaBuf {
uint32_t fourcc;
uint64_t modifier;
uint32_t texture;
+ uint32_t x;
+ uint32_t y;
+ uint32_t scanout_width;
+ uint32_t scanout_height;
bool y0_top;
void *sync;
int fence_fd;
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 385a3fa..3a88245 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -90,14 +90,31 @@ void egl_fb_setup_new_tex(egl_fb *fb, int width, int height)
void egl_fb_blit(egl_fb *dst, egl_fb *src, bool flip)
{
- GLuint y1, y2;
+ GLuint x1 = 0;
+ GLuint y1 = 0;
+ GLuint x2, y2;
+ GLuint w = src->width;
+ GLuint h = src->height;
glBindFramebuffer(GL_READ_FRAMEBUFFER, src->framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst->framebuffer);
glViewport(0, 0, dst->width, dst->height);
- y1 = flip ? src->height : 0;
- y2 = flip ? 0 : src->height;
- glBlitFramebuffer(0, y1, src->width, y2,
+
+ if (src->dmabuf) {
+ x1 = src->dmabuf->x;
+ y1 = src->dmabuf->y;
+ w = src->dmabuf->scanout_width;
+ h = src->dmabuf->scanout_height;
+ }
+
+ w = (x1 + w) > src->width ? src->width - x1 : w;
+ h = (y1 + h) > src->height ? src->height - y1 : h;
+
+ y2 = flip ? y1 : h + y1;
+ y1 = flip ? h + y1 : y1;
+ x2 = x1 + w;
+
+ glBlitFramebuffer(x1, y1, x2, y2,
0, 0, dst->width, dst->height,
GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index e912b20..f2026e4 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -152,8 +152,13 @@ void gd_egl_refresh(DisplayChangeListener *dcl)
}
vc->gfx.gls = qemu_gl_init_shader();
if (vc->gfx.ds) {
+ surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds);
surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds);
}
+ if (vc->gfx.guest_fb.dmabuf) {
+ egl_dmabuf_release_texture(vc->gfx.guest_fb.dmabuf);
+ gd_egl_scanout_dmabuf(dcl, vc->gfx.guest_fb.dmabuf);
+ }
}
graphic_hw_update(dcl->con);
@@ -178,6 +183,8 @@ void gd_egl_switch(DisplayChangeListener *dcl,
surface_height(vc->gfx.ds) == surface_height(surface)) {
resized = false;
}
+ eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
+ vc->gfx.esurface, vc->gfx.ectx);
surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds);
vc->gfx.ds = surface;
@@ -237,6 +244,9 @@ void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
#ifdef CONFIG_GBM
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
+ eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
+ vc->gfx.esurface, vc->gfx.ectx);
+
egl_dmabuf_import_texture(dmabuf);
if (!dmabuf->texture) {
return;
diff --git a/ui/gtk.c b/ui/gtk.c
index b0564d8..d2892ea 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -778,6 +778,9 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
if (!vc->gfx.ds) {
return FALSE;
}
+ if (!vc->gfx.surface) {
+ return FALSE;
+ }
vc->gfx.dcl.update_interval =
gd_monitor_update_interval(vc->window ? vc->window : s->window);
@@ -1242,6 +1245,16 @@ static gboolean gd_tab_window_close(GtkWidget *widget, GdkEvent *event,
vc->tab_item, vc->label);
gtk_widget_destroy(vc->window);
vc->window = NULL;
+#if defined(CONFIG_OPENGL)
+ if (vc->gfx.esurface) {
+ eglDestroySurface(qemu_egl_display, vc->gfx.esurface);
+ vc->gfx.esurface = NULL;
+ }
+ if (vc->gfx.ectx) {
+ eglDestroyContext(qemu_egl_display, vc->gfx.ectx);
+ vc->gfx.ectx = NULL;
+ }
+#endif
return TRUE;
}
@@ -1271,6 +1284,16 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
if (!vc->window) {
gtk_widget_set_sensitive(vc->menu_item, false);
vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+#if defined(CONFIG_OPENGL)
+ if (vc->gfx.esurface) {
+ eglDestroySurface(qemu_egl_display, vc->gfx.esurface);
+ vc->gfx.esurface = NULL;
+ }
+ if (vc->gfx.esurface) {
+ eglDestroyContext(qemu_egl_display, vc->gfx.ectx);
+ vc->gfx.ectx = NULL;
+ }
+#endif
gd_widget_reparent(s->notebook, vc->window, vc->tab_item);
g_signal_connect(vc->window, "delete-event",