summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-09-24 09:52:48 +0200
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-09-24 09:52:48 +0200
commit59b251cc39bc5735bbd33ab4fbf41dab03efef21 (patch)
tree739681c40561c612a5e79001f48ceae6c3658752
parentc02ecbcae20e4d86299a8e445ed116bf16924249 (diff)
Slightly simpler Fl_Wayland_Window_Driver::flush()
and beef up description of Wayland's mechanism to throttle screen redrawing.
-rw-r--r--documentation/src/wayland.dox75
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx7
2 files changed, 45 insertions, 37 deletions
diff --git a/documentation/src/wayland.dox b/documentation/src/wayland.dox
index 7431e8d5f..9842d59ac 100644
--- a/documentation/src/wayland.dox
+++ b/documentation/src/wayland.dox
@@ -568,23 +568,52 @@ 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.
+<h3>Throttling redrawing operations</h3>
An important detail here is that FLTK uses Wayland's synchronization
-mechanism to make sure the surface's \c wl_buffer is not changed until the surface is fully
-mapped on the display. This 3-step mechanism works as follows:
+mechanism to make sure the surface's \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 3-step mechanism works as follows:
- Fl_Wayland_Graphics_Driver::buffer_commit() first calls function \c wl_surface_frame() to
-obtain a <tt>struct wl_callback</tt> object and stores it as member \c cb of the surface's
-\ref wld_buffer.
-- Then it calls \c wl_callback_add_listener() to associate this object to the FLTK-defined,
-callback function \c surface_frame_done() that Wayland calls when it's ready for another
-mapping operation.
-- Finally \c surface_frame_done() destroys the \c wl_callback object by function
-\c wl_callback_destroy() and sets member \c cb to NULL.
+obtain a pointer to a <tt>struct wl_callback</tt> object and stores it as member
+\c cb of the surface's \ref wld_buffer.
+- Then it calls \c wl_callback_add_listener() to associate this object to the
+FLTK-defined, callback function \c surface_frame_done() that Wayland will call
+later when ready for another mapping operation. It next calls
+\c wl_surface_commit() which starts the mapping of the buffer content on
+the display.
+- Later, \c surface_frame_done() runs and destroys the \c wl_callback object by
+function \c wl_callback_destroy() and sets member \c cb to NULL.
+
+Member variable \c draw_buffer_needs_commit of the \ref wld_buffer is also
+important in this mechanism : it informs FLTK that the graphics buffer has
+changed and needs being committed. This variable is turned \c true every time a
+graphics operation changes the buffer content and turned \c false when the
+buffer gets committed.
This procedure ensures that FLTK never changes the surface's Wayland buffer
-while it's being used by the compositor because \c Fl_Wayland_Window_Driver::flush()
-checks that \c cb is NULL before calling \c Fl_Wayland_Graphics_Driver::buffer_commit().
-If it's not NULL, FLTK calls function \c wl_callback_destroy() which instructs the compositor
-to abort the mapping operation and to get ready for processing of a new byte buffer.
+while it's being used by the compositor and never calls \c wl_surface_commit()
+before Wayland gets ready for a new commit because
+\c Fl_Wayland_Window_Driver::flush() calls
+\c Fl_Wayland_Graphics_Driver::buffer_commit() only if \c cb is NULL.
+If it's not NULL, the exact content of function \c surface_frame_done() :
+\code
+static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) {
+ struct wld_window *window = (struct wld_window *)data;
+ wl_callback_destroy(cb);
+ if (window->buffer) {
+ window->buffer->cb = NULL;
+ if (window->buffer->draw_buffer_needs_commit) {
+ Fl_Wayland_Graphics_Driver::buffer_commit(window);
+ }
+ }
+}
+\endcode
+has the effect that when the mapping operation eventually completes, Wayland runs
+\c surface_frame_done(), which calls anew
+\c Fl_Wayland_Graphics_Driver::buffer_commit() because the buffer's
+\c draw_buffer_needs_commit member is true. The net result is that the screen
+shows the most recent surface content.
<h3>Progressive window drawing</h3>
FLTK supports progressive drawing when an app calls function Fl_Window::make_current()
@@ -604,26 +633,10 @@ which means that the compositor is ready to start performing a mapping operation
This occurs when the progressive drawing operation begins. Later, \c cb is generally found
non NULL when \c Fl_Wayland_Window_Driver::make_current() runs because the compositor
is busy processing the previous Wayland buffer. When the compositor has completed
-this processing, the client app runs \c surface_frame_done() :
-\code
-static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) {
- struct wld_window *window = (struct wld_window *)data;
- wl_callback_destroy(cb);
- if (window->buffer) {
- window->buffer->cb = NULL;
- if (window->buffer->draw_buffer_needs_commit) {
- Fl_Wayland_Graphics_Driver::buffer_commit(window);
- }
- }
-}
-\endcode
+this processing, the client app runs \c surface_frame_done()
which, provided member variable \c draw_buffer_needs_commit is true, calls
\c Fl_Wayland_Graphics_Driver::buffer_commit(). This makes the compositor map the
-Wayland buffer in its new, more advanced, state. Here is where member variable
-\c draw_buffer_needs_commit is useful : it informs Wayland that the graphics
-buffer has changed and needs being committed. This variable is turned \c true
-every time a graphics operation changes the buffer content and turned \c false
-when the buffer gets committed.
+Wayland buffer in its new, more advanced, state.
An example of progressive drawing is given by FLTK's mandelbrot test app.
When set to fullscreen, this app can be seen to progressively fill its window from
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
index f5b43c962..b149cbe0b 100644
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
@@ -399,12 +399,7 @@ void Fl_Wayland_Window_Driver::flush() {
Fl_Wayland_Window_Driver::in_flush_ = true;
Fl_Window_Driver::flush();
Fl_Wayland_Window_Driver::in_flush_ = false;
- if (window->buffer->cb) {
- wl_callback_destroy(window->buffer->cb);
- window->buffer->cb = NULL;
- r = NULL;
- }
- Fl_Wayland_Graphics_Driver::buffer_commit(window, r);
+ if (!window->buffer->cb) Fl_Wayland_Graphics_Driver::buffer_commit(window, r);
}