summaryrefslogtreecommitdiffstats
path: root/video/out/vo.c
diff options
context:
space:
mode:
authorRostislav Pehlivanov <atomnuker@gmail.com>2017-12-05 08:26:24 +0000
committerRostislav Pehlivanov <atomnuker@gmail.com>2017-12-05 08:26:24 +0000
commita743fef837bcab206b1e576db7e7a64b02890449 (patch)
tree875105fee109e9e6604af5d117c84e8e883c9375 /video/out/vo.c
parent713668b99a201a3ca33780d64bd4072ed966f406 (diff)
downloadmpv-a743fef837bcab206b1e576db7e7a64b02890449.tar.bz2
mpv-a743fef837bcab206b1e576db7e7a64b02890449.tar.xz
vo: add support for externally driven renderloop and make wayland use it
Fixes display-sync (though if you change virtual desktops you'll need to seek to re-enable display-sync) partially under wayland. As an advantage, rendering is completely disabled if you change desktops or alt+tab so you lose no performance if you leave mpv running elsewhere as long as it isn't visible. This could also be ported to other VOs which supports it.
Diffstat (limited to 'video/out/vo.c')
-rw-r--r--video/out/vo.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/video/out/vo.c b/video/out/vo.c
index f195568eaa..8e63be75e6 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -134,6 +134,8 @@ struct vo_internal {
int64_t nominal_vsync_interval;
+ bool external_renderloop_drive;
+
int64_t vsync_interval;
int64_t *vsync_samples;
int num_vsync_samples;
@@ -788,11 +790,12 @@ static void wait_until(struct vo *vo, int64_t target)
pthread_mutex_unlock(&in->lock);
}
-static bool render_frame(struct vo *vo)
+bool vo_render_frame_external(struct vo *vo)
{
struct vo_internal *in = vo->in;
struct vo_frame *frame = NULL;
bool got_frame = false;
+ bool flipped = false;
update_display_fps(vo);
@@ -854,6 +857,7 @@ static bool render_frame(struct vo *vo)
if (in->dropped_frame) {
in->drop_count += 1;
} else {
+ flipped = true;
in->rendering = true;
in->hasframe_rendered = true;
int64_t prev_drop_count = vo->in->drop_count;
@@ -904,6 +908,8 @@ static bool render_frame(struct vo *vo)
done:
talloc_free(frame);
pthread_mutex_unlock(&in->lock);
+ if (in->external_renderloop_drive)
+ return flipped;
return got_frame || (in->frame_queued && in->frame_queued->display_synced);
}
@@ -946,6 +952,44 @@ static void do_redraw(struct vo *vo)
talloc_free(frame);
}
+static void drop_unrendered_frame(struct vo *vo)
+{
+ struct vo_internal *in = vo->in;
+
+ pthread_mutex_lock(&in->lock);
+
+ if (!in->frame_queued)
+ goto end;
+
+ if ((in->frame_queued->pts + in->frame_queued->duration) > mp_time_us())
+ goto end;
+
+ MP_VERBOSE(vo, "Dropping unrendered frame (pts %li)\n", in->frame_queued->pts);
+
+ talloc_free(in->frame_queued);
+ in->frame_queued = NULL;
+ in->hasframe = false;
+ pthread_cond_broadcast(&in->wakeup);
+ wakeup_core(vo);
+
+end:
+ pthread_mutex_unlock(&in->lock);
+}
+
+void vo_enable_external_renderloop(struct vo *vo)
+{
+ struct vo_internal *in = vo->in;
+ MP_VERBOSE(vo, "Enabling event driven renderloop!\n");
+ in->external_renderloop_drive = true;
+}
+
+void vo_disable_external_renderloop(struct vo *vo)
+{
+ struct vo_internal *in = vo->in;
+ MP_VERBOSE(vo, "Disabling event driven renderloop!\n");
+ in->external_renderloop_drive = false;
+}
+
static void *vo_thread(void *ptr)
{
struct vo *vo = ptr;
@@ -967,7 +1011,11 @@ static void *vo_thread(void *ptr)
if (in->terminate)
break;
vo->driver->control(vo, VOCTRL_CHECK_EVENTS, NULL);
- bool working = render_frame(vo);
+ bool working = false;
+ if (!in->external_renderloop_drive || !in->hasframe_rendered)
+ working = vo_render_frame_external(vo);
+ else
+ drop_unrendered_frame(vo);
int64_t now = mp_time_us();
int64_t wait_until = now + (working ? 0 : (int64_t)1e9);
@@ -980,7 +1028,7 @@ static void *vo_thread(void *ptr)
wakeup_core(vo);
}
}
- if (vo->want_redraw && !in->want_redraw) {
+ if (vo->want_redraw) {
vo->want_redraw = false;
in->want_redraw = true;
wakeup_core(vo);