summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Kindestam <antonki@kth.se>2018-06-02 12:53:58 +0200
committersfan5 <sfan5@live.de>2019-05-04 14:17:11 +0200
commit8261924db93eb436a9e1606d437f0fe64e56dc66 (patch)
treef842ea92e1d575d78f8f95925b2e81ae93ad7a0e
parenta776628d88cb6dab677ba8977d54861d24571c69 (diff)
downloadmpv-8261924db93eb436a9e1606d437f0fe64e56dc66.tar.bz2
mpv-8261924db93eb436a9e1606d437f0fe64e56dc66.tar.xz
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.
-rw-r--r--DOCS/man/vo.rst5
-rw-r--r--video/out/drm_common.c102
-rw-r--r--video/out/drm_common.h10
-rw-r--r--video/out/opengl/context_drm_egl.c2
-rw-r--r--video/out/vo_drm.c2
5 files changed, 95 insertions, 26 deletions
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index a735dbc059..0583eb6c43 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -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>``
diff --git a/video/out/drm_common.c b/video/out/drm_common.c
index 36e72b3b9a..3a08cbf468 100644
--- a/video/out/drm_common.c
+++ b/video/out/drm_common.c
@@ -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 ----------------------------------------------------------------
diff --git a/video/out/drm_common.h b/video/out/drm_common.h
index f700e90ef5..036b28de9c 100644
--- a/video/out/drm_common.h
+++ b/video/out/drm_common.h
@@ -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
diff --git a/video/out/opengl/context_drm_egl.c b/video/out/opengl/context_drm_egl.c
index f8360d3e62..c4cc28b762 100644
--- a/video/out/opengl/context_drm_egl.c
+++ b/video/out/opengl/context_drm_egl.c
@@ -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);
diff --git a/video/out/vo_drm.c b/video/out/vo_drm.c
index 61553f7eee..281235e911 100644
--- a/video/out/vo_drm.c
+++ b/video/out/vo_drm.c
@@ -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");