From 34d5b73fbbae87db10e4503a363753ea60ba0b24 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sun, 19 Apr 2015 09:39:58 +0200 Subject: vo_drm: extract vt_switcher to drm_common --- video/out/drm_common.c | 151 +++++++++++++++++++++++++++++++++++++++++++ video/out/drm_common.h | 36 +++++++++++ video/out/vo_drm.c | 170 +++++++++++-------------------------------------- wscript_build.py | 1 + 4 files changed, 226 insertions(+), 132 deletions(-) create mode 100644 video/out/drm_common.c create mode 100644 video/out/drm_common.h diff --git a/video/out/drm_common.c b/video/out/drm_common.c new file mode 100644 index 0000000000..cbb0f0182a --- /dev/null +++ b/video/out/drm_common.c @@ -0,0 +1,151 @@ +/* + * This file is part of mpv. + * + * by rr- + * + * mpv is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mpv. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "drm_common.h" + +#include "common/common.h" +#include "common/msg.h" +#include "osdep/io.h" + +#define EVT_RELEASE 1 +#define EVT_ACQUIRE 2 +#define EVT_INTERRUPT 255 +#define HANDLER_ACQUIRE 0 +#define HANDLER_RELEASE 1 + +static int vt_switcher_pipe[2]; + +static void vt_switcher_sighandler(int sig) +{ + unsigned char event = sig == SIGUSR1 ? EVT_RELEASE : EVT_ACQUIRE; + write(vt_switcher_pipe[1], &event, sizeof(event)); +} + +int vt_switcher_init(struct vt_switcher *s, struct mp_log *log) +{ + s->log = log; + s->tty_fd = -1; + vt_switcher_pipe[0] = -1; + vt_switcher_pipe[1] = -1; + + if (mp_make_cloexec_pipe(vt_switcher_pipe)) { + MP_ERR(s, "Creating pipe failed: %s", mp_strerror(errno)); + return -1; + } + + s->tty_fd = open("/dev/tty", O_RDWR | O_CLOEXEC); + if (s->tty_fd < 0) { + MP_ERR(s, "Can't open TTY for VT control: %s", mp_strerror(errno)); + return -1; + } + + struct sigaction act; + act.sa_handler = vt_switcher_sighandler; + act.sa_flags = SA_RESTART; + sigemptyset(&act.sa_mask); + sigaction(SIGUSR1, &act, 0); + sigaction(SIGUSR2, &act, 0); + + struct vt_mode vt_mode; + if (ioctl(s->tty_fd, VT_GETMODE, &vt_mode) < 0) { + MP_ERR(s, "VT_GETMODE failed: %s", mp_strerror(errno)); + return -1; + } + + vt_mode.mode = VT_PROCESS; + vt_mode.relsig = SIGUSR1; + vt_mode.acqsig = SIGUSR2; + if (ioctl(s->tty_fd, VT_SETMODE, &vt_mode) < 0) { + MP_ERR(s, "VT_SETMODE failed: %s", mp_strerror(errno)); + return -1; + } + + return 0; +} + +void vt_switcher_acquire(struct vt_switcher *s, + void (*handler)(void*), void *user_data) +{ + s->handlers[HANDLER_ACQUIRE] = handler; + s->handler_data[HANDLER_ACQUIRE] = user_data; +} + +void vt_switcher_release(struct vt_switcher *s, + void (*handler)(void*), void *user_data) +{ + s->handlers[HANDLER_RELEASE] = handler; + s->handler_data[HANDLER_RELEASE] = user_data; +} + +void vt_switcher_interrupt_poll(struct vt_switcher *s) +{ + unsigned char event = EVT_INTERRUPT; + write(vt_switcher_pipe[1], &event, sizeof(event)); +} + +void vt_switcher_destroy(struct vt_switcher *s) +{ + close(s->tty_fd); + close(vt_switcher_pipe[0]); + close(vt_switcher_pipe[1]); +} + +void vt_switcher_poll(struct vt_switcher *s, int timeout_ms) +{ + struct pollfd fds[1] = { + { .events = POLLIN, .fd = vt_switcher_pipe[0] }, + }; + poll(fds, 1, timeout_ms); + if (!fds[0].revents) { + return; + } + + unsigned char event; + if (read(fds[0].fd, &event, sizeof(event)) != sizeof(event)) { + return; + } + + switch (event) { + case EVT_RELEASE: + s->handlers[HANDLER_RELEASE](s->handler_data[HANDLER_RELEASE]); + + if (ioctl(s->tty_fd, VT_RELDISP, 1) < 0) { + MP_ERR(s, "Failed to release virtual terminal\n"); + } + break; + + case EVT_ACQUIRE: + s->handlers[HANDLER_ACQUIRE](s->handler_data[HANDLER_ACQUIRE]); + + if (ioctl(s->tty_fd, VT_RELDISP, VT_ACKACQ) < 0) { + MP_ERR(s, "Failed to acquire virtual terminal\n"); + } + break; + + case EVT_INTERRUPT: + break; + } +} diff --git a/video/out/drm_common.h b/video/out/drm_common.h new file mode 100644 index 0000000000..5e6c1915ba --- /dev/null +++ b/video/out/drm_common.h @@ -0,0 +1,36 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mpv. If not, see . + */ + +#ifndef MP_VT_SWITCHER_H +#define MP_VT_SWITCHER_H + +struct vt_switcher { + int tty_fd; + struct mp_log *log; + void (*handlers[2])(void*); + void *handler_data[2]; +}; + +int vt_switcher_init(struct vt_switcher *s, struct mp_log *log); +void vt_switcher_destroy(struct vt_switcher *s); +void vt_switcher_poll(struct vt_switcher *s, int timeout_ms); +void vt_switcher_interrupt_poll(struct vt_switcher *s); + +void vt_switcher_acquire(struct vt_switcher *s, void (*handler)(void*), void *user_data); +void vt_switcher_release(struct vt_switcher *s, void (*handler)(void*), void *user_data); + +#endif diff --git a/video/out/vo_drm.c b/video/out/vo_drm.c index 9c9f365254..bcaf3821a0 100644 --- a/video/out/vo_drm.c +++ b/video/out/vo_drm.c @@ -22,21 +22,18 @@ #include #include #include -#include -#include #include -#include #include -#include #include #include #include #include -#include "osdep/io.h" -#include "osdep/timer.h" +#include "drm_common.h" + #include "common/msg.h" +#include "osdep/timer.h" #include "sub/osd.h" #include "video/fmt-conversion.h" #include "video/mp_image.h" @@ -44,14 +41,8 @@ #include "vo.h" #define USE_MASTER 0 -#define EVT_RELEASE 1 -#define EVT_ACQUIRE 2 -#define EVT_INTERRUPT 255 #define BUF_COUNT 2 -static int setup_vo_crtc(struct vo *vo); -static void release_vo_crtc(struct vo *vo); - struct modeset_buf { uint32_t width; uint32_t height; @@ -71,11 +62,6 @@ struct modeset_dev { int front_buf; }; -struct vt_switcher { - int tty_fd; - struct vo *vo; -}; - struct priv { int fd; struct vt_switcher vt_switcher; @@ -350,119 +336,6 @@ end: -static int vt_switcher_pipe[2]; - -static void vt_switcher_sighandler(int sig) -{ - unsigned char event = sig == SIGUSR1 ? EVT_RELEASE : EVT_ACQUIRE; - write(vt_switcher_pipe[1], &event, sizeof(event)); -} - -static void vt_switcher_interrupt(struct vt_switcher *s) -{ - unsigned char event = EVT_INTERRUPT; - write(vt_switcher_pipe[1], &event, sizeof(event)); -} - -static int vt_switcher_init(struct vt_switcher *s, struct vo *vo) -{ - s->tty_fd = -1; - vt_switcher_pipe[0] = -1; - vt_switcher_pipe[1] = -1; - - s->vo = vo; - if (mp_make_cloexec_pipe(vt_switcher_pipe)) { - MP_ERR(vo, "Creating pipe failed: %s", mp_strerror(errno)); - return -1; - } - - s->tty_fd = open("/dev/tty", O_RDWR | O_CLOEXEC); - if (s->tty_fd < 0) { - MP_ERR(vo, "Can't open TTY for VT control: %s", mp_strerror(errno)); - return -1; - } - - struct sigaction act; - act.sa_handler = vt_switcher_sighandler; - act.sa_flags = SA_RESTART; - sigemptyset(&act.sa_mask); - sigaction(SIGUSR1, &act, 0); - sigaction(SIGUSR2, &act, 0); - - struct vt_mode vt_mode; - if (ioctl(s->tty_fd, VT_GETMODE, &vt_mode) < 0) { - MP_ERR(vo, "VT_GETMODE failed: %s", mp_strerror(errno)); - return -1; - } - - vt_mode.mode = VT_PROCESS; - vt_mode.relsig = SIGUSR1; - vt_mode.acqsig = SIGUSR2; - if (ioctl(s->tty_fd, VT_SETMODE, &vt_mode) < 0) { - MP_ERR(vo, "VT_SETMODE failed: %s", mp_strerror(errno)); - return -1; - } - - return 0; -} - -static void vt_switcher_destroy(struct vt_switcher *s) -{ - close(s->tty_fd); - close(vt_switcher_pipe[0]); - close(vt_switcher_pipe[1]); -} - -static void vt_switcher_poll(struct vt_switcher *s, int timeout_ms) -{ - struct pollfd fds[1] = { - { .events = POLLIN, .fd = vt_switcher_pipe[0] }, - }; - poll(fds, 1, timeout_ms); - if (!fds[0].revents) return; - - unsigned char event; - if (read(fds[0].fd, &event, sizeof(event)) != sizeof(event)) return; - - switch (event) { - case EVT_RELEASE: - release_vo_crtc(s->vo); - if (USE_MASTER) { - //this function enables support for switching to x, weston etc. - //however, for whatever reason, it can be called only by root users. - //until things change, this is commented. - struct priv *p = s->vo->priv; - if (drmDropMaster(p->fd)) { - MP_WARN(s->vo, "Failed to drop DRM master: %s\n", mp_strerror(errno)); - } - } - - if (ioctl(s->tty_fd, VT_RELDISP, 1) < 0) { - MP_ERR(s->vo, "Failed to release virtual terminal\n"); - } - break; - - case EVT_ACQUIRE: - if (USE_MASTER) { - struct priv *p = s->vo->priv; - if (drmSetMaster(p->fd)) { - MP_WARN(s->vo, "Failed to acquire DRM master: %s\n", mp_strerror(errno)); - } - } - - setup_vo_crtc(s->vo); - if (ioctl(s->tty_fd, VT_RELDISP, VT_ACKACQ) < 0) { - MP_ERR(s->vo, "Failed to acquire virtual terminal\n"); - } - break; - - case EVT_INTERRUPT: - break; - } -} - - - static int setup_vo_crtc(struct vo *vo) { struct priv *p = vo->priv; @@ -491,6 +364,36 @@ static void release_vo_crtc(struct vo *vo) } } +static void release_vt(void *data) +{ + struct vo *vo = data; + release_vo_crtc(vo); + if (USE_MASTER) { + //this function enables support for switching to x, weston etc. + //however, for whatever reason, it can be called only by root users. + //until things change, this is commented. + struct priv *p = vo->priv; + if (drmDropMaster(p->fd)) { + MP_WARN(vo, "Failed to drop DRM master: %s\n", mp_strerror(errno)); + } + } +} + +static void acquire_vt(void *data) +{ + struct vo *vo = data; + if (USE_MASTER) { + struct priv *p = vo->priv; + if (drmSetMaster(p->fd)) { + MP_WARN(vo, "Failed to acquire DRM master: %s\n", mp_strerror(errno)); + } + } + + setup_vo_crtc(vo); +} + + + static int wait_events(struct vo *vo, int64_t until_time_us) { struct priv *p = vo->priv; @@ -503,7 +406,7 @@ static int wait_events(struct vo *vo, int64_t until_time_us) static void wakeup(struct vo *vo) { struct priv *p = vo->priv; - vt_switcher_interrupt(&p->vt_switcher); + vt_switcher_interrupt_poll(&p->vt_switcher); } static int reconfig(struct vo *vo, struct mp_image_params *params, int flags) @@ -621,9 +524,12 @@ static int preinit(struct vo *vo) p->sws = mp_sws_alloc(vo); p->fd = -1; - if (vt_switcher_init(&p->vt_switcher, vo)) + if (vt_switcher_init(&p->vt_switcher, vo->log)) goto err; + vt_switcher_acquire(&p->vt_switcher, acquire_vt, vo); + vt_switcher_release(&p->vt_switcher, release_vt, vo); + if (modeset_open(vo, &p->fd, p->device_path)) goto err; diff --git a/wscript_build.py b/wscript_build.py index 280e6a62ae..f3676ec441 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -363,6 +363,7 @@ def build(ctx): ( "video/out/wayland/memfile.c", "wayland" ), ( "video/out/win_state.c"), ( "video/out/x11_common.c", "x11" ), + ( "video/out/drm_common.c", "drm" ), ## osdep ( getch2_c ), -- cgit v1.2.3