summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcin Kurczewski <mkurczew@gmail.com>2015-04-20 18:57:24 +0200
committerwm4 <wm4@nowhere>2015-04-21 11:45:53 +0200
commita7cf35c1ca08cf59ae9f1d9e56c7fb486af6e9ff (patch)
tree2f21b63122242f791ee7085423e0187534f720d9
parent4ae8fc326d544f83777ad4f038ad6587af507fab (diff)
downloadmpv-a7cf35c1ca08cf59ae9f1d9e56c7fb486af6e9ff.tar.bz2
mpv-a7cf35c1ca08cf59ae9f1d9e56c7fb486af6e9ff.tar.xz
vo_drm: add vertical sync
-rw-r--r--video/out/vo_drm.c50
1 files changed, 45 insertions, 5 deletions
diff --git a/video/out/vo_drm.c b/video/out/vo_drm.c
index bcaf3821a0..3722f07db6 100644
--- a/video/out/vo_drm.c
+++ b/video/out/vo_drm.c
@@ -24,6 +24,7 @@
#include <fcntl.h>
#include <stdbool.h>
#include <sys/mman.h>
+#include <sys/poll.h>
#include <unistd.h>
#include <libswscale/swscale.h>
@@ -63,14 +64,17 @@ struct modeset_dev {
};
struct priv {
+ char *device_path;
+ int connector_id;
+
int fd;
struct vt_switcher vt_switcher;
struct modeset_dev *dev;
drmModeCrtc *old_crtc;
+ drmEventContext ev;
bool active;
- char *device_path;
- int connector_id;
+ bool pflip_happening;
int32_t device_w;
int32_t device_h;
@@ -334,6 +338,13 @@ end:
return ret;
}
+static void modeset_page_flipped(int fd, unsigned int frame, unsigned int sec,
+ unsigned int usec, void *data)
+{
+ struct priv *p = data;
+ p->pflip_happening = false;
+}
+
static int setup_vo_crtc(struct vo *vo)
@@ -350,7 +361,18 @@ static int setup_vo_crtc(struct vo *vo)
static void release_vo_crtc(struct vo *vo)
{
struct priv *p = vo->priv;
+
p->active = false;
+
+ // wait for current page flip
+ while (p->pflip_happening) {
+ int ret = drmHandleEvent(p->fd, &p->ev);
+ if (ret) {
+ MP_ERR(vo, "drmHandleEvent failed: %i\n", ret);
+ break;
+ }
+ }
+
if (p->old_crtc) {
drmModeSetCrtc(p->fd,
p->old_crtc->crtc_id,
@@ -487,15 +509,31 @@ static void flip_page(struct vo *vo)
{
struct priv *p = vo->priv;
if (!p->active) return;
+ if (p->pflip_happening) return;
- int ret = drmModeSetCrtc(p->fd, p->dev->crtc,
- p->dev->bufs[p->dev->front_buf].fb,
- 0, 0, &p->dev->conn, 1, &p->dev->mode);
+ int ret = drmModePageFlip(p->fd, p->dev->crtc,
+ p->dev->bufs[p->dev->front_buf].fb,
+ DRM_MODE_PAGE_FLIP_EVENT, p);
if (ret) {
MP_WARN(vo, "Cannot flip page for connector\n");
} else {
p->dev->front_buf++;
p->dev->front_buf %= BUF_COUNT;
+ p->pflip_happening = true;
+ }
+
+ // poll page flip finish event
+ const int timeout_ms = 3000;
+ struct pollfd fds[1] = {
+ { .events = POLLIN, .fd = p->fd },
+ };
+ poll(fds, 1, timeout_ms);
+ if (fds[0].revents & POLLIN) {
+ ret = drmHandleEvent(p->fd, &p->ev);
+ if (ret != 0) {
+ MP_ERR(vo, "drmHandleEvent failed: %i\n", ret);
+ return;
+ }
}
}
@@ -523,6 +561,8 @@ static int preinit(struct vo *vo)
struct priv *p = vo->priv;
p->sws = mp_sws_alloc(vo);
p->fd = -1;
+ p->ev.version = DRM_EVENT_CONTEXT_VERSION;
+ p->ev.page_flip_handler = modeset_page_flipped;
if (vt_switcher_init(&p->vt_switcher, vo->log))
goto err;