diff --git a/meson.build b/meson.build index 91b8e84b15..4485c74a56 100644 --- a/meson.build +++ b/meson.build @@ -424,6 +424,9 @@ if posix and not darwin 'osdep/timer-linux.c') endif +features += {'ppoll': cc.has_function('ppoll', args: '-D_GNU_SOURCE', + prefix: '#include ')} + cd_devices = { 'windows': 'D:', 'cygwin': 'D:', diff --git a/osdep/poll_wrapper.c b/osdep/poll_wrapper.c index e4ad0f698a..48a66d2cd1 100644 --- a/osdep/poll_wrapper.c +++ b/osdep/poll_wrapper.c @@ -20,9 +20,20 @@ #include #include +#include "config.h" #include "poll_wrapper.h" +#include "timer.h" +int mp_poll(struct pollfd *fds, int nfds, int64_t timeout_ns) +{ +#if HAVE_PPOLL + struct timespec ts = mp_time_ns_to_realtime(timeout_ns); + return ppoll(fds, nfds, &ts, NULL); +#endif + return poll(fds, nfds, timeout_ns / 1e6); +} + // poll shim that supports device files on macOS. int polldev(struct pollfd fds[], nfds_t nfds, int timeout) { diff --git a/osdep/poll_wrapper.h b/osdep/poll_wrapper.h index 8593c1e77c..b359ed39a0 100644 --- a/osdep/poll_wrapper.h +++ b/osdep/poll_wrapper.h @@ -1,7 +1,12 @@ #pragma once #include +#include // Behaves like poll(3) but works for device files on macOS. // Only supports POLLIN and POLLOUT. int polldev(struct pollfd fds[], nfds_t nfds, int timeout); + +// Generic polling wrapper. It will try and use higher resolution +// polling (ppoll) if available. +int mp_poll(struct pollfd *fds, int nfds, int64_t timeout_ns); diff --git a/video/out/drm_common.c b/video/out/drm_common.c index dd53793dbb..f8d68dfa81 100644 --- a/video/out/drm_common.c +++ b/video/out/drm_common.c @@ -42,6 +42,7 @@ #include "common/msg.h" #include "options/m_config.h" #include "osdep/io.h" +#include "osdep/poll_wrapper.h" #include "osdep/timer.h" #include "misc/ctype.h" #include "video/out/vo.h" @@ -283,12 +284,12 @@ static void vt_switcher_destroy(struct vt_switcher *s) close(vt_switcher_pipe[1]); } -static void vt_switcher_poll(struct vt_switcher *s, int timeout_ms) +static void vt_switcher_poll(struct vt_switcher *s, int timeout_ns) { struct pollfd fds[1] = { { .events = POLLIN, .fd = vt_switcher_pipe[0] }, }; - poll(fds, 1, timeout_ms); + mp_poll(fds, 1, timeout_ns); if (!fds[0].revents) return; @@ -1309,8 +1310,8 @@ void vo_drm_wait_events(struct vo *vo, int64_t until_time_ns) struct vo_drm_state *drm = vo->drm; if (drm->vt_switcher_active) { int64_t wait_ns = until_time_ns - mp_time_ns(); - int timeout_ms = MPCLAMP(wait_ns / 1e6, 1, 10000); - vt_switcher_poll(&drm->vt_switcher, timeout_ms); + int64_t timeout_ns = MPCLAMP(wait_ns, 1e6, 1e10); + vt_switcher_poll(&drm->vt_switcher, timeout_ns); } else { vo_wait_default(vo, until_time_ns); } diff --git a/video/out/x11_common.c b/video/out/x11_common.c index be5002b068..f77f4c86f8 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -55,6 +55,7 @@ #include "vo.h" #include "win_state.h" #include "osdep/io.h" +#include "osdep/poll_wrapper.h" #include "osdep/timer.h" #include "osdep/subprocess.h" @@ -2177,9 +2178,9 @@ void vo_x11_wait_events(struct vo *vo, int64_t until_time_ns) { .fd = x11->wakeup_pipe[0], .events = POLLIN }, }; int64_t wait_ns = until_time_ns - mp_time_ns(); - int timeout_ms = MPCLAMP(wait_ns / 1e6, 1, 10000); + int64_t timeout_ns = MPCLAMP(wait_ns, 1e6, 1e10); - poll(fds, 2, timeout_ms); + mp_poll(fds, 2, timeout_ns); if (fds[1].revents & POLLIN) mp_flush_wakeup_pipe(x11->wakeup_pipe[0]);