mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-13 04:27:47 -05:00
delayed rendering: ignore frame callback if delayed rendering is active
Before, we applied delayed rendering (that is, we gave the client a chance to do more writes before we scheduled a render refresh) only when the renderer were idle. However, with e.g. a high keyboard repeat rate, it is very much possible to start the render loop and then never break out of it while receiving keyboard input. This causes screen flickering, as we're no longer even trying to detect the clients transaction boundaries. So, let's rewrite how this is done. First, we give the user the ability to disable delayed rendering altogether, by setting either the lower or upper timeout to 0. Second, when delayed rendering is enabled, we ignore the frame callback. That is, when receiving input, we *always* reschedule the lower timeout timer, regardless of whether the render is idle or not. The render's frame callback handler will *not* render the grid if the delayed render timers are armed. This means for longer client data bursts, we may now skip frames. That is, we're trading screen flicker for the occasional frame hickup. For short client data bursts we should behave roughly as before. This greatly improves the behavior of fullscreen, or near fullscreen, updates of large grids (example, scrolling in emacs in fullscreen, with a vertical buffer split).
This commit is contained in:
parent
ba0d0e8bbb
commit
5a972cb98e
2 changed files with 10 additions and 8 deletions
5
render.c
5
render.c
|
|
@ -1474,7 +1474,10 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da
|
|||
|
||||
if (term->render.pending.grid) {
|
||||
term->render.pending.grid = false;
|
||||
grid_render(term);
|
||||
|
||||
/* TODO: need to check if this breaks GNOME/weston */
|
||||
if (!term->delayed_render_timer.is_armed)
|
||||
grid_render(term);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
13
terminal.c
13
terminal.c
|
|
@ -32,6 +32,8 @@
|
|||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
#define PTMX_TIMING 0
|
||||
|
||||
static const char *const XCURSOR_LEFT_PTR = "left_ptr";
|
||||
static const char *const XCURSOR_TEXT = "text";
|
||||
static const char *const XCURSOR_HAND2 = "hand2";
|
||||
|
|
@ -125,8 +127,6 @@ fdm_ptmx_out(struct fdm *fdm, int fd, int events, void *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
#define PTMX_TIMING 0
|
||||
|
||||
#if PTMX_TIMING
|
||||
static struct timespec last = {0};
|
||||
#endif
|
||||
|
|
@ -197,9 +197,10 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data)
|
|||
* compositor anyway. The delay we introduce here only
|
||||
* has any effect when the renderer is idle.
|
||||
*/
|
||||
if (term->window->frame_callback == NULL) {
|
||||
/* First timeout - reset each time we receive input. */
|
||||
uint64_t lower_ns = term->conf->tweak.delayed_render_lower_ns;
|
||||
uint64_t upper_ns = term->conf->tweak.delayed_render_upper_ns;
|
||||
|
||||
if (lower_ns > 0 && upper_ns > 0) {
|
||||
#if PTMX_TIMING
|
||||
struct timespec now;
|
||||
|
||||
|
|
@ -215,8 +216,6 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data)
|
|||
last = now;
|
||||
#endif
|
||||
|
||||
uint64_t lower_ns = term->conf->tweak.delayed_render_lower_ns;
|
||||
uint64_t upper_ns = term->conf->tweak.delayed_render_upper_ns;
|
||||
assert(lower_ns < 1000000000);
|
||||
assert(upper_ns < 1000000000);
|
||||
assert(upper_ns > lower_ns);
|
||||
|
|
@ -236,7 +235,7 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data)
|
|||
term->delayed_render_timer.is_armed = true;
|
||||
}
|
||||
} else
|
||||
term->render.pending.grid = true;
|
||||
render_refresh(term);
|
||||
}
|
||||
|
||||
if (hup) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue