[libvirt] [PATCH] qemu: add sdl opengl support

John Ferlan jferlan at redhat.com
Thu May 10 11:39:29 UTC 2018



On 05/10/2018 05:25 AM, Maciej Wolny wrote:
> 
> 
> On 04/05/18 00:08, John Ferlan wrote:
>>> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
>>> index 3569b9212..a2ef93c09 100644
>>> --- a/docs/schemas/domaincommon.rng
>>> +++ b/docs/schemas/domaincommon.rng
>>> @@ -3031,6 +3031,14 @@
>>>                <ref name="virYesNo"/>
>>>              </attribute>
>>>            </optional>
>>> +          <optional>
>>> +            <element name="gl">
>>> +              <attribute name="enable">
>>> +                <ref name="virYesNo"/>
>>> +              </attribute>
>>> +              <empty/>
>>> +            </element>
>>> +          </optional>
>>
>> I assume this is a copy of the spice gl - to reduce cut-paste-copy, you
>> could create a "name" for it and share that name between spice and sdl.
>> It's a common thing to do. Not required, but not difficult either.
> 
> Unfortunately, the SPICE GL property has a rendernode attribute, while
> the SDL one doesn't.. I think this prevents a sensible name definition
> which would fit both use cases.
> 

Fair enough - it was more a suggestion. I'll look at v2 in a bit.

>>
>>>          </group>
>>>          <group>
>>>            <attribute name="type">
>>> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
>>> index b0257068d..7d65ca9df 100644
>>> --- a/src/conf/domain_conf.c
>>> +++ b/src/conf/domain_conf.c
>>> @@ -13448,6 +13448,7 @@ static int
>>>  virDomainGraphicsDefParseXMLSDL(virDomainGraphicsDefPtr def,
>>>                                  xmlNodePtr node)
>>>  {
>>> +    xmlNodePtr cur;
>>>      char *fullscreen = virXMLPropString(node, "fullscreen");
>>>      int ret = -1;
>>>  
>>> @@ -13468,6 +13469,34 @@ virDomainGraphicsDefParseXMLSDL(virDomainGraphicsDefPtr def,
>>>      def->data.sdl.xauth = virXMLPropString(node, "xauth");
>>>      def->data.sdl.display = virXMLPropString(node, "display");
>>>  
>>> +    cur = node->children;
>>> +    while (cur != NULL) {
>>> +        if (cur->type == XML_ELEMENT_NODE) {
>>> +            if (virXMLNodeNameEqual(cur, "gl")) {
>>> +                char *enable = virXMLPropString(cur, "enable");
>>> +                int enableVal;
>>> +
>>> +                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);
>>> +                    VIR_FREE(enable);
>>> +                    goto cleanup;
>>> +                }
>>> +                VIR_FREE(enable);
>>> +
>>> +                def->data.sdl.gl = enableVal;
>>> +            }
>>> +        }
>>> +        cur = cur->next;
>>> +    }
>>> +
>>
>> I see this is just a copy of what Spice does, which probably needed some
>> adjustment anyway... IIRC: Peter Krempa recently went through an
>> exercise with the storage to change a number of these while loops using
>> virXMLNodeNameEqual into more direct XML searches. Since this is only
>> one element and attribute, I don't really think this loop is useful. I
>> know it's possible to get the data via another means and some of the
>> code already does that. The exact lines I'll leave to you to hash out.
>>
>>>      ret = 0;
>>>   cleanup:
>>>      VIR_FREE(fullscreen);
>>> @@ -25652,6 +25681,18 @@ virDomainGraphicsDefFormat(virBufferPtr buf,
>>>          if (def->data.sdl.fullscreen)
>>>              virBufferAddLit(buf, " fullscreen='yes'");
>>>  
>>> +        if (!children && def->data.sdl.gl) {
>>
>> This should be a comparison such as "def->data.sdl.gl !=
>> VIR_TRISTATE_BOOL_ABSENT"  (I know it's logically the same, but
>> daata.sdl.gl is not a boolean or a pointer).
>>
>>> +            virBufferAddLit(buf, ">\n");
>>> +            virBufferAdjustIndent(buf, 2);
>>> +            children = true;
>>> +        }
>>> +
>>> +        if (def->data.sdl.gl) {
>>
>> Similarly... yes, I know spice.gl isn't doing that.
>>
>>> +            virBufferAsprintf(buf, "<gl enable='%s'",
>>> +                              virTristateBoolTypeToString(def->data.sdl.gl));
>>> +            virBufferAddLit(buf, "/>\n");
>>> +        }
>>> +
>>>          break;
>>>  
>>>      case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
>>> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
>>> index 3c7eccb8c..90071d9c0 100644
>>> --- a/src/conf/domain_conf.h
>>> +++ b/src/conf/domain_conf.h
>>> @@ -1601,6 +1601,7 @@ struct _virDomainGraphicsDef {
>>>              char *display;
>>>              char *xauth;
>>>              bool fullscreen;
>>> +            virTristateBool gl;
>>>          } sdl;
>>>          struct {
>>>              int port;
>>> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
>>> index aa8d350f5..02680502e 100644
>>> --- a/src/qemu/qemu_capabilities.c
>>> +++ b/src/qemu/qemu_capabilities.c
>>> @@ -474,6 +474,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
>>>                "query-cpus-fast",
>>>                "disk-write-cache",
>>>                "nbd-tls",
>>> +              "sdl-gl",
>>>      );
>>>  
>>>  
>>> @@ -2451,6 +2452,7 @@ static struct virQEMUCapsCommandLineProps virQEMUCapsCommandLine[] = {
>>>      { "vnc", "vnc", QEMU_CAPS_VNC_MULTI_SERVERS },
>>>      { "chardev", "reconnect", QEMU_CAPS_CHARDEV_RECONNECT },
>>>      { "sandbox", "elevateprivileges", QEMU_CAPS_SECCOMP_BLACKLIST },
>>> +    { "sdl", "gl", QEMU_CAPS_SDL_GL },
>>>  };
>>>  
>>>  static int
>>> diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
>>> index 2afe7ef58..e36611e2a 100644
>>> --- a/src/qemu/qemu_capabilities.h
>>> +++ b/src/qemu/qemu_capabilities.h
>>> @@ -458,6 +458,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
>>>      QEMU_CAPS_QUERY_CPUS_FAST, /* query-cpus-fast command */
>>>      QEMU_CAPS_DISK_WRITE_CACHE, /* qemu block frontends support write-cache param */
>>>      QEMU_CAPS_NBD_TLS, /* NBD server supports TLS transport */
>>> +    QEMU_CAPS_SDL_GL, /* -sdl gl */
>>>  
>>>      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 418729b98..29214e806 100644
>>> --- a/src/qemu/qemu_command.c
>>> +++ b/src/qemu/qemu_command.c
>>> @@ -7988,6 +7988,7 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg,
>>>                               virQEMUCapsPtr qemuCaps,
>>>                               virDomainGraphicsDefPtr graphics)
>>>  {
>>> +    virBuffer opt = VIR_BUFFER_INITIALIZER;
>>>      switch (graphics->type) {
>>>      case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
>>>          if (graphics->data.sdl.xauth)
>>> @@ -8009,6 +8010,24 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg,
>>
>> Suggestion... Create a patch prior to this one that moves the code for
>> VIR_DOMAIN_GRAPHICS_TYPE_SDL into it's own helper - such as
>> qemuBuildGraphicsSDLCommandLine.
>>
>>>           * default, since the default changes :-( */
>>
>> The above comment can be removed in a separate patch since commit id
>> '4e8993a2' removed the check for QEMU_CAPS_SDL, although it took until
>> commit id '649a9dd7a' to "fix" the QEMU_CAPS_SDL to be X_QEMU_CAPS_SDL
>> since the QEMU 1.5 is our new minimum version supported.
>>
>>>          virCommandAddArg(cmd, "-sdl");
>>>  
>>> +        if (graphics->data.sdl.gl == VIR_TRISTATE_BOOL_YES) {
>>> +            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SDL_GL)) {
>>> +                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
>>> +                               _("This QEMU doesn't support SDL OpenGL"));
>>> +                return -1;
>>> +
>>> +            }
>>> +
>>> +            virBufferAsprintf(&opt, "gl=%s",
>>> +                              virTristateSwitchTypeToString(graphics->data.sdl.gl));
>>> +        }
>>> +
>>> +        {
>>> +            const char *optContent = virBufferCurrentContent(&opt);
>>> +            if (optContent && STRNEQ(optContent, ""))
>>> +                virCommandAddArgBuffer(cmd, &opt);
>>> +        }
>>
>> With it's own helper ^^this^^ awkward definition in the middle is
>> unnecessary I think... In fact, I don't even know why it matters - I
>> would think you could just do the virCommandAddArgBuffer right after the
>> virBufferAsprintf for "gl=%s"... I think the separate helper will be
>> good though in case there's more things added for sdl.
>>
>> e.g.:
>>             virCommandAddArgBuffer(cmd, &opt);
>>             virBufferFreeAndReset(&opt);
>>
>>
> 
> Without that 'if', it'll append an empty, quoted string ("''") to the
> command line. The lexical scope in there was indeed unnecessary.
>  

I'll look again in v2 - the command line building can be awkward for
those that don't do it often.

>>> +
>>>          break;
>>>  
>>>      case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
>>> diff --git a/tests/qemuxml2argvdata/video-virtio-gpu-sdl-gl.args b/tests/qemuxml2argvdata/video-virtio-gpu-sdl-gl.args
>>> new file mode 100644
>>> index 000000000..4172320ed
>>> --- /dev/null
>>> +++ b/tests/qemuxml2argvdata/video-virtio-gpu-sdl-gl.args
>>> @@ -0,0 +1,28 @@
>>> +LC_ALL=C \
>>> +PATH=/bin \
>>> +HOME=/home/test \
>>> +USER=test \
>>> +LOGNAME=test \
>>> +/usr/bin/qemu-system-i686 \
>>> +-name QEMUGuest1 \
>>> +-S \
>>> +-machine pc,accel=tcg,usb=off,dump-guest-core=off \
>>> +-m 1024 \
>>> +-smp 1,sockets=1,cores=1,threads=1 \
>>> +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
>>> +-no-user-config \
>>> +-nodefaults \
>>> +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
>>> +server,nowait \
>>> +-mon chardev=charmonitor,id=monitor,mode=control \
>>> +-rtc base=utc \
>>> +-no-shutdown \
>>> +-no-acpi \
>>> +-boot c \
>>> +-usb \
>>> +-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 \
>>> +-sdl gl=on \
>>> +-device virtio-gpu-pci,id=video0,virgl=on,bus=pci.0,addr=0x2 \
>>> +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
>>> diff --git a/tests/qemuxml2argvdata/video-virtio-gpu-sdl-gl.xml b/tests/qemuxml2argvdata/video-virtio-gpu-sdl-gl.xml
>>> new file mode 100644
>>> index 000000000..9dea73fbe
>>> --- /dev/null
>>> +++ b/tests/qemuxml2argvdata/video-virtio-gpu-sdl-gl.xml
>>> @@ -0,0 +1,38 @@
>>> +<domain type='qemu'>
>>> +  <name>QEMUGuest1</name>
>>> +  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
>>> +  <memory unit='KiB'>1048576</memory>
>>> +  <currentMemory unit='KiB'>1048576</currentMemory>
>>> +  <vcpu placement='static'>1</vcpu>
>>> +  <os>
>>> +    <type arch='i686' machine='pc'>hvm</type>
>>> +    <boot dev='hd'/>
>>> +  </os>
>>> +  <clock offset='utc'/>
>>> +  <on_poweroff>destroy</on_poweroff>
>>> +  <on_reboot>restart</on_reboot>
>>> +  <on_crash>destroy</on_crash>
>>> +  <devices>
>>> +    <emulator>/usr/bin/qemu-system-i686</emulator>
>>> +    <disk type='file' device='disk'>
>>> +      <driver name='qemu' type='qcow2' cache='none'/>
>>> +      <source file='/var/lib/libvirt/images/QEMUGuest1'/>
>>> +      <target dev='hda' bus='ide'/>
>>> +      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
>>> +    </disk>
>>> +    <controller type='ide' index='0'/>
>>> +    <controller type='usb' index='0'/>
>>> +    <controller type='pci' index='0' model='pci-root'/>
>>> +    <input type='mouse' bus='ps2'/>
>>> +    <input type='keyboard' bus='ps2'/>
>>> +    <graphics type='sdl'>
>>> +      <gl enable='yes'/>
>>> +    </graphics>
>>> +    <video>
>>> +      <model type='virtio' heads='1'>
>>> +        <acceleration accel3d='yes'/>
>>> +      </model>
>>> +    </video>
>>> +    <memballoon model='virtio'/>
>>> +  </devices>
>>> +</domain>
>>> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
>>> index 5b3bd4a99..0b06699f0 100644
>>> --- a/tests/qemuxml2argvtest.c
>>> +++ b/tests/qemuxml2argvtest.c
>>> @@ -1924,6 +1924,11 @@ mymain(void)
>>>              QEMU_CAPS_SPICE_GL,
>>>              QEMU_CAPS_SPICE_RENDERNODE,
>>>              QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
>>> +    DO_TEST("video-virtio-gpu-sdl-gl",
>>> +            QEMU_CAPS_DEVICE_VIRTIO_GPU,
>>> +            QEMU_CAPS_VIRTIO_GPU_VIRGL,
>>> +            QEMU_CAPS_SDL_GL,
>>> +            QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
>>
>> Newer code should use DO_TEST_CAPS_LATEST, but I think that'll fail
>> based on there being no capability defined in latest.
> 
> I haven't managed to make that working with DO_TEST_CAPS_LATEST.

Right as I noted in the response to your other posting here - that's
because you only modified the 2.4 capabilities and using the "latest"
probably won't work similarly.

Again I'll look at v2 and we can go from there.

John

> I need more information on how QEMU capabilities work.. Am I right to
> think that the actual capabilities will depend not only on the version
> of QEMU but also other packages in the system (say, virgl will require
> libvirglrenderer)? If so, do the files in tests/qemucapabilitiesdata
> only list basic capabilities that are always provided by that version of
> QEMU? Adding QEMU_CAPS_SDL_GL to the latest caps *.xml file isn't enough,
> that test will also need virgl (which is not listed in that file).
> 
>>
>> The only reason we're printing the "-sdl gl=on" in the .args file is
>> that you've passed the capability here.
>>
>>>      DO_TEST("video-virtio-gpu-secondary",
>>>              QEMU_CAPS_DEVICE_VIRTIO_GPU,
>>>              QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
>>>
>>
>> There needs to be an adjustment to qemuxml2xmltest.c as well. That'll
>> cause an output file to be generated/compared against as well.  Hint,
>> use VIR_TEST_REGENERATE_OUTPUT=1 after touching the output file.
>>
>> John
>>




More information about the libvir-list mailing list