Simple Directmedia Layer

kmsdrm: Support sorting displays via the priority hint

Use the connector name for displays and sort them according to priority, if the hint is set.

+65 -2
+3 -2
include/SDL3/SDL_hints.h
··· 3149 3149 * prioritized in the list of displays, as exposed by calling 3150 3150 * SDL_GetDisplays(), with the first listed becoming the primary display. The 3151 3151 * naming convention can vary depending on the environment, but it is usually 3152 - * a connector name (e.g. 'DP-1', 'DP-2', 'HDMI-1', etc...). 3152 + * a connector name (e.g. 'DP-1', 'DP-2', 'HDMI-A-1',etc...). 3153 3153 * 3154 - * On X11 and Wayland desktops, the connector names associated with displays 3154 + * On Wayland and X11 desktops, the connector names associated with displays 3155 3155 * can typically be found by using the `xrandr` utility. 3156 3156 * 3157 3157 * This hint is currently supported on the following drivers: 3158 3158 * 3159 + * - KMSDRM (kmsdrm) 3159 3160 * - Wayland (wayland) 3160 3161 * 3161 3162 * This hint should be set before SDL is initialized.
+2
src/video/kmsdrm/SDL_kmsdrmsym.h
··· 63 63 const uint32_t pitches[4], const uint32_t offsets[4], 64 64 const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags)) 65 65 66 + SDL_KMSDRM_SYM_OPT(const char *,drmModeGetConnectorTypeName,(uint32_t connector_type)) 67 + 66 68 SDL_KMSDRM_SYM(int,drmModeRmFB,(int fd, uint32_t bufferId)) 67 69 SDL_KMSDRM_SYM(drmModeFBPtr,drmModeGetFB,(int fd, uint32_t buf)) 68 70 SDL_KMSDRM_SYM(drmModeCrtcPtr,drmModeGetCrtc,(int fd, uint32_t crtcId))
+60
src/video/kmsdrm/SDL_kmsdrmvideo.c
··· 799 799 SDL_DisplayModeData *modedata = NULL; 800 800 drmModeEncoder *encoder = NULL; 801 801 drmModeCrtc *crtc = NULL; 802 + const char *connector_type = NULL; 802 803 SDL_DisplayID display_id; 803 804 SDL_PropertiesID display_properties; 805 + char name_fmt[64]; 804 806 int orientation; 805 807 int mode_index; 806 808 int i, j; ··· 963 965 KMSDRM_CrtcSetVrr(viddata->drm_fd, crtc->crtc_id, true); 964 966 } 965 967 968 + // Set the name by the connector type, if possible 969 + if (KMSDRM_drmModeGetConnectorTypeName) { 970 + connector_type = KMSDRM_drmModeGetConnectorTypeName(connector->connector_type); 971 + if (connector_type == NULL) { 972 + connector_type = "Unknown"; 973 + } 974 + SDL_snprintf(name_fmt, sizeof(name_fmt), "%s-%u", connector_type, connector->connector_type_id); 975 + } 976 + 966 977 /*****************************************/ 967 978 // Part 2: setup the SDL_Display itself. 968 979 /*****************************************/ ··· 984 995 CalculateRefreshRate(&dispdata->mode, &display.desktop_mode.refresh_rate_numerator, &display.desktop_mode.refresh_rate_denominator); 985 996 display.desktop_mode.format = SDL_PIXELFORMAT_ARGB8888; 986 997 display.desktop_mode.internal = modedata; 998 + if (connector_type) { 999 + display.name = name_fmt; 1000 + } 987 1001 988 1002 // Add the display to the list of SDL displays. 989 1003 display_id = SDL_AddVideoDisplay(&display, false); ··· 1016 1030 } 1017 1031 } // NOLINT(clang-analyzer-unix.Malloc): If no error `dispdata` is saved in the display 1018 1032 1033 + static void KMSDRM_SortDisplays(SDL_VideoDevice *_this) 1034 + { 1035 + const char *name_hint = SDL_GetHint(SDL_HINT_VIDEO_DISPLAY_PRIORITY); 1036 + 1037 + if (name_hint) { 1038 + char *saveptr; 1039 + char *str = SDL_strdup(name_hint); 1040 + SDL_VideoDisplay **sorted_list = SDL_malloc(sizeof(SDL_VideoDisplay *) * _this->num_displays); 1041 + 1042 + if (str && sorted_list) { 1043 + int sorted_index = 0; 1044 + 1045 + // Sort the requested displays to the front of the list. 1046 + const char *token = SDL_strtok_r(str, ",", &saveptr); 1047 + while (token) { 1048 + for (int i = 0; i < _this->num_displays; ++i) { 1049 + SDL_VideoDisplay *d = _this->displays[i]; 1050 + if (d && SDL_strcmp(token, d->name) == 0) { 1051 + sorted_list[sorted_index++] = d; 1052 + _this->displays[i] = NULL; 1053 + break; 1054 + } 1055 + } 1056 + 1057 + token = SDL_strtok_r(NULL, ",", &saveptr); 1058 + } 1059 + 1060 + // Append the remaining displays to the end of the list. 1061 + for (int i = 0; i < _this->num_displays; ++i) { 1062 + if (_this->displays[i]) { 1063 + sorted_list[sorted_index++] = _this->displays[i]; 1064 + } 1065 + } 1066 + 1067 + // Copy the sorted list back to the display list. 1068 + SDL_memcpy(_this->displays, sorted_list, sizeof(SDL_VideoDisplay *) * _this->num_displays); 1069 + } 1070 + 1071 + SDL_free(str); 1072 + SDL_free(sorted_list); 1073 + } 1074 + } 1075 + 1019 1076 /* Initializes the list of SDL displays: we build a new display for each 1020 1077 connecter connector we find. 1021 1078 This is to be called early, in VideoInit(), because it gets us ··· 1077 1134 result = SDL_SetError("No connected displays found."); 1078 1135 goto cleanup; 1079 1136 } 1137 + 1138 + // Sort the displays, if necessary 1139 + KMSDRM_SortDisplays(_this); 1080 1140 1081 1141 // Determine if video hardware supports async pageflips. 1082 1142 if (KMSDRM_drmGetCap(viddata->drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &async_pageflip) != 0) {