Since we support gl with SPICE and SDL with future VNC enablement in
sight (egl-headless), let's separate the gl-related attributes into a
standalone structure.
Signed-off-by: Erik Skultety <eskultet(a)redhat.com>
---
src/conf/domain_conf.c | 137 +++++++++++++++++++++++++-------------------
src/conf/domain_conf.h | 12 +++-
src/qemu/qemu_cgroup.c | 10 ++--
src/qemu/qemu_command.c | 66 ++++++++++++---------
src/qemu/qemu_domain.c | 7 ++-
src/security/security_dac.c | 7 ++-
6 files changed, 138 insertions(+), 101 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 09d9bac739..6bfa3ca130 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1420,8 +1420,6 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def)
break;
case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
- VIR_FREE(def->data.spice.rendernode);
- VIR_FREE(def->data.spice.keymap);
virDomainGraphicsAuthDefClear(&def->data.spice.auth);
break;
@@ -1429,6 +1427,8 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def)
break;
}
+ virDomainGraphicsGLDefFree(def->gl);
+
for (i = 0; i < def->nListens; i++)
virDomainGraphicsListenDefClear(&def->listens[i]);
VIR_FREE(def->listens);
@@ -1436,6 +1436,18 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def)
VIR_FREE(def);
}
+
+void
+virDomainGraphicsGLDefFree(virDomainGraphicsGLDefPtr def)
+{
+ if (!def)
+ return;
+
+ VIR_FREE(def->rendernode);
+ VIR_FREE(def);
+}
+
+
const char *virDomainInputDefGetPath(virDomainInputDefPtr input)
{
switch ((virDomainInputType) input->type) {
@@ -13555,6 +13567,48 @@ virDomainGraphicsListensParseXML(virDomainGraphicsDefPtr def,
}
+static int
+virDomainGraphicsGLDefParseXML(virDomainGraphicsDefPtr def,
+ xmlNodePtr node)
+{
+ virDomainGraphicsGLDefPtr gl = NULL;
+ char *enable = NULL;
+ int ret = -1;
+
+ if (!node)
+ return 0;
+
+ if (VIR_ALLOC(gl) < 0)
+ return -1;
+
+ if (!(enable = virXMLPropString(node, "enable"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("'enable' attribute is mandatory for graphics
"
+ "<gl> element"));
+ goto cleanup;
+ }
+
+ if ((gl->enable =
+ virTristateBoolTypeFromString(enable)) <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown value for attribute enable '%s'"),
+ enable);
+ goto cleanup;
+ }
+
+ if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
+ gl->rendernode = virXMLPropString(node, "rendernode");
+
+ VIR_STEAL_PTR(def->gl, gl);
+
+ ret = 0;
+ cleanup:
+ VIR_FREE(enable);
+ virDomainGraphicsGLDefFree(gl);
+ return ret;
+}
+
+
static int
virDomainGraphicsDefParseXMLVNC(virDomainGraphicsDefPtr def,
xmlNodePtr node,
@@ -13644,8 +13698,6 @@ virDomainGraphicsDefParseXMLSDL(virDomainGraphicsDefPtr def,
{
xmlNodePtr save = ctxt->node;
char *enable = NULL;
- int enableVal;
- xmlNodePtr glNode;
char *fullscreen = virXMLPropString(node, "fullscreen");
int ret = -1;
@@ -13668,23 +13720,9 @@ virDomainGraphicsDefParseXMLSDL(virDomainGraphicsDefPtr def,
def->data.sdl.xauth = virXMLPropString(node, "xauth");
def->data.sdl.display = virXMLPropString(node, "display");
- glNode = virXPathNode("./gl", ctxt);
- if (glNode) {
- enable = virXMLPropString(glNode, "enable");
- if (!enable) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("sdl gl element missing enable"));
- goto cleanup;
- }
-
- enableVal = virTristateBoolTypeFromString(enable);
- if (enableVal < 0) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unknown enable value '%s'"), enable);
- goto cleanup;
- }
- def->data.sdl.gl = enableVal;
- }
+ if (virDomainGraphicsGLDefParseXML(def,
+ virXPathNode("./gl[1]", ctxt)) < 0)
+ goto cleanup;
ret = 0;
cleanup:
@@ -14026,31 +14064,6 @@ virDomainGraphicsDefParseXMLSpice(virDomainGraphicsDefPtr def,
VIR_FREE(enable);
def->data.spice.filetransfer = enableVal;
- } else if (virXMLNodeNameEqual(cur, "gl")) {
- char *enable = virXMLPropString(cur, "enable");
- char *rendernode = virXMLPropString(cur, "rendernode");
- int enableVal;
-
- if (!enable) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("spice gl element missing enable"));
- VIR_FREE(rendernode);
- goto error;
- }
-
- if ((enableVal =
- virTristateBoolTypeFromString(enable)) <= 0) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unknown enable value '%s'"),
enable);
- VIR_FREE(enable);
- VIR_FREE(rendernode);
- goto error;
- }
- VIR_FREE(enable);
-
- def->data.spice.gl = enableVal;
- def->data.spice.rendernode = rendernode;
-
} else if (virXMLNodeNameEqual(cur, "mouse")) {
char *mode = virXMLPropString(cur, "mode");
int modeVal;
@@ -14071,6 +14084,9 @@ virDomainGraphicsDefParseXMLSpice(virDomainGraphicsDefPtr def,
VIR_FREE(mode);
def->data.spice.mousemode = modeVal;
+ } else if (virXMLNodeNameEqual(cur, "gl")) {
+ if (virDomainGraphicsGLDefParseXML(def, cur) < 0)
+ goto error;
}
}
cur = cur->next;
@@ -26148,18 +26164,25 @@ virDomainGraphicsListenDefFormatAddr(virBufferPtr buf,
virBufferAsprintf(buf, " listen='%s'", glisten->address);
}
+
static void
-virDomainSpiceGLDefFormat(virBufferPtr buf, virDomainGraphicsDefPtr def)
+virDomainGraphicsGLDefFormat(virBufferPtr buf, virDomainGraphicsDefPtr def)
{
- if (def->data.spice.gl == VIR_TRISTATE_BOOL_ABSENT)
+ virDomainGraphicsGLDefPtr gl = def->gl;
+
+ if (!gl)
return;
virBufferAsprintf(buf, "<gl enable='%s'",
- virTristateBoolTypeToString(def->data.spice.gl));
- virBufferEscapeString(buf, " rendernode='%s'",
def->data.spice.rendernode);
+ virTristateBoolTypeToString(gl->enable));
+
+ if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
+ virBufferEscapeString(buf, " rendernode='%s'",
gl->rendernode);
+
virBufferAddLit(buf, "/>\n");
}
+
static int
virDomainGraphicsDefFormat(virBufferPtr buf,
virDomainGraphicsDefPtr def,
@@ -26247,18 +26270,12 @@ virDomainGraphicsDefFormat(virBufferPtr buf,
if (def->data.sdl.fullscreen)
virBufferAddLit(buf, " fullscreen='yes'");
- if (!children && def->data.sdl.gl != VIR_TRISTATE_BOOL_ABSENT) {
+ if (!children && def->gl) {
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
children = true;
}
- if (def->data.sdl.gl != VIR_TRISTATE_BOOL_ABSENT) {
- virBufferAsprintf(buf, "<gl enable='%s'",
- virTristateBoolTypeToString(def->data.sdl.gl));
- virBufferAddLit(buf, "/>\n");
- }
-
break;
case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
@@ -26405,8 +26422,7 @@ virDomainGraphicsDefFormat(virBufferPtr buf,
if (!children && (def->data.spice.image || def->data.spice.jpeg ||
def->data.spice.zlib || def->data.spice.playback ||
def->data.spice.streaming || def->data.spice.copypaste
||
- def->data.spice.mousemode || def->data.spice.filetransfer
||
- def->data.spice.gl)) {
+ def->data.spice.mousemode ||
def->data.spice.filetransfer)) {
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
children = true;
@@ -26436,9 +26452,10 @@ virDomainGraphicsDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, "<filetransfer
enable='%s'/>\n",
virTristateBoolTypeToString(def->data.spice.filetransfer));
- virDomainSpiceGLDefFormat(buf, def);
}
+ virDomainGraphicsGLDefFormat(buf, def);
+
if (children) {
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</graphics>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 0924fc4f3c..20dc1334c4 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1598,6 +1598,13 @@ struct _virDomainGraphicsListenDef {
bool autoGenerated;
};
+typedef struct _virDomainGraphicsGLDef virDomainGraphicsGLDef;
+typedef virDomainGraphicsGLDef *virDomainGraphicsGLDefPtr;
+struct _virDomainGraphicsGLDef {
+ virTristateBool enable;
+ char *rendernode; /* SPICE only */
+};
+
struct _virDomainGraphicsDef {
/* Port value discipline:
* Value -1 is legacy syntax indicating that it should be auto-allocated.
@@ -1620,7 +1627,6 @@ struct _virDomainGraphicsDef {
char *display;
char *xauth;
bool fullscreen;
- virTristateBool gl;
} sdl;
struct {
int port;
@@ -1650,8 +1656,6 @@ struct _virDomainGraphicsDef {
int streaming;
virTristateBool copypaste;
virTristateBool filetransfer;
- virTristateBool gl;
- char *rendernode;
} spice;
} data;
/* nListens, listens, and *port are only useful if type is vnc,
@@ -1659,6 +1663,7 @@ struct _virDomainGraphicsDef {
* simplify parsing code.*/
size_t nListens;
virDomainGraphicsListenDefPtr listens;
+ virDomainGraphicsGLDefPtr gl;
};
typedef enum {
@@ -2837,6 +2842,7 @@ int virDomainObjWaitUntil(virDomainObjPtr vm,
void virDomainPanicDefFree(virDomainPanicDefPtr panic);
void virDomainResourceDefFree(virDomainResourceDefPtr resource);
void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def);
+void virDomainGraphicsGLDefFree(virDomainGraphicsGLDefPtr def);
const char *virDomainInputDefGetPath(virDomainInputDefPtr input);
void virDomainInputDefFree(virDomainInputDefPtr def);
virDomainDiskDefPtr virDomainDiskDefNew(virDomainXMLOptionPtr xmlopt);
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index c8fba7f9e6..81e86fa973 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -489,20 +489,20 @@ qemuSetupGraphicsCgroup(virDomainObjPtr vm,
virDomainGraphicsDefPtr gfx)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- const char *rendernode = gfx->data.spice.rendernode;
int ret;
if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
return 0;
if (gfx->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE ||
- gfx->data.spice.gl != VIR_TRISTATE_BOOL_YES ||
- !rendernode)
+ !gfx->gl ||
+ gfx->gl->enable != VIR_TRISTATE_BOOL_YES ||
+ !gfx->gl->rendernode)
return 0;
- ret = virCgroupAllowDevicePath(priv->cgroup, rendernode,
+ ret = virCgroupAllowDevicePath(priv->cgroup, gfx->gl->rendernode,
VIR_CGROUP_DEVICE_RW, false);
- virDomainAuditCgroupPath(vm, priv->cgroup, "allow", rendernode,
+ virDomainAuditCgroupPath(vm, priv->cgroup, "allow",
gfx->gl->rendernode,
"rw", ret);
return ret;
}
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 195d03e373..ef0be95b0f 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7740,7 +7740,8 @@ qemuBuildGraphicsSDLCommandLine(virQEMUDriverConfigPtr cfg
ATTRIBUTE_UNUSED,
virCommandAddArg(cmd, "-display");
virBufferAddLit(&opt, "sdl");
- if (graphics->data.sdl.gl != VIR_TRISTATE_BOOL_ABSENT) {
+ if (graphics->gl &&
+ graphics->gl->enable != VIR_TRISTATE_BOOL_ABSENT) {
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SDL_GL)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("OpenGL for SDL is not supported with this QEMU "
@@ -7749,7 +7750,7 @@ qemuBuildGraphicsSDLCommandLine(virQEMUDriverConfigPtr cfg
ATTRIBUTE_UNUSED,
}
virBufferAsprintf(&opt, ",gl=%s",
- virTristateSwitchTypeToString(graphics->data.sdl.gl));
+ virTristateSwitchTypeToString(graphics->gl->enable));
}
@@ -7886,6 +7887,35 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg,
}
+static int
+qemuBuildGraphicsSPICEGLCommandLine(virDomainGraphicsGLDefPtr gl,
+ 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)) {
+ 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;
+}
+
+
static int
qemuBuildGraphicsSPICECommandLine(virQEMUDriverConfigPtr cfg,
virCommandPtr cmd,
@@ -8089,31 +8119,6 @@ qemuBuildGraphicsSPICECommandLine(virQEMUDriverConfigPtr cfg,
}
}
- if (graphics->data.spice.gl == VIR_TRISTATE_BOOL_YES) {
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_GL)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("This QEMU doesn't support spice OpenGL"));
- goto error;
- }
-
- /* spice.gl is a TristateBool, but qemu expects on/off: use
- * TristateSwitch helper */
- virBufferAsprintf(&opt, "gl=%s,",
- virTristateSwitchTypeToString(graphics->data.spice.gl));
-
- if (graphics->data.spice.rendernode) {
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_RENDERNODE)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("This QEMU doesn't support spice OpenGL
rendernode"));
- goto error;
- }
-
- virBufferAddLit(&opt, "rendernode=");
- virQEMUBuildBufferEscapeComma(&opt, graphics->data.spice.rendernode);
- virBufferAddLit(&opt, ",");
- }
- }
-
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEAMLESS_MIGRATION)) {
/* If qemu supports seamless migration turn it
* unconditionally on. If migration destination
@@ -8122,10 +8127,17 @@ qemuBuildGraphicsSPICECommandLine(virQEMUDriverConfigPtr cfg,
virBufferAddLit(&opt, "seamless-migration=on,");
}
+ /* OpenGL magic */
+ if (graphics->gl &&
+ graphics->gl->enable == VIR_TRISTATE_BOOL_YES &&
+ qemuBuildGraphicsSPICEGLCommandLine(graphics->gl, &opt, qemuCaps) < 0)
+ goto error;
+
virBufferTrim(&opt, ",", -1);
virCommandAddArg(cmd, "-spice");
virCommandAddArgBuffer(cmd, &opt);
+
if (graphics->data.spice.keymap)
virCommandAddArgList(cmd, "-k",
graphics->data.spice.keymap, NULL);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index f8a662f747..948b9b7fd0 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -11290,11 +11290,12 @@ qemuDomainSetupGraphics(virQEMUDriverConfigPtr cfg
ATTRIBUTE_UNUSED,
virDomainGraphicsDefPtr gfx,
const struct qemuDomainCreateDeviceData *data)
{
- const char *rendernode = gfx->data.spice.rendernode;
+ const char *rendernode = NULL;
if (gfx->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE ||
- gfx->data.spice.gl != VIR_TRISTATE_BOOL_YES ||
- !rendernode)
+ !gfx->gl ||
+ gfx->gl->enable != VIR_TRISTATE_BOOL_YES ||
+ !gfx->gl->rendernode)
return 0;
return qemuDomainCreateDevice(rendernode, data, false);
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 4b623dcf39..e8757f04e8 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1431,10 +1431,11 @@ virSecurityDACSetGraphicsLabel(virSecurityManagerPtr mgr,
return -1;
if (gfx->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE &&
- gfx->data.spice.gl == VIR_TRISTATE_BOOL_YES &&
- gfx->data.spice.rendernode) {
+ gfx->gl &&
+ gfx->gl->enable == VIR_TRISTATE_BOOL_YES &&
+ gfx->gl->rendernode) {
if (virSecurityDACSetOwnership(priv, NULL,
- gfx->data.spice.rendernode,
+ gfx->gl->rendernode,
user, group) < 0)
return -1;
}
--
2.14.4