diff mbox series

[PULL,20/24] ui: add egl dmabuf import to gtkglarea

Message ID 20210205065620.1726554-21-kraxel@redhat.com (mailing list archive)
State New, archived
Headers show
Series [PULL,01/24] hw/display/qxl: Fix bad printf format specifiers | expand

Commit Message

Gerd Hoffmann Feb. 5, 2021, 6:56 a.m. UTC
From: Marc-André Lureau <marcandre.lureau@redhat.com>

GtkGLArea is used on wayland, where EGL is usually available.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20210204105232.834642-17-marcandre.lureau@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/gtk.h |  2 ++
 ui/gtk-gl-area.c | 18 ++++++++++++++++++
 ui/gtk.c         | 22 ++++++++++++++++++++++
 3 files changed, 42 insertions(+)
diff mbox series

Patch

diff --git a/include/ui/gtk.h b/include/ui/gtk.h
index aaef884b95b4..3c1cd98db8b1 100644
--- a/include/ui/gtk.h
+++ b/include/ui/gtk.h
@@ -134,6 +134,8 @@  QEMUGLContext gd_gl_area_create_context(DisplayChangeListener *dcl,
                                         QEMUGLParams *params);
 void gd_gl_area_destroy_context(DisplayChangeListener *dcl,
                                 QEMUGLContext ctx);
+void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl,
+                               QemuDmaBuf *dmabuf);
 void gd_gl_area_scanout_texture(DisplayChangeListener *dcl,
                                 uint32_t backing_id,
                                 bool backing_y_0_top,
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index 96fbe75387ce..72bcd949180f 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -213,6 +213,24 @@  void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
     gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area));
 }
 
+void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl,
+                               QemuDmaBuf *dmabuf)
+{
+#ifdef CONFIG_OPENGL_DMABUF
+    VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
+
+    gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area));
+    egl_dmabuf_import_texture(dmabuf);
+    if (!dmabuf->texture) {
+        return;
+    }
+
+    gd_gl_area_scanout_texture(dcl, dmabuf->texture,
+                               false, dmabuf->width, dmabuf->height,
+                               0, 0, dmabuf->width, dmabuf->height);
+#endif
+}
+
 void gtk_gl_area_init(void)
 {
     display_opengl = 1;
diff --git a/ui/gtk.c b/ui/gtk.c
index f41c396cb98a..79dc2401203a 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -627,6 +627,12 @@  static bool gd_has_dmabuf(DisplayChangeListener *dcl)
 {
     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
 
+    if (gtk_use_gl_area && !gtk_widget_get_realized(vc->gfx.drawing_area)) {
+        /* FIXME: Assume it will work, actual check done after realize */
+        /* fixing this would require delaying listener registration */
+        return true;
+    }
+
     return vc->gfx.has_dmabuf;
 }
 
@@ -647,6 +653,8 @@  static const DisplayChangeListenerOps dcl_gl_area_ops = {
     .dpy_gl_scanout_texture  = gd_gl_area_scanout_texture,
     .dpy_gl_scanout_disable  = gd_gl_area_scanout_disable,
     .dpy_gl_update           = gd_gl_area_scanout_flush,
+    .dpy_gl_scanout_dmabuf   = gd_gl_area_scanout_dmabuf,
+    .dpy_has_dmabuf          = gd_has_dmabuf,
 };
 
 static const DisplayChangeListenerOps dcl_egl_ops = {
@@ -1983,6 +1991,18 @@  static GtkWidget *gd_create_menu_machine(GtkDisplayState *s)
     return machine_menu;
 }
 
+#if defined(CONFIG_OPENGL)
+static void gl_area_realize(GtkGLArea *area, VirtualConsole *vc)
+{
+    gtk_gl_area_make_current(area);
+    qemu_egl_display = eglGetCurrentDisplay();
+    vc->gfx.has_dmabuf = qemu_egl_has_dmabuf();
+    if (!vc->gfx.has_dmabuf) {
+        error_report("GtkGLArea console lacks DMABUF support.");
+    }
+}
+#endif
+
 static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
                               QemuConsole *con, int idx,
                               GSList *group, GtkWidget *view_menu)
@@ -1998,6 +2018,8 @@  static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
     if (display_opengl) {
         if (gtk_use_gl_area) {
             vc->gfx.drawing_area = gtk_gl_area_new();
+            g_signal_connect(vc->gfx.drawing_area, "realize",
+                             G_CALLBACK(gl_area_realize), vc);
             vc->gfx.dcl.ops = &dcl_gl_area_ops;
         } else {
             vc->gfx.drawing_area = gtk_drawing_area_new();