From 4083c58b2b0b9f15ccfdb73f2e2b2bd78632011c Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sat, 30 Mar 2024 12:01:27 -0400 Subject: [PATCH] video: Support multiple video driver entries having the same name string Allow multiple bootstrap entries for a single video driver with the same name, which internally allows preferential and fallback init conditions while hiding the implementation details from applications (e.g. applications will just see "wayland", regardless of whether it's using the preferred or fallback driver list entry). If a driver is requested, all instances of it in the list will be tried before reporting failure, and client applications programmatically enumerating the video drivers will be presented with a deduplicated list of entries. --- src/video/SDL_video.c | 34 +++++++++++++++++++++++++--- src/video/wayland/SDL_waylandvideo.c | 3 +-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index e01e5853cfa4a6..fc77af764f6ab4 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -441,15 +441,41 @@ static int SDL_UninitializedVideo(void) return SDL_SetError("Video subsystem has not been initialized"); } +/* Deduplicated list of video bootstrap drivers. */ +static const VideoBootStrap *deduped_bootstrap[SDL_arraysize(bootstrap) - 1]; + int SDL_GetNumVideoDrivers(void) { - return SDL_arraysize(bootstrap) - 1; + static int num_drivers = -1; + + if (num_drivers >= 0) { + return num_drivers; + } + + num_drivers = 0; + + /* Build a list of unique video drivers. */ + for (int i = 0; bootstrap[i] != NULL; ++i) { + SDL_bool duplicate = SDL_FALSE; + for (int j = 0; j < i; ++j) { + if (SDL_strcmp(bootstrap[i]->name, bootstrap[j]->name) == 0) { + duplicate = SDL_TRUE; + break; + } + } + + if (!duplicate) { + deduped_bootstrap[num_drivers++] = bootstrap[i]; + } + } + + return num_drivers; } const char *SDL_GetVideoDriver(int index) { if (index >= 0 && index < SDL_GetNumVideoDrivers()) { - return bootstrap[index]->name; + return deduped_bootstrap[index]->name; } return NULL; } @@ -507,7 +533,9 @@ int SDL_VideoInit(const char *driver_name) if ((driver_attempt_len == SDL_strlen(bootstrap[i]->name)) && (SDL_strncasecmp(bootstrap[i]->name, driver_attempt, driver_attempt_len) == 0)) { video = bootstrap[i]->create(); - break; + if (video) { + break; + } } } diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 13bdbc105cd3a4..30f1048626fc49 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -65,7 +65,6 @@ #include #endif -#define WAYLANDVID_PREFERRED_DRIVER_NAME "wayland_preferred" #define WAYLANDVID_DRIVER_NAME "wayland" /* Clamp certain core protocol versions on older versions of libwayland. */ @@ -594,7 +593,7 @@ static SDL_VideoDevice *Wayland_Fallback_CreateDevice(void) } VideoBootStrap Wayland_preferred_bootstrap = { - WAYLANDVID_PREFERRED_DRIVER_NAME, "SDL Wayland video driver", + WAYLANDVID_DRIVER_NAME, "SDL Wayland video driver", Wayland_Preferred_CreateDevice, Wayland_ShowMessageBox };