summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcin Kurczewski <mkurczew@gmail.com>2015-04-19 09:39:58 +0200
committerwm4 <wm4@nowhere>2015-04-19 21:18:15 +0200
commit34d5b73fbbae87db10e4503a363753ea60ba0b24 (patch)
treec0f1152cb06ee85b76549aae0eda2a26c574dc0f
parentbd5d047c893cda0b533f9457a6fb2bfbd60de13e (diff)
downloadmpv-34d5b73fbbae87db10e4503a363753ea60ba0b24.tar.bz2
mpv-34d5b73fbbae87db10e4503a363753ea60ba0b24.tar.xz
vo_drm: extract vt_switcher to drm_common
-rw-r--r--video/out/drm_common.c151
-rw-r--r--video/out/drm_common.h36
-rw-r--r--video/out/vo_drm.c170
-rw-r--r--wscript_build.py1
4 files changed, 226 insertions, 132 deletions
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- <rr-@sakuya.pl>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/vt.h>
+#include <unistd.h>
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <assert.h>
#include <errno.h>
#include <fcntl.h>
-#include <poll.h>
-#include <signal.h>
#include <stdbool.h>
-#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <sys/vt.h>
#include <unistd.h>
#include <libswscale/swscale.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
-#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 ),