mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-02 05:12:02 +00:00
[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:
@@ -230,6 +230,11 @@ static const struct wp_image_description_v1_listener hdrImageDescListener =
|
|||||||
|
|
||||||
void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct Rect * damage, int count)
|
void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct Rect * damage, int count)
|
||||||
{
|
{
|
||||||
|
// 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 (!wlWm.swapWithDamage.init)
|
if (!wlWm.swapWithDamage.init)
|
||||||
{
|
{
|
||||||
if (wl_proxy_get_version((struct wl_proxy *) wlWm.surface) < 4)
|
if (wl_proxy_get_version((struct wl_proxy *) wlWm.surface) < 4)
|
||||||
@@ -245,6 +250,7 @@ void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct
|
|||||||
applyHDRPending();
|
applyHDRPending();
|
||||||
swapWithDamage(&wlWm.swapWithDamage, display, surface, damage, count);
|
swapWithDamage(&wlWm.swapWithDamage, display, surface, damage, count);
|
||||||
activateReadyHDRImageDesc();
|
activateReadyHDRImageDesc();
|
||||||
|
});
|
||||||
|
|
||||||
if (wlWm.needsResize)
|
if (wlWm.needsResize)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -322,7 +322,8 @@ static const struct wl_keyboard_listener keyboardListener = {
|
|||||||
|
|
||||||
static void waylandCleanUpPointer(void)
|
static void waylandCleanUpPointer(void)
|
||||||
{
|
{
|
||||||
INTERLOCKED_SECTION(wlWm.confineLock, {
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
|
{
|
||||||
if (wlWm.lockedPointer)
|
if (wlWm.lockedPointer)
|
||||||
{
|
{
|
||||||
zwp_locked_pointer_v1_destroy(wlWm.lockedPointer);
|
zwp_locked_pointer_v1_destroy(wlWm.lockedPointer);
|
||||||
@@ -438,15 +439,12 @@ bool waylandInputInit(void)
|
|||||||
wl_seat_add_listener(wlWm.seat, &seatListener, NULL);
|
wl_seat_add_listener(wlWm.seat, &seatListener, NULL);
|
||||||
wl_display_roundtrip(wlWm.display);
|
wl_display_roundtrip(wlWm.display);
|
||||||
|
|
||||||
LG_LOCK_INIT(wlWm.confineLock);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void waylandInputFree(void)
|
void waylandInputFree(void)
|
||||||
{
|
{
|
||||||
waylandUngrabPointer();
|
waylandUngrabPointer();
|
||||||
LG_LOCK_FREE(wlWm.confineLock);
|
|
||||||
|
|
||||||
if (wlWm.pointer)
|
if (wlWm.pointer)
|
||||||
waylandCleanUpPointer();
|
waylandCleanUpPointer();
|
||||||
@@ -482,7 +480,7 @@ void waylandGrabPointer(void)
|
|||||||
&relativePointerListener, NULL);
|
&relativePointerListener, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERLOCKED_SECTION(wlWm.confineLock,
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
{
|
{
|
||||||
if (!wlWm.confinedPointer && !wlWm.lockedPointer)
|
if (!wlWm.confinedPointer && !wlWm.lockedPointer)
|
||||||
{
|
{
|
||||||
@@ -496,7 +494,7 @@ void waylandGrabPointer(void)
|
|||||||
inline static void internalUngrabPointer(bool lock)
|
inline static void internalUngrabPointer(bool lock)
|
||||||
{
|
{
|
||||||
if (lock)
|
if (lock)
|
||||||
LG_LOCK(wlWm.confineLock);
|
LG_LOCK(wlWm.surfaceLock);
|
||||||
|
|
||||||
if (wlWm.confinedPointer)
|
if (wlWm.confinedPointer)
|
||||||
{
|
{
|
||||||
@@ -505,7 +503,7 @@ inline static void internalUngrabPointer(bool lock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lock)
|
if (lock)
|
||||||
LG_UNLOCK(wlWm.confineLock);
|
LG_UNLOCK(wlWm.surfaceLock);
|
||||||
|
|
||||||
if (!wlWm.warpSupport)
|
if (!wlWm.warpSupport)
|
||||||
{
|
{
|
||||||
@@ -536,7 +534,7 @@ void waylandCapturePointer(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERLOCKED_SECTION(wlWm.confineLock,
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
{
|
{
|
||||||
if (wlWm.confinedPointer)
|
if (wlWm.confinedPointer)
|
||||||
{
|
{
|
||||||
@@ -552,7 +550,7 @@ void waylandCapturePointer(void)
|
|||||||
|
|
||||||
void waylandUncapturePointer(void)
|
void waylandUncapturePointer(void)
|
||||||
{
|
{
|
||||||
INTERLOCKED_SECTION(wlWm.confineLock,
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
{
|
{
|
||||||
if (wlWm.lockedPointer)
|
if (wlWm.lockedPointer)
|
||||||
{
|
{
|
||||||
@@ -601,11 +599,10 @@ void waylandWarpPointer(int x, int y, bool exiting)
|
|||||||
if (!wlWm.pointerInSurface || wlWm.lockedPointer)
|
if (!wlWm.pointerInSurface || wlWm.lockedPointer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
INTERLOCKED_SECTION(wlWm.confineLock,
|
LG_LOCK(wlWm.surfaceLock);
|
||||||
{
|
|
||||||
if (wlWm.lockedPointer)
|
if (wlWm.lockedPointer)
|
||||||
{
|
{
|
||||||
LG_UNLOCK(wlWm.confineLock);
|
LG_UNLOCK(wlWm.surfaceLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,7 +635,7 @@ void waylandWarpPointer(int x, int y, bool exiting)
|
|||||||
|
|
||||||
wl_surface_commit(wlWm.surface);
|
wl_surface_commit(wlWm.surface);
|
||||||
wl_region_destroy(region);
|
wl_region_destroy(region);
|
||||||
});
|
LG_UNLOCK(wlWm.surfaceLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waylandRealignPointer(void)
|
void waylandRealignPointer(void)
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ static bool getCompositor(char * dst, size_t size)
|
|||||||
static bool waylandInit(const LG_DSInitParams params)
|
static bool waylandInit(const LG_DSInitParams params)
|
||||||
{
|
{
|
||||||
memset(&wlWm, 0, sizeof(wlWm));
|
memset(&wlWm, 0, sizeof(wlWm));
|
||||||
|
LG_LOCK_INIT(wlWm.surfaceLock);
|
||||||
LG_LOCK_INIT(wlWm.pendingHDRLock);
|
LG_LOCK_INIT(wlWm.pendingHDRLock);
|
||||||
LG_LOCK_INIT(wlWm.hdrLock);
|
LG_LOCK_INIT(wlWm.hdrLock);
|
||||||
wlWm.desktop = WL_Desktops[0];
|
wlWm.desktop = WL_Desktops[0];
|
||||||
@@ -214,6 +215,7 @@ static void waylandFree(void)
|
|||||||
wl_display_disconnect(wlWm.display);
|
wl_display_disconnect(wlWm.display);
|
||||||
LG_LOCK_FREE(wlWm.hdrLock);
|
LG_LOCK_FREE(wlWm.hdrLock);
|
||||||
LG_LOCK_FREE(wlWm.pendingHDRLock);
|
LG_LOCK_FREE(wlWm.pendingHDRLock);
|
||||||
|
LG_LOCK_FREE(wlWm.surfaceLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool waylandGetProp(LG_DSProperty prop, void * ret)
|
static bool waylandGetProp(LG_DSProperty prop, void * ret)
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ struct WaylandDSState
|
|||||||
struct wl_seat * seat;
|
struct wl_seat * seat;
|
||||||
struct wl_shm * shm;
|
struct wl_shm * shm;
|
||||||
struct wl_compositor * compositor;
|
struct wl_compositor * compositor;
|
||||||
|
LG_Lock surfaceLock;
|
||||||
|
|
||||||
struct WaylandScale scale;
|
struct WaylandScale scale;
|
||||||
bool fractionalScale;
|
bool fractionalScale;
|
||||||
@@ -192,7 +193,6 @@ struct WaylandDSState
|
|||||||
struct zwp_locked_pointer_v1 * lockedPointer;
|
struct zwp_locked_pointer_v1 * lockedPointer;
|
||||||
bool showPointer;
|
bool showPointer;
|
||||||
uint32_t pointerEnterSerial;
|
uint32_t pointerEnterSerial;
|
||||||
LG_Lock confineLock;
|
|
||||||
|
|
||||||
struct zwp_idle_inhibit_manager_v1 * idleInhibitManager;
|
struct zwp_idle_inhibit_manager_v1 * idleInhibitManager;
|
||||||
struct zwp_idle_inhibitor_v1 * idleInhibitor;
|
struct zwp_idle_inhibitor_v1 * idleInhibitor;
|
||||||
|
|||||||
@@ -154,7 +154,10 @@ bool waylandWindowInit(const char * title, const char * appId, bool fullscreen,
|
|||||||
title, appId, fullscreen, maximize, borderless, resizable))
|
title, appId, fullscreen, maximize, borderless, resizable))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
|
{
|
||||||
wl_surface_commit(wlWm.surface);
|
wl_surface_commit(wlWm.surface);
|
||||||
|
});
|
||||||
|
|
||||||
// The initial configure supplies the compositor-selected size for states
|
// The initial configure supplies the compositor-selected size for states
|
||||||
// such as fullscreen. It must be received before the first buffer is made.
|
// such as fullscreen. It must be received before the first buffer is made.
|
||||||
@@ -214,9 +217,12 @@ bool waylandWaitFrame(void)
|
|||||||
{
|
{
|
||||||
lgWaitEvent(wlWm.frameEvent, TIMEOUT_INFINITE);
|
lgWaitEvent(wlWm.frameEvent, TIMEOUT_INFINITE);
|
||||||
|
|
||||||
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
|
{
|
||||||
struct wl_callback * callback = wl_surface_frame(wlWm.surface);
|
struct wl_callback * callback = wl_surface_frame(wlWm.surface);
|
||||||
if (callback)
|
if (callback)
|
||||||
wl_callback_add_listener(callback, &frame_listener, NULL);
|
wl_callback_add_listener(callback, &frame_listener, NULL);
|
||||||
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -224,7 +230,10 @@ bool waylandWaitFrame(void)
|
|||||||
void waylandSkipFrame(void)
|
void waylandSkipFrame(void)
|
||||||
{
|
{
|
||||||
// If we decided to not render, we must commit the surface so that the callback is registered.
|
// If we decided to not render, we must commit the surface so that the callback is registered.
|
||||||
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
|
{
|
||||||
wl_surface_commit(wlWm.surface);
|
wl_surface_commit(wlWm.surface);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void waylandStopWaitFrame(void)
|
void waylandStopWaitFrame(void)
|
||||||
|
|||||||
Reference in New Issue
Block a user