summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/out/opengl/context_wayland.c26
-rw-r--r--video/out/vulkan/context.c11
-rw-r--r--video/out/vulkan/context.h6
-rw-r--r--video/out/vulkan/context_android.c4
-rw-r--r--video/out/vulkan/context_wayland.c35
-rw-r--r--video/out/vulkan/context_win.c4
-rw-r--r--video/out/vulkan/context_xlib.c4
-rw-r--r--video/out/wayland_common.c46
-rw-r--r--video/out/wayland_common.h2
9 files changed, 112 insertions, 26 deletions
diff --git a/video/out/opengl/context_wayland.c b/video/out/opengl/context_wayland.c
index 22c18d8290..6511e34499 100644
--- a/video/out/opengl/context_wayland.c
+++ b/video/out/opengl/context_wayland.c
@@ -34,6 +34,25 @@ struct priv {
struct wl_egl_window *egl_window;
};
+static const struct wl_callback_listener frame_listener;
+
+static void frame_callback(void *data, struct wl_callback *callback, uint32_t time)
+{
+ struct vo_wayland_state *wl = data;
+
+ if (callback)
+ wl_callback_destroy(callback);
+
+ wl->frame_callback = wl_surface_frame(wl->surface);
+ wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
+ wl->callback_wait = false;
+}
+
+static const struct wl_callback_listener frame_listener = {
+ frame_callback,
+};
+
+
static void resize(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
@@ -56,7 +75,11 @@ static void resize(struct ra_ctx *ctx)
static void wayland_egl_swap_buffers(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
+ struct vo_wayland_state *wl = ctx->vo->wl;
+
eglSwapBuffers(p->egl_display, p->egl_surface);
+ vo_wayland_wait_frame(wl);
+ wl->callback_wait = true;
}
static bool egl_create_context(struct ra_ctx *ctx)
@@ -87,6 +110,9 @@ static bool egl_create_context(struct ra_ctx *ctx)
ra_add_native_resource(ctx->ra, "wl", wl->display);
+ wl->frame_callback = wl_surface_frame(wl->surface);
+ wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
+
return true;
}
diff --git a/video/out/vulkan/context.c b/video/out/vulkan/context.c
index 4ff48ed250..ea546519ec 100644
--- a/video/out/vulkan/context.c
+++ b/video/out/vulkan/context.c
@@ -111,6 +111,7 @@ const struct m_sub_options vulkan_conf = {
struct priv {
struct mpvk_ctx *vk;
struct vulkan_opts *opts;
+ struct ra_vk_ctx_params params;
const struct pl_swapchain *swapchain;
struct ra_tex proxy_tex;
};
@@ -147,6 +148,7 @@ void ra_vk_ctx_uninit(struct ra_ctx *ctx)
}
bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk,
+ struct ra_vk_ctx_params params,
VkPresentModeKHR preferred_mode)
{
struct ra_swapchain *sw = ctx->swapchain = talloc_zero(NULL, struct ra_swapchain);
@@ -155,6 +157,7 @@ bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk,
struct priv *p = sw->priv = talloc_zero(sw, struct priv);
p->vk = vk;
+ p->params = params;
p->opts = mp_get_config_group(p, ctx->global, &vulkan_conf);
assert(vk->ctx);
@@ -176,16 +179,16 @@ bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk,
goto error;
// Create the swapchain
- struct pl_vulkan_swapchain_params params = {
+ struct pl_vulkan_swapchain_params pl_params = {
.surface = vk->surface,
.present_mode = preferred_mode,
.swapchain_depth = ctx->vo->opts->swapchain_depth,
};
if (p->opts->swap_mode >= 0) // user override
- params.present_mode = p->opts->swap_mode;
+ pl_params.present_mode = p->opts->swap_mode;
- p->swapchain = pl_vulkan_create_swapchain(vk->vulkan, &params);
+ p->swapchain = pl_vulkan_create_swapchain(vk->vulkan, &pl_params);
if (!p->swapchain)
goto error;
@@ -239,6 +242,8 @@ static void swap_buffers(struct ra_swapchain *sw)
{
struct priv *p = sw->priv;
pl_swapchain_swap_buffers(p->swapchain);
+ if (p->params.swap_buffers)
+ p->params.swap_buffers(sw->ctx);
}
static const struct ra_swapchain_fns vulkan_swapchain = {
diff --git a/video/out/vulkan/context.h b/video/out/vulkan/context.h
index 30c97cfb4f..90d7f8b8b2 100644
--- a/video/out/vulkan/context.h
+++ b/video/out/vulkan/context.h
@@ -3,9 +3,15 @@
#include "video/out/gpu/context.h"
#include "common.h"
+struct ra_vk_ctx_params {
+ // In case something special needs to be done on the buffer swap.
+ void (*swap_buffers)(struct ra_ctx *ctx);
+};
+
// Helpers for ra_ctx based on ra_vk. These initialize ctx->ra and ctx->swchain.
void ra_vk_ctx_uninit(struct ra_ctx *ctx);
bool ra_vk_ctx_init(struct ra_ctx *ctx, struct mpvk_ctx *vk,
+ struct ra_vk_ctx_params params,
VkPresentModeKHR preferred_mode);
// Handles a resize request, and updates ctx->vo->dwidth/dheight
diff --git a/video/out/vulkan/context_android.c b/video/out/vulkan/context_android.c
index 212fe0824b..ddab3917f1 100644
--- a/video/out/vulkan/context_android.c
+++ b/video/out/vulkan/context_android.c
@@ -53,6 +53,8 @@ static bool android_init(struct ra_ctx *ctx)
.window = vo_android_native_window(ctx->vo)
};
+ struct ra_vk_ctx_params params = {0};
+
VkInstance inst = vk->vkinst->instance;
VkResult res = vkCreateAndroidSurfaceKHR(inst, &info, NULL, &vk->surface);
if (res != VK_SUCCESS) {
@@ -60,7 +62,7 @@ static bool android_init(struct ra_ctx *ctx)
goto fail;
}
- if (!ra_vk_ctx_init(ctx, vk, VK_PRESENT_MODE_FIFO_KHR))
+ if (!ra_vk_ctx_init(ctx, vk, params, VK_PRESENT_MODE_FIFO_KHR))
goto fail;
return true;
diff --git a/video/out/vulkan/context_wayland.c b/video/out/vulkan/context_wayland.c
index 160e8f9da4..783509e4a1 100644
--- a/video/out/vulkan/context_wayland.c
+++ b/video/out/vulkan/context_wayland.c
@@ -26,6 +26,32 @@ struct priv {
struct mpvk_ctx vk;
};
+static const struct wl_callback_listener frame_listener;
+
+static void frame_callback(void *data, struct wl_callback *callback, uint32_t time)
+{
+ struct vo_wayland_state *wl = data;
+
+ if (callback)
+ wl_callback_destroy(callback);
+
+ wl->frame_callback = wl_surface_frame(wl->surface);
+ wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
+ wl->callback_wait = false;
+}
+
+static const struct wl_callback_listener frame_listener = {
+ frame_callback,
+};
+
+static void wayland_vk_swap_buffers(struct ra_ctx *ctx)
+{
+ struct vo_wayland_state *wl = ctx->vo->wl;
+
+ vo_wayland_wait_frame(wl);
+ wl->callback_wait = true;
+}
+
static void wayland_vk_uninit(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
@@ -53,6 +79,10 @@ static bool wayland_vk_init(struct ra_ctx *ctx)
.surface = ctx->vo->wl->surface,
};
+ struct ra_vk_ctx_params params = {
+ .swap_buffers = wayland_vk_swap_buffers,
+ };
+
VkInstance inst = vk->vkinst->instance;
VkResult res = vkCreateWaylandSurfaceKHR(inst, &wlinfo, NULL, &vk->surface);
if (res != VK_SUCCESS) {
@@ -66,11 +96,14 @@ static bool wayland_vk_init(struct ra_ctx *ctx)
* mean the entire player would block on acquiring swapchain images. Hence,
* use MAILBOX to guarantee that there'll always be a swapchain image and
* the player won't block waiting on those */
- if (!ra_vk_ctx_init(ctx, vk, VK_PRESENT_MODE_MAILBOX_KHR))
+ if (!ra_vk_ctx_init(ctx, vk, params, VK_PRESENT_MODE_MAILBOX_KHR))
goto error;
ra_add_native_resource(ctx->ra, "wl", ctx->vo->wl->display);
+ ctx->vo->wl->frame_callback = wl_surface_frame(ctx->vo->wl->surface);
+ wl_callback_add_listener(ctx->vo->wl->frame_callback, &frame_listener, ctx->vo->wl);
+
return true;
error:
diff --git a/video/out/vulkan/context_win.c b/video/out/vulkan/context_win.c
index dfc3ba417f..a89c64414b 100644
--- a/video/out/vulkan/context_win.c
+++ b/video/out/vulkan/context_win.c
@@ -56,6 +56,8 @@ static bool win_init(struct ra_ctx *ctx)
.hwnd = vo_w32_hwnd(ctx->vo),
};
+ struct ra_vk_ctx_params params = {0};
+
VkInstance inst = vk->vkinst->instance;
VkResult res = vkCreateWin32SurfaceKHR(inst, &wininfo, NULL, &vk->surface);
if (res != VK_SUCCESS) {
@@ -63,7 +65,7 @@ static bool win_init(struct ra_ctx *ctx)
goto error;
}
- if (!ra_vk_ctx_init(ctx, vk, VK_PRESENT_MODE_FIFO_KHR))
+ if (!ra_vk_ctx_init(ctx, vk, params, VK_PRESENT_MODE_FIFO_KHR))
goto error;
return true;
diff --git a/video/out/vulkan/context_xlib.c b/video/out/vulkan/context_xlib.c
index e2fc732e00..6278bc3c69 100644
--- a/video/out/vulkan/context_xlib.c
+++ b/video/out/vulkan/context_xlib.c
@@ -56,6 +56,8 @@ static bool xlib_init(struct ra_ctx *ctx)
.window = ctx->vo->x11->window,
};
+ struct ra_vk_ctx_params params = {0};
+
VkInstance inst = vk->vkinst->instance;
VkResult res = vkCreateXlibSurfaceKHR(inst, &xinfo, NULL, &vk->surface);
if (res != VK_SUCCESS) {
@@ -63,7 +65,7 @@ static bool xlib_init(struct ra_ctx *ctx)
goto error;
}
- if (!ra_vk_ctx_init(ctx, vk, VK_PRESENT_MODE_FIFO_KHR))
+ if (!ra_vk_ctx_init(ctx, vk, params, VK_PRESENT_MODE_FIFO_KHR))
goto error;
ra_add_native_resource(ctx->ra, "x11", ctx->vo->x11->display);
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index cc07296a43..fa409a5541 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -796,23 +796,6 @@ static const struct wl_surface_listener surface_listener = {
surface_handle_leave,
};
-static const struct wl_callback_listener frame_listener;
-
-static void frame_callback(void *data, struct wl_callback *callback, uint32_t time)
-{
- struct vo_wayland_state *wl = data;
-
- if (callback)
- wl_callback_destroy(callback);
-
- wl->frame_callback = wl_surface_frame(wl->surface);
- wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
-}
-
-static const struct wl_callback_listener frame_listener = {
- frame_callback,
-};
-
static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id,
const char *interface, uint32_t ver)
{
@@ -824,8 +807,6 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id
wl->surface = wl_compositor_create_surface(wl->compositor);
wl->cursor_surface = wl_compositor_create_surface(wl->compositor);
wl_surface_add_listener(wl->surface, &surface_listener, wl);
- wl->frame_callback = wl_surface_frame(wl->surface);
- wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
}
if (!strcmp(interface, wl_output_interface.name) && (ver >= 2) && found++) {
@@ -1428,6 +1409,33 @@ void vo_wayland_wakeup(struct vo *vo)
(void)write(wl->wakeup_pipe[1], &(char){0}, 1);
}
+void vo_wayland_wait_frame(struct vo_wayland_state *wl)
+{
+ struct pollfd fds[1] = {
+ {.fd = wl->display_fd, .events = POLLIN },
+ };
+
+ double vblank_time = 1e6 / wl->current_output->refresh_rate;
+ int64_t finish_time = mp_time_us() + vblank_time;
+
+ while (wl->callback_wait && finish_time > mp_time_us()) {
+
+ while (wl_display_prepare_read(wl->display) != 0)
+ wl_display_dispatch_pending(wl->display);
+ wl_display_flush(wl->display);
+
+ int poll_time = (finish_time - mp_time_us()) / 1000;
+ if (poll_time < 0) {
+ poll_time = 0;
+ }
+
+ poll(fds, 1, poll_time);
+
+ wl_display_read_events(wl->display);
+ wl_display_dispatch_pending(wl->display);
+ }
+}
+
void vo_wayland_wait_events(struct vo *vo, int64_t until_time_us)
{
struct vo_wayland_state *wl = vo->wl;
diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h
index b9ce1c53ce..1415c6935d 100644
--- a/video/out/wayland_common.h
+++ b/video/out/wayland_common.h
@@ -56,6 +56,7 @@ struct vo_wayland_state {
bool fullscreen;
bool maximized;
bool configured;
+ bool callback_wait;
int wakeup_pipe[2];
int pending_vo_events;
int mouse_x;
@@ -112,5 +113,6 @@ void vo_wayland_check_events(struct vo *vo);
void vo_wayland_uninit(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_frame(struct vo_wayland_state *wl);
#endif /* MPLAYER_WAYLAND_COMMON_H */