On 06/27/2018 09:34 AM, Erik Skultety wrote:
Since QEMU 2.10, there's a new cmdline option '-display
egl-headless'
which enables OpenGL support for cases where we can't render on a local
display (i.e. <listen> is set to either 'address' or 'network').
This is to work around the current restriction on the local node with
native OpenGL SPICE support. However, compared to native support,
egl-headless has overhead, because the rendered framebuffer has to be
copied back to QEMU's display area which is then accessed by either
SPICE or VNC and sent to the remote side.
blank line for readability
This patch enables this configuration feature by introducing a new
SPICE-only attribute 'native' which helps libvirt to determine whether
to use '-spice gl=on' or '-display egl-headless' on the cmdline. If the
attribute wasn't specified but OpenGL is to be enabled, then given the
nature of the <listen> element, libvirt will determine the default
value.
Signed-off-by: Erik Skultety <eskultet(a)redhat.com>
---
docs/formatdomain.html.in | 8 ++++
docs/schemas/domaincommon.rng | 16 +++++--
src/conf/domain_conf.c | 49 ++++++++++++++++++++--
src/conf/domain_conf.h | 1 +
src/qemu/qemu_command.c | 43 ++++++++++++-------
.../qemuxml2argvdata/graphics-spice-gl-native.args | 26 ++++++++++++
.../qemuxml2argvdata/graphics-spice-gl-native.xml | 25 +++++++++++
.../graphics-spice-gl-non-native.args | 27 ++++++++++++
.../graphics-spice-gl-non-native.xml | 24 +++++++++++
tests/qemuxml2argvtest.c | 8 ++++
.../video-virtio-gpu-spice-gl.xml | 2 +-
11 files changed, 206 insertions(+), 23 deletions(-)
create mode 100644 tests/qemuxml2argvdata/graphics-spice-gl-native.args
create mode 100644 tests/qemuxml2argvdata/graphics-spice-gl-native.xml
create mode 100644 tests/qemuxml2argvdata/graphics-spice-gl-non-native.args
create mode 100644 tests/qemuxml2argvdata/graphics-spice-gl-non-native.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index aa0d6b26df..c6ebd39bd9 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -6461,6 +6461,14 @@ qemu-kvm -net nic,model=? /dev/null
You can enable or disable OpenGL support explicitly with
the <code>gl</code> element, by setting the
<code>enable</code>
property. (QEMU only, <span class="since">since
1.3.3</span>).
+ Additionally, attribute <code>native</code>
+ (<span class="since">Since 4.6.0</span>) can be used
to specify
+ whether native OpenGL support should be used with SPICE or
+ egl-headless should be used instead. Note that the native OpenGL
+ support is only limited to the local setup
(<code>listen</code> is
+ either 'none' or 'socket') and for remote access
egl-headless
+ needs to be used. The supported values for this attribute are
'on'
+ and 'off'.
</p>
<p>
By default, QEMU will pick the first available GPU DRM render node.
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 20649c5f6f..4ad53d976b 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3066,6 +3066,11 @@
<attribute name="enable">
<ref name="virYesNo"/>
</attribute>
+ <optional>
+ <attribute name="native">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
<empty/>
</element>
</optional>
@@ -3322,9 +3327,14 @@
<ref name="absFilePath"/>
</attribute>
</optional>
- <empty/>
- </element>
- </optional>
+ <optional>
+ <attribute name="native">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
+ <empty/>
+ </element>
+ </optional>
</interleave>
</group>
<group>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2ccd9e124f..6d399a198e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4280,6 +4280,7 @@ virDomainDefPostParseGraphics(virDomainDef *def)
* same. */
if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
virDomainGraphicsListenDefPtr glisten = &graphics->listens[0];
+ virDomainGraphicsGLDefPtr gl = graphics->gl;
if (glisten->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS &&
graphics->data.spice.port == 0 &&
@@ -4288,6 +4289,28 @@ virDomainDefPostParseGraphics(virDomainDef *def)
VIR_FREE(glisten->address);
glisten->type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE;
}
+
+ /* Next we need to figure out how to properly configure the OpenGL
+ * if that is enabled and the 'native' attribute is missing.
+ * The cases are:
+ * 1) Listen type is either 'socket' or 'none' - SPICE
native
+ * OpenGL support (,gl=on) should be used because we're
+ * rendering on a local display.
+ *
+ * 2) Listen is either network or address - SPICE can't use
+ * the native OpenGL support remotely yet, so we use
+ * native='no' and format '-display egl-headless' onto
the
+ * cmdline.
+ */
+ if (graphics->gl &&
+ graphics->gl->enable == VIR_TRISTATE_BOOL_YES &&
+ graphics->gl->native == VIR_TRISTATE_BOOL_ABSENT) {
+ gl->native = VIR_TRISTATE_BOOL_NO;
+
+ if (glisten->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE ||
+ glisten->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET)
+ gl->native = VIR_TRISTATE_BOOL_YES;
+ }
So the upside/downside to setting something in the XML that wasn't
previously set by the consumer is that "we're stuck with it" going
forward, right? Additionally, we cannot ascertain whether we set native
to NO or YES or if the consumer did.
So the "other" side of this is this is being done in a domain_conf
function instead of some qemu device post parse function since if I'm
reading the RFC comments right, the desire is not to somehow
automagically add it, but rather force some usage.
Still, I wonder if what's been done follows the spirit of Gerd's comment:
"Hmm, I think it would be better to have egl-headless explicitly
configured in the domain xml instead of doing it automagically depending
on configuration."
could be turned into a "headless='yes|no|absent'" instead of native and
described as being necessary for specific conditions. Then perhaps a
qemu domain validation check to "force" the issue.
}
}
}
@@ -13573,6 +13596,7 @@ virDomainGraphicsGLDefParseXML(virDomainGraphicsDefPtr def,
{
virDomainGraphicsGLDefPtr gl = NULL;
char *enable = NULL;
+ char *native = NULL;
int ret = -1;
if (!node)
@@ -13596,14 +13620,26 @@ virDomainGraphicsGLDefParseXML(virDomainGraphicsDefPtr def,
goto cleanup;
}
- if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
- gl->rendernode = virXMLPropString(node, "rendernode");
+ /* SPICE recognizes a few more attributes */
+ if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+ gl->rendernode = virXMLPropString(node, "rendernode");
+
+ native = virXMLPropString(node, "native");
+ if (native &&
+ (gl->native = virTristateBoolTypeFromString(native)) <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown value for attribute enable
'%s'"),
+ enable);
I believe you wanted "s/enable/native" for 2 instances, copy pasta error
+ goto cleanup;
+ }
+ }
VIR_STEAL_PTR(def->gl, gl);
ret = 0;
cleanup:
VIR_FREE(enable);
+ VIR_FREE(native);
virDomainGraphicsGLDefFree(gl);
return ret;
}
@@ -26184,8 +26220,13 @@ virDomainGraphicsGLDefFormat(virBufferPtr buf,
virDomainGraphicsDefPtr def)
virBufferAsprintf(buf, "<gl enable='%s'",
virTristateBoolTypeToString(gl->enable));
- if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
- virBufferEscapeString(buf, " rendernode='%s'",
gl->rendernode);
+ if (gl->enable == VIR_TRISTATE_BOOL_YES) {
Not clear why the YES guard was put in place. Not that "enable=no and
rendernode=xxx" means anything, but that would be dropped with this change.
Since rng/grammar using interleave, order of attributes shouldn't matter
should it?
+ if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+ virBufferAsprintf(buf, " native='%s'",
+ virTristateBoolTypeToString(gl->native));
+ virBufferEscapeString(buf, " rendernode='%s'",
gl->rendernode);
+ }
+ }
virBufferAddLit(buf, "/>\n");
}
Do you think we need ABI checks for this? Could be challenging given the
post parse setting of the value.
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 20dc1334c4..99b5896391 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1602,6 +1602,7 @@ typedef struct _virDomainGraphicsGLDef virDomainGraphicsGLDef;
typedef virDomainGraphicsGLDef *virDomainGraphicsGLDefPtr;
struct _virDomainGraphicsGLDef {
virTristateBool enable;
+ virTristateBool native; /* -spice gl=on vs -display egl-headless for QEMU */
char *rendernode; /* SPICE only */
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 89a8408df6..fc80a6c3a6 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7896,27 +7896,39 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg,
static int
qemuBuildGraphicsSPICEGLCommandLine(virDomainGraphicsGLDefPtr gl,
+ virCommandPtr cmd,
virBufferPtr opt,
virQEMUCapsPtr qemuCaps)
{
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_GL)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("This QEMU doesn't support spice OpenGL"));
- return -1;
- }
-
- virBufferAddLit(opt, "gl=on,");
-
- if (gl->rendernode) {
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_RENDERNODE)) {
+ if (gl->native == VIR_TRISTATE_BOOL_NO) {
+ /* For non-native OpenGL, we need to add egl-headless to the cmdline.
+ *
+ * NB: QEMU defaults to '-spice gl=off', so we don't have to add
that
+ * explicitly, especially since we're not testing for GL capability
+ * presence.
+ */
+ virCommandAddArg(cmd, "-display");
+ virCommandAddArg(cmd, "egl-headless");
Similar thoughts as previous patch related to egl-headless and need for
capability and/or details related to what's being used to gate it's
presence on the command line.
Honestly it's confusing to read "when" it's supposed to be used between
the new code and what was written in the RFC. There's a comment
regarding nvidia, non-opengl config for vfio, where it's not clear to me
whether headless could be used (IOW: some gl=no condition).
John
+ } else {
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_GL)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("This QEMU doesn't support spice OpenGL
rendernode"));
+ _("This QEMU doesn't support spice OpenGL"));
return -1;
}
- virBufferAddLit(opt, "rendernode=");
- virQEMUBuildBufferEscapeComma(opt, gl->rendernode);
- virBufferAddLit(opt, ",");
+ virBufferAddLit(opt, "gl=on,");
+
+ if (gl->rendernode) {
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_RENDERNODE)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("This QEMU doesn't support spice OpenGL
rendernode"));
+ return -1;
+ }
+
+ virBufferAddLit(opt, "rendernode=");
+ virQEMUBuildBufferEscapeComma(opt, gl->rendernode);
+ virBufferAddLit(opt, ",");
+ }
}
return 0;
@@ -8137,7 +8149,8 @@ qemuBuildGraphicsSPICECommandLine(virQEMUDriverConfigPtr cfg,
/* OpenGL magic */
if (graphics->gl &&
graphics->gl->enable == VIR_TRISTATE_BOOL_YES &&
- qemuBuildGraphicsSPICEGLCommandLine(graphics->gl, &opt, qemuCaps) <
0)
+ qemuBuildGraphicsSPICEGLCommandLine(graphics->gl, cmd,
+ &opt, qemuCaps) < 0)
goto error;
virBufferTrim(&opt, ",", -1);
[...]