mirror of https://github.com/mpv-player/mpv
vo_drm: add vertical sync
This commit is contained in:
parent
4ae8fc326d
commit
a7cf35c1ca
|
@ -24,6 +24,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <libswscale/swscale.h>
|
#include <libswscale/swscale.h>
|
||||||
|
@ -63,14 +64,17 @@ struct modeset_dev {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct priv {
|
struct priv {
|
||||||
|
char *device_path;
|
||||||
|
int connector_id;
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
struct vt_switcher vt_switcher;
|
struct vt_switcher vt_switcher;
|
||||||
struct modeset_dev *dev;
|
struct modeset_dev *dev;
|
||||||
drmModeCrtc *old_crtc;
|
drmModeCrtc *old_crtc;
|
||||||
|
drmEventContext ev;
|
||||||
|
|
||||||
bool active;
|
bool active;
|
||||||
char *device_path;
|
bool pflip_happening;
|
||||||
int connector_id;
|
|
||||||
|
|
||||||
int32_t device_w;
|
int32_t device_w;
|
||||||
int32_t device_h;
|
int32_t device_h;
|
||||||
|
@ -334,6 +338,13 @@ end:
|
||||||
return ret;
|
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)
|
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)
|
static void release_vo_crtc(struct vo *vo)
|
||||||
{
|
{
|
||||||
struct priv *p = vo->priv;
|
struct priv *p = vo->priv;
|
||||||
|
|
||||||
p->active = false;
|
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) {
|
if (p->old_crtc) {
|
||||||
drmModeSetCrtc(p->fd,
|
drmModeSetCrtc(p->fd,
|
||||||
p->old_crtc->crtc_id,
|
p->old_crtc->crtc_id,
|
||||||
|
@ -487,15 +509,31 @@ static void flip_page(struct vo *vo)
|
||||||
{
|
{
|
||||||
struct priv *p = vo->priv;
|
struct priv *p = vo->priv;
|
||||||
if (!p->active) return;
|
if (!p->active) return;
|
||||||
|
if (p->pflip_happening) return;
|
||||||
|
|
||||||
int ret = drmModeSetCrtc(p->fd, p->dev->crtc,
|
int ret = drmModePageFlip(p->fd, p->dev->crtc,
|
||||||
p->dev->bufs[p->dev->front_buf].fb,
|
p->dev->bufs[p->dev->front_buf].fb,
|
||||||
0, 0, &p->dev->conn, 1, &p->dev->mode);
|
DRM_MODE_PAGE_FLIP_EVENT, p);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
MP_WARN(vo, "Cannot flip page for connector\n");
|
MP_WARN(vo, "Cannot flip page for connector\n");
|
||||||
} else {
|
} else {
|
||||||
p->dev->front_buf++;
|
p->dev->front_buf++;
|
||||||
p->dev->front_buf %= BUF_COUNT;
|
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;
|
struct priv *p = vo->priv;
|
||||||
p->sws = mp_sws_alloc(vo);
|
p->sws = mp_sws_alloc(vo);
|
||||||
p->fd = -1;
|
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))
|
if (vt_switcher_init(&p->vt_switcher, vo->log))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
Loading…
Reference in New Issue