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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list