mirror of https://github.com/mpv-player/mpv
drm_common: Add proper help option to drm-mode
This was implemented by using OPT_STRING_VALIDATE for drm-mode, instead of OPT_INT. Using a string here also prepares for future additions to drm-mode that aim to allow specifying a mode by its resolution.
This commit is contained in:
parent
a776628d88
commit
8261924db9
|
@ -479,13 +479,14 @@ Available video output drivers are:
|
|||
``--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
|
||||
connector. Use ``--drm-connector=help`` to get a 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 and frame rate).
|
||||
Mode ID to use (resolution and frame rate). Use ``--drm-mode=help`` to
|
||||
get a list of available modes for all active connectors.
|
||||
(default: 0)
|
||||
|
||||
``--drm-atomic=<no|auto>``
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "common/common.h"
|
||||
#include "common/msg.h"
|
||||
#include "osdep/io.h"
|
||||
#include "misc/ctype.h"
|
||||
|
||||
#define EVT_RELEASE 1
|
||||
#define EVT_ACQUIRE 2
|
||||
|
@ -47,7 +48,8 @@ const struct m_sub_options drm_conf = {
|
|||
.opts = (const struct m_option[]) {
|
||||
OPT_STRING_VALIDATE("drm-connector", drm_connector_spec,
|
||||
0, drm_validate_connector_opt),
|
||||
OPT_INT("drm-mode", drm_mode_id, 0),
|
||||
OPT_STRING_VALIDATE("drm-mode", drm_mode_spec,
|
||||
0, drm_validate_mode_opt),
|
||||
OPT_CHOICE("drm-atomic", drm_atomic, 0,
|
||||
({"no", 0},
|
||||
{"auto", 1})),
|
||||
|
@ -98,8 +100,8 @@ static const char *connector_names[] = {
|
|||
|
||||
// KMS ------------------------------------------------------------------------
|
||||
|
||||
static void get_connector_name(
|
||||
drmModeConnector *connector, char ret[MAX_CONNECTOR_NAME_LEN])
|
||||
static void get_connector_name(const drmModeConnector *connector,
|
||||
char ret[MAX_CONNECTOR_NAME_LEN])
|
||||
{
|
||||
snprintf(ret, MAX_CONNECTOR_NAME_LEN, "%s-%d",
|
||||
connector_names[connector->connector_type],
|
||||
|
@ -240,12 +242,15 @@ static bool setup_crtc(struct kms *kms, const drmModeRes *res)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool setup_mode(struct kms *kms, int mode_id)
|
||||
static bool setup_mode(struct kms *kms, const char *mode_spec)
|
||||
{
|
||||
const int mode_id = (mode_spec != NULL) ? atoi(mode_spec) : 0;
|
||||
|
||||
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_INFO(kms, "Available modes:\n");
|
||||
kms_show_available_modes(kms->log, kms->connector);
|
||||
return false;
|
||||
}
|
||||
|
@ -281,7 +286,8 @@ static void parse_connector_spec(struct mp_log *log,
|
|||
}
|
||||
|
||||
struct kms *kms_create(struct mp_log *log, const char *connector_spec,
|
||||
int mode_id, int draw_plane, int drmprime_video_plane,
|
||||
const char* mode_spec,
|
||||
int draw_plane, int drmprime_video_plane,
|
||||
bool use_atomic)
|
||||
{
|
||||
int card_no = -1;
|
||||
|
@ -317,7 +323,7 @@ struct kms *kms_create(struct mp_log *log, const char *connector_spec,
|
|||
goto err;
|
||||
if (!setup_crtc(kms, res))
|
||||
goto err;
|
||||
if (!setup_mode(kms, mode_id))
|
||||
if (!setup_mode(kms, mode_spec))
|
||||
goto err;
|
||||
|
||||
// Universal planes allows accessing all the planes (including primary)
|
||||
|
@ -381,9 +387,8 @@ static double mode_get_Hz(const drmModeModeInfo *mode)
|
|||
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@%.2fHz)\n", i,
|
||||
mp_info(log, " Mode %d: %s (%dx%d@%.2fHz)\n", i,
|
||||
connector->modes[i].name,
|
||||
connector->modes[i].hdisplay,
|
||||
connector->modes[i].vdisplay,
|
||||
|
@ -391,10 +396,10 @@ void kms_show_available_modes(
|
|||
}
|
||||
}
|
||||
|
||||
void kms_show_available_connectors(struct mp_log *log, int card_no)
|
||||
static void kms_show_foreach_connector(struct mp_log *log, int card_no,
|
||||
void (*show_fn)(struct mp_log*, int,
|
||||
const drmModeConnector*))
|
||||
{
|
||||
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);
|
||||
|
@ -412,12 +417,7 @@ void kms_show_available_connectors(struct mp_log *log, int card_no)
|
|||
= 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");
|
||||
show_fn(log, card_no, connector);
|
||||
drmModeFreeConnector(connector);
|
||||
}
|
||||
|
||||
|
@ -428,17 +428,65 @@ err:
|
|||
drmModeFreeResources(res);
|
||||
}
|
||||
|
||||
void kms_show_available_cards_and_connectors(struct mp_log *log)
|
||||
static void kms_show_connector_name_and_state_callback(
|
||||
struct mp_log *log, int card_no, const drmModeConnector *connector)
|
||||
{
|
||||
char other_connector_name[MAX_CONNECTOR_NAME_LEN];
|
||||
get_connector_name(connector, other_connector_name);
|
||||
const char *connection_str =
|
||||
(connector->connection == DRM_MODE_CONNECTED) ? "connected" : "disconnected";
|
||||
mp_info(log, " %s (%s)\n", other_connector_name, connection_str);
|
||||
}
|
||||
|
||||
void kms_show_available_connectors(struct mp_log *log, int card_no)
|
||||
{
|
||||
mp_info(log, "Available connectors for card %d:\n", card_no);
|
||||
kms_show_foreach_connector(
|
||||
log, card_no, kms_show_connector_name_and_state_callback);
|
||||
mp_info(log, "\n");
|
||||
}
|
||||
|
||||
static void kms_show_connector_modes_callback(struct mp_log *log, int card_no,
|
||||
const drmModeConnector *connector)
|
||||
{
|
||||
if (connector->connection != DRM_MODE_CONNECTED)
|
||||
return;
|
||||
|
||||
char other_connector_name[MAX_CONNECTOR_NAME_LEN];
|
||||
get_connector_name(connector, other_connector_name);
|
||||
mp_info(log, "Available modes for drm-connector=%d.%s\n",
|
||||
card_no, other_connector_name);
|
||||
kms_show_available_modes(log, connector);
|
||||
mp_info(log, "\n");
|
||||
}
|
||||
|
||||
void kms_show_available_connectors_and_modes(struct mp_log *log, int card_no)
|
||||
{
|
||||
kms_show_foreach_connector(log, card_no, kms_show_connector_modes_callback);
|
||||
}
|
||||
|
||||
static void kms_show_foreach_card(
|
||||
struct mp_log *log, void (*show_fn)(struct mp_log*,int))
|
||||
{
|
||||
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);
|
||||
show_fn(log, card_no);
|
||||
}
|
||||
}
|
||||
|
||||
void kms_show_available_cards_and_connectors(struct mp_log *log)
|
||||
{
|
||||
kms_show_foreach_card(log, kms_show_available_connectors);
|
||||
}
|
||||
|
||||
void kms_show_available_cards_connectors_and_modes(struct mp_log *log)
|
||||
{
|
||||
kms_show_foreach_card(log, kms_show_available_connectors_and_modes);
|
||||
}
|
||||
|
||||
double kms_get_display_fps(const struct kms *kms)
|
||||
{
|
||||
return mode_get_Hz(&kms->mode.mode);
|
||||
|
@ -454,7 +502,21 @@ int drm_validate_connector_opt(struct mp_log *log, const struct m_option *opt,
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int drm_validate_mode_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_connectors_and_modes(log);
|
||||
return M_OPT_EXIT;
|
||||
}
|
||||
for (unsigned i = 0; i < param.len; ++i) {
|
||||
if (!mp_isdigit(param.start[i])) {
|
||||
mp_fatal(log, "Invalid value for option drm-mode. Must be a positive number or 'help'\n");
|
||||
return M_OPT_INVALID;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// VT switcher ----------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ struct vt_switcher {
|
|||
|
||||
struct drm_opts {
|
||||
char *drm_connector_spec;
|
||||
int drm_mode_id;
|
||||
char *drm_mode_spec;
|
||||
int drm_atomic;
|
||||
int drm_draw_plane;
|
||||
int drm_drmprime_video_plane;
|
||||
|
@ -66,7 +66,8 @@ void vt_switcher_release(struct vt_switcher *s, void (*handler)(void*),
|
|||
void *user_data);
|
||||
|
||||
struct kms *kms_create(struct mp_log *log, const char *connector_spec,
|
||||
int mode_id, int draw_plane, int drmprime_video_plane,
|
||||
const char *mode_spec,
|
||||
int draw_plane, int drmprime_video_plane,
|
||||
bool use_atomic);
|
||||
void kms_destroy(struct kms *kms);
|
||||
double kms_get_display_fps(const struct kms *kms);
|
||||
|
@ -74,9 +75,14 @@ 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_connectors_and_modes(struct mp_log *log, int card_no);
|
||||
void kms_show_available_cards_and_connectors(struct mp_log *log);
|
||||
void kms_show_available_cards_connectors_and_modes(struct mp_log *log);
|
||||
|
||||
int drm_validate_connector_opt(struct mp_log *log, const struct m_option *opt,
|
||||
struct bstr name, struct bstr param);
|
||||
|
||||
int drm_validate_mode_opt(struct mp_log *log, const struct m_option *opt,
|
||||
struct bstr name, struct bstr param);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -764,7 +764,7 @@ static bool drm_egl_init(struct ra_ctx *ctx)
|
|||
|
||||
MP_VERBOSE(ctx, "Initializing KMS\n");
|
||||
p->kms = kms_create(ctx->log, ctx->vo->opts->drm_opts->drm_connector_spec,
|
||||
ctx->vo->opts->drm_opts->drm_mode_id,
|
||||
ctx->vo->opts->drm_opts->drm_mode_spec,
|
||||
ctx->vo->opts->drm_opts->drm_draw_plane,
|
||||
ctx->vo->opts->drm_opts->drm_drmprime_video_plane,
|
||||
ctx->vo->opts->drm_opts->drm_atomic);
|
||||
|
|
|
@ -419,7 +419,7 @@ static int preinit(struct vo *vo)
|
|||
|
||||
p->kms = kms_create(vo->log,
|
||||
vo->opts->drm_opts->drm_connector_spec,
|
||||
vo->opts->drm_opts->drm_mode_id,
|
||||
vo->opts->drm_opts->drm_mode_spec,
|
||||
0, 0, false);
|
||||
if (!p->kms) {
|
||||
MP_ERR(vo, "Failed to create KMS.\n");
|
||||
|
|
Loading…
Reference in New Issue