[client] wayland: serialize surface commits with EGL swaps

NVIDIA's Wayland EGL implementation sets explicit-sync acquire and
release points while presenting a frame. The requests emitted by
eglSwapBuffers and its final surface commit must be treated as one
logical transaction.

The pointer-warp path can commit the main surface from the input
thread while the render thread is inside eglSwapBuffers. If this
occurs between the explicit-sync requests, the cursor commit applies
incomplete pending state and the compositor disconnects the client
with:

  explicit sync is used, but no release point is set

Add a surface lock and hold it across EGL presentation. Use the same
lock for direct commits, frame callback registration, and
pointer-constraint updates, replacing the narrower confinement lock.
This prevents another thread from splitting the EGL transaction and
removes the need for __NV_DISABLE_EXPLICIT_SYNC=1.
This commit is contained in:
Geoffrey McRae
2026-07-30 11:09:07 +10:00
parent a9b8f437d4
commit f3155647d2
5 changed files with 74 additions and 60 deletions

View File

@@ -230,21 +230,27 @@ static const struct wp_image_description_v1_listener hdrImageDescListener =
void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct Rect * damage, int count)
{
if (!wlWm.swapWithDamage.init)
// EGL presentation sends a batch of Wayland requests ending in a surface
// commit. A concurrent commit would apply a partial batch and, when explicit
// sync is active, omit one of the required acquire/release timeline points.
INTERLOCKED_SECTION(wlWm.surfaceLock,
{
if (wl_proxy_get_version((struct wl_proxy *) wlWm.surface) < 4)
if (!wlWm.swapWithDamage.init)
{
DEBUG_INFO("Swapping buffers with damage: not supported, need wl_compositor v4");
swapWithDamageDisable(&wlWm.swapWithDamage);
if (wl_proxy_get_version((struct wl_proxy *) wlWm.surface) < 4)
{
DEBUG_INFO("Swapping buffers with damage: not supported, need wl_compositor v4");
swapWithDamageDisable(&wlWm.swapWithDamage);
}
else
swapWithDamageInit(&wlWm.swapWithDamage, display);
}
else
swapWithDamageInit(&wlWm.swapWithDamage, display);
}
waylandPresentationFrame();
applyHDRPending();
swapWithDamage(&wlWm.swapWithDamage, display, surface, damage, count);
activateReadyHDRImageDesc();
waylandPresentationFrame();
applyHDRPending();
swapWithDamage(&wlWm.swapWithDamage, display, surface, damage, count);
activateReadyHDRImageDesc();
});
if (wlWm.needsResize)
{