Skip to content

Commit

Permalink
kmsdrm: Support sorting displays via the priority hint
Browse files Browse the repository at this point in the history
Use the connector name for displays and sort them according to priority, if the hint is set.
  • Loading branch information
Kontrabant committed Oct 18, 2024
1 parent 2654d5d commit c98f5cf
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 2 deletions.
5 changes: 3 additions & 2 deletions include/SDL3/SDL_hints.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions src/video/kmsdrm/SDL_kmsdrmsym.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
60 changes: 60 additions & 0 deletions src/video/kmsdrm/SDL_kmsdrmvideo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
/*****************************************/
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.");
Expand Down

0 comments on commit c98f5cf

Please sign in to comment.