summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorRostislav Pehlivanov <atomnuker@gmail.com>2016-07-21 12:25:30 +0100
committerwm4 <wm4@nowhere>2016-07-21 14:45:38 +0200
commitc0ef3cf9c2d8db023dd3d5dcdeb2c2c592ad6b58 (patch)
tree91331f7e448cd34974f2b1a639aefc92e7a0e8dd /video
parent8f51418ca4d08533fe23a8f233e59afb2241a9b8 (diff)
downloadmpv-c0ef3cf9c2d8db023dd3d5dcdeb2c2c592ad6b58.tar.bz2
mpv-c0ef3cf9c2d8db023dd3d5dcdeb2c2c592ad6b58.tar.xz
wayland: port to the new wakeup/wait_events framework
This fits natively into the vo/backend and allows to simplify the polling code. One new change is the fact that surface_handle_enter flags VO_EVENT_WIN_STATE and VO_EVENT_RESIZE instead of only VO_EVENT_WIN_STATE. Before this, the code hackily relied on the timeout and the loop in the wait_frame function to track and set the scaling factor. Instead, this triggers mpv to run a schedule_resize and adjust the new VO output dimensions immediately. This is also more accurate since surface_handle_enter() gets called when a surface is created, moved and resized, which is exactly what the rest of the player might be interested in.
Diffstat (limited to 'video')
-rw-r--r--video/out/opengl/context_wayland.c15
-rw-r--r--video/out/vo_wayland.c8
-rw-r--r--video/out/wayland_common.c94
-rw-r--r--video/out/wayland_common.h7
4 files changed, 53 insertions, 71 deletions
diff --git a/video/out/opengl/context_wayland.c b/video/out/opengl/context_wayland.c
index e74132bcf2..b1d9a32bca 100644
--- a/video/out/opengl/context_wayland.c
+++ b/video/out/opengl/context_wayland.c
@@ -207,8 +207,7 @@ static void waylandgl_swap_buffers(MPGLContext *ctx)
if (!wl->frame.callback)
vo_wayland_request_frame(ctx->vo, NULL, NULL);
- if (!vo_wayland_wait_frame(ctx->vo))
- MP_DBG(wl, "discarding frame callback\n");
+ vo_wayland_wait_events(ctx->vo, 0);
eglSwapBuffers(wl->egl_context.egl.dpy, wl->egl_context.egl_surface);
}
@@ -225,6 +224,16 @@ static int waylandgl_control(MPGLContext *ctx, int *events, int request,
return r;
}
+static void wayland_wakeup(struct MPGLContext *ctx)
+{
+ vo_wayland_wakeup(ctx->vo);
+}
+
+static void wayland_wait_events(struct MPGLContext *ctx, int64_t until_time_us)
+{
+ vo_wayland_wait_events(ctx->vo, until_time_us);
+}
+
static int waylandgl_init(struct MPGLContext *ctx, int flags)
{
if (!vo_wayland_init(ctx->vo))
@@ -239,5 +248,7 @@ const struct mpgl_driver mpgl_driver_wayland = {
.reconfig = waylandgl_reconfig,
.swap_buffers = waylandgl_swap_buffers,
.control = waylandgl_control,
+ .wakeup = wayland_wakeup,
+ .wait_events = wayland_wait_events,
.uninit = waylandgl_uninit,
};
diff --git a/video/out/vo_wayland.c b/video/out/vo_wayland.c
index 2997b38cde..236421e4ef 100644
--- a/video/out/vo_wayland.c
+++ b/video/out/vo_wayland.c
@@ -373,8 +373,7 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
p->original_image = mpi;
}
- if (!vo_wayland_wait_frame(vo))
- MP_DBG(p->wl, "discarding frame callback\n");
+ vo_wayland_wait_events(vo, 0);
shm_buffer_t *buf = buffer_pool_get_back(&p->video_bufpool);
@@ -513,8 +512,7 @@ static void flip_page(struct vo *vo)
if (!p->wl->frame.callback)
vo_wayland_request_frame(vo, p, redraw);
- if (!vo_wayland_wait_frame(vo))
- MP_DBG(p->wl, "discarding frame callback\n");
+ vo_wayland_wait_events(vo, 0);
}
static int query_format(struct vo *vo, int format)
@@ -675,6 +673,8 @@ const struct vo_driver video_out_wayland = {
.control = control,
.draw_image = draw_image,
.flip_page = flip_page,
+ .wakeup = vo_wayland_wakeup,
+ .wait_events = vo_wayland_wait_events,
.uninit = uninit,
.options = (const struct m_option[]) {
OPT_FLAG("alpha", enable_alpha, 0),
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index 6861c93fca..b216bfde8a 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -40,6 +40,7 @@
#include "vo.h"
#include "win_state.h"
+#include "osdep/io.h"
#include "osdep/timer.h"
#include "input/input.h"
@@ -225,7 +226,7 @@ static void surface_handle_enter(void *data,
}
}
- wl->window.events |= VO_EVENT_WIN_STATE;
+ wl->window.events |= VO_EVENT_WIN_STATE | VO_EVENT_RESIZE;
}
static void surface_handle_leave(void *data,
@@ -833,10 +834,6 @@ static void frame_callback(void *data,
wl_callback_add_listener(wl->frame.callback, &frame_listener, wl);
wl_surface_commit(wl->window.video_surface);
-
- wl->frame.last_us = mp_time_us();
- wl->frame.pending = true;
- wl->frame.dropping = false;
}
static const struct wl_callback_listener frame_listener = {
@@ -1045,7 +1042,7 @@ int vo_wayland_init (struct vo *vo)
o->refresh_rate / 1000.0f);
}
- vo->event_fd = wl->display.display_fd;
+ mp_make_wakeup_pipe(wl->wakeup_pipe);
return true;
}
@@ -1057,6 +1054,8 @@ void vo_wayland_uninit (struct vo *vo)
destroy_window(wl);
destroy_display(wl);
destroy_input(wl);
+ for (int n = 0; n < 2; n++)
+ close(wl->wakeup_pipe[n]);
talloc_free(wl);
vo->wayland = NULL;
}
@@ -1096,47 +1095,11 @@ static void vo_wayland_fullscreen (struct vo *vo)
}
}
-static int vo_wayland_poll (struct vo *vo, int timeout_msecs)
-{
- struct vo_wayland_state *wl = vo->wayland;
- struct wl_display *dp = wl->display.display;
-
- wl_display_dispatch_pending(dp);
- wl_display_flush(dp);
-
- struct pollfd fd = {
- wl->display.display_fd,
- POLLIN | POLLERR | POLLHUP,
- 0
- };
-
- /* wl_display_dispatch is blocking
- * wl_dipslay_dispatch_pending is non-blocking but does not read from the fd
- *
- * when pausing no input events get queued so we have to check if there
- * are events to read from the file descriptor through poll */
- int polled;
- if ((polled = poll(&fd, 1, timeout_msecs)) > 0) {
- if (fd.revents & POLLERR || fd.revents & POLLHUP) {
- MP_FATAL(wl, "error occurred on the display fd: "
- "closing file descriptor\n");
- close(wl->display.display_fd);
- mp_input_put_key(vo->input_ctx, MP_KEY_CLOSE_WIN);
- }
- if (fd.revents & POLLIN)
- wl_display_dispatch(dp);
- else
- wl_display_dispatch_pending(dp);
- }
-
- return polled;
-}
-
-static int vo_wayland_check_events (struct vo *vo)
+static int vo_wayland_check_events(struct vo *vo)
{
struct vo_wayland_state *wl = vo->wayland;
- vo_wayland_poll(vo, 0);
+ vo_wayland_wait_events(vo, 0);
/* If drag & drop was ended poll the file descriptor from the offer if
* there is data to read.
@@ -1331,29 +1294,38 @@ void vo_wayland_request_frame(struct vo *vo, void *data, vo_wayland_frame_cb cb)
frame_callback(wl, NULL, 0);
}
-bool vo_wayland_wait_frame(struct vo *vo)
+void vo_wayland_wakeup(struct vo *vo)
{
struct vo_wayland_state *wl = vo->wayland;
+ (void)write(wl->wakeup_pipe[1], &(char){0}, 1);
+}
- if (!wl->frame.callback || wl->frame.dropping)
- return false;
+void vo_wayland_wait_events(struct vo *vo, int64_t until_time_us)
+{
+ struct vo_wayland_state *wl = vo->wayland;
+ struct wl_display *dp = wl->display.display;
- // If mpv isn't receiving frame callbacks (for 100ms), this usually means that
- // mpv window is not visible and compositor tells kindly to not draw anything.
- while (!wl->frame.pending) {
- int64_t timeout = wl->frame.last_us + (100 * 1000) - mp_time_us();
+ wl_display_dispatch_pending(dp);
+ wl_display_flush(dp);
- if (timeout <= 0)
- break;
+ struct pollfd fds[2] = {
+ {.fd = wl->display.display_fd, .events = POLLIN },
+ {.fd = wl->wakeup_pipe[0], .events = POLLIN },
+ };
- if (vo_wayland_poll(vo, timeout) <= 0)
- break;
- }
+ int64_t wait_us = until_time_us - mp_time_us();
+ int timeout_ms = MPCLAMP((wait_us + 500) / 1000, 0, 10000);
- wl->frame.dropping = !wl->frame.pending;
- wl->frame.pending = false;
+ poll(fds, 2, timeout_ms);
- // Return false if the frame callback was not received
- // Handler should act accordingly.
- return !wl->frame.dropping;
+ if (fds[0].revents & POLLERR || fds[0].revents & POLLHUP) {
+ MP_FATAL(wl, "error occurred on the display fd: "
+ "closing file descriptor\n");
+ close(wl->display.display_fd);
+ mp_input_put_key(vo->input_ctx, MP_KEY_CLOSE_WIN);
+ } else if (fds[0].revents & POLLIN) {
+ wl_display_dispatch(dp);
+ } else if (fds[1].revents & POLLIN) {
+ wl_display_dispatch_pending(dp);
+ }
}
diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h
index ec3f72ce67..cf659fb8e6 100644
--- a/video/out/wayland_common.h
+++ b/video/out/wayland_common.h
@@ -53,14 +53,12 @@ typedef void (*vo_wayland_frame_cb)(void *data, uint32_t time);
struct vo_wayland_state {
struct vo *vo;
struct mp_log* log;
+ int wakeup_pipe[2];
struct {
void *data;
vo_wayland_frame_cb function;
struct wl_callback *callback;
- uint64_t last_us;
- bool pending;
- bool dropping;
} frame;
#if HAVE_GL_WAYLAND
@@ -150,8 +148,9 @@ int vo_wayland_init(struct vo *vo);
void vo_wayland_uninit(struct vo *vo);
bool vo_wayland_config(struct vo *vo);
int vo_wayland_control(struct vo *vo, int *events, int request, void *arg);
+void vo_wayland_wakeup(struct vo *vo);
+void vo_wayland_wait_events(struct vo *vo, int64_t until_time_us);
void vo_wayland_request_frame(struct vo *vo, void *data, vo_wayland_frame_cb cb);
-bool vo_wayland_wait_frame(struct vo *vo);
#endif /* MPLAYER_WAYLAND_COMMON_H */