mirror of
https://github.com/mpv-player/mpv
synced 2025-03-25 04:38:01 +00:00
vo_drm: extract vt_switcher to drm_common
This commit is contained in:
parent
bd5d047c89
commit
34d5b73fbb
151
video/out/drm_common.c
Normal file
151
video/out/drm_common.c
Normal file
@ -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;
|
||||
}
|
||||
}
|
36
video/out/drm_common.h
Normal file
36
video/out/drm_common.h
Normal file
@ -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
|
@ -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;
|
||||
|
||||
|
@ -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 ),
|
||||
|
Loading…
Reference in New Issue
Block a user