summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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',