@@ -822,8 +822,9 @@ void DisplayServerWayland::show_window(WindowID p_window_id) {
822822 }
823823#endif
824824
825- // NOTE: The public window-handling methods might depend on this flag being
826- // set. Ensure to not make any of these calls before this assignment.
825+ // NOTE: Some public window-handling methods might depend on this flag being
826+ // set. Make sure the method you're calling does not depend on it before this
827+ // assignment.
827828 wd.visible = true ;
828829
829830 // Actually try to apply the window's mode now that it's visible.
@@ -1349,7 +1350,7 @@ void DisplayServerWayland::window_set_vsync_mode(DisplayServer::VSyncMode p_vsyn
13491350 if (rendering_context) {
13501351 rendering_context->window_set_vsync_mode (p_window_id, p_vsync_mode);
13511352
1352- wd.emulate_vsync = (rendering_context->window_get_vsync_mode (p_window_id) == DisplayServer::VSYNC_ENABLED);
1353+ wd.emulate_vsync = (!wayland_thread. is_fifo_available () && rendering_context->window_get_vsync_mode (p_window_id) == DisplayServer::VSYNC_ENABLED);
13531354
13541355 if (wd.emulate_vsync ) {
13551356 print_verbose (" VSYNC: manually throttling frames using MAILBOX." );
@@ -1362,6 +1363,8 @@ void DisplayServerWayland::window_set_vsync_mode(DisplayServer::VSyncMode p_vsyn
13621363 if (egl_manager) {
13631364 egl_manager->set_use_vsync (p_vsync_mode != DisplayServer::VSYNC_DISABLED);
13641365
1366+ // NOTE: Mesa's EGL implementation does not seem to make use of fifo_v1 so
1367+ // we'll have to always emulate V-Sync.
13651368 wd.emulate_vsync = egl_manager->is_using_vsync ();
13661369
13671370 if (wd.emulate_vsync ) {
@@ -1542,38 +1545,14 @@ bool DisplayServerWayland::color_picker(const Callable &p_callback) {
15421545}
15431546
15441547void DisplayServerWayland::try_suspend () {
1545- bool must_emulate = false ;
1546-
1547- for (KeyValue<DisplayServer::WindowID, WindowData> &pair : windows) {
1548- if (pair.value .emulate_vsync ) {
1549- must_emulate = true ;
1550- break ;
1551- }
1552- }
1553-
15541548 // Due to various reasons, we manually handle display synchronization by
15551549 // waiting for a frame event (request to draw) or, if available, the actual
15561550 // window's suspend status. When a window is suspended, we can avoid drawing
15571551 // altogether, either because the compositor told us that we don't need to or
15581552 // because the pace of the frame events became unreliable.
1559- if (must_emulate) {
1560- bool frame = wayland_thread.wait_frame_suspend_ms (WAYLAND_MAX_FRAME_TIME_US / 1000 );
1561- if (!frame) {
1562- suspend_state = SuspendState::TIMEOUT;
1563- }
1564- }
1565-
1566- // If we suspended by capability, we'll know with this check. We must do this
1567- // after `wait_frame_suspend_ms` as it progressively dispatches the event queue
1568- // during the "timeout".
1569- if (wayland_thread.is_suspended ()) {
1570- suspend_state = SuspendState::CAPABILITY;
1571- }
1572-
1573- if (suspend_state == SuspendState::TIMEOUT) {
1574- DEBUG_LOG_WAYLAND (" Suspending. Reason: timeout." );
1575- } else if (suspend_state == SuspendState::CAPABILITY) {
1576- DEBUG_LOG_WAYLAND (" Suspending. Reason: capability." );
1553+ bool frame = wayland_thread.wait_frame_suspend_ms (WAYLAND_MAX_FRAME_TIME_US / 1000 );
1554+ if (!frame) {
1555+ suspend_state = SuspendState::TIMEOUT;
15771556 }
15781557}
15791558
@@ -1724,51 +1703,75 @@ void DisplayServerWayland::process_events() {
17241703
17251704 wayland_thread.keyboard_echo_keys ();
17261705
1727- if (suspend_state == SuspendState::NONE) {
1728- // Due to the way legacy suspension works, we have to treat low processor
1729- // usage mode very differently than the regular one.
1730- if (OS::get_singleton ()->is_in_low_processor_usage_mode ()) {
1731- // NOTE: We must avoid committing a surface if we expect a new frame, as we
1732- // might otherwise commit some inconsistent data (e.g. buffer scale). Note
1733- // that if a new frame is expected it's going to be committed by the renderer
1734- // soon anyways.
1735- if (!RenderingServer::get_singleton ()->has_changed ()) {
1736- // We _can't_ commit in a different thread (such as in the frame callback
1737- // itself) because we would risk to step on the renderer's feet, which would
1738- // cause subtle but severe issues, such as crashes on setups with explicit
1739- // sync. This isn't normally a problem, as the renderer commits at every
1740- // frame (which is what we need for atomic surface updates anyways), but in
1741- // low processor usage mode that expectation is broken. When it's on, our
1742- // frame rate stops being constant. This also reflects in the frame
1743- // information we use for legacy suspension. In order to avoid issues, let's
1744- // manually commit all surfaces, so that we can get fresh frame data.
1745- wayland_thread.commit_surfaces ();
1746- try_suspend ();
1706+ switch (suspend_state) {
1707+ case SuspendState::NONE: {
1708+ bool emulate_vsync = false ;
1709+ for (KeyValue<DisplayServer::WindowID, WindowData> &pair : windows) {
1710+ if (pair.value .emulate_vsync ) {
1711+ emulate_vsync = true ;
1712+ break ;
1713+ }
17471714 }
1748- } else {
1749- try_suspend ();
1750- }
1751- } else {
1752- if (suspend_state == SuspendState::CAPABILITY) {
1753- // If we suspended by capability we can assume that it will be reset when
1754- // the compositor wants us to repaint.
1755- if (!wayland_thread.is_suspended ()) {
1756- suspend_state = SuspendState::NONE;
1757- DEBUG_LOG_WAYLAND (" Unsuspending from capability." );
1715+
1716+ if (emulate_vsync) {
1717+ // Due to the way legacy suspension works, we have to treat low processor
1718+ // usage mode very differently than the regular one.
1719+ if (OS::get_singleton ()->is_in_low_processor_usage_mode ()) {
1720+ // NOTE: We must avoid committing a surface if we expect a new frame, as we
1721+ // might otherwise commit some inconsistent data (e.g. buffer scale). Note
1722+ // that if a new frame is expected it's going to be committed by the renderer
1723+ // soon anyways.
1724+ if (!RenderingServer::get_singleton ()->has_changed ()) {
1725+ // We _can't_ commit in a different thread (such as in the frame callback
1726+ // itself) because we would risk to step on the renderer's feet, which would
1727+ // cause subtle but severe issues, such as crashes on setups with explicit
1728+ // sync. This isn't normally a problem, as the renderer commits at every
1729+ // frame (which is what we need for atomic surface updates anyways), but in
1730+ // low processor usage mode that expectation is broken. When it's on, our
1731+ // frame rate stops being constant. This also reflects in the frame
1732+ // information we use for legacy suspension. In order to avoid issues, let's
1733+ // manually commit all surfaces, so that we can get fresh frame data.
1734+ wayland_thread.commit_surfaces ();
1735+ try_suspend ();
1736+ }
1737+ } else {
1738+ try_suspend ();
1739+ }
1740+ }
1741+
1742+ if (wayland_thread.is_suspended ()) {
1743+ suspend_state = SuspendState::CAPABILITY;
17581744 }
1759- } else if (suspend_state == SuspendState::TIMEOUT) {
1745+
1746+ if (suspend_state == SuspendState::TIMEOUT) {
1747+ DEBUG_LOG_WAYLAND (" Suspending. Reason: timeout." );
1748+ } else if (suspend_state == SuspendState::CAPABILITY) {
1749+ DEBUG_LOG_WAYLAND (" Suspending. Reason: capability." );
1750+ }
1751+ } break ;
1752+
1753+ case SuspendState::TIMEOUT: {
17601754 // Certain compositors might not report the "suspended" wm_capability flag.
17611755 // Because of this we'll wake up at the next frame event, indicating the
17621756 // desire for the compositor to let us repaint.
17631757 if (wayland_thread.get_reset_frame ()) {
17641758 suspend_state = SuspendState::NONE;
17651759 DEBUG_LOG_WAYLAND (" Unsuspending from timeout." );
17661760 }
1767- }
17681761
1769- // Since we're not rendering, nothing is committing the windows'
1770- // surfaces. We have to do it ourselves.
1771- wayland_thread.commit_surfaces ();
1762+ // Since we're not rendering, nothing is committing the windows'
1763+ // surfaces. We have to do it ourselves.
1764+ wayland_thread.commit_surfaces ();
1765+ } break ;
1766+
1767+ case SuspendState::CAPABILITY: {
1768+ // If we suspended by capability we can assume that it will be reset when
1769+ // the compositor wants us to repaint.
1770+ if (!wayland_thread.is_suspended ()) {
1771+ suspend_state = SuspendState::NONE;
1772+ DEBUG_LOG_WAYLAND (" Unsuspending from capability." );
1773+ }
1774+ } break ;
17721775 }
17731776
17741777#ifdef DBUS_ENABLED
0 commit comments