diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 9f6b58ba4b..58a2fc5dff 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -2900,6 +2900,10 @@ extern "C" { * - "gpu" * - "software" * + * This hint accepts a comma-separated list of driver names, and each will + * be tried in the order listed when creating a renderer until one succeeds + * or all of them fail. + * * The default varies by platform, but it's the first one in the list that is * available on the current platform. * @@ -3289,6 +3293,10 @@ extern "C" { * force a specific target, such as "x11" if, say, you are on Wayland but want * to try talking to the X server instead. * + * This hint accepts a comma-separated list of driver names, and each will + * be tried in the order listed during init, until one succeeds or all of them + * fail. + * * This hint should be set before SDL is initialized. * * \since This hint is available since SDL 3.1.3. diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 56a6770f97..5cd37654ed 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -219,6 +219,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_CreateWindowAndRenderer(const char *title, * don't need a specific renderer, specify NULL and SDL will attempt to choose * the best option for you, based on what is available on the user's system. * + * If `name` is a comma-separated list, SDL will try each name, in the order + * listed, until one succeeds or all of them fail. + * * By default the rendering size matches the window size in pixels, but you * can call SDL_SetRenderLogicalPresentation() to change the content size and * scaling options. diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 9774abe169..45f3686a31 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -958,10 +958,8 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) #ifndef SDL_RENDER_DISABLED SDL_Window *window = (SDL_Window *)SDL_GetPointerProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER, NULL); SDL_Surface *surface = (SDL_Surface *)SDL_GetPointerProperty(props, SDL_PROP_RENDERER_CREATE_SURFACE_POINTER, NULL); - const char *name = SDL_GetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING, NULL); - const int n = SDL_GetNumRenderDrivers(); + const char *driver_name = SDL_GetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING, NULL); const char *hint; - int i, attempted = 0; SDL_PropertiesID new_props; #ifdef SDL_PLATFORM_ANDROID @@ -1008,28 +1006,34 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) } } else { bool rc = false; - if (!name) { - name = SDL_GetHint(SDL_HINT_RENDER_DRIVER); + if (!driver_name) { + driver_name = SDL_GetHint(SDL_HINT_RENDER_DRIVER); } - if (name) { - for (i = 0; i < n; i++) { - const SDL_RenderDriver *driver = render_drivers[i]; - if (SDL_strcasecmp(name, driver->name) == 0) { - // Create a new renderer instance - ++attempted; - rc = driver->CreateRenderer(renderer, window, props); - break; + if (driver_name && *driver_name != 0) { + const char *driver_attempt = driver_name; + while (driver_attempt && *driver_attempt != 0 && !rc) { + const char *driver_attempt_end = SDL_strchr(driver_attempt, ','); + const size_t driver_attempt_len = (driver_attempt_end) ? (driver_attempt_end - driver_attempt) : SDL_strlen(driver_attempt); + + for (int i = 0; render_drivers[i]; i++) { + const SDL_RenderDriver *driver = render_drivers[i]; + if ((driver_attempt_len == SDL_strlen(driver->name)) && (SDL_strncasecmp(driver->name, driver_attempt, driver_attempt_len) == 0)) { + rc = driver->CreateRenderer(renderer, window, props); + if (rc) { + break; + } + } } + + driver_attempt = (driver_attempt_end) ? (driver_attempt_end + 1) : NULL; } } else { - for (i = 0; i < n; i++) { + for (int i = 0; render_drivers[i]; i++) { const SDL_RenderDriver *driver = render_drivers[i]; - // Create a new renderer instance - ++attempted; rc = driver->CreateRenderer(renderer, window, props); if (rc) { - break; // Yay, we got one! + break; } SDL_DestroyRendererWithoutFreeing(renderer); SDL_zerop(renderer); // make sure we don't leave function pointers from a previous CreateRenderer() in this struct. @@ -1037,7 +1041,9 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) } if (!rc) { - if (!name || !attempted) { + if (driver_name) { + SDL_SetError("%s not available", driver_name); + } else { SDL_SetError("Couldn't find matching render driver"); } goto error;