diff options
-rw-r--r-- | video/out/drm_common.c | 139 | ||||
-rw-r--r-- | video/out/drm_common.h | 1 | ||||
-rw-r--r-- | wscript | 2 |
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; @@ -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', |