From df3c87545399991167ee3902543b211cf10ec8b0 Mon Sep 17 00:00:00 2001
From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
Date: Tue, 21 May 2024 15:28:18 +0200
Subject: Beef up documentation about throttling window redraws under Wayland
---
documentation/src/wayland.dox | 66 ++++++++++++++++++++++++++++---------------
1 file changed, 44 insertions(+), 22 deletions(-)
diff --git a/documentation/src/wayland.dox b/documentation/src/wayland.dox
index d62e9da78..4c1066b05 100644
--- a/documentation/src/wayland.dox
+++ b/documentation/src/wayland.dox
@@ -602,13 +602,37 @@ FLTK has computed a damaged region. If that region is not null,
surface to the Wayland buffer and calls function \c wl_surface_damage_buffer() for these
parts to inform the compositor of what parts of the surface need its attention.
-
Throttling redraw operations
-An important detail here is that FLTK uses Wayland's synchronization
-mechanism to make sure the surface's \c wl_buffer is not changed while the
+Wayland buffer deletion
+Each \ref wld_buffer record contains boolean member \c in_use which is set to \c true
+just before the buffer gets committed, and boolean member \c released which
+is set to \c true when FLTK no longer needs the buffer and calls
+\c Fl_Wayland_Graphics_Driver::buffer_release().
+FLTK's buffer-creating function, \c Fl_Wayland_Graphics_Driver::create_shm_buffer(),
+attaches a 1-member listener to each buffer which Wayland calls after a commit
+operation to indicate the client is allowed to re-use the buffer.
+This listener's member function, \c buffer_release_listener(),
+turns to false member \c in_use of the buffer's \ref wld_buffer record.
+Since the two events 'FLTK no longer needs the buffer' and
+'the client is allowed to re-use the buffer' can arrive in
+any order, FLTK deletes the struct wl_buffer object by running
+\c do_buffer_release() only after both events happened, that is, when \c in_use is
+\c false and \c released is \c true. That's why function \c do_buffer_release()
+is called by both functions \c Fl_Wayland_Graphics_Driver::buffer_release()
+and \c buffer_release_listener().
+
+
+\section throttling Throttling window redraws
+
+FLTK uses Wayland's synchronization
+mechanism to make sure any committed \c wl_buffer is not changed while the
compositor is using it and to refrain from calling \c wl_surface_commit()
more frequently than the system can process it.
-This 2-step mechanism works as follows:
-- Fl_Wayland_Graphics_Driver::buffer_commit() first calls function \c wl_surface_frame() to
+Firstly, as seen above, Wayland calls function \c buffer_release_listener() when the client is
+free to reuse or destroy a given \c wl_buffer. FLTK won't change or destroy a committed
+\c wl_buffer before that call.
+Second, this 2-step mechanism prevents Wayland clients from committing new buffer states
+too frequently:
+- \c Fl_Wayland_Graphics_Driver::buffer_commit() first calls function \c wl_surface_frame() to
obtain a pointer to a struct wl_callback object and stores it as member
\c frame_cb of the surface's \ref wld_window.
Then it calls \c wl_callback_add_listener() to associate this object to the
@@ -695,23 +719,6 @@ a new buffer. When the compositor is not ready, the app does not block but conti
computing and drawing in memory but not on display more lines of the desired Mandelbrot
graph.
-Wayland buffer deletion
-Each \ref wld_buffer record contains boolean member \c in_use which is set to \c true
-just before the buffer gets committed, and boolean member \c released which
-is set to \c true when FLTK no longer needs the buffer and calls
-\c Fl_Wayland_Graphics_Driver::buffer_release().
-FLTK's buffer-creating function, \c Fl_Wayland_Graphics_Driver::create_shm_buffer(),
-attaches a 1-member listener to each buffer which Wayland calls after a commit
-operation to indicate the client is allowed to re-use the buffer.
-This listener's member function, \c buffer_release_listener(),
-turns to false member \c in_use of the buffer's \ref wld_buffer record.
-Since the two events 'FLTK no longer needs the buffer' and
-'the client is allowed to re-use the buffer' can arrive in
-any order, FLTK deletes the struct wl_buffer object by running
-\c do_buffer_release() only after both events happened, that is, when \c in_use is
-\c false and \c released is \c true. That's why function \c do_buffer_release()
-is called by both functions \c Fl_Wayland_Graphics_Driver::buffer_release()
-and \c buffer_release_listener().
\section wayland-buffer-factory Buffer factories
@@ -1278,6 +1285,21 @@ force linking any FLTK app with these GL-related libraries.
For example, \c Fl_Wayland_Window_Driver::flush() needs to call
\c Fl_Gl_Window::valid(0).
+Throttling GL window redraws
+Although no documentation covering this subject was found, the EGL library internally
+uses \c wl_callback objects to throttle GL window redraws, and FLTK needs not interfere with
+these operations. Nevertheless FLTK uses \c wl_callback objects for GL windows in 2 cases:
+- when a top-level GL window is being interactively resized, with the
+code described above;
+- when a GL subwindow is being refreshed by \c Fl_Wayland_Gl_Window_Driver::swap_buffers().
+FLTK checks that \c xid->frame_cb is NULL and if so creates a \c wl_callback calling
+\c wl_surface_frame() before calling \c eglSwapBuffers(). This is useful if the GL subwindow
+becomes entirely out from the screen area. In that case, the Mutter compositor stops signaling
+that the subwindow is ready for new commits which FLTK detects because \c xid->frame_cb remains
+non-NULL. If the subwindow eventually re-appears partially on-screen, \c xid->frame_cb
+becomes NULL and FLTK calls \c eglSwapBuffers() to redraw the GL scene.
+
+
\section wayland-type FLTK-defined, Wayland-specific types
\anchor wld_window
--
cgit v1.2.3