Quellcode durchsuchen

render: SDL_HINT_RENDER_DRIVER now accepts a comma-separated list.

Fixes #11077.
Ryan C. Gordon vor 2 Monaten
Ursprung
Commit
c45c4a5e51
3 geänderte Dateien mit 37 neuen und 20 gelöschten Zeilen
  1. 8 0
      include/SDL3/SDL_hints.h
  2. 3 0
      include/SDL3/SDL_render.h
  3. 26 20
      src/render/SDL_render.c

+ 8 - 0
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.

+ 3 - 0
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.

+ 26 - 20
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 (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 = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
+        }
+
+        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;