summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Ekström <jeebjp@gmail.com>2021-01-18 23:28:28 +0200
committersfan5 <sfan5@live.de>2021-10-25 20:37:03 +0200
commite6cf918eb8ba3e6892f7d22a6bbcbbae3e6b5bf5 (patch)
treec6391903eb29ef014e7a729ca06523fa9b8d6985
parent12056fdcd4a54dd03d4a88017340d0798e845f09 (diff)
downloadmpv-e6cf918eb8ba3e6892f7d22a6bbcbbae3e6b5bf5.tar.bz2
mpv-e6cf918eb8ba3e6892f7d22a6bbcbbae3e6b5bf5.tar.xz
drm_common: utilize drmGetDevices when iterating over cards
Based on the idea behind emersion's change to drm_info (https://github.com/ascent12/drm_info/commit/869e789a645b92a99e592a230fe39b0c59a2cd7d). Lets us by default skip devices which are not capable of doing what the DRM master output requires (not primary devices), as some devices have card0 actually not be such. Negative part is that the number given to drm-connector is no longer a direct mapping against a file name.
-rw-r--r--video/out/drm_common.c139
-rw-r--r--video/out/drm_common.h1
-rw-r--r--wscript2
3 files changed, 113 insertions, 29 deletions
diff --git a/video/out/drm_common.c b/video/out/drm_common.c
index 727221b6b1..07c6815209 100644
--- a/video/out/drm_common.c
+++ b/video/out/drm_common.c
@@ -67,7 +67,8 @@ static int drm_validate_mode_opt(
static void kms_show_available_modes(
struct mp_log *log, const drmModeConnector *connector);
-static void kms_show_available_connectors(struct mp_log *log, int card_no);
+static void kms_show_available_connectors(struct mp_log *log, int card_no,
+ const char *card_path);
static double mode_get_Hz(const drmModeModeInfo *mode);
#define OPT_BASE_STRUCT struct drm_opts
@@ -200,7 +201,8 @@ static bool setup_connector(struct kms *kms, const drmModeRes *res,
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);
+ kms_show_available_connectors(kms->log, kms->card_no,
+ kms->primary_node_path);
return false;
}
} else {
@@ -499,11 +501,62 @@ err:
return false;
}
-static int open_card(int card_no)
+static int open_card_path(const char *path)
{
- 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);
+ return open(path, O_RDWR | O_CLOEXEC);
+}
+
+static char *get_primary_device_path(struct mp_log *log, int *card_no)
+{
+ drmDevice *devices[DRM_MAX_MINOR] = { 0 };
+ int card_count = drmGetDevices2(0, devices, MP_ARRAY_SIZE(devices));
+ char *device_path = NULL;
+ bool card_no_given = (*card_no >= 0);
+
+ if (card_count < 0) {
+ mp_err(log, "Listing DRM devices with drmGetDevices failed! (%s)\n",
+ mp_strerror(errno));
+ goto err;
+ }
+
+ if (card_no_given && *card_no > (card_count - 1)) {
+ mp_err(log, "Card number %d given too high! %d devices located.\n",
+ *card_no, card_count);
+ goto err;
+ }
+
+ for (int i = card_no_given ? *card_no : 0; i < card_count; i++) {
+ drmDevice *dev = devices[i];
+
+ if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY))) {
+ if (card_no_given) {
+ mp_err(log,
+ "DRM card number %d given, yet it does not have "
+ "a primary node!\n", i);
+ break;
+ }
+
+ continue;
+ }
+
+ const char *primary_node_path = dev->nodes[DRM_NODE_PRIMARY];
+
+ mp_verbose(log, "Picked DRM card %d, primary node %s%s.\n",
+ i, primary_node_path,
+ card_no_given ? "" : " as the default");
+
+ device_path = talloc_strdup(log, primary_node_path);
+ *card_no = i;
+ break;
+ }
+
+ if (!device_path)
+ mp_err(log, "No primary DRM device could be picked!\n");
+
+err:
+ drmFreeDevices(devices, card_count);
+
+ return device_path;
}
static void parse_connector_spec(struct mp_log *log,
@@ -511,7 +564,7 @@ static void parse_connector_spec(struct mp_log *log,
int *card_no, char **connector_name)
{
if (!connector_spec) {
- *card_no = 0;
+ *card_no = -1;
*connector_name = NULL;
return;
}
@@ -520,7 +573,7 @@ static void parse_connector_spec(struct mp_log *log,
*card_no = atoi(connector_spec);
*connector_name = talloc_strdup(log, dot_ptr + 1);
} else {
- *card_no = 0;
+ *card_no = -1;
*connector_name = talloc_strdup(log, connector_spec);
}
}
@@ -533,11 +586,19 @@ struct kms *kms_create(struct mp_log *log, const char *connector_spec,
int card_no = -1;
char *connector_name = NULL;
parse_connector_spec(log, connector_spec, &card_no, &connector_name);
+ char *primary_node_path = get_primary_device_path(log, &card_no);
+
+ if (!primary_node_path) {
+ mp_err(log,
+ "Failed to find a usable DRM primary node!\n");
+ return NULL;
+ }
struct kms *kms = talloc(NULL, struct kms);
*kms = (struct kms) {
.log = mp_log_new(kms, log, "kms"),
- .fd = open_card(card_no),
+ .primary_node_path = primary_node_path,
+ .fd = open_card_path(primary_node_path),
.connector = NULL,
.encoder = NULL,
.mode = {{0}},
@@ -553,12 +614,6 @@ struct kms *kms_create(struct mp_log *log, const char *connector_spec,
goto err;
}
- char *devname = drmGetDeviceNameFromFd(kms->fd);
- if (devname) {
- mp_verbose(log, "Device name: %s\n", devname);
- drmFree(devname);
- }
-
drmVersionPtr ver = drmGetVersion(kms->fd);
if (ver) {
mp_verbose(log, "Driver: %s %d.%d.%d (%s)\n", ver->name,
@@ -608,6 +663,7 @@ err:
drmModeFreeResources(res);
if (connector_name)
talloc_free(connector_name);
+
kms_destroy(kms);
return NULL;
}
@@ -654,12 +710,13 @@ static void kms_show_available_modes(
}
static void kms_show_foreach_connector(struct mp_log *log, int card_no,
+ const char *card_path,
void (*show_fn)(struct mp_log*, int,
const drmModeConnector*))
{
- int fd = open_card(card_no);
+ int fd = open_card_path(card_path);
if (fd < 0) {
- mp_err(log, "Failed to open card %d\n", card_no);
+ mp_err(log, "Failed to open card %d (%s)\n", card_no, card_path);
return;
}
@@ -695,11 +752,13 @@ static void kms_show_connector_name_and_state_callback(
mp_info(log, " %s (%s)\n", other_connector_name, connection_str);
}
-static void kms_show_available_connectors(struct mp_log *log, int card_no)
+static void kms_show_available_connectors(struct mp_log *log, int card_no,
+ const char *card_path)
{
- mp_info(log, "Available connectors for card %d:\n", card_no);
+ mp_info(log, "Available connectors for card %d (%s):\n", card_no,
+ card_path);
kms_show_foreach_connector(
- log, card_no, kms_show_connector_name_and_state_callback);
+ log, card_no, card_path, kms_show_connector_name_and_state_callback);
mp_info(log, "\n");
}
@@ -717,21 +776,45 @@ static void kms_show_connector_modes_callback(struct mp_log *log, int card_no,
mp_info(log, "\n");
}
-static void kms_show_available_connectors_and_modes(struct mp_log *log, int card_no)
+static void kms_show_available_connectors_and_modes(struct mp_log *log,
+ int card_no,
+ const char *card_path)
{
- kms_show_foreach_connector(log, card_no, kms_show_connector_modes_callback);
+ kms_show_foreach_connector(log, card_no, card_path,
+ kms_show_connector_modes_callback);
}
static void kms_show_foreach_card(
- struct mp_log *log, void (*show_fn)(struct mp_log*,int))
+ struct mp_log *log, void (*show_fn)(struct mp_log*,int,const char *))
{
- for (int card_no = 0; card_no < DRM_MAX_MINOR; card_no++) {
- int fd = open_card(card_no);
- if (fd < 0)
- break;
+ drmDevice *devices[DRM_MAX_MINOR] = { 0 };
+ int card_count = drmGetDevices2(0, devices, MP_ARRAY_SIZE(devices));
+ if (card_count < 0) {
+ mp_err(log, "Listing DRM devices with drmGetDevices failed! (%s)\n",
+ mp_strerror(errno));
+ return;
+ }
+
+ for (int i = 0; i < card_count; i++) {
+ drmDevice *dev = devices[i];
+
+ if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY)))
+ continue;
+
+ const char *primary_node_path = dev->nodes[DRM_NODE_PRIMARY];
+
+ int fd = open_card_path(primary_node_path);
+ if (fd < 0) {
+ mp_err(log, "Failed to open primary DRM node path %s!\n",
+ primary_node_path);
+ continue;
+ }
+
close(fd);
- show_fn(log, card_no);
+ show_fn(log, i, primary_node_path);
}
+
+ drmFreeDevices(devices, card_count);
}
static void kms_show_available_cards_and_connectors(struct mp_log *log)
diff --git a/video/out/drm_common.h b/video/out/drm_common.h
index aa08312ad2..e11d240dca 100644
--- a/video/out/drm_common.h
+++ b/video/out/drm_common.h
@@ -29,6 +29,7 @@
struct kms {
struct mp_log *log;
+ char *primary_node_path;
int fd;
drmModeConnector *connector;
drmModeEncoder *encoder;
diff --git a/wscript b/wscript
index 289cd9771b..4012fa1f7d 100644
--- a/wscript
+++ b/wscript
@@ -487,7 +487,7 @@ video_output_features = [
'name': '--drm',
'desc': 'DRM',
'deps': 'vt.h || consio.h',
- 'func': check_pkg_config('libdrm', '>= 2.4.74'),
+ 'func': check_pkg_config('libdrm', '>= 2.4.75'),
}, {
'name': '--gbm',
'desc': 'GBM',