mirror of
https://github.com/mpv-player/mpv
synced 2025-02-16 12:17:12 +00:00
wayland: add presentation time
Use ust/msc/refresh values from wayland's presentation time in mpv's ra_swapchain_fns.get_vsync for the wayland contexts.
This commit is contained in:
parent
3568aed164
commit
bedca07a02
@ -25,6 +25,9 @@
|
|||||||
#include "egl_helpers.h"
|
#include "egl_helpers.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
// Generated from presentation-time.xml
|
||||||
|
#include "video/out/wayland/presentation-time.h"
|
||||||
|
|
||||||
struct priv {
|
struct priv {
|
||||||
GL gl;
|
GL gl;
|
||||||
EGLDisplay egl_display;
|
EGLDisplay egl_display;
|
||||||
@ -45,13 +48,62 @@ static void frame_callback(void *data, struct wl_callback *callback, uint32_t ti
|
|||||||
|
|
||||||
wl->frame_callback = wl_surface_frame(wl->surface);
|
wl->frame_callback = wl_surface_frame(wl->surface);
|
||||||
wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
|
wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
|
||||||
wl->callback_wait = false;
|
wl->frame_wait = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_callback_listener frame_listener = {
|
static const struct wl_callback_listener frame_listener = {
|
||||||
frame_callback,
|
frame_callback,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct wp_presentation_feedback_listener feedback_listener;
|
||||||
|
|
||||||
|
static void feedback_sync_output(void *data, struct wp_presentation_feedback *fback,
|
||||||
|
struct wl_output *output)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void feedback_presented(void *data, struct wp_presentation_feedback *fback,
|
||||||
|
uint32_t tv_sec_hi, uint32_t tv_sec_lo,
|
||||||
|
uint32_t tv_nsec, uint32_t refresh_nsec,
|
||||||
|
uint32_t seq_hi, uint32_t seq_lo,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
struct vo_wayland_state *wl = data;
|
||||||
|
wp_presentation_feedback_destroy(fback);
|
||||||
|
vo_wayland_sync_shift(wl);
|
||||||
|
|
||||||
|
// Very similar to oml_sync_control, in this case we assume that every
|
||||||
|
// time the compositor receives feedback, a buffer swap has been already
|
||||||
|
// been performed.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// - tv_sec_lo + tv_sec_hi is the equivalent of oml's ust
|
||||||
|
// - 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].sbc = wl->user_sbc;
|
||||||
|
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].refresh_usec = (uint64_t)refresh_nsec/1000;
|
||||||
|
wl->sync[index].filled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void feedback_discarded(void *data, struct wp_presentation_feedback *fback)
|
||||||
|
{
|
||||||
|
wp_presentation_feedback_destroy(fback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_presentation_feedback_listener feedback_listener = {
|
||||||
|
feedback_sync_output,
|
||||||
|
feedback_presented,
|
||||||
|
feedback_discarded,
|
||||||
|
};
|
||||||
|
|
||||||
static void resize(struct ra_ctx *ctx)
|
static void resize(struct ra_ctx *ctx)
|
||||||
{
|
{
|
||||||
@ -77,9 +129,32 @@ static void wayland_egl_swap_buffers(struct ra_ctx *ctx)
|
|||||||
struct priv *p = ctx->priv;
|
struct priv *p = ctx->priv;
|
||||||
struct vo_wayland_state *wl = ctx->vo->wl;
|
struct vo_wayland_state *wl = ctx->vo->wl;
|
||||||
|
|
||||||
|
if (wl->presentation) {
|
||||||
|
wl->feedback = wp_presentation_feedback(wl->presentation, wl->surface);
|
||||||
|
wp_presentation_feedback_add_listener(wl->feedback, &feedback_listener, wl);
|
||||||
|
wl->user_sbc += 1;
|
||||||
|
int index = last_available_sync(wl);
|
||||||
|
if (index < 0)
|
||||||
|
queue_new_sync(wl);
|
||||||
|
}
|
||||||
|
|
||||||
eglSwapBuffers(p->egl_display, p->egl_surface);
|
eglSwapBuffers(p->egl_display, p->egl_surface);
|
||||||
vo_wayland_wait_frame(wl);
|
vo_wayland_wait_frame(wl);
|
||||||
wl->callback_wait = true;
|
|
||||||
|
if (wl->presentation)
|
||||||
|
wayland_sync_swap(wl);
|
||||||
|
|
||||||
|
wl->frame_wait = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wayland_egl_get_vsync(struct ra_ctx *ctx, struct vo_vsync_info *info)
|
||||||
|
{
|
||||||
|
struct vo_wayland_state *wl = ctx->vo->wl;
|
||||||
|
if (wl->presentation) {
|
||||||
|
info->vsync_duration = wl->vsync_duration;
|
||||||
|
info->skipped_vsyncs = wl->last_skipped_vsyncs;
|
||||||
|
info->last_queue_display_time = wl->last_queue_display_time;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool egl_create_context(struct ra_ctx *ctx)
|
static bool egl_create_context(struct ra_ctx *ctx)
|
||||||
@ -103,6 +178,7 @@ static bool egl_create_context(struct ra_ctx *ctx)
|
|||||||
|
|
||||||
struct ra_gl_ctx_params params = {
|
struct ra_gl_ctx_params params = {
|
||||||
.swap_buffers = wayland_egl_swap_buffers,
|
.swap_buffers = wayland_egl_swap_buffers,
|
||||||
|
.get_vsync = wayland_egl_get_vsync,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!ra_gl_ctx_init(ctx, &p->gl, params))
|
if (!ra_gl_ctx_init(ctx, &p->gl, params))
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
struct ra_vk_ctx_params {
|
struct ra_vk_ctx_params {
|
||||||
|
// See ra_swapchain_fns.get_vsync.
|
||||||
|
void (*get_vsync)(struct ra_ctx *ctx, struct vo_vsync_info *info);
|
||||||
|
|
||||||
// In case something special needs to be done on the buffer swap.
|
// In case something special needs to be done on the buffer swap.
|
||||||
void (*swap_buffers)(struct ra_ctx *ctx);
|
void (*swap_buffers)(struct ra_ctx *ctx);
|
||||||
};
|
};
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
// Generated from presentation-time.xml
|
||||||
|
#include "video/out/wayland/presentation-time.h"
|
||||||
|
|
||||||
struct priv {
|
struct priv {
|
||||||
struct mpvk_ctx vk;
|
struct mpvk_ctx vk;
|
||||||
};
|
};
|
||||||
@ -37,19 +40,92 @@ static void frame_callback(void *data, struct wl_callback *callback, uint32_t ti
|
|||||||
|
|
||||||
wl->frame_callback = wl_surface_frame(wl->surface);
|
wl->frame_callback = wl_surface_frame(wl->surface);
|
||||||
wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
|
wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
|
||||||
wl->callback_wait = false;
|
wl->frame_wait = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_callback_listener frame_listener = {
|
static const struct wl_callback_listener frame_listener = {
|
||||||
frame_callback,
|
frame_callback,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct wp_presentation_feedback_listener feedback_listener;
|
||||||
|
|
||||||
|
static void feedback_sync_output(void *data, struct wp_presentation_feedback *fback,
|
||||||
|
struct wl_output *output)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void feedback_presented(void *data, struct wp_presentation_feedback *fback,
|
||||||
|
uint32_t tv_sec_hi, uint32_t tv_sec_lo,
|
||||||
|
uint32_t tv_nsec, uint32_t refresh_nsec,
|
||||||
|
uint32_t seq_hi, uint32_t seq_lo,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
struct vo_wayland_state *wl = data;
|
||||||
|
wp_presentation_feedback_destroy(fback);
|
||||||
|
vo_wayland_sync_shift(wl);
|
||||||
|
|
||||||
|
// Very similar to oml_sync_control, in this case we assume that every
|
||||||
|
// time the compositor receives feedback, a buffer swap has been already
|
||||||
|
// been performed.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// - tv_sec_lo + tv_sec_hi is the equivalent of oml's ust
|
||||||
|
// - 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].sbc = wl->user_sbc;
|
||||||
|
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].refresh_usec = (uint64_t)refresh_nsec/1000;
|
||||||
|
wl->sync[index].filled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void feedback_discarded(void *data, struct wp_presentation_feedback *fback)
|
||||||
|
{
|
||||||
|
wp_presentation_feedback_destroy(fback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_presentation_feedback_listener feedback_listener = {
|
||||||
|
feedback_sync_output,
|
||||||
|
feedback_presented,
|
||||||
|
feedback_discarded,
|
||||||
|
};
|
||||||
|
|
||||||
static void wayland_vk_swap_buffers(struct ra_ctx *ctx)
|
static void wayland_vk_swap_buffers(struct ra_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct vo_wayland_state *wl = ctx->vo->wl;
|
struct vo_wayland_state *wl = ctx->vo->wl;
|
||||||
|
|
||||||
|
if (wl->presentation) {
|
||||||
|
wl->feedback = wp_presentation_feedback(wl->presentation, wl->surface);
|
||||||
|
wp_presentation_feedback_add_listener(wl->feedback, &feedback_listener, wl);
|
||||||
|
wl->user_sbc += 1;
|
||||||
|
int index = last_available_sync(wl);
|
||||||
|
if (index < 0)
|
||||||
|
queue_new_sync(wl);
|
||||||
|
}
|
||||||
|
|
||||||
vo_wayland_wait_frame(wl);
|
vo_wayland_wait_frame(wl);
|
||||||
wl->callback_wait = true;
|
|
||||||
|
if (wl->presentation)
|
||||||
|
wayland_sync_swap(wl);
|
||||||
|
|
||||||
|
wl->frame_wait = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wayland_vk_get_vsync(struct ra_ctx *ctx, struct vo_vsync_info *info)
|
||||||
|
{
|
||||||
|
struct vo_wayland_state *wl = ctx->vo->wl;
|
||||||
|
if (wl->presentation) {
|
||||||
|
info->vsync_duration = wl->vsync_duration;
|
||||||
|
info->skipped_vsyncs = wl->last_skipped_vsyncs;
|
||||||
|
info->last_queue_display_time = wl->last_queue_display_time;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wayland_vk_uninit(struct ra_ctx *ctx)
|
static void wayland_vk_uninit(struct ra_ctx *ctx)
|
||||||
@ -81,6 +157,7 @@ static bool wayland_vk_init(struct ra_ctx *ctx)
|
|||||||
|
|
||||||
struct ra_vk_ctx_params params = {
|
struct ra_vk_ctx_params params = {
|
||||||
.swap_buffers = wayland_vk_swap_buffers,
|
.swap_buffers = wayland_vk_swap_buffers,
|
||||||
|
.get_vsync = wayland_vk_get_vsync,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkInstance inst = vk->vkinst->instance;
|
VkInstance inst = vk->vkinst->instance;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <time.h>
|
||||||
#include "common/msg.h"
|
#include "common/msg.h"
|
||||||
#include "input/input.h"
|
#include "input/input.h"
|
||||||
#include "input/keycodes.h"
|
#include "input/keycodes.h"
|
||||||
@ -37,6 +38,9 @@
|
|||||||
// Generated from xdg-decoration-unstable-v1.xml
|
// Generated from xdg-decoration-unstable-v1.xml
|
||||||
#include "video/out/wayland/xdg-decoration-v1.h"
|
#include "video/out/wayland/xdg-decoration-v1.h"
|
||||||
|
|
||||||
|
// Generated from presentation-time.xml
|
||||||
|
#include "video/out/wayland/presentation-time.h"
|
||||||
|
|
||||||
static void xdg_wm_base_ping(void *data, struct xdg_wm_base *wm_base, uint32_t serial)
|
static void xdg_wm_base_ping(void *data, struct xdg_wm_base *wm_base, uint32_t serial)
|
||||||
{
|
{
|
||||||
xdg_wm_base_pong(wm_base, serial);
|
xdg_wm_base_pong(wm_base, serial);
|
||||||
@ -796,6 +800,19 @@ static const struct wl_surface_listener surface_listener = {
|
|||||||
surface_handle_leave,
|
surface_handle_leave,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void pres_set_clockid(void *data, struct wp_presentation *pres,
|
||||||
|
uint32_t clockid)
|
||||||
|
{
|
||||||
|
struct vo_wayland_state *wl = data;
|
||||||
|
|
||||||
|
wl->presentation = pres;
|
||||||
|
clockid = CLOCK_MONOTONIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_presentation_listener pres_listener = {
|
||||||
|
pres_set_clockid,
|
||||||
|
};
|
||||||
|
|
||||||
static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id,
|
static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id,
|
||||||
const char *interface, uint32_t ver)
|
const char *interface, uint32_t ver)
|
||||||
{
|
{
|
||||||
@ -844,6 +861,11 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id
|
|||||||
wl->xdg_decoration_manager = wl_registry_bind(reg, id, &zxdg_decoration_manager_v1_interface, 1);
|
wl->xdg_decoration_manager = wl_registry_bind(reg, id, &zxdg_decoration_manager_v1_interface, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(interface, wp_presentation_interface.name) && found++) {
|
||||||
|
wl->presentation = wl_registry_bind(reg, id, &wp_presentation_interface, 1);
|
||||||
|
wp_presentation_add_listener(wl->presentation, &pres_listener, wl);
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) && found++) {
|
if (!strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) && found++) {
|
||||||
wl->idle_inhibit_manager = wl_registry_bind(reg, id, &zwp_idle_inhibit_manager_v1_interface, 1);
|
wl->idle_inhibit_manager = wl_registry_bind(reg, id, &zwp_idle_inhibit_manager_v1_interface, 1);
|
||||||
}
|
}
|
||||||
@ -1056,6 +1078,16 @@ int vo_wayland_init(struct vo *vo)
|
|||||||
wl_data_device_manager_interface.name);
|
wl_data_device_manager_interface.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wl->presentation) {
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n",
|
||||||
|
wp_presentation_interface.name);
|
||||||
|
}
|
||||||
|
|
||||||
if (wl->xdg_decoration_manager) {
|
if (wl->xdg_decoration_manager) {
|
||||||
wl->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(wl->xdg_decoration_manager, wl->xdg_toplevel);
|
wl->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(wl->xdg_decoration_manager, wl->xdg_toplevel);
|
||||||
set_border_decorations(wl, vo->opts->border);
|
set_border_decorations(wl, vo->opts->border);
|
||||||
@ -1142,6 +1174,9 @@ void vo_wayland_uninit(struct vo *vo)
|
|||||||
if (wl->frame_callback)
|
if (wl->frame_callback)
|
||||||
wl_callback_destroy(wl->frame_callback);
|
wl_callback_destroy(wl->frame_callback);
|
||||||
|
|
||||||
|
if (wl->presentation)
|
||||||
|
wp_presentation_destroy(wl->presentation);
|
||||||
|
|
||||||
if (wl->pointer)
|
if (wl->pointer)
|
||||||
wl_pointer_destroy(wl->pointer);
|
wl_pointer_destroy(wl->pointer);
|
||||||
|
|
||||||
@ -1403,6 +1438,73 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg)
|
|||||||
return VO_NOTIMPL;
|
return VO_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vo_wayland_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
vo_wayland_sync_shift(wl);
|
||||||
|
wl->sync[0].sbc = wl->user_sbc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wayland_sync_swap(struct vo_wayland_state *wl)
|
||||||
|
{
|
||||||
|
int index = wl->sync_size - 1;
|
||||||
|
|
||||||
|
wl->last_skipped_vsyncs = 0;
|
||||||
|
|
||||||
|
// If these are the same (can happen if a frame takes too long), update
|
||||||
|
// the ust/msc/sbc based on when the next frame is expected to arrive.
|
||||||
|
if (wl->sync[index].ust == wl->last_ust && wl->last_ust) {
|
||||||
|
wl->sync[index].ust += wl->sync[index].refresh_usec;
|
||||||
|
wl->sync[index].msc += 1;
|
||||||
|
wl->sync[index].sbc += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int64_t sbc_passed = wl->sync[index].sbc ? wl->sync[index].sbc - wl->last_sbc: 0;
|
||||||
|
wl->last_sbc = wl->sync[index].sbc;
|
||||||
|
|
||||||
|
if (msc_passed && ust_passed)
|
||||||
|
wl->vsync_duration = ust_passed / msc_passed;
|
||||||
|
|
||||||
|
if (sbc_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_sbc_mp_time = ust_mp_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wl->sync[index].sbc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wl->last_queue_display_time = wl->last_sbc_mp_time + sbc_passed*wl->vsync_duration;
|
||||||
|
}
|
||||||
|
|
||||||
void vo_wayland_wakeup(struct vo *vo)
|
void vo_wayland_wakeup(struct vo *vo)
|
||||||
{
|
{
|
||||||
struct vo_wayland_state *wl = vo->wl;
|
struct vo_wayland_state *wl = vo->wl;
|
||||||
@ -1416,9 +1518,9 @@ void vo_wayland_wait_frame(struct vo_wayland_state *wl)
|
|||||||
};
|
};
|
||||||
|
|
||||||
double vblank_time = 1e6 / wl->current_output->refresh_rate;
|
double vblank_time = 1e6 / wl->current_output->refresh_rate;
|
||||||
int64_t finish_time = mp_time_us() + vblank_time;
|
int64_t finish_time = mp_time_us() + vblank_time + 1000;
|
||||||
|
|
||||||
while (wl->callback_wait && finish_time > mp_time_us()) {
|
while (wl->frame_wait && finish_time > mp_time_us()) {
|
||||||
|
|
||||||
while (wl_display_prepare_read(wl->display) != 0)
|
while (wl_display_prepare_read(wl->display) != 0)
|
||||||
wl_display_dispatch_pending(wl->display);
|
wl_display_dispatch_pending(wl->display);
|
||||||
|
@ -25,6 +25,14 @@
|
|||||||
#include "vo.h"
|
#include "vo.h"
|
||||||
#include "input/event.h"
|
#include "input/event.h"
|
||||||
|
|
||||||
|
struct vo_wayland_sync {
|
||||||
|
int64_t ust;
|
||||||
|
int64_t msc;
|
||||||
|
int64_t sbc;
|
||||||
|
int64_t refresh_usec;
|
||||||
|
bool filled;
|
||||||
|
};
|
||||||
|
|
||||||
struct vo_wayland_output {
|
struct vo_wayland_output {
|
||||||
struct vo_wayland_state *wl;
|
struct vo_wayland_state *wl;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
@ -56,7 +64,7 @@ struct vo_wayland_state {
|
|||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool maximized;
|
bool maximized;
|
||||||
bool configured;
|
bool configured;
|
||||||
bool callback_wait;
|
bool frame_wait;
|
||||||
int wakeup_pipe[2];
|
int wakeup_pipe[2];
|
||||||
int pending_vo_events;
|
int pending_vo_events;
|
||||||
int mouse_x;
|
int mouse_x;
|
||||||
@ -74,11 +82,25 @@ struct vo_wayland_state {
|
|||||||
struct xdg_wm_base *wm_base;
|
struct xdg_wm_base *wm_base;
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
struct xdg_toplevel *xdg_toplevel;
|
||||||
struct xdg_surface *xdg_surface;
|
struct xdg_surface *xdg_surface;
|
||||||
|
struct wp_presentation *presentation;
|
||||||
|
struct wp_presentation_feedback *feedback;
|
||||||
struct zxdg_decoration_manager_v1 *xdg_decoration_manager;
|
struct zxdg_decoration_manager_v1 *xdg_decoration_manager;
|
||||||
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration;
|
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration;
|
||||||
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
|
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
|
||||||
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
|
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
|
||||||
|
|
||||||
|
/* Presentation Feedback */
|
||||||
|
struct vo_wayland_sync *sync;
|
||||||
|
int sync_size;
|
||||||
|
int64_t user_sbc;
|
||||||
|
int64_t last_ust;
|
||||||
|
int64_t last_msc;
|
||||||
|
int64_t last_sbc;
|
||||||
|
int64_t last_sbc_mp_time;
|
||||||
|
int64_t vsync_duration;
|
||||||
|
int64_t last_skipped_vsyncs;
|
||||||
|
int64_t last_queue_display_time;
|
||||||
|
|
||||||
/* Input */
|
/* Input */
|
||||||
struct wl_seat *seat;
|
struct wl_seat *seat;
|
||||||
struct wl_pointer *pointer;
|
struct wl_pointer *pointer;
|
||||||
@ -109,10 +131,14 @@ struct vo_wayland_state {
|
|||||||
int vo_wayland_init(struct vo *vo);
|
int vo_wayland_init(struct vo *vo);
|
||||||
int vo_wayland_reconfig(struct vo *vo);
|
int vo_wayland_reconfig(struct vo *vo);
|
||||||
int vo_wayland_control(struct vo *vo, int *events, int request, void *arg);
|
int vo_wayland_control(struct vo *vo, int *events, int request, void *arg);
|
||||||
|
int last_available_sync(struct vo_wayland_state *wl);
|
||||||
void vo_wayland_check_events(struct vo *vo);
|
void vo_wayland_check_events(struct vo *vo);
|
||||||
void vo_wayland_uninit(struct vo *vo);
|
void vo_wayland_uninit(struct vo *vo);
|
||||||
void vo_wayland_wakeup(struct vo *vo);
|
void vo_wayland_wakeup(struct vo *vo);
|
||||||
void vo_wayland_wait_events(struct vo *vo, int64_t until_time_us);
|
void vo_wayland_wait_events(struct vo *vo, int64_t until_time_us);
|
||||||
void vo_wayland_wait_frame(struct vo_wayland_state *wl);
|
void vo_wayland_wait_frame(struct vo_wayland_state *wl);
|
||||||
|
void wayland_sync_swap(struct vo_wayland_state *wl);
|
||||||
|
void vo_wayland_sync_shift(struct vo_wayland_state *wl);
|
||||||
|
void queue_new_sync(struct vo_wayland_state *wl);
|
||||||
|
|
||||||
#endif /* MPLAYER_WAYLAND_COMMON_H */
|
#endif /* MPLAYER_WAYLAND_COMMON_H */
|
||||||
|
@ -129,6 +129,12 @@ def build(ctx):
|
|||||||
ctx.wayland_protocol_header(proto_dir = ctx.env.WL_PROTO_DIR,
|
ctx.wayland_protocol_header(proto_dir = ctx.env.WL_PROTO_DIR,
|
||||||
protocol = "unstable/idle-inhibit/idle-inhibit-unstable-v1",
|
protocol = "unstable/idle-inhibit/idle-inhibit-unstable-v1",
|
||||||
target = "video/out/wayland/idle-inhibit-v1.h")
|
target = "video/out/wayland/idle-inhibit-v1.h")
|
||||||
|
ctx.wayland_protocol_code(proto_dir = ctx.env.WL_PROTO_DIR,
|
||||||
|
protocol = "stable/presentation-time/presentation-time",
|
||||||
|
target = "video/out/wayland/presentation-time.c")
|
||||||
|
ctx.wayland_protocol_header(proto_dir = ctx.env.WL_PROTO_DIR,
|
||||||
|
protocol = "stable/presentation-time/presentation-time",
|
||||||
|
target = "video/out/wayland/presentation-time.h")
|
||||||
ctx.wayland_protocol_code(proto_dir = ctx.env.WL_PROTO_DIR,
|
ctx.wayland_protocol_code(proto_dir = ctx.env.WL_PROTO_DIR,
|
||||||
protocol = "unstable/xdg-decoration/xdg-decoration-unstable-v1",
|
protocol = "unstable/xdg-decoration/xdg-decoration-unstable-v1",
|
||||||
target = "video/out/wayland/xdg-decoration-v1.c")
|
target = "video/out/wayland/xdg-decoration-v1.c")
|
||||||
@ -499,6 +505,7 @@ def build(ctx):
|
|||||||
( "video/out/vulkan/utils.c", "vulkan" ),
|
( "video/out/vulkan/utils.c", "vulkan" ),
|
||||||
( "video/out/w32_common.c", "win32-desktop" ),
|
( "video/out/w32_common.c", "win32-desktop" ),
|
||||||
( "video/out/wayland/idle-inhibit-v1.c", "wayland" ),
|
( "video/out/wayland/idle-inhibit-v1.c", "wayland" ),
|
||||||
|
( "video/out/wayland/presentation-time.c", "wayland" ),
|
||||||
( "video/out/wayland/xdg-decoration-v1.c", "wayland" ),
|
( "video/out/wayland/xdg-decoration-v1.c", "wayland" ),
|
||||||
( "video/out/wayland/xdg-shell.c", "wayland" ),
|
( "video/out/wayland/xdg-shell.c", "wayland" ),
|
||||||
( "video/out/wayland_common.c", "wayland" ),
|
( "video/out/wayland_common.c", "wayland" ),
|
||||||
|
Loading…
Reference in New Issue
Block a user