Basic API usage

Pekka Paalanen ppaalanen at gmail.com
Thu Sep 17 08:19:37 UTC 2020


On Wed, 16 Sep 2020 17:10:49 +0200
Jan Bruns <code at abnuto.de> wrote:

> Pekka Paalanen wrote:
> 
>  >> Would they introduce
>  >> structures named like
>  >>
>  >> VK_STRUCTURE_TYPE_WAYLAND_NOLIBWAYLAND_SURFACE_CREATE_INFO_KHR or
>  >> VK_STRUCTURE_TYPE_DIRECTWAYLAND_SURFACE_CREATE_INFO_KHR, in addition to
>  >> the existing VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR?  
>  >
>  > I cannot guess what you are thinking here. If Vulkan didn't use
>  > actually implemented types from *some* Wayland implementation in its
>  > API, what could it use?  
> 
> 
> Assume there'd be some core wayland approved protocol like (roughly, 
> just designed for this posting):
> 
> <protocol name="inheritance_v0.0.0.0.0.0">
> 
>    <interface name="wl_subwire_parent" version="1">
>      <description summary="allow another connection to use our objects">
>         Interface used to move wayland objects to other connections.
>      </description>
> 
>      <event name="tellname">
>        <description summary="A wayland-server chosen name.">
>       Child connections use this name to identify the parent.
>        </description>
>        <arg name="name" type="string" />
>      </event>
> 
>      <event name="authping">
>        <description summary="Incoming request for alternate connection.">
>        </description>
>        <arg name="name" type="string" summary="the child's name"/>
>        <arg name="secatt" type="string" summary="security attribute"/>
>        <arg name="serial" type="int" summary="wayland-server chosen"/>
>      </event>
> 
>      <request name="authpong">
>        <description summary="Autenticate the alternate connection."> 
> </description>
>        <arg name="decision" type="int" enum="authresult" summary="enum 
> to allow or deny"/>
>        <arg name="serial" type="int" summary="serial from authping"/>
>      </request>
> 
>      <enum name="authresult">
>        <description summary="authentication result"> </description>
>        <entry name="deny" value="0" summary="indicate denied request"/>
>        <entry name="allow" value="1" summary="indicate allowed request"/>
>      </enum>
> 
>      <request name="sendobj">
>        <description summary="send an obj to child connection.">
>       Allow the child connection to send request and/or receive events
>           for the specified object.
>           We'll uses pname to refer to the object for commincation 
> beyond wayland protocol.
>        </description>
>        <arg name="sharemode" type="uint" enum="sharemode" 
> summary="details about sharing"/>
>        <arg name="type" type="string" summary="interface name of object 
> becoming inherited on the other side"/>
>        <arg name="obj" type="object" summary="obj to send"/>
>        <arg name="pname" type="uint" summary="parent-chosen name"/>
>      </request>
> 
>      <enum name="sharemode" bitfield="true">
>        <description summary="how to share the obj">
>        </description>
>        <entry name="parent_req" value="1" summary="parent to still send 
> requests"/>  
>        <entry name="parent_ev" value="2" summary="parent to still 
> receive events"/>
>        <entry name="child_req" value="4" summary="child to send requests"/>
>        <entry name="child_ev" value="8" summary="child to receive events"/>
>      </enum>
>    </interface>
> 
>    <interface name="wl_subwire_child" version="1">
>      <description summary="child-side connection">
>         Interface used to inherit wayland objects from other connections.
>      </description>
> 
>      <event name="tellname">
>        <description summary="A wayland-server chosen name.">
>       Parent connections use this name to identify the child.
>        </description>
>        <arg name="name" type="string" />
>      </event>
> 
>      <request name="authenticate">
>        <description summary="request authentication">
>       Request to treat the active connection as a child.
>        </description>
>        <arg name="name" type="string" summary="the parent's name to 
> inherit from"/>
>        <arg name="secatt" type="string" summary="security attribute"/>
>        <arg name="serial" type="int" summary="child-chosen id of request"/>
>      </request>
> 
>      <event name="authentication_result">
>        <description summary="Notification about the authentication 
> outcome.">  
>        </description>
>        <arg name="serial" type="int" summary="id used for authenticate 
> request"/>  
>        <arg name="result" type="int" summary="authentication outcome"/>
>      </event>
> 
>      <event name="parent_obj">
>        <description summary="Receive an obj from parent.">
>          Receive an obj from parent.
>          The parent uses pname to refer to the object for commincation 
> beyond wayland protocol.
>        </description>
>        <arg name="sender" type="string" summary="the sending parent's 
> name."/>  
>        <arg name="type" type="string" summary="interface name of 
> inherited object"/>
>        <arg name="obj" type="new_id" summary="inherited object"/>
>        <arg name="pname" type="uint" summary="parent-chosen name"/>
>      </event>
> 
>    </interface>
> </protocol>
> 
> 
> 
> The Vk-structure for passing the surrface to Vk would instead of
> 
> 
> typedef struct VkWaylandSurfaceCreateInfoKHR {
>      VkStructureType                   sType;
>      const void*                       pNext;
>      VkWaylandSurfaceCreateFlagsKHR    flags;
>      struct wl_display*                display;
>      struct wl_surface*                surface;
> } VkWaylandSurfaceCreateInfoKHR;
> 
> 
> would turn into something like
> 
> typedef struct VkRealYetUnrealWaylandSurfaceCreateInfoKHR {
>      VkStructureType                   sType;
>      const void*                       pNext;
>      VkWaylandSurfaceCreateFlagsKHR    flags;
>      char*                             wl_parent_name; // wayland server 
> generated wl_subwire_parent.tellname.name
>      uint                              display_name; // 
> wl_subwire_parent.sendobj.pname;
>      uint                              surface_name; // 
> wl_subwire_parent.sendobj.pname;
> } VkRealYetUnrealWaylandSurfaceCreateInfoKHR;
> 
> 
> And the difference is that there'd only be references to the protocol, 
> instead of secret references to specific implementations.
> 
> The Vk implementation as well as the application instanciating the Vk 
> would then both be free to choose whatever implementation to talk 
> wayland protocol.

Ok, yeah, you could invent something like that, but how do you then
guarantee the strict message ordering requirements that Wayland
protocol relies on.

Take for example EGL's eglSwapBuffers(). That function is required to
issue wl_surface.commit exactly once on the wl_surface associated with
the EGLSurface before it returns. With that guarantee, applications can
put window state changes and more into the exact same commit, which is
required for both avoiding glitches and in some cases also for message
sequence correctness. An incorrect sequence may result in a protocol
error, which disconnects the client.

If you send two requests through two different Wayland connections,
there is no guarantee whatsoever on which one a compositor will
process first.

Yes, you could add even more protocol to the "child connection"
extension to ensure the message ordering, but it will get even more
complicated and more roundtrip-happy. Roundtrips are a thing we are
trying to explicitly minimize when designing Wayland protocol for
performance reasons.

People have some experience with trying to synchronize two connections:
Xwayland support requires a Wayland compositor to talk both Wayland and
X11 to Xwayland, and such case is full of opportunities for dead-locks.
Granted, that is amplified by X11's round-trippy nature and less of a
problem with Wayland since Wayland rarely requires a blocking wait for
a reply.

I didn't even touch the issue of allocating object IDs yet.

I think the trade-off is not worth it.

>  > For comparison, VkXcbSurfaceCreateInfoKHR uses libxcb types in the API,
>  > so you are forced to use libxcb if you want to use that. Likewise in
>  > EGL, you are forced to use libX11 if you want to use the EGL X11
>  > platform, and libwayland-client if you want to use the EGL Wayland
>  > platform.  
> 
> XCB aims to be some specific protocol-talker implementation.
> Isn't that very diffrent from what wayland should be?

X11 and Wayland are protocols. libxcb and libwayland are
protocol-talker implementations for X11 and Wayland.

No, designing Wayland so that you could use multiple different
implementations in one process to talk through the same Wayland
connection and mix and match those freely message by message was never
a goal. OTOH, connection isolation by default was an explicit design
goal, as was maximizing asynchronicity and minimizing the number of
times anyone needs to wait.

Today with hindsight, I think those were good decisions: it looks like
the protocol and the implementations would have been more complicated or
less efficient than they are now, or there would be unfixable races
and glitches even more.

This is what Wayland is. What you describe is something very different.

>  > In any case, Wayland per se is not tied to any particular
>  > implementation, even through libwayland is the authoritative
>  > implementation. You are free to write a Wayland protocol implementation
>  > from scratch with your own language. If the implementation is correct,
>  > it will have no trouble as a client communicating with a Wayland
>  > compositor written in C and using libwayland-server, for instance. Or
>  > vice versa, your own compositor in your own language can well accept
>  > any existing client written in any language.
>  >
>  > It is also possible to replace libwayland in one process with a
>  > completely different but ABI-compatible implementation. Just make sure
>  > all pieces in the process use the same implementation. Between
>  > processes, each process can use a totally different Wayland
>  > implementation if you want to, as long as they all talk the same binary
>  > wire format.  
> 
> Well, isn't that yet still pretty much a sleeping dreamer...

There is nothing stopping it. I believe there are people working
towards a Rust implementation of Wayland message passing with the
eventual goal of making the Rust library a drop-in replacement to
libwayland, with the benefit of offering a safe and very Rust'y Rust
interface in addition to the old C ABI. You will be able to make the
switch system-wide or per-program, as long as you don't mix different
implementations in the same process over the same connection.

Or at least there has been talk to that end, and I would warmly welcome
such project.

I'm sure there already are from-scratch Wayland implementations, and
they are interoperable with libwayland on the other side of the process
boundary. ISTR there are also Wayland debugging tools that do not use
libwayland as the interface wasn't a good fit for a pass-through proxy.


I think there is nothing more I can give you. Wayland is not what you
imagined or wished for.


Thanks,
pq
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20200917/7fb69646/attachment.sig>


More information about the wayland-devel mailing list