SDL: Removed the limit on the number of supported renderer texture formats

From 598b4e0a1f2f7aa09771cc2e9abb76d868d58316 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 9 May 2024 12:10:42 -0700
Subject: [PATCH] Removed the limit on the number of supported renderer texture
 formats

Fixes https://github.com/libsdl-org/SDL/issues/9056
---
 include/SDL3/SDL_render.h                |  2 +-
 src/render/SDL_render.c                  | 17 +++++-
 src/render/SDL_sysrender.h               |  6 ++-
 src/render/direct3d/SDL_render_d3d.c     | 16 +++---
 src/render/direct3d11/SDL_render_d3d11.c | 31 +++++------
 src/render/direct3d12/SDL_render_d3d12.c | 33 +++++-------
 src/render/metal/SDL_render_metal.m      | 31 +++++------
 src/render/opengl/SDL_render_gl.c        | 29 +++++------
 src/render/opengles2/SDL_render_gles2.c  | 28 +++++-----
 src/render/ps2/SDL_render_ps2.c          | 20 +++----
 src/render/psp/SDL_render_psp.c          | 24 ++++-----
 src/render/software/SDL_render_sw.c      | 66 +++++++++++-------------
 src/render/vitagxm/SDL_render_vita_gxm.c | 32 +++++-------
 src/render/vulkan/SDL_render_vulkan.c    | 33 +++++-------
 14 files changed, 162 insertions(+), 206 deletions(-)

diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h
index 56bc513089d0c..628bad30dceae 100644
--- a/include/SDL3/SDL_render.h
+++ b/include/SDL3/SDL_render.h
@@ -87,7 +87,7 @@ typedef struct SDL_RendererInfo
     const char *name;           /**< The name of the renderer */
     SDL_RendererFlags flags;    /**< Supported ::SDL_RendererFlags */
     int num_texture_formats;    /**< The number of available texture formats */
-    SDL_PixelFormatEnum texture_formats[16]; /**< The available texture formats */
+    const SDL_PixelFormatEnum *texture_formats; /**< The available texture formats */
     int max_texture_width;      /**< The maximum texture width */
     int max_texture_height;     /**< The maximum texture height */
 } SDL_RendererInfo;
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index b78e32722c843..bf346cba90ae8 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -137,6 +137,17 @@ char SDL_renderer_magic;
 char SDL_texture_magic;
 
 
+int SDL_AddSupportedTextureFormat(SDL_Renderer *renderer, SDL_PixelFormatEnum format)
+{
+    SDL_PixelFormatEnum *texture_formats = (SDL_PixelFormatEnum *)SDL_realloc((void *)renderer->info.texture_formats, (renderer->info.num_texture_formats + 1) * sizeof(SDL_PixelFormatEnum));
+    if (!texture_formats) {
+        return -1;
+    }
+    texture_formats[renderer->info.num_texture_formats++] = format;
+    renderer->info.texture_formats = texture_formats;
+    return 0;
+}
+
 void SDL_SetupRendererColorspace(SDL_Renderer *renderer, SDL_PropertiesID props)
 {
     renderer->output_colorspace = (SDL_Colorspace)SDL_GetNumberProperty(props, SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB);
@@ -780,7 +791,7 @@ const char *SDL_GetRenderDriver(int index)
                             SDL_GetNumRenderDrivers() - 1);
         return NULL;
     }
-    return render_drivers[index]->info.name;
+    return render_drivers[index]->name;
 #else
     SDL_SetError("SDL not built with rendering support");
     return NULL;
@@ -979,7 +990,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
         if (name) {
             for (i = 0; i < n; i++) {
                 const SDL_RenderDriver *driver = render_drivers[i];
-                if (SDL_strcasecmp(name, driver->info.name) == 0) {
+                if (SDL_strcasecmp(name, driver->name) == 0) {
                     // Create a new renderer instance
                     ++attempted;
                     rc = driver->CreateRenderer(renderer, window, props);
@@ -1104,6 +1115,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
 #ifdef SDL_PLATFORM_ANDROID
     Android_ActivityMutex_Unlock();
 #endif
+    SDL_free((void *)renderer->info.texture_formats);
     SDL_free(renderer);
     return NULL;
 
@@ -4588,6 +4600,7 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer)
         renderer->magic = NULL;     // It's no longer magical...
     }
 
+    SDL_free((void *)renderer->info.texture_formats);
     SDL_free(renderer);
 }
 
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index b26c5752b1553..d3556b7cc254d 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -299,8 +299,7 @@ struct SDL_RenderDriver
 {
     int (*CreateRenderer)(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID props);
 
-    /* Info about the renderer capabilities */
-    SDL_RendererInfo info;
+    const char *name;
 };
 
 /* Not all of these are available in a given build. Use #ifdefs, etc. */
@@ -316,6 +315,9 @@ extern SDL_RenderDriver PSP_RenderDriver;
 extern SDL_RenderDriver SW_RenderDriver;
 extern SDL_RenderDriver VITA_GXM_RenderDriver;
 
+/* Add a supported texture format to a renderer */
+extern int SDL_AddSupportedTextureFormat(SDL_Renderer *renderer, SDL_PixelFormatEnum format);
+
 /* Setup colorspace conversion */
 extern void SDL_SetupRendererColorspace(SDL_Renderer *renderer, SDL_PropertiesID props);
 
diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c
index 51d4c4bad9703..a7b2b0edb749c 100644
--- a/src/render/direct3d/SDL_render_d3d.c
+++ b/src/render/direct3d/SDL_render_d3d.c
@@ -1617,10 +1617,12 @@ int D3D_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Propertie
     renderer->DestroyTexture = D3D_DestroyTexture;
     renderer->DestroyRenderer = D3D_DestroyRenderer;
     renderer->SetVSync = D3D_SetVSync;
-    renderer->info = D3D_RenderDriver.info;
     renderer->driverdata = data;
     D3D_InvalidateCachedState(renderer);
 
+    renderer->info.name = D3D_RenderDriver.name;
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
+
     SDL_GetWindowSizeInPixels(window, &w, &h);
     if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
         fullscreen_mode = SDL_GetWindowFullscreenMode(window);
@@ -1717,8 +1719,8 @@ int D3D_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Propertie
             }
         }
         if (data->shaders[SHADER_YUV]) {
-            renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
-            renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
+            SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
+            SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
         }
     }
 #endif
@@ -1729,12 +1731,6 @@ int D3D_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Propertie
 }
 
 SDL_RenderDriver D3D_RenderDriver = {
-    D3D_CreateRenderer,
-    { "direct3d",
-      SDL_RENDERER_PRESENTVSYNC,
-      1,
-      { SDL_PIXELFORMAT_ARGB8888 },
-      0,
-      0 }
+    D3D_CreateRenderer, "direct3d"
 };
 #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c
index 9430f451427d7..f8d05e773a2ca 100644
--- a/src/render/direct3d11/SDL_render_d3d11.c
+++ b/src/render/direct3d11/SDL_render_d3d11.c
@@ -2801,10 +2801,20 @@ static int D3D11_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_
     renderer->RenderPresent = D3D11_RenderPresent;
     renderer->DestroyTexture = D3D11_DestroyTexture;
     renderer->DestroyRenderer = D3D11_DestroyRenderer;
-    renderer->info = D3D11_RenderDriver.info;
     renderer->driverdata = data;
     D3D11_InvalidateCachedState(renderer);
 
+    renderer->info.name = D3D11_RenderDriver.name;
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR2101010);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA64_FLOAT);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P010);
+
 #if SDL_WINAPI_FAMILY_PHONE
     /* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1.
      * Failure to use it seems to either result in:
@@ -2844,24 +2854,7 @@ static int D3D11_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_
 }
 
 SDL_RenderDriver D3D11_RenderDriver = {
-    D3D11_CreateRenderer,
-    {
-        "direct3d11",
-        SDL_RENDERER_PRESENTVSYNC,   /* flags.  see SDL_RendererFlags */
-        9,                           /* num_texture_formats */
-        {                            /* texture_formats */
-          SDL_PIXELFORMAT_ARGB8888,
-          SDL_PIXELFORMAT_XRGB8888,
-          SDL_PIXELFORMAT_XBGR2101010,
-          SDL_PIXELFORMAT_RGBA64_FLOAT,
-          SDL_PIXELFORMAT_YV12,
-          SDL_PIXELFORMAT_IYUV,
-          SDL_PIXELFORMAT_NV12,
-          SDL_PIXELFORMAT_NV21,
-          SDL_PIXELFORMAT_P010 },
-        0, /* max_texture_width: will be filled in later */
-        0  /* max_texture_height: will be filled in later */
-    }
+    D3D11_CreateRenderer, "direct3d11"
 };
 
 #endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */
diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c
index f74c686575fbf..ab3696645da21 100644
--- a/src/render/direct3d12/SDL_render_d3d12.c
+++ b/src/render/direct3d12/SDL_render_d3d12.c
@@ -3219,10 +3219,22 @@ int D3D12_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Propert
     renderer->RenderPresent = D3D12_RenderPresent;
     renderer->DestroyTexture = D3D12_DestroyTexture;
     renderer->DestroyRenderer = D3D12_DestroyRenderer;
-    renderer->info = D3D12_RenderDriver.info;
     renderer->driverdata = data;
     D3D12_InvalidateCachedState(renderer);
 
+    renderer->info.name = D3D12_RenderDriver.name;
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR2101010);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA64_FLOAT);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P010);
+    renderer->info.max_texture_width = 16384;
+    renderer->info.max_texture_height = 16384;
+
     if (SDL_GetBooleanProperty(create_props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
     }
@@ -3247,24 +3259,7 @@ int D3D12_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Propert
 }
 
 SDL_RenderDriver D3D12_RenderDriver = {
-    D3D12_CreateRenderer,
-    {
-        "direct3d12",
-        SDL_RENDERER_PRESENTVSYNC,   /* flags.  see SDL_RendererFlags */
-        9,                           /* num_texture_formats */
-        {                            /* texture_formats */
-          SDL_PIXELFORMAT_ARGB8888,
-          SDL_PIXELFORMAT_XRGB8888,
-          SDL_PIXELFORMAT_XBGR2101010,
-          SDL_PIXELFORMAT_RGBA64_FLOAT,
-          SDL_PIXELFORMAT_YV12,
-          SDL_PIXELFORMAT_IYUV,
-          SDL_PIXELFORMAT_NV12,
-          SDL_PIXELFORMAT_NV21,
-          SDL_PIXELFORMAT_P010 },
-        16384, /* max_texture_width */
-        16384  /* max_texture_height */
-    }
+    D3D12_CreateRenderer, "direct3d12"
 };
 
 /* Ends C function definitions when using C++ */
diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m
index 81d1edb60dcea..7b376889ae70b 100644
--- a/src/render/metal/SDL_render_metal.m
+++ b/src/render/metal/SDL_render_metal.m
@@ -2139,7 +2139,17 @@ in case we want to use it later (recreating the renderer)
         renderer->GetMetalLayer = METAL_GetMetalLayer;
         renderer->GetMetalCommandEncoder = METAL_GetMetalCommandEncoder;
 
-        renderer->info = METAL_RenderDriver.info;
+        renderer->info.name = METAL_RenderDriver.name;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR2101010);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA64_FLOAT);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA128_FLOAT);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P010);
 
 #if (defined(SDL_PLATFORM_MACOS) && defined(MAC_OS_X_VERSION_10_13)) || TARGET_OS_MACCATALYST
         if (@available(macOS 10.13, *)) {
@@ -2195,24 +2205,7 @@ in case we want to use it later (recreating the renderer)
 }
 
 SDL_RenderDriver METAL_RenderDriver = {
-    METAL_CreateRenderer,
-    {
-        "metal",
-        SDL_RENDERER_PRESENTVSYNC,
-        10,
-        { SDL_PIXELFORMAT_ARGB8888,
-          SDL_PIXELFORMAT_ABGR8888,
-          SDL_PIXELFORMAT_XBGR2101010,
-          SDL_PIXELFORMAT_RGBA64_FLOAT,
-          SDL_PIXELFORMAT_RGBA128_FLOAT,
-          SDL_PIXELFORMAT_YV12,
-          SDL_PIXELFORMAT_IYUV,
-          SDL_PIXELFORMAT_NV12,
-          SDL_PIXELFORMAT_NV21,
-          SDL_PIXELFORMAT_P010 },
-        0,
-        0,
-    }
+    METAL_CreateRenderer, "metal"
 };
 
 #endif /* SDL_VIDEO_RENDER_METAL */
diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c
index 82cd82cbd375e..c6ec932980056 100644
--- a/src/render/opengl/SDL_render_gl.c
+++ b/src/render/opengl/SDL_render_gl.c
@@ -1678,12 +1678,18 @@ static int GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pro
     renderer->DestroyTexture = GL_DestroyTexture;
     renderer->DestroyRenderer = GL_DestroyRenderer;
     renderer->SetVSync = GL_SetVSync;
-    renderer->info = GL_RenderDriver.info;
     renderer->info.flags = 0; /* will set some flags below. */
     renderer->driverdata = data;
     GL_InvalidateCachedState(renderer);
     renderer->window = window;
 
+    renderer->info.name = GL_RenderDriver.name;
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR8888);
+
     data->context = SDL_GL_CreateContext(window);
     if (!data->context) {
         goto error;
@@ -1793,18 +1799,18 @@ static int GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pro
 #if SDL_HAVE_YUV
     /* We support YV12 textures using 3 textures and a shader */
     if (data->shaders && data->num_texture_units >= 3) {
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
     }
 
     /* We support NV12 textures using 2 textures and a shader */
     if (data->shaders && data->num_texture_units >= 2) {
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
     }
 #endif
 #ifdef SDL_PLATFORM_MACOS
-    renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_UYVY;
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_UYVY);
 #endif
 
     renderer->rect_index_order[0] = 0;
@@ -1871,16 +1877,7 @@ static int GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pro
 }
 
 SDL_RenderDriver GL_RenderDriver = {
-    GL_CreateRenderer,
-    { "opengl",
-      SDL_RENDERER_PRESENTVSYNC,
-      4,
-      { SDL_PIXELFORMAT_ARGB8888,
-        SDL_PIXELFORMAT_ABGR8888,
-        SDL_PIXELFORMAT_XRGB8888,
-        SDL_PIXELFORMAT_XBGR8888 },
-      0,
-      0 }
+    GL_CreateRenderer, "opengl"
 };
 
 #endif /* SDL_VIDEO_RENDER_OGL */
diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c
index 294317237f749..8aa1b9a12ab27 100644
--- a/src/render/opengles2/SDL_render_gles2.c
+++ b/src/render/opengles2/SDL_render_gles2.c
@@ -2087,11 +2087,16 @@ static int GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_
     if (!data) {
         goto error;
     }
-    renderer->info = GLES2_RenderDriver.info;
     renderer->driverdata = data;
     GLES2_InvalidateCachedState(renderer);
     renderer->window = window;
 
+    renderer->info.name = GLES2_RenderDriver.name;
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA32);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA32);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX32);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX32);
+
     /* Create an OpenGL ES 2.0 context */
     data->context = SDL_GL_CreateContext(window);
     if (!data->context) {
@@ -2183,14 +2188,14 @@ static int GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_
     renderer->DestroyRenderer = GLES2_DestroyRenderer;
     renderer->SetVSync = GLES2_SetVSync;
 #if SDL_HAVE_YUV
-    renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
-    renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
-    renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
-    renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
 #endif
 #ifdef GL_TEXTURE_EXTERNAL_OES
     if (GLES2_CacheShader(data, GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES, GL_FRAGMENT_SHADER)) {
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_EXTERNAL_OES;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_EXTERNAL_OES);
     }
 #endif
 
@@ -2243,16 +2248,7 @@ static int GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_
 }
 
 SDL_RenderDriver GLES2_RenderDriver = {
-    GLES2_CreateRenderer,
-    { "opengles2",
-      SDL_RENDERER_PRESENTVSYNC,
-      4,
-      { SDL_PIXELFORMAT_RGBA32,
-        SDL_PIXELFORMAT_BGRA32,
-        SDL_PIXELFORMAT_BGRX32,
-        SDL_PIXELFORMAT_RGBX32 },
-      0,
-      0 }
+    GLES2_CreateRenderer, "opengles2"
 };
 
 #endif /* SDL_VIDEO_RENDER_OGL_ES2 */
diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c
index 978190efdad50..9df8320777681 100644
--- a/src/render/ps2/SDL_render_ps2.c
+++ b/src/render/ps2/SDL_render_ps2.c
@@ -692,11 +692,16 @@ static int PS2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
     renderer->DestroyTexture = PS2_DestroyTexture;
     renderer->DestroyRenderer = PS2_DestroyRenderer;
     renderer->SetVSync = PS2_SetVSync;
-    renderer->info = PS2_RenderDriver.info;
     renderer->driverdata = data;
     PS2_InvalidateCachedState(renderer);
     renderer->window = window;
 
+    renderer->info.name = PS2_RenderDriver.name;
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR1555);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
+    renderer->info.max_texture_width = 1024;
+    renderer->info.max_texture_height = 1024;
+
     if (data->vsync) {
         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
     }
@@ -704,18 +709,7 @@ static int PS2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
 }
 
 SDL_RenderDriver PS2_RenderDriver = {
-    .CreateRenderer = PS2_CreateRenderer,
-    .info = {
-        .name = "PS2 gsKit",
-        .flags = SDL_RENDERER_PRESENTVSYNC,
-        .num_texture_formats = 2,
-        .texture_formats = {
-            [0] = SDL_PIXELFORMAT_ABGR1555,
-            [1] = SDL_PIXELFORMAT_ABGR8888,
-        },
-        .max_texture_width = 1024,
-        .max_texture_height = 1024,
-    }
+    PS2_CreateRenderer, "PS2 gsKit"
 };
 
 #endif /* SDL_VIDEO_RENDER_PS2 */
diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c
index 600a9815857b6..cb9ea3f8aa8f4 100644
--- a/src/render/psp/SDL_render_psp.c
+++ b/src/render/psp/SDL_render_psp.c
@@ -1324,11 +1324,18 @@ static int PSP_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
     renderer->DestroyTexture = PSP_DestroyTexture;
     renderer->DestroyRenderer = PSP_DestroyRenderer;
     renderer->SetVSync = PSP_SetVSync;
-    renderer->info = PSP_RenderDriver.info;
     renderer->driverdata = data;
     PSP_InvalidateCachedState(renderer);
     renderer->window = window;
 
+    renderer->info.name = PSP_RenderDriver.name;
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGR565);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR1555);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR4444);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
+    renderer->info.max_texture_width = 512;
+    renderer->info.max_texture_height = 512;
+
     data->initialized = SDL_TRUE;
     data->most_recent_target = NULL;
     data->least_recent_target = NULL;
@@ -1399,20 +1406,7 @@ static int PSP_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
 }
 
 SDL_RenderDriver PSP_RenderDriver = {
-    .CreateRenderer = PSP_CreateRenderer,
-    .info = {
-        .name = "PSP",
-        .flags = SDL_RENDERER_PRESENTVSYNC,
-        .num_texture_formats = 4,
-        .texture_formats = {
-            [0] = SDL_PIXELFORMAT_BGR565,
-            [1] = SDL_PIXELFORMAT_ABGR1555,
-            [2] = SDL_PIXELFORMAT_ABGR4444,
-            [3] = SDL_PIXELFORMAT_ABGR8888,
-        },
-        .max_texture_width = 512,
-        .max_texture_height = 512,
-    }
+    PSP_CreateRenderer, "PSP"
 };
 
 #endif /* SDL_VIDEO_RENDER_PSP */
diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c
index 552a76109d35d..80cd0406b749e 100644
--- a/src/render/software/SDL_render_sw.c
+++ b/src/render/software/SDL_render_sw.c
@@ -1023,58 +1023,58 @@ static void SW_DestroyRenderer(SDL_Renderer *renderer)
 static void SW_SelectBestFormats(SDL_Renderer *renderer, SDL_PixelFormatEnum format)
 {
     /* Prefer the format used by the framebuffer by default. */
-    renderer->info.texture_formats[renderer->info.num_texture_formats++] = format;
+    SDL_AddSupportedTextureFormat(renderer, format);
 
     switch (format) {
     case SDL_PIXELFORMAT_XRGB4444:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_ARGB4444;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB4444);
         break;
     case SDL_PIXELFORMAT_XBGR4444:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_ABGR4444;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR4444);
         break;
     case SDL_PIXELFORMAT_ARGB4444:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_XRGB4444;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB4444);
         break;
     case SDL_PIXELFORMAT_ABGR4444:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_XBGR4444;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR4444);
         break;
 
     case SDL_PIXELFORMAT_XRGB1555:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_ARGB1555;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB1555);
         break;
     case SDL_PIXELFORMAT_XBGR1555:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_ABGR1555;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR1555);
         break;
     case SDL_PIXELFORMAT_ARGB1555:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_XRGB1555;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB1555);
         break;
     case SDL_PIXELFORMAT_ABGR1555:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_XBGR1555;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR1555);
         break;
 
     case SDL_PIXELFORMAT_XRGB8888:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_ARGB8888;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
         break;
     case SDL_PIXELFORMAT_RGBX8888:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_RGBA8888;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA8888);
         break;
     case SDL_PIXELFORMAT_XBGR8888:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_ABGR8888;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
         break;
     case SDL_PIXELFORMAT_BGRX8888:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_BGRA8888;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA8888);
         break;
     case SDL_PIXELFORMAT_ARGB8888:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_XRGB8888;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888);
         break;
     case SDL_PIXELFORMAT_RGBA8888:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_RGBX8888;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX8888);
         break;
     case SDL_PIXELFORMAT_ABGR8888:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_XBGR8888;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR8888);
         break;
     case SDL_PIXELFORMAT_BGRA8888:
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_BGRX8888;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX8888);
         break;
     default:
         break;
@@ -1088,30 +1088,30 @@ static void SW_SelectBestFormats(SDL_Renderer *renderer, SDL_PixelFormatEnum for
             switch (SDL_PIXELORDER(format)) {
             case SDL_PACKEDORDER_BGRX:
             case SDL_PACKEDORDER_BGRA:
-                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_BGRX8888;
-                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_BGRA8888;
+                SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX8888);
+                SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA8888);
                 break;
             case SDL_PACKEDORDER_RGBX:
             case SDL_PACKEDORDER_RGBA:
-                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_RGBX8888;
-                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_RGBA8888;
+                SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX8888);
+                SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA8888);
                 break;
             case SDL_PACKEDORDER_XBGR:
             case SDL_PACKEDORDER_ABGR:
-                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_XBGR8888;
-                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_ABGR8888;
+                SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR8888);
+                SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
                 break;
             case SDL_PACKEDORDER_XRGB:
             case SDL_PACKEDORDER_ARGB:
             default:
-                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_XRGB8888;
-                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_ARGB8888;
+                SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888);
+                SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
                 break;
             }
         }
     } else {
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_XRGB8888;
-        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_ARGB8888;
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888);
+        SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
     }
 }
 
@@ -1155,10 +1155,11 @@ int SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, SD
     renderer->RenderPresent = SW_RenderPresent;
     renderer->DestroyTexture = SW_DestroyTexture;
     renderer->DestroyRenderer = SW_DestroyRenderer;
-    renderer->info = SW_RenderDriver.info;
     renderer->driverdata = data;
     SW_InvalidateCachedState(renderer);
 
+    renderer->info.name = SW_RenderDriver.name;
+
     SW_SelectBestFormats(renderer, surface->format->format);
 
     SDL_SetupRendererColorspace(renderer, create_props);
@@ -1200,14 +1201,7 @@ static int SW_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pro
 }
 
 SDL_RenderDriver SW_RenderDriver = {
-    SW_CreateRenderer,
-    { SDL_SOFTWARE_RENDERER,
-      SDL_RENDERER_PRESENTVSYNC,
-      0,
-      { /* formats filled in later */
-        SDL_PIXELFORMAT_UNKNOWN },
-      0,
-      0 }
+    SW_CreateRenderer, SDL_SOFTWARE_RENDERER
 };
 
 #endif /* SDL_VIDEO_RENDER_SW */
diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c
index 52cc8eb26e298..3cb1ba0d915e9 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm.c
+++ b/src/render/vitagxm/SDL_render_vita_gxm.c
@@ -100,24 +100,7 @@ static void VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture
 static void VITA_GXM_DestroyRenderer(SDL_Renderer *renderer);
 
 SDL_RenderDriver VITA_GXM_RenderDriver = {
-    .CreateRenderer = VITA_GXM_CreateRenderer,
-    .info = {
-        .name = "VITA gxm",
-        .flags = SDL_RENDERER_PRESENTVSYNC,
-        .num_texture_formats = 8,
-        .

(Patch may be truncated, please check the link at the top of this post.)