Browse Source

Wayland: Fix engine stalls wihle waiting frames

There were two edge cases in the frame waiting logic (aka manual frame
throttling or emulated vsync) which would cause the editor to stall in
one way or another:

 1. Waiting right after starting the editor would cause a deadlock
between both threads until something happened in the Wayland event
queue, in turn unblocking the Wayland thread and kickstartin the whole
thing;

 2. Starting the editor (and probably other long-loading stuff) without
low consumption mode would suspend the window and never commit its
surfaces, thus never signaling the compositor that we want frame events.
Riteo 7 months ago
parent
commit
cbd68eb403

+ 4 - 0
platform/linuxbsd/wayland/display_server_wayland.cpp

@@ -1317,6 +1317,10 @@ void DisplayServerWayland::process_events() {
 				DEBUG_LOG_WAYLAND("Unsuspending from timeout.");
 				DEBUG_LOG_WAYLAND("Unsuspending from timeout.");
 			}
 			}
 		}
 		}
+
+		// Since we're not rendering, nothing is committing the windows'
+		// surfaces. We have to do it ourselves.
+		wayland_thread.commit_surfaces();
 	}
 	}
 
 
 #ifdef DBUS_ENABLED
 #ifdef DBUS_ENABLED

+ 10 - 0
platform/linuxbsd/wayland/wayland_thread.cpp

@@ -4298,6 +4298,16 @@ bool WaylandThread::get_reset_frame() {
 // Dispatches events until a frame event is received, a window is reported as
 // Dispatches events until a frame event is received, a window is reported as
 // suspended or the timeout expires.
 // suspended or the timeout expires.
 bool WaylandThread::wait_frame_suspend_ms(int p_timeout) {
 bool WaylandThread::wait_frame_suspend_ms(int p_timeout) {
+	// This is a bit of a chicken and egg thing... Looks like the main event loop
+	// has to call its rightfully forever-blocking poll right in between
+	// `wl_display_prepare_read` and `wl_display_read`. This means, that it will
+	// basically be guaranteed to stay stuck in a "prepare read" state, where it
+	// will block any other attempt at reading the display fd, such as ours. The
+	// solution? Let's make sure the mutex is locked (it should) and unblock the
+	// main thread with a roundtrip!
+	MutexLock mutex_lock(mutex);
+	wl_display_roundtrip(wl_display);
+
 	if (main_window.suspended) {
 	if (main_window.suspended) {
 		// The window is suspended! The compositor is telling us _explicitly_ that we
 		// The window is suspended! The compositor is telling us _explicitly_ that we
 		// don't need to draw, without letting us guess through the frame event's
 		// don't need to draw, without letting us guess through the frame event's