doc: update GPU buffer exchange section

Finally, a buffer exchange mechanism for the 21st century.

Signed-off-by: Julian Orth <ju.orth@gmail.com>
This commit is contained in:
Julian Orth 2025-09-02 14:09:55 +02:00
parent 8b102c3bc4
commit bb7b284623
2 changed files with 99 additions and 50 deletions

View file

@ -280,65 +280,113 @@
</para> </para>
</section> </section>
<section id="sect-Wayland-Architecture-wayland_hw_enabling"> <section id="sect-Wayland-Architecture-wayland_hw_enabling">
<title>Hardware Enabling for Wayland</title> <title>Accelerated GPU Buffer Exchange</title>
<para> <para>
Typically, hardware enabling includes modesetting/display Clients
and EGL/GLES2. On top of that Wayland needs a way to share <ulink url="https://docs.kernel.org/userspace-api/dma-buf-alloc-exchange.html">exchange</ulink>
buffers efficiently between processes. There are two sides GPU buffers with the compositor as dma-buf file descriptors, which are universal handles
to that, the client side and the server side. that are independent of any particular rendering API or memory allocator. The
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/stable/linux-dmabuf/linux-dmabuf-v1.xml">linux-dmabuf-v1</ulink>
protocol is used to turn one or more dma-buf FDs into a
<link linkend="protocol-spec-wl_buffer">wl_buffer</link>.
</para> </para>
<para> <para>
On the client side we've defined a Wayland EGL platform. In If the client uses the
the EGL model, that consists of the native types <ulink url="https://docs.vulkan.org/spec/latest/chapters/VK_KHR_surface/wsi.html">Vulkan</ulink>
(EGLNativeDisplayType, EGLNativeWindowType and or
EGLNativePixmapType) and a way to create those types. In <ulink url="https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_platform_wayland.txt">EGL</ulink>
other words, it's the glue code that binds the EGL stack and (via
its buffer sharing mechanism to the generic Wayland API. The <ulink url="https://gitlab.freedesktop.org/wayland/wayland/-/tree/main/egl">wayland-egl</ulink>)
EGL stack is expected to provide an implementation of the window-system integration
Wayland EGL platform. The full API is in the wayland-egl.h (WSI), this is done transparently by the WSI.
header. The open source implementation in the mesa EGL stack
is in wayland-egl.c and platform_wayland.c.
</para> </para>
<para> <para>
Under the hood, the EGL stack is expected to define a Clients can alternatively allocate and import dma-bufs themselves
vendor-specific protocol extension that lets the client side using the GBM library, Vulkan, udmabuf, or dma-buf heaps.
EGL stack communicate buffer details with the compositor in </para>
order to share buffers. The point of the wayland-egl.h API <itemizedlist>
is to abstract that away and just let the client create an <listitem>
EGLSurface for a Wayland surface and start rendering. The <para>
open source stack uses the drm Wayland extension, which lets Using GBM, the client can allocate a gbm_bo and export one or more
the client discover the drm device to use and authenticate dma-buf FDs from it.
and then share drm (GEM) buffers with the compositor. </para>
</listitem>
<listitem>
<para>
Using Vulkan, the client can create a VkDeviceMemory object and use
<ulink url="https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_external_memory_dma_buf.html">VK_EXT_external_memory_dma_buf</ulink>
and
<ulink url="https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_image_drm_format_modifier.html">VK_EXT_image_drm_format_modifier</ulink>
to export a dma-buf FD from it.
</para>
</listitem>
<listitem>
<para>
<ulink url="https://lwn.net/Articles/749206/">udmabuf</ulink>
can be used to create dma-buf FDs from linear host memory.
</para>
</listitem>
<listitem>
<para>
<ulink url="https://docs.kernel.org/userspace-api/dma-buf-heaps.html">Dma-buf heaps</ulink>
can be used by privileged applications to create dma-buf FDs on embedded
devices.
</para>
</listitem>
</itemizedlist>
<para>
Compositors use
<ulink url="https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_external_memory_dma_buf.html">VK_EXT_external_memory_dma_buf</ulink>
and
<ulink url="https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_image_drm_format_modifier.html">VK_EXT_image_drm_format_modifier</ulink>
or
<ulink url="https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import.txt">EGL_EXT_image_dma_buf_import</ulink>
and
<ulink url="https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import_modifiers.txt">EGL_EXT_image_dma_buf_import_modifiers</ulink>
to import the dma-bufs provided by the client into their own Vulkan or
EGL renderers.
</para> </para>
<para> <para>
The server side of Wayland is the compositor and core UX for Clients do not need to wait for the GPU to finish rendering before submitting
the vertical, typically integrating task switcher, app dma-bufs to the compositor. Clients can use the
launcher, lock screen in one monolithic application. The <ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml">linux-drm-syncobj-v1</ulink>
server runs on top of a modesetting API (kernel modesetting, protocol to exchange DRM synchronization objects with the compositor. These objects
OpenWF Display or similar) and composites the final UI using are used to asynchronously signal ownership transfer of buffers from clients to the
a mix of EGL/GLES2 compositor and hardware overlays if compositor and vice versa. The WSIs do this transparently.
available. Enabling modesetting, EGL/GLES2 and overlays is
something that should be part of standard hardware bringup.
The extra requirement for Wayland enabling is the
EGL_WL_bind_wayland_display extension that lets the
compositor create an EGLImage from a generic Wayland shared
buffer. It's similar to the EGL_KHR_image_pixmap extension
to create an EGLImage from an X pixmap.
</para> </para>
<para> <para>
The extension has a setup step where you have to bind the If the linux-drm-syncobj-v1 protocol is not supported by the compositor, clients
EGL display to a Wayland display. Then as the compositor and compositors can use the
receives generic Wayland buffers from the clients (typically <ulink url="https://docs.kernel.org/driver-api/dma-buf.html#c.dma_buf_export_sync_file">DMA_BUF_IOCTL_EXPORT_SYNC_FILE</ulink>
when the client calls eglSwapBuffers), it will be able to and
pass the struct wl_buffer pointer to eglCreateImageKHR as <ulink url="https://docs.kernel.org/driver-api/dma-buf.html#c.dma_buf_import_sync_file">DMA_BUF_IOCTL_IMPORT_SYNC_FILE</ulink>
the EGLClientBuffer argument and with EGL_WAYLAND_BUFFER_WL ioctls to access and create implicit synchronization barriers.
as the target. This will create an EGLImage, which can then </para>
be used by the compositor as a texture or passed to the </section>
modesetting code to use as an overlay plane. Again, this is <section id="sect-Wayland-Architecture-kms">
implemented by the vendor specific protocol extension, which <title>Display Programming</title>
on the server side will receive the driver specific details <para>
about the shared buffer and turn that into an EGL image when Compositors enumerate DRM KMS devices using
the user calls eglCreateImageKHR. <ulink url="https://en.wikipedia.org/wiki/Udev">udev</ulink>.
Udev also notifies compositors of KMS device and display hotplug events.
</para>
<para>
Access to DRM KMS device ioctls is privileged. Since compositors usually run as
unprivileged applications, they typically gain access to a privileged file
descriptor using the
<ulink url="https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html#Session%20Objects">TakeDevice</ulink>
method provided by logind.
</para>
<para>
Using the file descriptor, compositors use KMS
<ulink url="https://docs.kernel.org/gpu/drm-kms.html">ioctls</ulink>
to enumerate the available displays.
</para>
<para>
Compositors use
<ulink url="https://docs.kernel.org/gpu/drm-kms.html#atomic-mode-setting">atomic mode setting</ulink>
to change the buffer shown by the display, to change the display's resolution, to
enable or disable HDR, and so on.
</para> </para>
</section> </section>
</chapter> </chapter>

View file

@ -98,6 +98,7 @@ custom_target(
'Wayland-docbook-html', 'Wayland-docbook-html',
command: [ command: [
xmlto, xmlto,
'--skip-validation',
'--stringparam', 'chunker.output.encoding=UTF-8', '--stringparam', 'chunker.output.encoding=UTF-8',
'--stringparam', 'chunk.section.depth=0', '--stringparam', 'chunk.section.depth=0',
'--stringparam', 'toc.section.depth=1', '--stringparam', 'toc.section.depth=1',