diff --git a/client/displayservers/Wayland/gl.c b/client/displayservers/Wayland/gl.c index 63d86e8a..bef88d87 100644 --- a/client/displayservers/Wayland/gl.c +++ b/client/displayservers/Wayland/gl.c @@ -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) { diff --git a/client/displayservers/Wayland/input.c b/client/displayservers/Wayland/input.c index 867afa97..bbb71f63 100644 --- a/client/displayservers/Wayland/input.c +++ b/client/displayservers/Wayland/input.c @@ -322,7 +322,8 @@ static const struct wl_keyboard_listener keyboardListener = { static void waylandCleanUpPointer(void) { - INTERLOCKED_SECTION(wlWm.confineLock, { + INTERLOCKED_SECTION(wlWm.surfaceLock, + { if (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_display_roundtrip(wlWm.display); - LG_LOCK_INIT(wlWm.confineLock); - return true; } void waylandInputFree(void) { waylandUngrabPointer(); - LG_LOCK_FREE(wlWm.confineLock); if (wlWm.pointer) waylandCleanUpPointer(); @@ -482,7 +480,7 @@ void waylandGrabPointer(void) &relativePointerListener, NULL); } - INTERLOCKED_SECTION(wlWm.confineLock, + INTERLOCKED_SECTION(wlWm.surfaceLock, { if (!wlWm.confinedPointer && !wlWm.lockedPointer) { @@ -496,7 +494,7 @@ void waylandGrabPointer(void) inline static void internalUngrabPointer(bool lock) { if (lock) - LG_LOCK(wlWm.confineLock); + LG_LOCK(wlWm.surfaceLock); if (wlWm.confinedPointer) { @@ -505,7 +503,7 @@ inline static void internalUngrabPointer(bool lock) } if (lock) - LG_UNLOCK(wlWm.confineLock); + LG_UNLOCK(wlWm.surfaceLock); if (!wlWm.warpSupport) { @@ -536,7 +534,7 @@ void waylandCapturePointer(void) return; } - INTERLOCKED_SECTION(wlWm.confineLock, + INTERLOCKED_SECTION(wlWm.surfaceLock, { if (wlWm.confinedPointer) { @@ -545,14 +543,14 @@ void waylandCapturePointer(void) } wlWm.lockedPointer = zwp_pointer_constraints_v1_lock_pointer( - wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL, - ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); + wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL, + ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); }); } void waylandUncapturePointer(void) { - INTERLOCKED_SECTION(wlWm.confineLock, + INTERLOCKED_SECTION(wlWm.surfaceLock, { if (wlWm.lockedPointer) { @@ -601,44 +599,43 @@ void waylandWarpPointer(int x, int y, bool exiting) if (!wlWm.pointerInSurface || wlWm.lockedPointer) return; - INTERLOCKED_SECTION(wlWm.confineLock, + LG_LOCK(wlWm.surfaceLock); + if (wlWm.lockedPointer) { - if (wlWm.lockedPointer) - { - LG_UNLOCK(wlWm.confineLock); - return; - } + LG_UNLOCK(wlWm.surfaceLock); + return; + } - int width, height; - wlWm.desktop->getSize(&width, &height); + int width, height; + wlWm.desktop->getSize(&width, &height); - if (x < 0) x = 0; - else if (x >= width) x = width - 1; - if (y < 0) y = 0; - else if (y >= height) y = height - 1; + if (x < 0) x = 0; + else if (x >= width) x = width - 1; + if (y < 0) y = 0; + else if (y >= height) y = height - 1; - struct wl_region * region = wl_compositor_create_region(wlWm.compositor); - wl_region_add(region, x, y, 1, 1); - - if (wlWm.confinedPointer) - { - zwp_confined_pointer_v1_set_region(wlWm.confinedPointer, region); - wl_surface_commit(wlWm.surface); - zwp_confined_pointer_v1_set_region(wlWm.confinedPointer, NULL); - } - else - { - struct zwp_confined_pointer_v1 * confine; - confine = zwp_pointer_constraints_v1_confine_pointer( - wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, region, - ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); - wl_surface_commit(wlWm.surface); - zwp_confined_pointer_v1_destroy(confine); - } + struct wl_region * region = wl_compositor_create_region(wlWm.compositor); + wl_region_add(region, x, y, 1, 1); + if (wlWm.confinedPointer) + { + zwp_confined_pointer_v1_set_region(wlWm.confinedPointer, region); wl_surface_commit(wlWm.surface); - wl_region_destroy(region); - }); + zwp_confined_pointer_v1_set_region(wlWm.confinedPointer, NULL); + } + else + { + struct zwp_confined_pointer_v1 * confine; + confine = zwp_pointer_constraints_v1_confine_pointer( + wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, region, + ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); + wl_surface_commit(wlWm.surface); + zwp_confined_pointer_v1_destroy(confine); + } + + wl_surface_commit(wlWm.surface); + wl_region_destroy(region); + LG_UNLOCK(wlWm.surfaceLock); } void waylandRealignPointer(void) diff --git a/client/displayservers/Wayland/wayland.c b/client/displayservers/Wayland/wayland.c index 94d3ac90..e72f1472 100644 --- a/client/displayservers/Wayland/wayland.c +++ b/client/displayservers/Wayland/wayland.c @@ -108,6 +108,7 @@ static bool getCompositor(char * dst, size_t size) static bool waylandInit(const LG_DSInitParams params) { memset(&wlWm, 0, sizeof(wlWm)); + LG_LOCK_INIT(wlWm.surfaceLock); LG_LOCK_INIT(wlWm.pendingHDRLock); LG_LOCK_INIT(wlWm.hdrLock); wlWm.desktop = WL_Desktops[0]; @@ -214,6 +215,7 @@ static void waylandFree(void) wl_display_disconnect(wlWm.display); LG_LOCK_FREE(wlWm.hdrLock); LG_LOCK_FREE(wlWm.pendingHDRLock); + LG_LOCK_FREE(wlWm.surfaceLock); } static bool waylandGetProp(LG_DSProperty prop, void * ret) diff --git a/client/displayservers/Wayland/wayland.h b/client/displayservers/Wayland/wayland.h index 1d80297b..dfe369b0 100644 --- a/client/displayservers/Wayland/wayland.h +++ b/client/displayservers/Wayland/wayland.h @@ -134,6 +134,7 @@ struct WaylandDSState struct wl_seat * seat; struct wl_shm * shm; struct wl_compositor * compositor; + LG_Lock surfaceLock; struct WaylandScale scale; bool fractionalScale; @@ -192,7 +193,6 @@ struct WaylandDSState struct zwp_locked_pointer_v1 * lockedPointer; bool showPointer; uint32_t pointerEnterSerial; - LG_Lock confineLock; struct zwp_idle_inhibit_manager_v1 * idleInhibitManager; struct zwp_idle_inhibitor_v1 * idleInhibitor; diff --git a/client/displayservers/Wayland/window.c b/client/displayservers/Wayland/window.c index 9eccc126..26c51b8b 100644 --- a/client/displayservers/Wayland/window.c +++ b/client/displayservers/Wayland/window.c @@ -154,7 +154,10 @@ bool waylandWindowInit(const char * title, const char * appId, bool fullscreen, title, appId, fullscreen, maximize, borderless, resizable)) return false; - wl_surface_commit(wlWm.surface); + INTERLOCKED_SECTION(wlWm.surfaceLock, + { + wl_surface_commit(wlWm.surface); + }); // The initial configure supplies the compositor-selected size for states // 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); - struct wl_callback * callback = wl_surface_frame(wlWm.surface); - if (callback) - wl_callback_add_listener(callback, &frame_listener, NULL); + INTERLOCKED_SECTION(wlWm.surfaceLock, + { + struct wl_callback * callback = wl_surface_frame(wlWm.surface); + if (callback) + wl_callback_add_listener(callback, &frame_listener, NULL); + }); return false; } @@ -224,7 +230,10 @@ bool waylandWaitFrame(void) void waylandSkipFrame(void) { // If we decided to not render, we must commit the surface so that the callback is registered. - wl_surface_commit(wlWm.surface); + INTERLOCKED_SECTION(wlWm.surfaceLock, + { + wl_surface_commit(wlWm.surface); + }); } void waylandStopWaitFrame(void)