aboutsummaryrefslogtreecommitdiff
path: root/wiki/Development:-Redraw-Loop.md
diff options
context:
space:
mode:
authorKent Daleng <lolexplode@gmail.com>2025-03-15 16:42:05 +0100
committerGitHub <noreply@github.com>2025-03-15 15:42:05 +0000
commit392fc27de110d3548095e465d5cb38bd8d5730ea (patch)
treec465f8975db4e6f90c9f875cb6e7722af175901f /wiki/Development:-Redraw-Loop.md
parent9e560e7e607638da4f47b6dfef5a83b18711f75d (diff)
downloadniri-392fc27de110d3548095e465d5cb38bd8d5730ea.tar.gz
niri-392fc27de110d3548095e465d5cb38bd8d5730ea.tar.bz2
niri-392fc27de110d3548095e465d5cb38bd8d5730ea.zip
Use anchors on the wiki (#1266)
* wiki testing * wiki updates * use .md with anchors, revert sidebar * bump wiki action * add some more anchors, fix some language * change links to be more descriptive by themselves
Diffstat (limited to 'wiki/Development:-Redraw-Loop.md')
-rw-r--r--wiki/Development:-Redraw-Loop.md22
1 files changed, 22 insertions, 0 deletions
diff --git a/wiki/Development:-Redraw-Loop.md b/wiki/Development:-Redraw-Loop.md
new file mode 100644
index 00000000..7f3d1873
--- /dev/null
+++ b/wiki/Development:-Redraw-Loop.md
@@ -0,0 +1,22 @@
+On a TTY, only one frame can be submitted to an output at a time, and the compositor must wait until the output repaints (indicated by a VBlank) to be able to submit the next frame.
+In niri we keep track of this via the `RedrawState` enum that you can find in an `OutputState`.
+
+Here's a diagram of state transitions for the `RedrawState` state machine:
+
+<picture>
+ <source media="(prefers-color-scheme: dark)" srcset="./img/RedrawState-dark.drawio.png">
+ <img alt="RedrawState state transition diagram" src="./img/RedrawState-light.drawio.png">
+</picture>
+
+`Idle` is the default state, when the output does not need to be repainted.
+Any operation that may cause the screen to update calls `queue_redraw()`, which moves the output to a `Queued` state.
+Then, at the end of an event loop dispatch, niri calls `redraw()` for every `Queued` output.
+
+If the redraw causes damage (i.e. something on the output changed), we move into the `WaitingForVBlank` state, since we cannot redraw until we receive a VBlank event.
+However, if there's no damage, we do not return to `Idle` right away.
+Instead, we set a timer to fire roughly at when the next VBlank would occur, and transition to a `WaitingForEstimatedVBlank` state.
+
+This is necessary in order to throttle frame callbacks sent to applications to at most once per output refresh cycle.
+Without this throttling, applications can start continuously redrawing without damage (for instance, if the application window is partially off-screen, and it is only the off-screen part that changes), and eating a lot of CPU in the process.
+
+Then, either the estimated VBlank timer completes, and we go back to `Idle`, or maybe we call `queue_redraw()` once more and try to redraw again.