diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 33baa75c73f89..3afd1a5676344 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -3149,13 +3149,14 @@ extern "C" { * prioritized in the list of displays, as exposed by calling * SDL_GetDisplays(), with the first listed becoming the primary display. The * naming convention can vary depending on the environment, but it is usually - * a connector name (e.g. 'DP-1', 'DP-2', 'HDMI-1', etc...). + * a connector name (e.g. 'DP-1', 'DP-2', 'HDMI-A-1',etc...). * - * On X11 and Wayland desktops, the connector names associated with displays + * On Wayland and X11 desktops, the connector names associated with displays * can typically be found by using the `xrandr` utility. * * This hint is currently supported on the following drivers: * + * - KMSDRM (kmsdrm) * - Wayland (wayland) * * This hint should be set before SDL is initialized. diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h index 1f0646636ebcd..5f389d854ab2f 100644 --- a/src/video/kmsdrm/SDL_kmsdrmsym.h +++ b/src/video/kmsdrm/SDL_kmsdrmsym.h @@ -63,6 +63,8 @@ SDL_KMSDRM_SYM_OPT(int,drmModeAddFB2WithModifiers,(int fd, uint32_t width, const uint32_t pitches[4], const uint32_t offsets[4], const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags)) +SDL_KMSDRM_SYM_OPT(const char *,drmModeGetConnectorTypeName,(uint32_t connector_type)) + SDL_KMSDRM_SYM(int,drmModeRmFB,(int fd, uint32_t bufferId)) SDL_KMSDRM_SYM(drmModeFBPtr,drmModeGetFB,(int fd, uint32_t buf)) SDL_KMSDRM_SYM(drmModeCrtcPtr,drmModeGetCrtc,(int fd, uint32_t crtcId)) diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 9097254ad7657..ae9b623583ccd 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -799,8 +799,10 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto SDL_DisplayModeData *modedata = NULL; drmModeEncoder *encoder = NULL; drmModeCrtc *crtc = NULL; + const char *connector_type = NULL; SDL_DisplayID display_id; SDL_PropertiesID display_properties; + char name_fmt[64]; int orientation; int mode_index; int i, j; @@ -963,6 +965,15 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto KMSDRM_CrtcSetVrr(viddata->drm_fd, crtc->crtc_id, true); } + // Set the name by the connector type, if possible + if (KMSDRM_drmModeGetConnectorTypeName) { + connector_type = KMSDRM_drmModeGetConnectorTypeName(connector->connector_type); + if (connector_type == NULL) { + connector_type = "Unknown"; + } + SDL_snprintf(name_fmt, sizeof(name_fmt), "%s-%u", connector_type, connector->connector_type_id); + } + /*****************************************/ // Part 2: setup the SDL_Display itself. /*****************************************/ @@ -984,6 +995,9 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto CalculateRefreshRate(&dispdata->mode, &display.desktop_mode.refresh_rate_numerator, &display.desktop_mode.refresh_rate_denominator); display.desktop_mode.format = SDL_PIXELFORMAT_ARGB8888; display.desktop_mode.internal = modedata; + if (connector_type) { + display.name = name_fmt; + } // Add the display to the list of SDL displays. display_id = SDL_AddVideoDisplay(&display, false); @@ -1016,6 +1030,49 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto } } // NOLINT(clang-analyzer-unix.Malloc): If no error `dispdata` is saved in the display +static void KMSDRM_SortDisplays(SDL_VideoDevice *_this) +{ + const char *name_hint = SDL_GetHint(SDL_HINT_VIDEO_DISPLAY_PRIORITY); + + if (name_hint) { + char *saveptr; + char *str = SDL_strdup(name_hint); + SDL_VideoDisplay **sorted_list = SDL_malloc(sizeof(SDL_VideoDisplay *) * _this->num_displays); + + if (str && sorted_list) { + int sorted_index = 0; + + // Sort the requested displays to the front of the list. + const char *token = SDL_strtok_r(str, ",", &saveptr); + while (token) { + for (int i = 0; i < _this->num_displays; ++i) { + SDL_VideoDisplay *d = _this->displays[i]; + if (d && SDL_strcmp(token, d->name) == 0) { + sorted_list[sorted_index++] = d; + _this->displays[i] = NULL; + break; + } + } + + token = SDL_strtok_r(NULL, ",", &saveptr); + } + + // Append the remaining displays to the end of the list. + for (int i = 0; i < _this->num_displays; ++i) { + if (_this->displays[i]) { + sorted_list[sorted_index++] = _this->displays[i]; + } + } + + // Copy the sorted list back to the display list. + SDL_memcpy(_this->displays, sorted_list, sizeof(SDL_VideoDisplay *) * _this->num_displays); + } + + SDL_free(str); + SDL_free(sorted_list); + } +} + /* Initializes the list of SDL displays: we build a new display for each connecter connector we find. This is to be called early, in VideoInit(), because it gets us @@ -1078,6 +1135,9 @@ static bool KMSDRM_InitDisplays(SDL_VideoDevice *_this) goto cleanup; } + // Sort the displays, if necessary + KMSDRM_SortDisplays(_this); + // Determine if video hardware supports async pageflips. if (KMSDRM_drmGetCap(viddata->drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &async_pageflip) != 0) { SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not determine async page flip capability.");