mirror of https://github.com/mpv-player/mpv
vo_drm: change CLI options + refactors
- Change connector selection to accept human readable names (such as eDP-1, HDMI-A-2) rather than arbitrary numbers. - Change GPU selection to accept GPU number rather than device paths. - Merge connector and GPU selection into one --drm-connector. - Add support for --drm-connector=help. - Add support for --drm-* in EGL backend. - Refactor KMS; reduce state sharing across drm_common.
This commit is contained in:
parent
e9c43258b8
commit
403f489f6c
|
@ -495,13 +495,13 @@ Available video output drivers are:
|
|||
|
||||
The following global options are supported by this video output:
|
||||
|
||||
``--drm-connector=<number>``
|
||||
Select the connector to use (usually this is a monitor.) If set to -1,
|
||||
mpv renders the output on the first available connector. (default: -1)
|
||||
|
||||
``--drm-devpath=<filename>``
|
||||
Path to graphic card device.
|
||||
(default: /dev/dri/card0)
|
||||
``--drm-connector=[<gpu_number>.]<name>``
|
||||
Select the connector to use (usually this is a monitor.) If ``<name>``
|
||||
is empty or ``auto``, mpv renders the output on the first available
|
||||
connector. Use ``--drm-connector=help`` to get list of available
|
||||
connectors. When using multiple graphic cards, use the ``<gpu_number>``
|
||||
argument to disambiguate.
|
||||
(default: empty)
|
||||
|
||||
``--drm-mode=<number>``
|
||||
Mode ID to use (resolution, bit depth and frame rate).
|
||||
|
|
|
@ -48,6 +48,10 @@
|
|||
#include "player/command.h"
|
||||
#include "stream/stream.h"
|
||||
|
||||
#if HAVE_DRM
|
||||
#include "video/out/drm_common.h"
|
||||
#endif
|
||||
|
||||
extern const char mp_help_text[];
|
||||
|
||||
static void print_version(struct mp_log *log)
|
||||
|
@ -190,6 +194,11 @@ static const m_option_t mp_vo_opt_list[] = {
|
|||
#if HAVE_WIN32
|
||||
OPT_STRING("vo-mmcss-profile", mmcss_profile, 0),
|
||||
#endif
|
||||
#if HAVE_DRM
|
||||
OPT_STRING_VALIDATE("drm-connector", drm_connector_spec,
|
||||
0, drm_validate_connector_opt),
|
||||
OPT_INT("drm-mode", drm_mode_id, 0),
|
||||
#endif
|
||||
|
||||
{0}
|
||||
};
|
||||
|
|
|
@ -51,6 +51,9 @@ typedef struct mp_vo_opts {
|
|||
struct sws_opts *sws_opts;
|
||||
// vo_opengl, vo_opengl_cb
|
||||
int hwdec_preload_api;
|
||||
// vo_drm
|
||||
char *drm_connector_spec;
|
||||
int drm_mode_id;
|
||||
} mp_vo_opts;
|
||||
|
||||
struct mp_cache_opts {
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vt.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -35,71 +37,114 @@
|
|||
#define HANDLER_RELEASE 1
|
||||
#define RELEASE_SIGNAL SIGUSR1
|
||||
#define ACQUIRE_SIGNAL SIGUSR2
|
||||
#define MAX_CONNECTOR_NAME_LEN 20
|
||||
|
||||
static int vt_switcher_pipe[2];
|
||||
|
||||
static const char *connector_names[] = {
|
||||
"Unknown", // DRM_MODE_CONNECTOR_Unknown
|
||||
"VGA", // DRM_MODE_CONNECTOR_VGA
|
||||
"DVI-I", // DRM_MODE_CONNECTOR_DVII
|
||||
"DVI-D", // DRM_MODE_CONNECTOR_DVID
|
||||
"DVI-A", // DRM_MODE_CONNECTOR_DVIA
|
||||
"Composite", // DRM_MODE_CONNECTOR_Composite
|
||||
"SVIDEO", // DRM_MODE_CONNECTOR_SVIDEO
|
||||
"LVDS", // DRM_MODE_CONNECTOR_LVDS
|
||||
"Component", // DRM_MODE_CONNECTOR_Component
|
||||
"DIN", // DRM_MODE_CONNECTOR_9PinDIN
|
||||
"DP", // DRM_MODE_CONNECTOR_DisplayPort
|
||||
"HDMI-A", // DRM_MODE_CONNECTOR_HDMIA
|
||||
"HDMI-B", // DRM_MODE_CONNECTOR_HDMIB
|
||||
"TV", // DRM_MODE_CONNECTOR_TV
|
||||
"eDP", // DRM_MODE_CONNECTOR_eDP
|
||||
"Virtual", // DRM_MODE_CONNECTOR_VIRTUAL
|
||||
"DSI", // DRM_MODE_CONNECTOR_DSI
|
||||
"DPI", // DRM_MODE_CONNECTOR_DPI
|
||||
};
|
||||
|
||||
// KMS ------------------------------------------------------------------------
|
||||
|
||||
static bool is_connector_valid(struct kms *kms, int connector_id,
|
||||
drmModeConnector *connector, bool silent)
|
||||
static void get_connector_name(
|
||||
drmModeConnector *connector, char ret[MAX_CONNECTOR_NAME_LEN])
|
||||
{
|
||||
if (!connector) {
|
||||
if (!silent) {
|
||||
MP_ERR(kms, "Cannot get connector %d: %s\n", connector_id,
|
||||
mp_strerror(errno));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (connector->connection != DRM_MODE_CONNECTED) {
|
||||
if (!silent) {
|
||||
MP_ERR(kms, "Connector %d is disconnected\n", connector_id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (connector->count_modes == 0) {
|
||||
if (!silent) {
|
||||
MP_ERR(kms, "Connector %d has no valid modes\n", connector_id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
snprintf(ret, MAX_CONNECTOR_NAME_LEN, "%s-%d",
|
||||
connector_names[connector->connector_type],
|
||||
connector->connector_type_id);
|
||||
}
|
||||
|
||||
static bool setup_connector(
|
||||
struct kms *kms, const drmModeRes *res, int connector_id)
|
||||
// Gets the first connector whose name matches the input parameter.
|
||||
// The returned connector may be disconnected.
|
||||
// Result must be freed with drmModeFreeConnector.
|
||||
static drmModeConnector *get_connector_by_name(const struct kms *kms,
|
||||
const drmModeRes *res,
|
||||
const char *connector_name)
|
||||
{
|
||||
drmModeConnector *connector = NULL;
|
||||
if (connector_id == -1) {
|
||||
// get the first connected connector
|
||||
for (int i = 0; i < res->count_connectors; i++) {
|
||||
connector = drmModeGetConnector(kms->fd, res->connectors[i]);
|
||||
if (is_connector_valid(kms, i, connector, true)) {
|
||||
connector_id = i;
|
||||
break;
|
||||
}
|
||||
if (connector) {
|
||||
drmModeFreeConnector(connector);
|
||||
connector = NULL;
|
||||
}
|
||||
for (int i = 0; i < res->count_connectors; i++) {
|
||||
drmModeConnector *connector
|
||||
= drmModeGetConnector(kms->fd, res->connectors[i]);
|
||||
if (!connector)
|
||||
continue;
|
||||
char other_connector_name[MAX_CONNECTOR_NAME_LEN];
|
||||
get_connector_name(connector, other_connector_name);
|
||||
if (!strcmp(connector_name, other_connector_name))
|
||||
return connector;
|
||||
drmModeFreeConnector(connector);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Gets the first connected connector.
|
||||
// Result must be freed with drmModeFreeConnector.
|
||||
static drmModeConnector *get_first_connected_connector(const struct kms *kms,
|
||||
const drmModeRes *res)
|
||||
{
|
||||
for (int i = 0; i < res->count_connectors; i++) {
|
||||
drmModeConnector *connector
|
||||
= drmModeGetConnector(kms->fd, res->connectors[i]);
|
||||
if (!connector)
|
||||
continue;
|
||||
if (connector->connection == DRM_MODE_CONNECTED
|
||||
&& connector->count_modes > 0) {
|
||||
return connector;
|
||||
}
|
||||
if (connector_id == -1) {
|
||||
drmModeFreeConnector(connector);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool setup_connector(struct kms *kms, const drmModeRes *res,
|
||||
const char *connector_name)
|
||||
{
|
||||
drmModeConnector *connector;
|
||||
|
||||
if (connector_name
|
||||
&& strcmp(connector_name, "")
|
||||
&& strcmp(connector_name, "auto")) {
|
||||
connector = get_connector_by_name(kms, res, connector_name);
|
||||
if (!connector) {
|
||||
MP_ERR(kms, "No connector with name %s found\n", connector_name);
|
||||
kms_show_available_connectors(kms->log, kms->card_no);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
connector = get_first_connected_connector(kms, res);
|
||||
if (!connector) {
|
||||
MP_ERR(kms, "No connected connectors found\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (connector_id < 0 || connector_id >= res->count_connectors) {
|
||||
MP_ERR(kms, "Bad connector ID. Max valid connector ID = %u\n",
|
||||
res->count_connectors);
|
||||
if (connector->connection != DRM_MODE_CONNECTED) {
|
||||
drmModeFreeConnector(connector);
|
||||
MP_ERR(kms, "Chosen connector is disconnected\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
connector = drmModeGetConnector(kms->fd, res->connectors[connector_id]);
|
||||
if (!is_connector_valid(kms, connector_id, connector, false))
|
||||
if (connector->count_modes == 0) {
|
||||
drmModeFreeConnector(connector);
|
||||
MP_ERR(kms, "Chosen connector has no valid modes\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
kms->connector = connector;
|
||||
return true;
|
||||
|
@ -130,8 +175,7 @@ static bool setup_crtc(struct kms *kms, const drmModeRes *res)
|
|||
drmModeFreeEncoder(encoder);
|
||||
}
|
||||
|
||||
MP_ERR(kms,
|
||||
"Connector %u has no suitable CRTC\n",
|
||||
MP_ERR(kms, "Connector %u has no suitable CRTC\n",
|
||||
kms->connector->connector_id);
|
||||
return false;
|
||||
}
|
||||
|
@ -139,20 +183,10 @@ static bool setup_crtc(struct kms *kms, const drmModeRes *res)
|
|||
static bool setup_mode(struct kms *kms, int mode_id)
|
||||
{
|
||||
if (mode_id < 0 || mode_id >= kms->connector->count_modes) {
|
||||
MP_ERR(
|
||||
kms,
|
||||
"Bad mode ID (max = %d).\n",
|
||||
kms->connector->count_modes - 1);
|
||||
MP_ERR(kms, "Bad mode ID (max = %d).\n",
|
||||
kms->connector->count_modes - 1);
|
||||
|
||||
MP_INFO(kms, "Available modes:\n");
|
||||
for (unsigned int i = 0; i < kms->connector->count_modes; i++) {
|
||||
MP_INFO(kms,
|
||||
"Mode %d: %s (%dx%d)\n",
|
||||
i,
|
||||
kms->connector->modes[i].name,
|
||||
kms->connector->modes[i].hdisplay,
|
||||
kms->connector->modes[i].vdisplay);
|
||||
}
|
||||
kms_show_available_modes(kms->log, kms->connector);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -160,36 +194,66 @@ static bool setup_mode(struct kms *kms, int mode_id)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
struct kms *kms_create(struct mp_log *log)
|
||||
static int open_card(int card_no)
|
||||
{
|
||||
struct kms *ret = talloc(NULL, struct kms);
|
||||
*ret = (struct kms) {
|
||||
.log = mp_log_new(ret, log, "kms"),
|
||||
.fd = -1,
|
||||
char card_path[128];
|
||||
snprintf(card_path, sizeof(card_path), DRM_DEV_NAME, DRM_DIR_NAME, card_no);
|
||||
return open(card_path, O_RDWR | O_CLOEXEC);
|
||||
}
|
||||
|
||||
static void parse_connector_spec(struct mp_log *log,
|
||||
const char *connector_spec,
|
||||
int *card_no, char **connector_name)
|
||||
{
|
||||
if (!connector_spec) {
|
||||
*card_no = 0;
|
||||
*connector_name = NULL;
|
||||
return;
|
||||
}
|
||||
char *dot_ptr = strchr(connector_spec, '.');
|
||||
if (dot_ptr) {
|
||||
*card_no = atoi(connector_spec);
|
||||
*connector_name = talloc_strdup(log, dot_ptr + 1);
|
||||
} else {
|
||||
*card_no = 0;
|
||||
*connector_name = talloc_strdup(log, connector_spec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct kms *kms_create(struct mp_log *log, const char *connector_spec,
|
||||
int mode_id)
|
||||
{
|
||||
int card_no = -1;
|
||||
char *connector_name = NULL;
|
||||
parse_connector_spec(log, connector_spec, &card_no, &connector_name);
|
||||
|
||||
struct kms *kms = talloc(NULL, struct kms);
|
||||
*kms = (struct kms) {
|
||||
.log = mp_log_new(kms, log, "kms"),
|
||||
.fd = open_card(card_no),
|
||||
.connector = NULL,
|
||||
.encoder = NULL,
|
||||
.mode = { 0 },
|
||||
.crtc_id = -1,
|
||||
.card_no = card_no,
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool kms_setup(struct kms *kms, const char *device_path, int connector_id, int mode_id)
|
||||
{
|
||||
kms->fd = open(device_path, O_RDWR | O_CLOEXEC);
|
||||
drmModeRes *res = NULL;
|
||||
|
||||
if (kms->fd < 0) {
|
||||
MP_ERR(kms, "Cannot open \"%s\": %s.\n", device_path, mp_strerror(errno));
|
||||
return false;
|
||||
mp_err(log, "Cannot open card \"%d\": %s.\n",
|
||||
card_no, mp_strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
drmModeRes *res = drmModeGetResources(kms->fd);
|
||||
res = drmModeGetResources(kms->fd);
|
||||
if (!res) {
|
||||
MP_ERR(kms, "Cannot retrieve DRM resources: %s\n", mp_strerror(errno));
|
||||
return false;
|
||||
mp_err(log, "Cannot retrieve DRM resources: %s\n", mp_strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!setup_connector(kms, res, connector_id))
|
||||
if (!setup_connector(kms, res, connector_name))
|
||||
goto err;
|
||||
if (!setup_crtc(kms, res))
|
||||
goto err;
|
||||
|
@ -197,11 +261,15 @@ bool kms_setup(struct kms *kms, const char *device_path, int connector_id, int m
|
|||
goto err;
|
||||
|
||||
drmModeFreeResources(res);
|
||||
return true;
|
||||
return kms;
|
||||
|
||||
err:
|
||||
drmModeFreeResources(res);
|
||||
return false;
|
||||
if (res)
|
||||
drmModeFreeResources(res);
|
||||
if (connector_name)
|
||||
talloc_free(connector_name);
|
||||
kms_destroy(kms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void kms_destroy(struct kms *kms)
|
||||
|
@ -220,11 +288,81 @@ void kms_destroy(struct kms *kms)
|
|||
talloc_free(kms);
|
||||
}
|
||||
|
||||
void kms_show_available_modes(
|
||||
struct mp_log *log, const drmModeConnector *connector)
|
||||
{
|
||||
mp_info(log, "Available modes:\n");
|
||||
for (unsigned int i = 0; i < connector->count_modes; i++) {
|
||||
mp_info(log, "Mode %d: %s (%dx%d)\n", i,
|
||||
connector->modes[i].name,
|
||||
connector->modes[i].hdisplay,
|
||||
connector->modes[i].vdisplay);
|
||||
}
|
||||
}
|
||||
|
||||
void kms_show_available_connectors(struct mp_log *log, int card_no)
|
||||
{
|
||||
mp_info(log, "Available connectors for card %d:\n", card_no);
|
||||
|
||||
int fd = open_card(card_no);
|
||||
if (fd < 0) {
|
||||
mp_err(log, "Failed to open card %d\n", card_no);
|
||||
return;
|
||||
}
|
||||
|
||||
drmModeRes *res = drmModeGetResources(fd);
|
||||
if (!res) {
|
||||
mp_err(log, "Cannot retrieve DRM resources: %s\n", mp_strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (int i = 0; i < res->count_connectors; i++) {
|
||||
drmModeConnector *connector
|
||||
= drmModeGetConnector(fd, res->connectors[i]);
|
||||
if (!connector)
|
||||
continue;
|
||||
char other_connector_name[MAX_CONNECTOR_NAME_LEN];
|
||||
get_connector_name(connector, other_connector_name);
|
||||
mp_info(log, "%s (%s)\n", other_connector_name,
|
||||
connector->connection == DRM_MODE_CONNECTED
|
||||
? "connected"
|
||||
: "disconnected");
|
||||
drmModeFreeConnector(connector);
|
||||
}
|
||||
|
||||
err:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (res)
|
||||
drmModeFreeResources(res);
|
||||
}
|
||||
|
||||
void kms_show_available_cards_and_connectors(struct mp_log *log)
|
||||
{
|
||||
for (int card_no = 0; card_no < DRM_MAX_MINOR; card_no++) {
|
||||
int fd = open_card(card_no);
|
||||
if (fd < 0)
|
||||
break;
|
||||
close(fd);
|
||||
kms_show_available_connectors(log, card_no);
|
||||
}
|
||||
}
|
||||
|
||||
double kms_get_display_fps(const struct kms *kms)
|
||||
{
|
||||
return kms->mode.clock * 1000.0 / kms->mode.htotal / kms->mode.vtotal;
|
||||
}
|
||||
|
||||
int drm_validate_connector_opt(struct mp_log *log, const struct m_option *opt,
|
||||
struct bstr name, struct bstr param)
|
||||
{
|
||||
if (bstr_equals0(param, "help")) {
|
||||
kms_show_available_cards_and_connectors(log);
|
||||
return M_OPT_EXIT;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// VT switcher ----------------------------------------------------------------
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include "options/m_option.h"
|
||||
|
||||
struct kms {
|
||||
struct mp_log *log;
|
||||
|
@ -29,6 +30,7 @@ struct kms {
|
|||
drmModeEncoder *encoder;
|
||||
drmModeModeInfo mode;
|
||||
uint32_t crtc_id;
|
||||
int card_no;
|
||||
};
|
||||
|
||||
struct vt_switcher {
|
||||
|
@ -43,12 +45,22 @@ 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);
|
||||
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);
|
||||
|
||||
struct kms *kms_create(struct mp_log *log);
|
||||
bool kms_setup(struct kms *kms, const char *device_path, int conn_id, int mode_id);
|
||||
struct kms *kms_create(struct mp_log *log, const char *connector_spec,
|
||||
int mode_id);
|
||||
void kms_destroy(struct kms *kms);
|
||||
double kms_get_display_fps(const struct kms *kms);
|
||||
|
||||
void kms_show_available_connectors(struct mp_log *log, int card_no);
|
||||
void kms_show_available_modes(struct mp_log *log,
|
||||
const drmModeConnector *connector);
|
||||
void kms_show_available_cards_and_connectors(struct mp_log *log);
|
||||
|
||||
int drm_validate_connector_opt(struct mp_log *log, const struct m_option *opt,
|
||||
struct bstr name, struct bstr param);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -94,7 +94,8 @@ static bool init_egl(struct MPGLContext *ctx, int flags)
|
|||
&p->egl.context, &config))
|
||||
return -1;
|
||||
MP_VERBOSE(ctx->vo, "Initializing EGL surface\n");
|
||||
p->egl.surface = eglCreateWindowSurface(p->egl.display, config, p->gbm.surface, NULL);
|
||||
p->egl.surface
|
||||
= eglCreateWindowSurface(p->egl.display, config, p->gbm.surface, NULL);
|
||||
if (p->egl.surface == EGL_NO_SURFACE) {
|
||||
MP_ERR(ctx->vo, "Failed to create EGL surface.\n");
|
||||
return false;
|
||||
|
@ -147,7 +148,7 @@ static void update_framebuffer_from_bo(
|
|||
int handle = gbm_bo_get_handle(bo).u32;
|
||||
|
||||
int ret = drmModeAddFB(p->kms->fd, p->fb.width, p->fb.height,
|
||||
24, 32, stride, handle, &p->fb.id);
|
||||
24, 32, stride, handle, &p->fb.id);
|
||||
if (ret) {
|
||||
MP_ERR(ctx->vo, "Failed to create framebuffer: %s\n", mp_strerror(errno));
|
||||
}
|
||||
|
@ -155,7 +156,7 @@ static void update_framebuffer_from_bo(
|
|||
}
|
||||
|
||||
static void page_flipped(int fd, unsigned int frame, unsigned int sec,
|
||||
unsigned int usec, void *data)
|
||||
unsigned int usec, void *data)
|
||||
{
|
||||
struct priv *p = data;
|
||||
p->waiting_for_flip = false;
|
||||
|
@ -167,12 +168,8 @@ static bool crtc_setup(struct MPGLContext *ctx)
|
|||
if (p->active)
|
||||
return true;
|
||||
p->old_crtc = drmModeGetCrtc(p->kms->fd, p->kms->crtc_id);
|
||||
int ret = drmModeSetCrtc(p->kms->fd, p->kms->crtc_id,
|
||||
p->fb.id,
|
||||
0,
|
||||
0,
|
||||
&p->kms->connector->connector_id,
|
||||
1,
|
||||
int ret = drmModeSetCrtc(p->kms->fd, p->kms->crtc_id, p->fb.id,
|
||||
0, 0, &p->kms->connector->connector_id, 1,
|
||||
&p->kms->mode);
|
||||
p->active = true;
|
||||
return ret == 0;
|
||||
|
@ -197,12 +194,9 @@ static void crtc_release(struct MPGLContext *ctx)
|
|||
|
||||
if (p->old_crtc) {
|
||||
drmModeSetCrtc(p->kms->fd,
|
||||
p->old_crtc->crtc_id,
|
||||
p->old_crtc->buffer_id,
|
||||
p->old_crtc->x,
|
||||
p->old_crtc->y,
|
||||
&p->kms->connector->connector_id,
|
||||
1,
|
||||
p->old_crtc->crtc_id, p->old_crtc->buffer_id,
|
||||
p->old_crtc->x, p->old_crtc->y,
|
||||
&p->kms->connector->connector_id, 1,
|
||||
&p->old_crtc->mode);
|
||||
drmModeFreeCrtc(p->old_crtc);
|
||||
p->old_crtc = NULL;
|
||||
|
@ -220,7 +214,8 @@ static void release_vt(void *data)
|
|||
//until things change, this is commented.
|
||||
struct priv *p = ctx->priv;
|
||||
if (drmDropMaster(p->kms->fd)) {
|
||||
MP_WARN(ctx->vo, "Failed to drop DRM master: %s\n", mp_strerror(errno));
|
||||
MP_WARN(ctx->vo, "Failed to drop DRM master: %s\n",
|
||||
mp_strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,7 +227,8 @@ static void acquire_vt(void *data)
|
|||
if (USE_MASTER) {
|
||||
struct priv *p = ctx->priv;
|
||||
if (drmSetMaster(p->kms->fd)) {
|
||||
MP_WARN(ctx->vo, "Failed to acquire DRM master: %s\n", mp_strerror(errno));
|
||||
MP_WARN(ctx->vo, "Failed to acquire DRM master: %s\n",
|
||||
mp_strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,7 +243,8 @@ static void drm_egl_uninit(MPGLContext *ctx)
|
|||
if (p->vt_switcher_active)
|
||||
vt_switcher_destroy(&p->vt_switcher);
|
||||
|
||||
eglMakeCurrent(p->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglMakeCurrent(p->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
eglDestroyContext(p->egl.display, p->egl.context);
|
||||
eglDestroySurface(p->egl.display, p->egl.surface);
|
||||
gbm_surface_destroy(p->gbm.surface);
|
||||
|
@ -287,18 +284,13 @@ static int drm_egl_init(struct MPGLContext *ctx, int flags)
|
|||
}
|
||||
|
||||
MP_VERBOSE(ctx->vo, "Initializing KMS\n");
|
||||
p->kms = kms_create(ctx->vo->log);
|
||||
p->kms = kms_create(ctx->vo->log, ctx->vo->opts->drm_connector_spec,
|
||||
ctx->vo->opts->drm_mode_id);
|
||||
if (!p->kms) {
|
||||
MP_ERR(ctx->vo, "Failed to create KMS.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: arguments should be configurable
|
||||
if (!kms_setup(p->kms, "/dev/dri/card0", -1, 0)) {
|
||||
MP_ERR(ctx->vo, "Failed to configure KMS.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!init_gbm(ctx)) {
|
||||
MP_ERR(ctx->vo, "Failed to setup GBM.\n");
|
||||
return -1;
|
||||
|
@ -309,7 +301,8 @@ static int drm_egl_init(struct MPGLContext *ctx, int flags)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!eglMakeCurrent(p->egl.display, p->egl.surface, p->egl.surface, p->egl.context)) {
|
||||
if (!eglMakeCurrent(p->egl.display, p->egl.surface, p->egl.surface,
|
||||
p->egl.context)) {
|
||||
MP_ERR(ctx->vo, "Failed to make context current.\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -337,11 +330,8 @@ static int drm_egl_init(struct MPGLContext *ctx, int flags)
|
|||
}
|
||||
|
||||
if (!crtc_setup(ctx)) {
|
||||
MP_ERR(
|
||||
ctx->vo,
|
||||
"Failed to set CRTC for connector %u: %s\n",
|
||||
p->kms->connector->connector_id,
|
||||
mp_strerror(errno));
|
||||
MP_ERR(ctx->vo, "Failed to set CRTC for connector %u: %s\n",
|
||||
p->kms->connector->connector_id, mp_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,8 +54,7 @@ struct framebuffer {
|
|||
};
|
||||
|
||||
struct priv {
|
||||
char *device_path;
|
||||
int connector_id;
|
||||
char *connector_spec;
|
||||
int mode_id;
|
||||
|
||||
struct kms *kms;
|
||||
|
@ -70,8 +69,8 @@ struct priv {
|
|||
bool active;
|
||||
bool pflip_happening;
|
||||
|
||||
int32_t device_w;
|
||||
int32_t device_h;
|
||||
int32_t screen_w;
|
||||
int32_t screen_h;
|
||||
struct mp_image *last_input;
|
||||
struct mp_image *cur_frame;
|
||||
struct mp_rect src;
|
||||
|
@ -158,8 +157,7 @@ static bool fb_setup_double_buffering(struct vo *vo)
|
|||
|
||||
for (unsigned int i = 0; i < BUF_COUNT; i++) {
|
||||
if (!fb_setup_single(vo, p->kms->fd, &p->bufs[i])) {
|
||||
MP_ERR(vo, "Cannot create framebuffer for connector %d\n",
|
||||
p->kms->connector->connector_id);
|
||||
MP_ERR(vo, "Cannot create framebuffer\n");
|
||||
for (unsigned int j = 0; j < i; j++) {
|
||||
fb_destroy(p->kms->fd, &p->bufs[j]);
|
||||
}
|
||||
|
@ -171,7 +169,7 @@ static bool fb_setup_double_buffering(struct vo *vo)
|
|||
}
|
||||
|
||||
static void page_flipped(int fd, unsigned int frame, unsigned int sec,
|
||||
unsigned int usec, void *data)
|
||||
unsigned int usec, void *data)
|
||||
{
|
||||
struct priv *p = data;
|
||||
p->pflip_happening = false;
|
||||
|
@ -185,10 +183,7 @@ static bool crtc_setup(struct vo *vo)
|
|||
p->old_crtc = drmModeGetCrtc(p->kms->fd, p->kms->crtc_id);
|
||||
int ret = drmModeSetCrtc(p->kms->fd, p->kms->crtc_id,
|
||||
p->bufs[p->front_buf + BUF_COUNT - 1].fb,
|
||||
0,
|
||||
0,
|
||||
&p->kms->connector->connector_id,
|
||||
1,
|
||||
0, 0, &p->kms->connector->connector_id, 1,
|
||||
&p->kms->mode);
|
||||
p->active = true;
|
||||
return ret == 0;
|
||||
|
@ -212,13 +207,10 @@ static void crtc_release(struct vo *vo)
|
|||
}
|
||||
|
||||
if (p->old_crtc) {
|
||||
drmModeSetCrtc(p->kms->fd,
|
||||
p->old_crtc->crtc_id,
|
||||
drmModeSetCrtc(p->kms->fd, p->old_crtc->crtc_id,
|
||||
p->old_crtc->buffer_id,
|
||||
p->old_crtc->x,
|
||||
p->old_crtc->y,
|
||||
&p->kms->connector->connector_id,
|
||||
1,
|
||||
p->old_crtc->x, p->old_crtc->y,
|
||||
&p->kms->connector->connector_id, 1,
|
||||
&p->old_crtc->mode);
|
||||
drmModeFreeCrtc(p->old_crtc);
|
||||
p->old_crtc = NULL;
|
||||
|
@ -274,8 +266,8 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
|
|||
{
|
||||
struct priv *p = vo->priv;
|
||||
|
||||
vo->dwidth = p->device_w;
|
||||
vo->dheight = p->device_h;
|
||||
vo->dwidth = p->screen_w;
|
||||
vo->dheight = p->screen_h;
|
||||
vo_get_src_dst_rects(vo, &p->src, &p->dst, &p->osd);
|
||||
|
||||
int w = p->dst.x1 - p->dst.x0;
|
||||
|
@ -302,7 +294,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
|
|||
};
|
||||
|
||||
talloc_free(p->cur_frame);
|
||||
p->cur_frame = mp_image_alloc(IMGFMT, p->device_w, p->device_h);
|
||||
p->cur_frame = mp_image_alloc(IMGFMT, p->screen_w, p->screen_h);
|
||||
mp_image_params_guess_csp(&p->sws->dst);
|
||||
mp_image_set_params(p->cur_frame, &p->sws->dst);
|
||||
|
||||
|
@ -338,14 +330,11 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
|
|||
struct framebuffer *front_buf = &p->bufs[p->front_buf];
|
||||
int w = p->dst.x1 - p->dst.x0;
|
||||
int h = p->dst.y1 - p->dst.y0;
|
||||
int x = (p->device_w - w) >> 1;
|
||||
int y = (p->device_h - h) >> 1;
|
||||
int x = (p->screen_w - w) >> 1;
|
||||
int y = (p->screen_h - h) >> 1;
|
||||
int shift = y * front_buf->stride + x * BYTES_PER_PIXEL;
|
||||
memcpy_pic(front_buf->map + shift,
|
||||
p->cur_frame->planes[0],
|
||||
w * BYTES_PER_PIXEL,
|
||||
h,
|
||||
front_buf->stride,
|
||||
memcpy_pic(front_buf->map + shift, p->cur_frame->planes[0],
|
||||
w * BYTES_PER_PIXEL, h, front_buf->stride,
|
||||
p->cur_frame->stride[0]);
|
||||
}
|
||||
|
||||
|
@ -422,17 +411,13 @@ static int preinit(struct vo *vo)
|
|||
MP_WARN(vo, "Failed to set up VT switcher. Terminal switching will be unavailable.\n");
|
||||
}
|
||||
|
||||
p->kms = kms_create(vo->log);
|
||||
p->kms = kms_create(
|
||||
vo->log, vo->opts->drm_connector_spec, vo->opts->drm_mode_id);
|
||||
if (!p->kms) {
|
||||
MP_ERR(vo, "Failed to create KMS.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!kms_setup(p->kms, p->device_path, p->connector_id, p->mode_id)) {
|
||||
MP_ERR(vo, "Failed to configure KMS.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!fb_setup_double_buffering(vo)) {
|
||||
MP_ERR(vo, "Failed to set up double buffering.\n");
|
||||
goto err;
|
||||
|
@ -440,18 +425,16 @@ static int preinit(struct vo *vo)
|
|||
|
||||
uint64_t has_dumb;
|
||||
if (drmGetCap(p->kms->fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0) {
|
||||
MP_ERR(vo, "Device \"%s\" does not support dumb buffers.\n", p->device_path);
|
||||
MP_ERR(vo, "Card \"%d\" does not support dumb buffers.\n",
|
||||
p->kms->card_no);
|
||||
goto err;
|
||||
}
|
||||
|
||||
p->device_w = p->bufs[0].width;
|
||||
p->device_h = p->bufs[0].height;
|
||||
p->screen_w = p->bufs[0].width;
|
||||
p->screen_h = p->bufs[0].height;
|
||||
|
||||
if (!crtc_setup(vo)) {
|
||||
MP_ERR(vo,
|
||||
"Cannot set CRTC for connector %u: %s\n",
|
||||
p->kms->connector->connector_id,
|
||||
mp_strerror(errno));
|
||||
MP_ERR(vo, "Cannot set CRTC: %s\n", mp_strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -507,16 +490,5 @@ const struct vo_driver video_out_drm = {
|
|||
.wait_events = wait_events,
|
||||
.wakeup = wakeup,
|
||||
.priv_size = sizeof(struct priv),
|
||||
.options = (const struct m_option[]) {
|
||||
OPT_STRING("devpath", device_path, 0),
|
||||
OPT_INT("connector", connector_id, 0),
|
||||
OPT_INT("mode", mode_id, 0),
|
||||
{0},
|
||||
},
|
||||
.priv_defaults = &(const struct priv) {
|
||||
.device_path = "/dev/dri/card0",
|
||||
.connector_id = -1,
|
||||
.mode_id = 0,
|
||||
},
|
||||
.legacy_prefix = "drm",
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue