main: use a timer FD to delay render refresh after client data

This ensures we never wait *longer* than 1ms (previously, we could end
up doing multiple polls, each with a timeout value of 1ms - thereby
potentially delaying the refresh indefinitely).
This commit is contained in:
Daniel Eklöf 2019-08-30 17:57:46 +02:00
parent fb018eb64e
commit 9f7ea6292e
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F

33
main.c
View file

@ -14,6 +14,7 @@
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/time.h>
#include <freetype/tttables.h> #include <freetype/tttables.h>
#include <wayland-client.h> #include <wayland-client.h>
@ -888,8 +889,9 @@ main(int argc, char *const *argv)
} }
} }
bool timeout_is_armed = false;
int timeout_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);
int timeout_ms = -1;
while (true) { while (true) {
struct pollfd fds[] = { struct pollfd fds[] = {
{.fd = wl_display_get_fd(term.wl.display), .events = POLLIN}, {.fd = wl_display_get_fd(term.wl.display), .events = POLLIN},
@ -897,10 +899,11 @@ main(int argc, char *const *argv)
{.fd = term.kbd.repeat.fd, .events = POLLIN}, {.fd = term.kbd.repeat.fd, .events = POLLIN},
{.fd = term.flash.fd, .events = POLLIN}, {.fd = term.flash.fd, .events = POLLIN},
{.fd = term.blink.fd, .events = POLLIN}, {.fd = term.blink.fd, .events = POLLIN},
{.fd = timeout_fd, .events = POLLIN},
}; };
wl_display_flush(term.wl.display); wl_display_flush(term.wl.display);
int pret = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout_ms); int pret = poll(fds, sizeof(fds) / sizeof(fds[0]), -1);
if (pret == -1) { if (pret == -1) {
if (errno == EINTR) if (errno == EINTR)
@ -910,13 +913,19 @@ main(int argc, char *const *argv)
break; break;
} }
if (pret == 0 || (timeout_ms != -1 && !(fds[1].revents & POLLIN))) { if (fds[5].revents & POLLIN) {
/* Delayed rendering */ assert(timeout_is_armed);
render_refresh(&term);
}
/* Reset poll timeout to infinity */ uint64_t unused;
timeout_ms = -1; ssize_t ret = read(timeout_fd, &unused, sizeof(unused));
if (ret < 0 && errno != EAGAIN)
LOG_ERRNO("failed to read timeout timer");
else if (ret > 0) {
timeout_is_armed = false;
render_refresh(&term);
}
}
if (fds[0].revents & POLLIN) { if (fds[0].revents & POLLIN) {
wl_display_dispatch(term.wl.display); wl_display_dispatch(term.wl.display);
@ -968,7 +977,10 @@ main(int argc, char *const *argv)
* ourselves we just received keyboard input, and in * ourselves we just received keyboard input, and in
* this case *not* delay rendering? * this case *not* delay rendering?
*/ */
timeout_ms = 1; if (!timeout_is_armed) {
timerfd_settime(timeout_fd, 0, &(struct itimerspec){.it_value = {.tv_nsec = 1000000}}, NULL);
timeout_is_armed = true;
}
} }
} }
@ -1039,9 +1051,10 @@ main(int argc, char *const *argv)
render_refresh(&term); render_refresh(&term);
} }
} }
} }
close(timeout_fd);
out: out:
mtx_lock(&term.render.workers.lock); mtx_lock(&term.render.workers.lock);
assert(tll_length(term.render.workers.queue) == 0); assert(tll_length(term.render.workers.queue) == 0);