diff options
Diffstat (limited to 'video/out/opengl/context_glx.c')
-rw-r--r-- | video/out/opengl/context_glx.c | 101 |
1 files changed, 5 insertions, 96 deletions
diff --git a/video/out/opengl/context_glx.c b/video/out/opengl/context_glx.c index 1f3225a9ac..7dc8062c1c 100644 --- a/video/out/opengl/context_glx.c +++ b/video/out/opengl/context_glx.c @@ -40,6 +40,7 @@ #include "osdep/timer.h" #include "video/out/x11_common.h" #include "context.h" +#include "oml_sync.h" #include "utils.h" struct priv { @@ -49,14 +50,7 @@ struct priv { GLXFBConfig fbc; Bool (*XGetSyncValues)(Display*, GLXDrawable, int64_t*, int64_t*, int64_t*); - int64_t last_ust; - int64_t last_msc; - int64_t last_sbc; - int64_t last_sbc_mp_time; - int64_t user_sbc; - int64_t vsync_duration; - int64_t last_skipped_vsyncs; - int64_t last_queue_display_time; + struct oml_sync sync; }; static void glx_uninit(struct ra_ctx *ctx) @@ -232,91 +226,12 @@ static void update_vsync_oml(struct ra_ctx *ctx) assert(p->XGetSyncValues); - p->last_skipped_vsyncs = 0; - p->user_sbc += 1; - - // This extension returns two unrelated values: - // (ust, msc): clock time and incrementing counter of last vsync (this is - // reported continuously, even if we don't swap) - // sbc: swap counter of frame that was last displayed (every swap - // increments the user_sbc, and the reported sbc is the sbc - // of the frame that was just displayed) - // Invariants: - // - ust and msc change in lockstep (no value can change with the other) - // - msc is incremented; if you query it in a loop, and your thread isn't - // frozen or starved by the scheduler, it will usually not change or - // be incremented by 1 (while the ust will be incremented by vsync - // duration) - // - sbc is never higher than the user_sbc - // - (ust, msc) are equal to or higher by vsync increments than the display - // time of the frame referenced by the sbc - // Note that (ust, msc) and sbc are not locked to each other. The following - // can easily happen if vsync skips occur: - // - you draw a frame, in the meantime hardware swaps sbc_1 - // - another display vsync happens during drawing - // - you call swap() - // - query (ust, msc) and sbc - // - sbc contains sbc_1, but (ust, msc) contains the vsync after it - // As a consequence, it's hard to detect the latency or vsync skips. int64_t ust, msc, sbc; if (!p->XGetSyncValues(ctx->vo->x11->display, ctx->vo->x11->window, &ust, &msc, &sbc)) - { - // Assume the extension is effectively unsupported. - p->vsync_duration = -1; - p->last_skipped_vsyncs = -1; - p->last_queue_display_time = -1; - return; - } - - int64_t ust_passed = p->last_ust ? ust - p->last_ust : 0; - p->last_ust = ust; - - int64_t msc_passed = p->last_msc ? msc - p->last_msc : 0; - p->last_msc = msc; - - int64_t sbc_passed = sbc - p->last_sbc; - p->last_sbc = sbc; - - // Display frame duration. This makes assumptions about UST (see below). - if (msc_passed && ust_passed) - p->vsync_duration = ust_passed / msc_passed; - - // Only if a new frame was displayed (sbc increased) we have sort-of a - // chance that the current (ust, msc) is for the sbc. But this is racy, - // because skipped frames drops could have increased the msc right after the - // display event and before we queried the values. This code hopes for the - // best and ignores this. - if (sbc_passed) { - // The extension spec doesn't define what the UST is (not even its unit). - // Simply assume UST is a simple CLOCK_MONOTONIC usec value. The swap - // buffer call happened "some" but very small time ago, so we can get - // away with querying the current time. There is also the implicit - // assumption that mpv's timer and the UST use the same clock (which it - // does on POSIX). - 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 - ust); - - // Assume this is exactly when the actual display event for this sbc - // happened. This is subject to the race mentioned above. - p->last_sbc_mp_time = ust_mp_time; - } + ust = msc = sbc = -1; - // At least one frame needs to be actually displayed before - // p->last_sbc_mp_time is set. - if (!sbc) - return; - - // Extrapolate from the last sbc time (when a frame was actually displayed), - // and by adding the number of frames that were queued since to it. - // For every unit the sbc is smaller than user_sbc, the actual display - // is one frame ahead (assumes glx_swap_buffers() is called for every - // vsync). - p->last_queue_display_time = - p->last_sbc_mp_time + (p->user_sbc - sbc) * p->vsync_duration; + oml_sync_swap(&p->sync, ust, msc, sbc); } static void glx_swap_buffers(struct ra_ctx *ctx) @@ -332,9 +247,7 @@ static void glx_swap_buffers(struct ra_ctx *ctx) static void glx_get_vsync(struct ra_ctx *ctx, struct vo_vsync_info *info) { struct priv *p = ctx->priv; - info->vsync_duration = p->vsync_duration; - info->skipped_vsyncs = p->last_skipped_vsyncs; - info->last_queue_display_time = p->last_queue_display_time; + oml_sync_get_info(&p->sync, info); } static bool glx_init(struct ra_ctx *ctx) @@ -426,10 +339,6 @@ static bool glx_init(struct ra_ctx *ctx) if (!ra_gl_ctx_init(ctx, gl, params)) goto uninit; - p->vsync_duration = -1; - p->last_skipped_vsyncs = -1; - p->last_queue_display_time = -1; - return true; uninit: |