mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
render: when double-buffering, pre-apply previous frame's damage early
Foot likes it when compositor releases buffer immediately, as that means we only have to re-render the cells that have changed since the last frame. For various reasons, not all compositors do this. In this case, foot is typically forced to switch between two buffers, i.e. double-buffer. In this case, each frame starts with copying over the damage from the previous frame, to the new frame. Then we start rendering the updated cells. Bringing over the previous frame's damage can be slow, if the changed area was large (e.g. when scrolling one or a few lines, or on full screen updates). It's also done single-threaded. Thus it not only slows down frame rendering, but pauses everything else (i.e. input processing). All in all, it reduces performance and increases input latency. But we don't have to wait until it's time to render a frame to copy over the previous frame's damage. We can do that as soon as the compositor has released the buffer (for the frame _before_ the previous frame). And we can do this in a thread. This frees up foot to continue processing input, and reduces frame rendering time since we can now start rendering the modified cells immediately, without first doing a large memcpy(3). In worst case scenarios (or perhaps we should consider them best case scenarios...), I've seen up to a 10x performance increase in frame rendering times (this obviously does *not* include the time it takes to copy over the previous frame's damage, since that doesn't affect neither input processing nor frame rendering). Implemented by adding a callback mechanism to the shm abstraction layer. Use it for the grid buffers, and kick off a thread that copies the previous frame's damage, and resets the buffers age to 0 (so that foot understands it can start render to it immediately when it later needs to render a frame). Since we have certain way of knowing if a compositor releases buffers immediately or not, use a bit of heuristics; if we see 10 consecutive non-immediate releases (that is, we reset the counter as soon as we do see an immediate release), this new "pre-apply damage" logic is enabled. It can be force-disabled with tweak.pre-apply-damage=no. We also need to take care to wait for the thread before resetting the render's "last_buf" pointer (or we'll SEGFAULT in the thread...). We must also ensure we wait for the thread to finish before we start rendering a new frame. Under normal circumstances, the wait time is always 0, the thread has almost always finished long before we need to render the next frame. But it _can_ happen. Closes #2188
This commit is contained in:
parent
bb314425ef
commit
299186a654
11 changed files with 287 additions and 26 deletions
|
|
@ -2093,6 +2093,41 @@ any of these options.
|
|||
|
||||
Default: _auto_
|
||||
|
||||
*pre-apply-damage*
|
||||
Boolean. When enabled, foot will attempt to "pre-apply" the damage
|
||||
from the last frame when foot is forced to double-buffer
|
||||
(i.e. when the compositor does not release SHM buffers
|
||||
immediately). All text after this assumes the compositor is not
|
||||
releasing buffers immediately.
|
||||
|
||||
When this option is disabled, each time foot needs to render a
|
||||
frame, it has to first copy over areas that changed in the last
|
||||
frame (i.e. all changes between the last two frames). This is
|
||||
basically a *memcpy*(3), which can be slow if the changed area is
|
||||
large. It is also done on the main thread, which means foot cannot
|
||||
do anything else at the same time; no other rendering, no VT
|
||||
parsing. After the changes have been brought over to the new
|
||||
frame, foot proceeds with rendering the cells that has changed
|
||||
between the last frame and the new frame.
|
||||
|
||||
When this open is enabled, the changes between the last two frames
|
||||
are brought over to what will become the next frame before foot
|
||||
starts rendering the next frame. As soon as the compositor
|
||||
releases the previous buffer (typically right after foot has
|
||||
pushed a new frame), foot kicks off a thread that copies over the
|
||||
changes to the newly released buffer. Since this is done in a
|
||||
thread, foot can continue processing input at the same
|
||||
time. Later, when it is time to render a new frame, the changes
|
||||
have already been transferred, and foot can immediately start with
|
||||
the actual rendering.
|
||||
|
||||
Thus, having this option enabled improves both performance
|
||||
(copying the last two frames' changes is threaded), and improves
|
||||
input latency (rending the next frame no longer has to first bring
|
||||
over the changes between the last two frames).
|
||||
|
||||
Default: _yes_
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
*foot*(1), *footclient*(1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue