summaryrefslogtreecommitdiffstats
path: root/video/out/wayland_common.c
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2022-06-10 11:49:28 -0500
committerDudemanguy <random342@airmail.cc>2022-06-19 18:13:55 +0000
commit7ce26dd3248a45a4d5e0a8c15a981834e7efc733 (patch)
treeb79e41d7b30ceaa8df3d1c64427acb73775916ba /video/out/wayland_common.c
parent44ecf83a1bd94f69cbe7e55b900f2502d15d7d5c (diff)
downloadmpv-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.c96
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;