https://bugs.kde.org/show_bug.cgi?id=527879
Bug ID: 527879
Summary: linux-drm-syncobj-v1 is never advertised on FreeBSD:
the kernel-version check treats every non-Linux system
as kernel 0.0.0
Classification: Plasma
Product: kwin
Version First 6.7.5
Reported In:
Platform: Other
OS: Linux
Status: REPORTED
Severity: normal
Priority: NOR
Component: wayland-generic
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
## Summary
`WaylandServer::setRenderBackend()` advertises
`wp_linux_drm_syncobj_manager_v1`
only if `linuxKernelVersion() >= 6.6`. `linuxKernelVersion()`
(`src/utils/kernel.h`) returns `Version(0, 0, 0)` whenever `uname().sysname` is
not `"Linux"`. On FreeBSD the check therefore always fails and explicit sync is
never offered to clients, even though the DRM driver supports timeline syncobjs
and `DRM_IOCTL_SYNCOBJ_EVENTFD`. This is the ioctl that the version check is
meant to guard.
On NVIDIA this has a real cost. Without explicit sync, and with the compositor
on an NVIDIA device, NVIDIA's `egl-wayland2` client platform cannot use
implicit sync either. It falls back to a `glFinish()` on every
`eglSwapBuffers`, and the driver's `glFinish()` busy-waits. A Qt OpenGL client
animating at 60 fps uses about 14–20% of one CPU core on Wayland, against about
1.5% on X11.
## Environment
- FreeBSD 15.1-RELEASE amd64
- KWin / Plasma 6.7.5, KDE Frameworks 6.31.0, Qt 6.11.2
- NVIDIA RTX A400, driver 615.78.08 (also seen with 595.112.07),
nvidia-drm-612-kmod, drm-612-kmod 6.12.85
- egl-wayland2 1.0.2, libdrm, libwayland 1.26.0
## The code
`src/wayland_server.cpp` (v6.7.5):
```cpp
void WaylandServer::setRenderBackend(RenderBackend *backend)
{
if (backend->drmDevice()->supportsSyncObjTimelines()) {
// ensure the DRM_IOCTL_SYNCOBJ_EVENTFD ioctl is supported
const auto linuxVersion = linuxKernelVersion();
if (linuxVersion < Version(6, 6)) {
return;
}
...
```
`src/utils/kernel.h`:
```cpp
inline static Version linuxKernelVersion()
{
struct utsname name;
uname(&name);
if (qstrcmp(name.sysname, "Linux") == 0) {
return Version::parseString(name.release);
}
return Version(0, 0, 0);
}
```
## Evidence
1. **The global is missing.** With `WAYLAND_DEBUG=1`, a client's registry
contains `wp_presentation`, `zwp_linux_dmabuf_v1` (v5) and the others, but
no
`wp_linux_drm_syncobj_manager_v1`.
2. **The driver supports what KWin needs.** A small libdrm test on
`/dev/dri/card0` (`nvidia-drm`) shows:
```
DRM_CAP_SYNCOBJ ret=0 val=1
DRM_CAP_SYNCOBJ_TIMELINE ret=0 val=1
drmSyncobjCreate ret=0
drmSyncobjEventfd ret=0 (real syncobj, point 1, eventfd from
eventfd(2))
drmSyncobjQuery ret=0
drmSyncobjEventfd on handle 0 -> ENOENT (ioctl known, handle invalid)
```
`supportsSyncObjTimelines()` is therefore true. Only the version check stops
the protocol from being advertised.
3. **What the client does instead.** A debug build of egl-wayland2 1.0.2 shows
every busy sample of the client's main thread in the `glFinish()` fallback:
```
#4 clock_gettime () from /lib/libsys.so.7
#5-#10 ?? () from /usr/local/lib/libnvidia-eglcore.so.1
#11 SyncRendering (...) at src/wayland/wayland-surface.c:1280
#12 eplWlSwapBuffers (...) at src/wayland/wayland-surface.c:1367
#13 HookSwapBuffersWithDamage (...) at src/base/platform-base.c:1114
#14 HookSwapBuffers (...) at src/base/platform-base.c:1152
#15-#16 libEGL_nvidia.so.0
#17 QtWaylandClient::QWaylandGLContext::swapBuffers
```
egl-wayland2 sets `supports_implicit_sync = false` when the server runs on
an
NVIDIA device (`wayland-display.c:1015`). With no syncobj protocol
available,
`SyncRendering()` has no option except a CPU wait. The egl-wayland2
maintainers have reviewed this path (NVIDIA/egl-wayland2#64).
## Steps to reproduce
1. Plasma Wayland session on FreeBSD (any GPU whose DRM driver reports
`DRM_CAP_SYNCOBJ_TIMELINE`).
2. `WAYLAND_DEBUG=1 weston-info` (or any client) and look for
`wp_linux_drm_syncobj_manager_v1`: it is not listed.
3. On NVIDIA: run a Qt 6 `QOpenGLWidget` app that redraws every frame and
compare its CPU time (`procstat -r <pid>` over 10 s) with the same app on
Plasma X11.
## Suggested fix
The 6.6 check exists to make sure `DRM_IOCTL_SYNCOBJ_EVENTFD` is available. The
other check, for 6.6.0–6.6.18 and 6.7, covers specific broken Linux releases.
Neither one means anything on a non-Linux kernel. Options:
- Run the version checks only when the system is Linux. On other systems, rely
on `supportsSyncObjTimelines()`.
- Or, more generally, probe the ioctl at runtime: call `drmSyncobjEventfd()` on
handle 0. A kernel that implements the ioctl fails with `ENOENT` (verified on
FreeBSD above). A kernel without it rejects the unknown ioctl with `EINVAL`.
The broken-releases check on Linux would remain.
I can test a patch on this setup.
--
You are receiving this mail because:
You are watching all bug changes.