diff options
author | Dudemanguy <random342@airmail.cc> | 2022-06-10 11:49:28 -0500 |
---|---|---|
committer | Dudemanguy <random342@airmail.cc> | 2022-06-19 18:13:55 +0000 |
commit | 7ce26dd3248a45a4d5e0a8c15a981834e7efc733 (patch) | |
tree | b79e41d7b30ceaa8df3d1c64427acb73775916ba /video/out/wayland_common.c | |
parent | 44ecf83a1bd94f69cbe7e55b900f2502d15d7d5c (diff) | |
download | mpv-7ce26dd3248a45a4d5e0a8c15a981834e7efc733.tar.bz2 mpv-7ce26dd3248a45a4d5e0a8c15a981834e7efc733.tar.xz |
vo: move wayland presentation to separate files
Wayland had some specific code that it used for implementing the
presentation time protocol. It turns out that xorg's present extension
is extremely similar, so it would be silly to duplicate this whole mess
again. Factor this out to separate, independent code and introduce the
mp_present struct which is used for handling the ust/msc values and some
other associated values. Also, add in some helper functions so all the
dirty details live specifically in present_sync. The only
wayland-specific part is actually obtaining ust/msc values. Since only
wayland or xorg are expected to use this, add a conditional to the build
that only adds this file when either one of those are present.
You may observe that sbc is completely omitted. This field existed in
wayland, but was completely unused (presentation time doesn't return
this). Xorg's present extension also doesn't use this so just get rid of
it all together. The actual calculation is slightly altered so it is
correct for our purposes. We want to get the presentation event of the
last frame that was just occured (this function executes right after the
buffer swap). The adjustment is to just remove the vsync_duration
subtraction. Also, The overly-complicated queue approach is removed.
This has no actual use in practice (on wayland or xorg). Presentation
statistics are only ever used after the immediate preceding swap to
update vsync timings or thrown away.
Diffstat (limited to 'video/out/wayland_common.c')
-rw-r--r-- | video/out/wayland_common.c | 96 |
1 files changed, 7 insertions, 89 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 698cec1ec8..c705f6e165 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -30,6 +30,7 @@ #include "options/m_config.h" #include "osdep/io.h" #include "osdep/timer.h" +#include "present_sync.h" #include "wayland_common.h" #include "win_state.h" @@ -143,28 +144,18 @@ struct vo_wayland_output { struct wl_list link; }; -struct vo_wayland_sync { - int64_t ust; - int64_t msc; - int64_t sbc; - bool filled; -}; - static int check_for_resize(struct vo_wayland_state *wl, wl_fixed_t x_w, wl_fixed_t y_w, int edge_pixels, enum xdg_toplevel_resize_edge *edge); static int get_mods(struct vo_wayland_state *wl); -static int last_available_sync(struct vo_wayland_state *wl); static int lookupkey(int key); static int set_cursor_visibility(struct vo_wayland_state *wl, bool on); static int spawn_cursor(struct vo_wayland_state *wl); static void greatest_common_divisor(struct vo_wayland_state *wl, int a, int b); -static void queue_new_sync(struct vo_wayland_state *wl); static void remove_output(struct vo_wayland_output *out); static void request_decoration_mode(struct vo_wayland_state *wl, uint32_t mode); static void set_geometry(struct vo_wayland_state *wl); static void set_surface_scaling(struct vo_wayland_state *wl); -static void sync_shift(struct vo_wayland_state *wl); static void window_move(struct vo_wayland_state *wl, uint32_t serial); /* Wayland listener boilerplate */ @@ -980,7 +971,6 @@ static void feedback_presented(void *data, struct wp_presentation_feedback *fbac uint32_t flags) { struct vo_wayland_state *wl = data; - sync_shift(wl); if (fback) wp_presentation_feedback_destroy(fback); @@ -996,15 +986,10 @@ static void feedback_presented(void *data, struct wp_presentation_feedback *fbac // - seq_lo + seq_hi is the equivalent of oml's msc // - these values are updated everytime the compositor receives feedback. - int index = last_available_sync(wl); - if (index < 0) { - queue_new_sync(wl); - index = 0; - } int64_t sec = (uint64_t) tv_sec_lo + ((uint64_t) tv_sec_hi << 32); - wl->sync[index].ust = sec * 1000000LL + (uint64_t) tv_nsec / 1000; - wl->sync[index].msc = (uint64_t) seq_lo + ((uint64_t) seq_hi << 32); - wl->sync[index].filled = true; + int64_t ust = sec * 1000000LL + (uint64_t) tv_nsec / 1000; + int64_t msc = (uint64_t) seq_lo + ((uint64_t) seq_hi << 32); + present_update_sync_values(wl->present, ust, msc); } static void feedback_discarded(void *data, struct wp_presentation_feedback *fback) @@ -1378,15 +1363,6 @@ static struct vo_wayland_output *find_output(struct vo_wayland_state *wl) return fallback_output; } -static int last_available_sync(struct vo_wayland_state *wl) -{ - for (int i = wl->sync_size - 1; i > -1; --i) { - if (!wl->sync[i].filled) - return i; - } - return -1; -} - static int lookupkey(int key) { const char *passthrough_keys = " -+*/<>`~!@#$%^&()_{}:;\"\',.?\\|=[]"; @@ -1403,13 +1379,6 @@ static int lookupkey(int key) return mpkey; } -static void queue_new_sync(struct vo_wayland_state *wl) -{ - wl->sync_size += 1; - wl->sync = talloc_realloc(wl, wl->sync, struct vo_wayland_sync, wl->sync_size); - sync_shift(wl); -} - static void request_decoration_mode(struct vo_wayland_state *wl, uint32_t mode) { wl->requested_decoration = mode; @@ -1544,15 +1513,6 @@ static int spawn_cursor(struct vo_wayland_state *wl) return 0; } -static void sync_shift(struct vo_wayland_state *wl) -{ - for (int i = wl->sync_size - 1; i > 0; --i) { - wl->sync[i] = wl->sync[i-1]; - } - struct vo_wayland_sync sync = {0, 0, 0, 0}; - wl->sync[0] = sync; -} - static void toggle_fullscreen(struct vo_wayland_state *wl) { if (!wl->xdg_toplevel) @@ -1813,6 +1773,7 @@ int vo_wayland_init(struct vo *vo) .display = wl_display_connect(NULL), .vo = vo, .log = mp_log_new(wl, vo->log, "wayland"), + .refresh_interval = 0, .scaling = 1, .wakeup_pipe = {-1, -1}, .dnd_fd = -1, @@ -1874,13 +1835,7 @@ int vo_wayland_init(struct vo *vo) } if (wl->presentation) { - wl->last_ust = 0; - wl->last_msc = 0; - wl->refresh_interval = 0; - wl->sync = talloc_zero_array(wl, struct vo_wayland_sync, 1); - struct vo_wayland_sync sync = {0, 0, 0, 0}; - wl->sync[0] = sync; - wl->sync_size += 1; + wl->present = talloc_zero(wl, struct mp_present); } else { MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", wp_presentation_interface.name); @@ -1979,43 +1934,6 @@ bool vo_wayland_supported_format(struct vo *vo, uint32_t drm_format) return false; } -void vo_wayland_sync_swap(struct vo_wayland_state *wl) -{ - int index = wl->sync_size - 1; - - // If these are the same, presentation feedback has not been received. - // This can happen if a frame takes too long and misses vblank. - // Additionally, a compositor may return an ust value of 0. In either case, - // Don't attempt to use these statistics and wait until the next presentation - // event arrives. - if (!wl->sync[index].ust || wl->sync[index].ust == wl->last_ust) { - wl->last_skipped_vsyncs = -1; - wl->vsync_duration = -1; - wl->last_queue_display_time = -1; - return; - } - - wl->last_skipped_vsyncs = 0; - - int64_t ust_passed = wl->sync[index].ust ? wl->sync[index].ust - wl->last_ust: 0; - wl->last_ust = wl->sync[index].ust; - int64_t msc_passed = wl->sync[index].msc ? wl->sync[index].msc - wl->last_msc: 0; - wl->last_msc = wl->sync[index].msc; - - if (msc_passed && ust_passed) - wl->vsync_duration = ust_passed / msc_passed; - - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts)) { - return; - } - - uint64_t now_monotonic = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000; - uint64_t ust_mp_time = mp_time_us() - (now_monotonic - wl->sync[index].ust); - - wl->last_queue_display_time = ust_mp_time + wl->vsync_duration; -} - void vo_wayland_uninit(struct vo *vo) { struct vo_wayland_state *wl = vo->wl; @@ -2149,7 +2067,7 @@ void vo_wayland_wait_frame(struct vo_wayland_state *wl) * 4. make up crap if vblank_time is still <= 0 (better than nothing) */ if (wl->presentation) - vblank_time = wl->vsync_duration; + vblank_time = wl->present->vsync_duration; if (vblank_time <= 0 && wl->refresh_interval > 0) vblank_time = wl->refresh_interval; |