[PATCH] qemu: Add GTK display with OpenGL support

Kirill Shchetiniuk via Devel posted 1 patch 7 months, 3 weeks ago
Failed in applying to current master (apply log)
src/conf/domain_conf.c                        | 79 ++++++++++++++++++-
src/conf/domain_conf.h                        |  8 ++
src/conf/schemas/domaincommon.rng             | 28 +++++++
src/qemu/qemu_capabilities.c                  |  5 ++
src/qemu/qemu_capabilities.h                  |  2 +
src/qemu/qemu_command.c                       | 39 ++++++++-
src/qemu/qemu_domain.c                        |  1 +
src/qemu/qemu_driver.c                        |  2 +
src/qemu/qemu_extdevice.c                     |  2 +
src/qemu/qemu_hotplug.c                       |  1 +
src/qemu/qemu_process.c                       |  8 ++
src/qemu/qemu_validate.c                      | 16 ++++
src/security/virt-aa-helper.c                 |  6 ++
src/vmx/vmx.c                                 |  1 +
tests/domaincapsdata/qemu_10.0.0.s390x.xml    |  1 +
tests/domaincapsdata/qemu_7.0.0.ppc64.xml     |  1 +
tests/domaincapsdata/qemu_7.1.0.ppc64.xml     |  1 +
tests/domaincapsdata/qemu_7.2.0.ppc.xml       |  1 +
.../qemu_8.2.0-tcg-virt.loongarch64.xml       |  1 +
.../qemu_8.2.0-virt.aarch64.xml               |  1 +
.../qemu_8.2.0-virt.loongarch64.xml           |  1 +
tests/domaincapsdata/qemu_8.2.0.aarch64.xml   |  1 +
tests/domaincapsdata/qemu_8.2.0.armv7l.xml    |  1 +
tests/domaincapsdata/qemu_9.0.0.sparc.xml     |  1 +
tests/domaincapsdata/qemu_9.1.0.s390x.xml     |  1 +
tests/domaincapsdata/qemu_9.2.0.s390x.xml     |  1 +
.../caps_10.0.0_s390x.xml                     |  1 +
.../qemucapabilitiesdata/caps_7.0.0_ppc64.xml |  1 +
.../qemucapabilitiesdata/caps_7.1.0_ppc64.xml |  1 +
tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml |  1 +
.../caps_8.2.0_aarch64.xml                    |  1 +
.../caps_8.2.0_armv7l.xml                     |  1 +
.../caps_8.2.0_loongarch64.xml                |  1 +
.../qemucapabilitiesdata/caps_9.0.0_sparc.xml |  1 +
.../qemucapabilitiesdata/caps_9.1.0_s390x.xml |  1 +
.../qemucapabilitiesdata/caps_9.2.0_s390x.xml |  1 +
36 files changed, 218 insertions(+), 2 deletions(-)
[PATCH] qemu: Add GTK display with OpenGL support
Posted by Kirill Shchetiniuk via Devel 7 months, 3 weeks ago
From: Kirill Shchetiniuk <kshcheti@redhat.com>

Introduce GTK display support with OpenGL for the QEMU driver.

 - Add new XML options for GTK display type.
 - Include capability flags for the QEMU driver.

Note: The `QEMU_CAPS_GTK_GL` flag cannot yet be checked, so device
definition validation is incomplete. A placeholder is left for
future implementation, when the GTK along with OpenGL capability
check would be available in QEMU.

Resolves: https://gitlab.com/libvirt/libvirt/-/issues/570

Signed-off-by: Kirill Shchetiniuk <kshcheti@redhat.com>
---
 src/conf/domain_conf.c                        | 79 ++++++++++++++++++-
 src/conf/domain_conf.h                        |  8 ++
 src/conf/schemas/domaincommon.rng             | 28 +++++++
 src/qemu/qemu_capabilities.c                  |  5 ++
 src/qemu/qemu_capabilities.h                  |  2 +
 src/qemu/qemu_command.c                       | 39 ++++++++-
 src/qemu/qemu_domain.c                        |  1 +
 src/qemu/qemu_driver.c                        |  2 +
 src/qemu/qemu_extdevice.c                     |  2 +
 src/qemu/qemu_hotplug.c                       |  1 +
 src/qemu/qemu_process.c                       |  8 ++
 src/qemu/qemu_validate.c                      | 16 ++++
 src/security/virt-aa-helper.c                 |  6 ++
 src/vmx/vmx.c                                 |  1 +
 tests/domaincapsdata/qemu_10.0.0.s390x.xml    |  1 +
 tests/domaincapsdata/qemu_7.0.0.ppc64.xml     |  1 +
 tests/domaincapsdata/qemu_7.1.0.ppc64.xml     |  1 +
 tests/domaincapsdata/qemu_7.2.0.ppc.xml       |  1 +
 .../qemu_8.2.0-tcg-virt.loongarch64.xml       |  1 +
 .../qemu_8.2.0-virt.aarch64.xml               |  1 +
 .../qemu_8.2.0-virt.loongarch64.xml           |  1 +
 tests/domaincapsdata/qemu_8.2.0.aarch64.xml   |  1 +
 tests/domaincapsdata/qemu_8.2.0.armv7l.xml    |  1 +
 tests/domaincapsdata/qemu_9.0.0.sparc.xml     |  1 +
 tests/domaincapsdata/qemu_9.1.0.s390x.xml     |  1 +
 tests/domaincapsdata/qemu_9.2.0.s390x.xml     |  1 +
 .../caps_10.0.0_s390x.xml                     |  1 +
 .../qemucapabilitiesdata/caps_7.0.0_ppc64.xml |  1 +
 .../qemucapabilitiesdata/caps_7.1.0_ppc64.xml |  1 +
 tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml |  1 +
 .../caps_8.2.0_aarch64.xml                    |  1 +
 .../caps_8.2.0_armv7l.xml                     |  1 +
 .../caps_8.2.0_loongarch64.xml                |  1 +
 .../qemucapabilitiesdata/caps_9.0.0_sparc.xml |  1 +
 .../qemucapabilitiesdata/caps_9.1.0_s390x.xml |  1 +
 .../qemucapabilitiesdata/caps_9.2.0_s390x.xml |  1 +
 36 files changed, 218 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 542d6ade91..73550f7fcf 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -960,6 +960,7 @@ VIR_ENUM_IMPL(virDomainGraphics,
               "spice",
               "egl-headless",
               "dbus",
+              "gtk",
 );
 
 VIR_ENUM_IMPL(virDomainGraphicsListen,
@@ -2054,6 +2055,12 @@ void virDomainGraphicsDefFree(virDomainGraphicsDef *def)
         g_free(def->data.dbus.rendernode);
         break;
 
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
+        g_free(def->data.gtk.display);
+        g_free(def->data.gtk.xauth);
+        g_free(def->data.gtk.rendernode);
+        break;
+
     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
         break;
     }
@@ -12199,6 +12206,39 @@ virDomainGraphicsDefParseXMLDBus(virDomainGraphicsDef *def,
 }
 
 
+static int
+virDomainGraphicsDefParseXMLGTK(virDomainGraphicsDef *def,
+                                xmlNodePtr node,
+                                xmlXPathContextPtr ctxt)
+{
+    VIR_XPATH_NODE_AUTORESTORE(ctxt)
+    xmlNodePtr glNode;
+    virTristateBool fullscreen;
+
+    ctxt->node = node;
+
+    if (virXMLPropTristateBool(node, "fullscreen", VIR_XML_PROP_NONE,
+                               &fullscreen) < 0)
+        return -1;
+
+    virTristateBoolToBool(fullscreen, &def->data.gtk.fullscreen);
+    def->data.gtk.xauth = virXMLPropString(node, "xauth");
+    def->data.gtk.display = virXMLPropString(node, "display");
+
+    if ((glNode = virXPathNode("./gl", ctxt))) {
+        def->data.gtk.rendernode = virXMLPropString(glNode,
+                                                     "rendernode");
+
+        if (virXMLPropTristateBool(glNode, "enable",
+                                   VIR_XML_PROP_REQUIRED,
+                                   &def->data.gtk.gl) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
 virDomainGraphicsDef *
 virDomainGraphicsDefNew(virDomainXMLOption *xmlopt)
 {
@@ -12275,6 +12315,10 @@ virDomainGraphicsDefParseXML(virDomainXMLOption *xmlopt,
         if (virDomainGraphicsDefParseXMLDBus(def, node, ctxt) < 0)
             goto error;
         break;
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
+        if (virDomainGraphicsDefParseXMLGTK(def, node, ctxt) < 0)
+            goto error;
+        break;
     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
         break;
     }
@@ -27118,6 +27162,23 @@ virDomainGraphicsDefFormatDBus(virBuffer *attrBuf,
     virDomainGraphicsDefFormatAudio(childBuf, def->data.dbus.audioId);
 }
 
+static void
+virDomainGraphicsDefFormatGTK(virBuffer *attrBuf,
+                              virBuffer *childBuf,
+                              virDomainGraphicsDef *def)
+{
+    virBufferEscapeString(attrBuf, " display='%s'", def->data.gtk.display);
+
+    virBufferEscapeString(attrBuf, " xauth='%s'", def->data.gtk.xauth);
+
+    if (def->data.gtk.fullscreen)
+        virBufferAddLit(attrBuf, " fullscreen='yes'");
+
+    virDomainGraphicsDefFormatGL(childBuf, def->data.gtk.gl,
+                                 def->data.gtk.rendernode);
+}
+
+
 static int
 virDomainGraphicsDefFormat(virBuffer *buf,
                            virDomainGraphicsDef *def,
@@ -27166,6 +27227,10 @@ virDomainGraphicsDefFormat(virBuffer *buf,
         virDomainGraphicsDefFormatDBus(&attrBuf, &childBuf, def);
         break;
 
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
+        virDomainGraphicsDefFormatGTK(&attrBuf, &childBuf, def);
+        break;
+
     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
         break;
     }
@@ -31949,6 +32014,11 @@ virDomainGraphicsDefHasOpenGL(const virDomainDef *def)
             if (graphics->data.dbus.gl == VIR_TRISTATE_BOOL_YES)
                 return true;
 
+            continue;
+        case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
+            if (graphics->data.gtk.gl == VIR_TRISTATE_BOOL_YES)
+                return true;
+
             continue;
         case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
             break;
@@ -31966,7 +32036,8 @@ virDomainGraphicsSupportsRenderNode(const virDomainGraphicsDef *graphics)
 
     if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE ||
         graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS ||
-        graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_DBUS)
+        graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_DBUS ||
+        graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_GTK)
         ret = true;
 
     return ret;
@@ -31988,6 +32059,9 @@ virDomainGraphicsGetRenderNode(const virDomainGraphicsDef *graphics)
     case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
         ret = graphics->data.dbus.rendernode;
         break;
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
+        ret = graphics->data.gtk.rendernode;
+        break;
     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
@@ -32012,6 +32086,9 @@ virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef *graphics)
     if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_DBUS &&
         graphics->data.dbus.gl != VIR_TRISTATE_BOOL_YES)
         return false;
+    if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_GTK &&
+        graphics->data.gtk.gl != VIR_TRISTATE_BOOL_YES)
+        return false;
 
     if (virDomainGraphicsGetRenderNode(graphics))
         return false;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 58b97a2b54..f4f06db8a8 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1896,6 +1896,7 @@ typedef enum {
     VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
     VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS,
     VIR_DOMAIN_GRAPHICS_TYPE_DBUS,
+    VIR_DOMAIN_GRAPHICS_TYPE_GTK,
 
     VIR_DOMAIN_GRAPHICS_TYPE_LAST
 } virDomainGraphicsType;
@@ -2083,6 +2084,13 @@ struct _virDomainGraphicsDef {
             unsigned int audioId;
             bool fromConfig;    /* true if the @address is config file originated */
         } dbus;
+        struct {
+            char *display;
+            char *xauth;
+            bool fullscreen;
+            char *rendernode;
+            virTristateBool gl;
+        } gtk;
     } data;
     /* nListens, listens, and *port are only useful if type is vnc,
      * rdp, or spice. They've been extracted from the union only to
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 5597d5a66b..61c1d3ad97 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -4593,6 +4593,34 @@
             </element>
           </optional>
         </group>
+        <group>
+          <attribute name="type">
+            <value>gtk</value>
+          </attribute>
+          <optional>
+            <attribute name="display">
+              <text/>
+            </attribute>
+          </optional>
+          <optional>
+            <attribute name="xauth">
+              <text/>
+            </attribute>
+          </optional>
+          <optional>
+            <attribute name="fullscreen">
+              <ref name="virYesNo"/>
+            </attribute>
+          </optional>
+          <optional>
+            <element name="gl">
+              <attribute name="enable">
+                <ref name="virYesNo"/>
+              </attribute>
+              <empty/>
+            </element>
+          </optional>
+        </group>
       </choice>
     </element>
   </define>
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index a804335c85..de7ce95499 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -732,6 +732,8 @@ VIR_ENUM_IMPL(virQEMUCaps,
 
               /* 475 */
               "virtio-scsi.iothread-mapping", /* QEMU_CAPS_VIRTIO_SCSI_IOTHREAD_MAPPING */
+              "gtk", /* QEMU_CAPS_GTK */
+              "gtk-gl", /* QEMU_CAPS_GTK_GL */
     );
 
 
@@ -1602,6 +1604,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = {
     { "set-numa-node/arg-type/+hmat-lb", QEMU_CAPS_NUMA_HMAT },
     { "query-cpu-model-expansion/ret-type/deprecated-props", QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION_DEPRECATED_PROPS },
     { "migrate-incoming/arg-type/exit-on-error", QEMU_CAPS_MIGRATE_INCOMING_EXIT_ON_ERROR },
+    { "query-display-options/ret-type/type/^gtk", QEMU_CAPS_GTK },
 };
 
 typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps;
@@ -6499,6 +6502,8 @@ virQEMUCapsFillDomainDeviceGraphicsCaps(virQEMUDriverConfig *cfg,
                                      VIR_DOMAIN_GRAPHICS_TYPE_RDP);
         }
     }
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_GTK))
+        VIR_DOMAIN_CAPS_ENUM_SET(dev->type, VIR_DOMAIN_GRAPHICS_TYPE_GTK);
 }
 
 
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index ea7c14daa9..f4ab1a821f 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -713,6 +713,8 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
 
     /* 475 */
     QEMU_CAPS_VIRTIO_SCSI_IOTHREAD_MAPPING, /* virtio-scsi supports per-virtqueue iothread mapping */
+    QEMU_CAPS_GTK, /* support for GTK graphics is compiled into qemu */
+    QEMU_CAPS_GTK_GL, /* support OpenGL for gtk graphics */
 
     QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index e6d308534f..e97992ff56 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8483,6 +8483,34 @@ qemuBuildGraphicsDBusCommandLine(virDomainDef *def,
 }
 
 
+static int
+qemuBuildGraphicsGTKCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED,
+                                virCommand *cmd,
+                                virDomainGraphicsDef *graphics)
+{
+    g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
+
+    if (graphics->data.gtk.xauth)
+        virCommandAddEnvPair(cmd, "XAUTHORITY", graphics->data.gtk.xauth);
+    if (graphics->data.gtk.display)
+        virCommandAddEnvPair(cmd, "DISPLAY", graphics->data.gtk.display);
+    if (graphics->data.gtk.fullscreen)
+        virCommandAddArg(cmd, "-full-screen");
+
+    virCommandAddArg(cmd, "-display");
+    virBufferAddLit(&opt, "gtk");
+
+    if (graphics->data.gtk.gl != VIR_TRISTATE_BOOL_ABSENT)
+        virBufferAsprintf(&opt, ",gl=%s",
+                          virTristateSwitchTypeToString(graphics->data.gtk.gl));
+
+    virCommandAddArgBuffer(cmd, &opt);
+
+    return 0;
+}
+
+
+
 static int
 qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg,
                              virCommand *cmd,
@@ -8523,6 +8551,11 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg,
             if (qemuBuildGraphicsDBusCommandLine(def, cmd, graphics) < 0)
                 return -1;
 
+            break;
+        case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
+            if (qemuBuildGraphicsGTKCommandLine(cfg, cmd, graphics) < 0)
+                return -1;
+
             break;
         case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
             break;
@@ -10076,6 +10109,7 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver,
     int egl_headless = 0;
     int dbus = 0;
     int rdp = 0;
+    int gtk = 0;
 
     if (!driver->privileged) {
         /* If we have no cgroups then we can have no tunings that
@@ -10126,13 +10160,16 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver,
         case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
             ++rdp;
             break;
+        case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
+            ++gtk;
+            break;
         case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
         case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
             break;
         }
     }
 
-    if (sdl > 1 || vnc > 1 || spice > 1 || egl_headless > 1 || dbus > 1 || rdp > 1) {
+    if (sdl > 1 || vnc > 1 || spice > 1 || egl_headless > 1 || dbus > 1 || rdp > 1 || gtk > 1) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("only 1 graphics device of each type (sdl, vnc, spice, headless, dbus, rdp) is supported"));
         return -1;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 52da234343..f96c926424 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -4104,6 +4104,7 @@ qemuDomainDefSuggestDefaultAudioBackend(virQEMUDriver *driver,
         case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
         case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
         case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
+        case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
             break;
         case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
         default:
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a34d6f1437..da22681053 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -14837,6 +14837,7 @@ qemuDomainOpenGraphics(virDomainPtr dom,
     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Can only open VNC, SPICE or D-Bus p2p graphics backends, not %1$s"),
                        virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
@@ -14908,6 +14909,7 @@ qemuDomainOpenGraphicsFD(virDomainPtr dom,
     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Can only open VNC, SPICE or D-Bus p2p graphics backends, not %1$s"),
                        virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index 31c7a14156..f6888acf2f 100644
--- a/src/qemu/qemu_extdevice.c
+++ b/src/qemu/qemu_extdevice.c
@@ -256,6 +256,7 @@ qemuExtDevicesStart(virQEMUDriver *driver,
         case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
         case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
         case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
+        case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
         case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
         default:
             continue;
@@ -339,6 +340,7 @@ qemuExtDevicesStop(virQEMUDriver *driver,
         case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
         case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
         case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
+        case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
         case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
         default:
             continue;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 5326aba281..d67c407309 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4688,6 +4688,7 @@ qemuDomainChangeGraphics(virQEMUDriver *driver,
     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
     case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unable to change config on '%1$s' graphics type"), type);
         break;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1af91c5909..b61240b653 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3005,6 +3005,7 @@ qemuProcessInitPasswords(virQEMUDriver *driver,
                 cfg->rdpUsername, cfg->rdpPassword, asyncJob);
             break;
         case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
+        case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
         case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
         case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
         case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
@@ -5065,6 +5066,7 @@ qemuProcessGraphicsReservePorts(virDomainGraphicsDef *graphics,
     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
     case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
         break;
     }
@@ -5109,6 +5111,7 @@ qemuProcessGraphicsAllocatePorts(virQEMUDriver *driver,
     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
     case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
         break;
     }
@@ -5280,6 +5283,7 @@ qemuProcessGraphicsSetupListen(virQEMUDriver *driver,
     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
     case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
         break;
     }
@@ -5359,6 +5363,9 @@ qemuProcessGraphicsSetupRenderNode(virDomainGraphicsDef *graphics,
     case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
         rendernode = &graphics->data.dbus.rendernode;
         break;
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
+        rendernode = &graphics->data.gtk.rendernode;
+        break;
     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
@@ -5571,6 +5578,7 @@ qemuProcessStartValidateGraphics(virDomainObj *vm)
         case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
         case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
         case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
+        case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
         case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
             break;
         }
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index b2c3c9e2f6..be92785d71 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -4523,6 +4523,17 @@ qemuValidateDomainDeviceDefRDPGraphics(const virDomainGraphicsDef *graphics)
 }
 
 
+static int
+qemuValidateDomainDeviceDefGTKGraphics(const virDomainGraphicsDef *graphics G_GNUC_UNUSED,
+                                       virQEMUCaps *qemuCaps G_GNUC_UNUSED)
+{
+    /* TODO: OpenGL check */
+    /* For now it's not possible to check if gtk-gl capability is available in QEMU */
+    /* Add cappability check later when will be possible to gather the capability from QEMU */
+    return 0;
+}
+
+
 static int
 qemuValidateDomainDeviceDefGraphics(const virDomainGraphicsDef *graphics,
                                     const virDomainDef *def,
@@ -4600,6 +4611,11 @@ qemuValidateDomainDeviceDefGraphics(const virDomainGraphicsDef *graphics,
             return -1;
 
         break;
+    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
+        if (qemuValidateDomainDeviceDefGTKGraphics(graphics, qemuCaps) < 0)
+            return -1;
+
+        break;
 
     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index e3802c18be..d3de4ea4d1 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -1037,6 +1037,12 @@ get_files(vahControl * ctl)
                          "r") != 0)
             goto cleanup;
 
+    if (ctl->def->ngraphics == 1 &&
+        ctl->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_GTK)
+        if (vah_add_file(&buf, ctl->def->graphics[0]->data.gtk.xauth,
+                         "r") != 0)
+            goto cleanup;
+
     for (i = 0; i < ctl->def->nhostdevs; i++)
         if (ctl->def->hostdevs[i]) {
             virDomainHostdevDef *dev = ctl->def->hostdevs[i];
diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
index 0dd03c1a88..74d90ec77a 100644
--- a/src/vmx/vmx.c
+++ b/src/vmx/vmx.c
@@ -3527,6 +3527,7 @@ virVMXFormatConfig(virVMXContext *ctx, virDomainXMLOption *xmlopt, virDomainDef
           case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
           case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
           case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
+          case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("Unsupported graphics type '%1$s'"),
                            virDomainGraphicsTypeToString(def->graphics[i]->type));
diff --git a/tests/domaincapsdata/qemu_10.0.0.s390x.xml b/tests/domaincapsdata/qemu_10.0.0.s390x.xml
index d66240307e..a81db8e950 100644
--- a/tests/domaincapsdata/qemu_10.0.0.s390x.xml
+++ b/tests/domaincapsdata/qemu_10.0.0.s390x.xml
@@ -256,6 +256,7 @@
         <value>rdp</value>
         <value>egl-headless</value>
         <value>dbus</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml
index 52c73d10a4..e840a0e488 100644
--- a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml
+++ b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml
@@ -77,6 +77,7 @@
         <value>sdl</value>
         <value>vnc</value>
         <value>egl-headless</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_7.1.0.ppc64.xml b/tests/domaincapsdata/qemu_7.1.0.ppc64.xml
index ca0bc6f0b5..235e851e86 100644
--- a/tests/domaincapsdata/qemu_7.1.0.ppc64.xml
+++ b/tests/domaincapsdata/qemu_7.1.0.ppc64.xml
@@ -70,6 +70,7 @@
     <graphics supported='yes'>
       <enum name='type'>
         <value>vnc</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_7.2.0.ppc.xml b/tests/domaincapsdata/qemu_7.2.0.ppc.xml
index 21dbe730c5..ae379b863e 100644
--- a/tests/domaincapsdata/qemu_7.2.0.ppc.xml
+++ b/tests/domaincapsdata/qemu_7.2.0.ppc.xml
@@ -69,6 +69,7 @@
         <value>spice</value>
         <value>egl-headless</value>
         <value>dbus</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml b/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml
index 18979cf280..3ac273e119 100644
--- a/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml
+++ b/tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml
@@ -75,6 +75,7 @@
         <value>rdp</value>
         <value>spice</value>
         <value>dbus</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml
index ce17865e24..98346d23d3 100644
--- a/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml
+++ b/tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml
@@ -123,6 +123,7 @@
         <value>rdp</value>
         <value>egl-headless</value>
         <value>dbus</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml b/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml
index 8f4ebbc107..b6d0f4d455 100644
--- a/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml
+++ b/tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml
@@ -79,6 +79,7 @@
         <value>rdp</value>
         <value>spice</value>
         <value>dbus</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml
index ce17865e24..98346d23d3 100644
--- a/tests/domaincapsdata/qemu_8.2.0.aarch64.xml
+++ b/tests/domaincapsdata/qemu_8.2.0.aarch64.xml
@@ -123,6 +123,7 @@
         <value>rdp</value>
         <value>egl-headless</value>
         <value>dbus</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_8.2.0.armv7l.xml b/tests/domaincapsdata/qemu_8.2.0.armv7l.xml
index ee653c0c49..77d90635cd 100644
--- a/tests/domaincapsdata/qemu_8.2.0.armv7l.xml
+++ b/tests/domaincapsdata/qemu_8.2.0.armv7l.xml
@@ -73,6 +73,7 @@
         <value>spice</value>
         <value>egl-headless</value>
         <value>dbus</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_9.0.0.sparc.xml b/tests/domaincapsdata/qemu_9.0.0.sparc.xml
index c7862f5842..396b40e221 100644
--- a/tests/domaincapsdata/qemu_9.0.0.sparc.xml
+++ b/tests/domaincapsdata/qemu_9.0.0.sparc.xml
@@ -64,6 +64,7 @@
         <value>spice</value>
         <value>egl-headless</value>
         <value>dbus</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_9.1.0.s390x.xml b/tests/domaincapsdata/qemu_9.1.0.s390x.xml
index b73e0d0688..e6345ebffb 100644
--- a/tests/domaincapsdata/qemu_9.1.0.s390x.xml
+++ b/tests/domaincapsdata/qemu_9.1.0.s390x.xml
@@ -208,6 +208,7 @@
         <value>rdp</value>
         <value>egl-headless</value>
         <value>dbus</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/domaincapsdata/qemu_9.2.0.s390x.xml b/tests/domaincapsdata/qemu_9.2.0.s390x.xml
index 605a3af5c7..3dac7c0462 100644
--- a/tests/domaincapsdata/qemu_9.2.0.s390x.xml
+++ b/tests/domaincapsdata/qemu_9.2.0.s390x.xml
@@ -208,6 +208,7 @@
         <value>rdp</value>
         <value>egl-headless</value>
         <value>dbus</value>
+        <value>gtk</value>
       </enum>
     </graphics>
     <video supported='yes'>
diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml b/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml
index be2e91ed92..078f5cea12 100644
--- a/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml
@@ -133,6 +133,7 @@
   <flag name='migrate-incoming.exit-on-error'/>
   <flag name='virtio-mem-ccw'/>
   <flag name='shim'/>
+  <flag name='gtk'/>
   <version>9002050</version>
   <microcodeVersion>39100285</microcodeVersion>
   <package>v9.2.0-1203-gd6430c17d7</package>
diff --git a/tests/qemucapabilitiesdata/caps_7.0.0_ppc64.xml b/tests/qemucapabilitiesdata/caps_7.0.0_ppc64.xml
index d78c239372..6dc012bcff 100644
--- a/tests/qemucapabilitiesdata/caps_7.0.0_ppc64.xml
+++ b/tests/qemucapabilitiesdata/caps_7.0.0_ppc64.xml
@@ -149,6 +149,7 @@
   <flag name='usb-mtp'/>
   <flag name='netdev.user'/>
   <flag name='acpi-erst'/>
+  <flag name='gtk'/>
   <version>7000000</version>
   <microcodeVersion>42900243</microcodeVersion>
   <package>v7.0.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_7.1.0_ppc64.xml b/tests/qemucapabilitiesdata/caps_7.1.0_ppc64.xml
index d6edb65e96..97728e0141 100644
--- a/tests/qemucapabilitiesdata/caps_7.1.0_ppc64.xml
+++ b/tests/qemucapabilitiesdata/caps_7.1.0_ppc64.xml
@@ -150,6 +150,7 @@
   <flag name='usb-mtp'/>
   <flag name='netdev.user'/>
   <flag name='acpi-erst'/>
+  <flag name='gtk'/>
   <version>7001000</version>
   <microcodeVersion>42900244</microcodeVersion>
   <package>v7.1.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml b/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml
index fe318e0a52..bf9a38e123 100644
--- a/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml
+++ b/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml
@@ -145,6 +145,7 @@
   <flag name='usb-mtp'/>
   <flag name='netdev.user'/>
   <flag name='acpi-erst'/>
+  <flag name='gtk'/>
   <version>7002000</version>
   <microcodeVersion>0</microcodeVersion>
   <package>qemu-7.2.0-6.fc37</package>
diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml
index 837502c336..d21b2cfddb 100644
--- a/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml
@@ -160,6 +160,7 @@
   <flag name='virtio-sound'/>
   <flag name='netdev.user'/>
   <flag name='acpi-erst'/>
+  <flag name='gtk'/>
   <version>8002000</version>
   <microcodeVersion>61700246</microcodeVersion>
   <package>v8.2.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml b/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml
index f062f31abc..14013d1c1e 100644
--- a/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml
+++ b/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml
@@ -167,6 +167,7 @@
   <flag name='virtio-sound'/>
   <flag name='netdev.user'/>
   <flag name='acpi-erst'/>
+  <flag name='gtk'/>
   <version>8002000</version>
   <microcodeVersion>0</microcodeVersion>
   <package>qemu-8.2.0-7.fc39</package>
diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml b/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml
index 2a37631381..37e8dbe371 100644
--- a/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml
@@ -150,6 +150,7 @@
   <flag name='virtio-sound'/>
   <flag name='netdev.user'/>
   <flag name='acpi-erst'/>
+  <flag name='gtk'/>
   <version>8002000</version>
   <microcodeVersion>106300246</microcodeVersion>
   <package>v8.2.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml b/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml
index 38835ba0cb..703ec9a5a8 100644
--- a/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml
+++ b/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml
@@ -70,6 +70,7 @@
   <flag name='blockjob.backing-mask-protocol'/>
   <flag name='display-reload'/>
   <flag name='netdev.user'/>
+  <flag name='gtk'/>
   <version>9000000</version>
   <microcodeVersion>0</microcodeVersion>
   <package>qemu-9.0.0-1.fc40</package>
diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml
index 0d566d13d5..d046779f9a 100644
--- a/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml
@@ -125,6 +125,7 @@
   <flag name='netdev.user'/>
   <flag name='query-cpu-model-expansion.deprecated-props'/>
   <flag name='migrate-incoming.exit-on-error'/>
+  <flag name='gtk'/>
   <version>9001000</version>
   <microcodeVersion>39100246</microcodeVersion>
   <package>v9.1.0</package>
diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml b/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml
index e1323f9b72..9b201aca19 100644
--- a/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml
@@ -128,6 +128,7 @@
   <flag name='netdev-stream-reconnect-miliseconds'/>
   <flag name='query-cpu-model-expansion.deprecated-props'/>
   <flag name='migrate-incoming.exit-on-error'/>
+  <flag name='gtk'/>
   <version>9002000</version>
   <microcodeVersion>39100247</microcodeVersion>
   <package>v9.2.0</package>
-- 
2.49.0
Re: [PATCH] qemu: Add GTK display with OpenGL support
Posted by Peter Krempa via Devel 7 months, 3 weeks ago
On Mon, Apr 28, 2025 at 12:22:22 +0200, Kirill Shchetiniuk via Devel wrote:
> From: Kirill Shchetiniuk <kshcheti@redhat.com>
> 
> Introduce GTK display support with OpenGL for the QEMU driver.
> 
>  - Add new XML options for GTK display type.
>  - Include capability flags for the QEMU driver.
> 
> Note: The `QEMU_CAPS_GTK_GL` flag cannot yet be checked, so device
> definition validation is incomplete. A placeholder is left for
> future implementation, when the GTK along with OpenGL capability
> check would be available in QEMU.
> 
> Resolves: https://gitlab.com/libvirt/libvirt/-/issues/570
> 
> Signed-off-by: Kirill Shchetiniuk <kshcheti@redhat.com>
> ---

[...]

> diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
> index 5597d5a66b..61c1d3ad97 100644
> --- a/src/conf/schemas/domaincommon.rng
> +++ b/src/conf/schemas/domaincommon.rng
> @@ -4593,6 +4593,34 @@
>              </element>
>            </optional>
>          </group>
> +        <group>
> +          <attribute name="type">
> +            <value>gtk</value>
> +          </attribute>
> +          <optional>
> +            <attribute name="display">
> +              <text/>
> +            </attribute>
> +          </optional>
> +          <optional>
> +            <attribute name="xauth">
> +              <text/>

Since this is a path you want to use:

 <ref name="absFilePath"/>


> +            </attribute>
> +          </optional>
> +          <optional>

[...]

> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index e6d308534f..e97992ff56 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -8483,6 +8483,34 @@ qemuBuildGraphicsDBusCommandLine(virDomainDef *def,
>  }
>  
>  
> +static int
> +qemuBuildGraphicsGTKCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED,

Why are you passing this argument if it's not used?

> +                                virCommand *cmd,
> +                                virDomainGraphicsDef *graphics)
> +{
> +    g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
> +
> +    if (graphics->data.gtk.xauth)
> +        virCommandAddEnvPair(cmd, "XAUTHORITY", graphics->data.gtk.xauth);

I also realized that this is passin the path to the '.Xauthority' file
to the qemu process. Note that in the default privileged configuration
where qemu runs as a different process this will not work as the qemu
process will not have access to the cookie inside the file due to
permissions.

Also you can't simply apply security labelling on that file because it
would break other things.

I don't have a suggestion how to fix this, besides perhaps copying the
authority file at startup somewhere for the qemu process to be able to
access it.

Either way in the current state it will require mentioning this caveat.
Re: [PATCH] qemu: Add GTK display with OpenGL support
Posted by Kirill Shchetiniuk via Devel 7 months, 3 weeks ago
On Mon, Apr 28, 2025 at 02:40:49PM +0200, Peter Krempa wrote:
> On Mon, Apr 28, 2025 at 12:22:22 +0200, Kirill Shchetiniuk via Devel wrote:
> > From: Kirill Shchetiniuk <kshcheti@redhat.com>
> >
> > Introduce GTK display support with OpenGL for the QEMU driver.
> >
> >  - Add new XML options for GTK display type.
> >  - Include capability flags for the QEMU driver.
> >
> > Note: The `QEMU_CAPS_GTK_GL` flag cannot yet be checked, so device
> > definition validation is incomplete. A placeholder is left for
> > future implementation, when the GTK along with OpenGL capability
> > check would be available in QEMU.
> >
> > Resolves: https://gitlab.com/libvirt/libvirt/-/issues/570
> >
> > Signed-off-by: Kirill Shchetiniuk <kshcheti@redhat.com>
> > ---
>
> [...]
>
> > diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
> > index 5597d5a66b..61c1d3ad97 100644
> > --- a/src/conf/schemas/domaincommon.rng
> > +++ b/src/conf/schemas/domaincommon.rng
> > @@ -4593,6 +4593,34 @@
> >              </element>
> >            </optional>
> >          </group>
> > +        <group>
> > +          <attribute name="type">
> > +            <value>gtk</value>
> > +          </attribute>
> > +          <optional>
> > +            <attribute name="display">
> > +              <text/>
> > +            </attribute>
> > +          </optional>
> > +          <optional>
> > +            <attribute name="xauth">
> > +              <text/>
>
> Since this is a path you want to use:
>
>  <ref name="absFilePath"/>
>

Will fix it with next series, also saw the <text/> approach for xauth in SDL
device schema, will fix it there too later with separate patch, to maintain
it consistent.

>
> > +            </attribute>
> > +          </optional>
> > +          <optional>
>
> [...]
>
> > diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> > index e6d308534f..e97992ff56 100644
> > --- a/src/qemu/qemu_command.c
> > +++ b/src/qemu/qemu_command.c
> > @@ -8483,6 +8483,34 @@ qemuBuildGraphicsDBusCommandLine(virDomainDef *def,
> >  }
> >
> >
> > +static int
> > +qemuBuildGraphicsGTKCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED,
>
> Why are you passing this argument if it's not used?
>
> > +                                virCommand *cmd,
> > +                                virDomainGraphicsDef *graphics)
> > +{
> > +    g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
> > +
> > +    if (graphics->data.gtk.xauth)
> > +        virCommandAddEnvPair(cmd, "XAUTHORITY", graphics->data.gtk.xauth);
>
> I also realized that this is passin the path to the '.Xauthority' file
> to the qemu process. Note that in the default privileged configuration
> where qemu runs as a different process this will not work as the qemu
> process will not have access to the cookie inside the file due to
> permissions.
>
> Also you can't simply apply security labelling on that file because it
> would break other things.
>
> I don't have a suggestion how to fix this, besides perhaps copying the
> authority file at startup somewhere for the qemu process to be able to
> access it.
>
> Either way in the current state it will require mentioning this caveat.
>
>

Yeah, I already noticed that issue with access to xauth file. I generaly
thought to make an `xauth` attribute mandatory to force the user to create
a readable file with cookie for qemu user, but not sure if it's a good
approach.
Re: [PATCH] qemu: Add GTK display with OpenGL support
Posted by Peter Krempa via Devel 7 months, 3 weeks ago
On Mon, Apr 28, 2025 at 12:22:22 +0200, Kirill Shchetiniuk via Devel wrote:
> From: Kirill Shchetiniuk <kshcheti@redhat.com>
> 
> Introduce GTK display support with OpenGL for the QEMU driver.
> 
>  - Add new XML options for GTK display type.
>  - Include capability flags for the QEMU driver.
> 
> Note: The `QEMU_CAPS_GTK_GL` flag cannot yet be checked, so device
> definition validation is incomplete. A placeholder is left for
> future implementation, when the GTK along with OpenGL capability
> check would be available in QEMU.

Can you elaborate? WHy can't it be checked?

> Resolves: https://gitlab.com/libvirt/libvirt/-/issues/570
> 
> Signed-off-by: Kirill Shchetiniuk <kshcheti@redhat.com>
> ---

You will need to split this patch.

At least the capability flag needs to be a separate commit that only
adds the capability flag.

I'm also missing qemuxmlconftest test cases and docs/formatdomain.rst
documentation changes.


[...]

>  36 files changed, 218 insertions(+), 2 deletions(-)
> 
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 542d6ade91..73550f7fcf 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -960,6 +960,7 @@ VIR_ENUM_IMPL(virDomainGraphics,
>                "spice",
>                "egl-headless",
>                "dbus",
> +              "gtk",
>  );
>  
>  VIR_ENUM_IMPL(virDomainGraphicsListen,
> @@ -2054,6 +2055,12 @@ void virDomainGraphicsDefFree(virDomainGraphicsDef *def)
>          g_free(def->data.dbus.rendernode);
>          break;
>  
> +    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
> +        g_free(def->data.gtk.display);
> +        g_free(def->data.gtk.xauth);
> +        g_free(def->data.gtk.rendernode);
> +        break;
> +
>      case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
>          break;
>      }
> @@ -12199,6 +12206,39 @@ virDomainGraphicsDefParseXMLDBus(virDomainGraphicsDef *def,
>  }
>  
>  
> +static int
> +virDomainGraphicsDefParseXMLGTK(virDomainGraphicsDef *def,
> +                                xmlNodePtr node,
> +                                xmlXPathContextPtr ctxt)
> +{
> +    VIR_XPATH_NODE_AUTORESTORE(ctxt)
> +    xmlNodePtr glNode;
> +    virTristateBool fullscreen;
> +
> +    ctxt->node = node;
> +
> +    if (virXMLPropTristateBool(node, "fullscreen", VIR_XML_PROP_NONE,
> +                               &fullscreen) < 0)

You parse a tristate ...

> +        return -1;
> +
> +    virTristateBoolToBool(fullscreen, &def->data.gtk.fullscreen);

... but store it only as boolean?

> +    def->data.gtk.xauth = virXMLPropString(node, "xauth");
> +    def->data.gtk.display = virXMLPropString(node, "display");
> +
> +    if ((glNode = virXPathNode("./gl", ctxt))) {
> +        def->data.gtk.rendernode = virXMLPropString(glNode,
> +                                                     "rendernode");
> +
> +        if (virXMLPropTristateBool(glNode, "enable",
> +                                   VIR_XML_PROP_REQUIRED,
> +                                   &def->data.gtk.gl) < 0)
> +            return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +
>  virDomainGraphicsDef *
>  virDomainGraphicsDefNew(virDomainXMLOption *xmlopt)
>  {

[...]

> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
> index a804335c85..de7ce95499 100644
> --- a/src/qemu/qemu_capabilities.c
> +++ b/src/qemu/qemu_capabilities.c
> @@ -732,6 +732,8 @@ VIR_ENUM_IMPL(virQEMUCaps,
>  
>                /* 475 */
>                "virtio-scsi.iothread-mapping", /* QEMU_CAPS_VIRTIO_SCSI_IOTHREAD_MAPPING */
> +              "gtk", /* QEMU_CAPS_GTK */
> +              "gtk-gl", /* QEMU_CAPS_GTK_GL */
>      );
>  
>  
> @@ -1602,6 +1604,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = {
>      { "set-numa-node/arg-type/+hmat-lb", QEMU_CAPS_NUMA_HMAT },
>      { "query-cpu-model-expansion/ret-type/deprecated-props", QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION_DEPRECATED_PROPS },
>      { "migrate-incoming/arg-type/exit-on-error", QEMU_CAPS_MIGRATE_INCOMING_EXIT_ON_ERROR },
> +    { "query-display-options/ret-type/type/^gtk", QEMU_CAPS_GTK },
>  };
>  
>  typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps;
> @@ -6499,6 +6502,8 @@ virQEMUCapsFillDomainDeviceGraphicsCaps(virQEMUDriverConfig *cfg,
>                                       VIR_DOMAIN_GRAPHICS_TYPE_RDP);
>          }
>      }
> +    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_GTK))
> +        VIR_DOMAIN_CAPS_ENUM_SET(dev->type, VIR_DOMAIN_GRAPHICS_TYPE_GTK);
>  }
>  
>  

[...]

> diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
> index b2c3c9e2f6..be92785d71 100644
> --- a/src/qemu/qemu_validate.c
> +++ b/src/qemu/qemu_validate.c
> @@ -4523,6 +4523,17 @@ qemuValidateDomainDeviceDefRDPGraphics(const virDomainGraphicsDef *graphics)
>  }
>  
>  
> +static int
> +qemuValidateDomainDeviceDefGTKGraphics(const virDomainGraphicsDef *graphics G_GNUC_UNUSED,
> +                                       virQEMUCaps *qemuCaps G_GNUC_UNUSED)
> +{
> +    /* TODO: OpenGL check */
> +    /* For now it's not possible to check if gtk-gl capability is available in QEMU */
> +    /* Add cappability check later when will be possible to gather the capability from QEMU */

So why does the patch add the capability then? Or is this comment no
longer applicable?

> +    return 0;
> +}
> +
> +
>  static int
>  qemuValidateDomainDeviceDefGraphics(const virDomainGraphicsDef *graphics,
>                                      const virDomainDef *def,
Re: [PATCH] qemu: Add GTK display with OpenGL support
Posted by Kirill Shchetiniuk via Devel 7 months, 3 weeks ago
On Mon, Apr 28, 2025 at 12:33:19PM +0200, Peter Krempa wrote:
> On Mon, Apr 28, 2025 at 12:22:22 +0200, Kirill Shchetiniuk via Devel wrote:
> > From: Kirill Shchetiniuk <kshcheti@redhat.com>
> >
> > Introduce GTK display support with OpenGL for the QEMU driver.
> >
> >  - Add new XML options for GTK display type.
> >  - Include capability flags for the QEMU driver.
> >
> > Note: The `QEMU_CAPS_GTK_GL` flag cannot yet be checked, so device
> > definition validation is incomplete. A placeholder is left for
> > future implementation, when the GTK along with OpenGL capability
> > check would be available in QEMU.
>
> Can you elaborate? WHy can't it be checked?


So I have discussed this with Michal Privoznik, it's possible to
directly gather if GTK capability is enable, but there is now
straight way to check if OpenGL for GTK is enabled too. Michal
purposed a way to check this with a small hack, check if GTK
capability is presented along with egl-headless, but we decided
better not to check OpenGL for GTK cabability for now, as it's not
straightforward approch, and I decided to leave a placeholer
for the future check to do not forget to add this later.

>
> > Resolves: https://gitlab.com/libvirt/libvirt/-/issues/570
> >
> > Signed-off-by: Kirill Shchetiniuk <kshcheti@redhat.com>
> > ---
>
> You will need to split this patch.
>
> At least the capability flag needs to be a separate commit that only
> adds the capability flag.
>
> I'm also missing qemuxmlconftest test cases and docs/formatdomain.rst
> documentation changes.
>

Sure, will this with next series, thanks!

>
> [...]
>
> >  36 files changed, 218 insertions(+), 2 deletions(-)
> >
> > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> > index 542d6ade91..73550f7fcf 100644
> > --- a/src/conf/domain_conf.c
> > +++ b/src/conf/domain_conf.c
> > @@ -960,6 +960,7 @@ VIR_ENUM_IMPL(virDomainGraphics,
> >                "spice",
> >                "egl-headless",
> >                "dbus",
> > +              "gtk",
> >  );
> >
> >  VIR_ENUM_IMPL(virDomainGraphicsListen,
> > @@ -2054,6 +2055,12 @@ void virDomainGraphicsDefFree(virDomainGraphicsDef *def)
> >          g_free(def->data.dbus.rendernode);
> >          break;
> >
> > +    case VIR_DOMAIN_GRAPHICS_TYPE_GTK:
> > +        g_free(def->data.gtk.display);
> > +        g_free(def->data.gtk.xauth);
> > +        g_free(def->data.gtk.rendernode);
> > +        break;
> > +
> >      case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
> >          break;
> >      }
> > @@ -12199,6 +12206,39 @@ virDomainGraphicsDefParseXMLDBus(virDomainGraphicsDef *def,
> >  }
> >
> >
> > +static int
> > +virDomainGraphicsDefParseXMLGTK(virDomainGraphicsDef *def,
> > +                                xmlNodePtr node,
> > +                                xmlXPathContextPtr ctxt)
> > +{
> > +    VIR_XPATH_NODE_AUTORESTORE(ctxt)
> > +    xmlNodePtr glNode;
> > +    virTristateBool fullscreen;
> > +
> > +    ctxt->node = node;
> > +
> > +    if (virXMLPropTristateBool(node, "fullscreen", VIR_XML_PROP_NONE,
> > +                               &fullscreen) < 0)
>
> You parse a tristate ...
>
> > +        return -1;
> > +
> > +    virTristateBoolToBool(fullscreen, &def->data.gtk.fullscreen);
>
> ... but store it only as boolean?

So I saw the same approach in virDomainGraphicsDefParseXMLSDL and decided to
use it too. Do you suggest virXPathBoolean instead or something else?

>
> > +    def->data.gtk.xauth = virXMLPropString(node, "xauth");
> > +    def->data.gtk.display = virXMLPropString(node, "display");
> > +
> > +    if ((glNode = virXPathNode("./gl", ctxt))) {
> > +        def->data.gtk.rendernode = virXMLPropString(glNode,
> > +                                                     "rendernode");
> > +
> > +        if (virXMLPropTristateBool(glNode, "enable",
> > +                                   VIR_XML_PROP_REQUIRED,
> > +                                   &def->data.gtk.gl) < 0)
> > +            return -1;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +
> >  virDomainGraphicsDef *
> >  virDomainGraphicsDefNew(virDomainXMLOption *xmlopt)
> >  {
>
> [...]
>
> > diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
> > index a804335c85..de7ce95499 100644
> > --- a/src/qemu/qemu_capabilities.c
> > +++ b/src/qemu/qemu_capabilities.c
> > @@ -732,6 +732,8 @@ VIR_ENUM_IMPL(virQEMUCaps,
> >
> >                /* 475 */
> >                "virtio-scsi.iothread-mapping", /* QEMU_CAPS_VIRTIO_SCSI_IOTHREAD_MAPPING */
> > +              "gtk", /* QEMU_CAPS_GTK */
> > +              "gtk-gl", /* QEMU_CAPS_GTK_GL */
> >      );
> >
> >
> > @@ -1602,6 +1604,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = {
> >      { "set-numa-node/arg-type/+hmat-lb", QEMU_CAPS_NUMA_HMAT },
> >      { "query-cpu-model-expansion/ret-type/deprecated-props", QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION_DEPRECATED_PROPS },
> >      { "migrate-incoming/arg-type/exit-on-error", QEMU_CAPS_MIGRATE_INCOMING_EXIT_ON_ERROR },
> > +    { "query-display-options/ret-type/type/^gtk", QEMU_CAPS_GTK },
> >  };
> >
> >  typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps;
> > @@ -6499,6 +6502,8 @@ virQEMUCapsFillDomainDeviceGraphicsCaps(virQEMUDriverConfig *cfg,
> >                                       VIR_DOMAIN_GRAPHICS_TYPE_RDP);
> >          }
> >      }
> > +    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_GTK))
> > +        VIR_DOMAIN_CAPS_ENUM_SET(dev->type, VIR_DOMAIN_GRAPHICS_TYPE_GTK);
> >  }
> >
> >
>
> [...]
>
> > diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
> > index b2c3c9e2f6..be92785d71 100644
> > --- a/src/qemu/qemu_validate.c
> > +++ b/src/qemu/qemu_validate.c
> > @@ -4523,6 +4523,17 @@ qemuValidateDomainDeviceDefRDPGraphics(const virDomainGraphicsDef *graphics)
> >  }
> >
> >
> > +static int
> > +qemuValidateDomainDeviceDefGTKGraphics(const virDomainGraphicsDef *graphics G_GNUC_UNUSED,
> > +                                       virQEMUCaps *qemuCaps G_GNUC_UNUSED)
> > +{
> > +    /* TODO: OpenGL check */
> > +    /* For now it's not possible to check if gtk-gl capability is available in QEMU */
> > +    /* Add cappability check later when will be possible to gather the capability from QEMU */
>
> So why does the patch add the capability then? Or is this comment no
> longer applicable?
>

So I didn't know how to do it better, decided to leave a placeholder for future changes.
With next series will remove the yet unused gtk-gl capability, and leave the placeholder
only.

>
> > +    return 0;
> > +}
> > +
> > +
> >  static int
> >  qemuValidateDomainDeviceDefGraphics(const virDomainGraphicsDef *graphics,
> >                                      const virDomainDef *def,
>
Re: [PATCH] qemu: Add GTK display with OpenGL support
Posted by Peter Krempa via Devel 7 months, 3 weeks ago
On Mon, Apr 28, 2025 at 12:33:19 +0200, Peter Krempa via Devel wrote:
> On Mon, Apr 28, 2025 at 12:22:22 +0200, Kirill Shchetiniuk via Devel wrote:
> > From: Kirill Shchetiniuk <kshcheti@redhat.com>
> > 
> > Introduce GTK display support with OpenGL for the QEMU driver.
> > 
> >  - Add new XML options for GTK display type.
> >  - Include capability flags for the QEMU driver.
> > 
> > Note: The `QEMU_CAPS_GTK_GL` flag cannot yet be checked, so device
> > definition validation is incomplete. A placeholder is left for
> > future implementation, when the GTK along with OpenGL capability
> > check would be available in QEMU.
> 
> Can you elaborate? WHy can't it be checked?

Since the 'gtk' backend in support was introduced predating qemu-2.12.
I'm guessing what's happening is that you tried to use
DO_TEST_CAPS_LATEST which failed.

For the above the solution is not to ignore the check but rather one of:

1) update the 'x86_64' test data with a qemu built with gtk support
2) add a variant of the test data from a qemu built with gtk support
3) use DO_TEST_FULL and ARG_FLAGS to add the capability for the test
file
4) base the tesst on one of the other arches which were built wit gtk

Since I'm the one maintaining the capability dumps, maitaining a variant
for this is overkill; adding it to the main build is possible (I can
send the update).

I was historically building qemu with '--disable-gtk' as it mirrored
what fedora was doing but it seems that GTK is enabled in the current
fedora build.

Option 3) is acceptable for a niche feature and option 4) can
theoretically regress in the future.
Re: [PATCH] qemu: Add GTK display with OpenGL support
Posted by Peter Krempa via Devel 7 months, 3 weeks ago
On Mon, Apr 28, 2025 at 12:57:42 +0200, Peter Krempa via Devel wrote:
> On Mon, Apr 28, 2025 at 12:33:19 +0200, Peter Krempa via Devel wrote:
> > On Mon, Apr 28, 2025 at 12:22:22 +0200, Kirill Shchetiniuk via Devel wrote:

[...]

> Since the 'gtk' backend in support was introduced predating qemu-2.12.
> I'm guessing what's happening is that you tried to use
> DO_TEST_CAPS_LATEST which failed.
> 
> For the above the solution is not to ignore the check but rather one of:
> 
> 1) update the 'x86_64' test data with a qemu built with gtk support

[...]

> Since I'm the one maintaining the capability dumps, maitaining a variant
> for this is overkill; adding it to the main build is possible (I can
> send the update).

Update of the test data adding GTK support:

https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/5LQ7AYCWWMT5PTETUV4CEKLKA5XCQOLS/