Add a new attribute 'rendernode' to <gl> spice element.
Give it to QEMU if qemu supports it (queued for 2.9).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
<clipboard copypaste='no'/>
<mouse mode='client'/>
<filetransfer enable='no'/>
- <gl enable='yes'/>
+ <gl enable='yes' rendernode='/dev/dri/by-path/pci-0000:00:02.0-render'/>
</graphics></pre>
<p>
Spice supports variable compression settings for audio, images and
the <code>gl</code> element, by setting the <code>enable</code>
property. (QEMU only, <span class="since">since 1.3.3</span>).
</p>
+ <p>
+ By default, QEMU will pick the first available GPU DRM render node.
+ You may specify a DRM render node path to use instead. (QEMU only,
+ <span class="since">since 3.1.0</span>).
+ </p>
</dd>
<dt><code>rdp</code></dt>
<dd>
<attribute name="enable">
<ref name="virYesNo"/>
</attribute>
+ <optional>
+ <attribute name="rendernode">
+ <ref name="absFilePath"/>
+ </attribute>
+ </optional>
<empty/>
</element>
</optional>
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;
def->data.spice.filetransfer = enableVal;
} else if (xmlStrEqual(cur->name, BAD_CAST "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;
}
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 (xmlStrEqual(cur->name, BAD_CAST "mouse")) {
char *mode = virXMLPropString(cur, "mode");
int modeVal;
virBufferAsprintf(buf, " listen='%s'", glisten->address);
}
+static void
+virDomainSpiceGLDefFormat(virBufferPtr buf, virDomainGraphicsDefPtr def)
+{
+ if (def->data.spice.gl == VIR_TRISTATE_BOOL_ABSENT)
+ return;
+
+ virBufferAsprintf(buf, "<gl enable='%s'",
+ virTristateBoolTypeToString(def->data.spice.gl));
+ virBufferEscapeString(buf, " rendernode='%s'", def->data.spice.rendernode);
+ virBufferAddLit(buf, "/>\n");
+}
static int
virDomainGraphicsDefFormat(virBufferPtr buf,
if (def->data.spice.filetransfer)
virBufferAsprintf(buf, "<filetransfer enable='%s'/>\n",
virTristateBoolTypeToString(def->data.spice.filetransfer));
- if (def->data.spice.gl)
- virBufferAsprintf(buf, "<gl enable='%s'/>\n",
- virTristateBoolTypeToString(def->data.spice.gl));
+
+ virDomainSpiceGLDefFormat(buf, def);
}
if (children) {
virTristateBool copypaste;
virTristateBool filetransfer;
virTristateBool gl;
+ char *rendernode;
} spice;
} data;
/* nListens, listens, and *port are only useful if type is vnc,
"query-cpu-model-expansion", /* 245 */
"virtio-net.host_mtu",
+ "spice-rendernode",
);
{ "spice", "unix", QEMU_CAPS_SPICE_UNIX },
{ "drive", "throttling.bps-total-max-length", QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH },
{ "drive", "throttling.group", QEMU_CAPS_DRIVE_IOTUNE_GROUP },
+ { "spice", "rendernode", QEMU_CAPS_SPICE_RENDERNODE },
};
static int
/* 245 */
QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION, /* qmp query-cpu-model-expansion */
QEMU_CAPS_VIRTIO_NET_HOST_MTU, /* virtio-net-*.host_mtu */
+ QEMU_CAPS_SPICE_RENDERNODE, /* -spice rendernode */
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
* 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;
+ }
+
+ virBufferAsprintf(&opt, "rendernode=%s,", graphics->data.spice.rendernode);
+ }
}
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEAMLESS_MIGRATION)) {
-drive file=/var/lib/libvirt/images/QEMUGuest1,format=qcow2,if=none,\
id=drive-ide0-0-0,cache=none \
-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
--spice port=0,gl=on \
+-spice port=0,gl=on,rendernode=/dev/dri/foo \
-device virtio-gpu-pci,id=video0,virgl=on,bus=pci.0,addr=0x2 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='spice' autoport='no'>
- <gl enable='yes'/>
+ <gl enable='yes' rendernode='/dev/dri/foo'/>
</graphics>
<video>
<model type='virtio' heads='1'>
QEMU_CAPS_VIRTIO_GPU_VIRGL,
QEMU_CAPS_SPICE,
QEMU_CAPS_SPICE_GL,
+ QEMU_CAPS_SPICE_RENDERNODE,
QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
DO_TEST("video-virtio-gpu-secondary",
QEMU_CAPS_DEVICE_VIRTIO_GPU,
<input type='keyboard' bus='ps2'/>
<graphics type='spice'>
<listen type='none'/>
- <gl enable='yes'/>
+ <gl enable='yes' rendernode='/dev/dri/foo'/>
</graphics>
<video>
<model type='virtio' heads='1' primary='yes'>