SDL: Fixed memory leak if the GPU renderer can't be initialized

From bef07023d67f1c8fb13fb3e7e6e5d1b33c7fc1ab Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 30 Aug 2024 14:48:08 -0700
Subject: [PATCH] Fixed memory leak if the GPU renderer can't be initialized

DestroyRenderer needs to be set before we return false from GPU_CreateRenderer()
---
 src/render/sdlgpu/SDL_render_gpu.c | 59 ++++++++++++++----------------
 1 file changed, 28 insertions(+), 31 deletions(-)

diff --git a/src/render/sdlgpu/SDL_render_gpu.c b/src/render/sdlgpu/SDL_render_gpu.c
index 9738a2d66df66..f15928d67da04 100644
--- a/src/render/sdlgpu/SDL_render_gpu.c
+++ b/src/render/sdlgpu/SDL_render_gpu.c
@@ -1170,21 +1170,41 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
 {
     GPU_RenderData *data = NULL;
 
-    data = (GPU_RenderData *)SDL_calloc(1, sizeof(*data));
-    if (!data) {
-        return false;
-    }
-
-    renderer->internal = data;
-
     SDL_SetupRendererColorspace(renderer, create_props);
 
     if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
         // TODO
-        SDL_SetError("Unsupported output colorspace");
+        return SDL_SetError("Unsupported output colorspace");
+    }
+
+    data = (GPU_RenderData *)SDL_calloc(1, sizeof(*data));
+    if (!data) {
         return false;
     }
 
+    renderer->SupportsBlendMode = GPU_SupportsBlendMode;
+    renderer->CreateTexture = GPU_CreateTexture;
+    renderer->UpdateTexture = GPU_UpdateTexture;
+    renderer->LockTexture = GPU_LockTexture;
+    renderer->UnlockTexture = GPU_UnlockTexture;
+    renderer->SetTextureScaleMode = GPU_SetTextureScaleMode;
+    renderer->SetRenderTarget = GPU_SetRenderTarget;
+    renderer->QueueSetViewport = GPU_QueueNoOp;
+    renderer->QueueSetDrawColor = GPU_QueueNoOp;
+    renderer->QueueDrawPoints = GPU_QueueDrawPoints;
+    renderer->QueueDrawLines = GPU_QueueDrawPoints; // lines and points queue vertices the same way.
+    renderer->QueueGeometry = GPU_QueueGeometry;
+    renderer->InvalidateCachedState = GPU_InvalidateCachedState;
+    renderer->RunCommandQueue = GPU_RunCommandQueue;
+    renderer->RenderReadPixels = GPU_RenderReadPixels;
+    renderer->RenderPresent = GPU_RenderPresent;
+    renderer->DestroyTexture = GPU_DestroyTexture;
+    renderer->DestroyRenderer = GPU_DestroyRenderer;
+    renderer->SetVSync = GPU_SetVSync;
+    renderer->internal = data;
+    renderer->window = window;
+    renderer->name = GPU_RenderDriver.name;
+
     bool debug = SDL_GetBooleanProperty(create_props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOL, false);
     bool lowpower = SDL_GetBooleanProperty(create_props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOL, false);
 
@@ -1219,29 +1239,6 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
         return false;
     }
 
-    renderer->SupportsBlendMode = GPU_SupportsBlendMode;
-    renderer->CreateTexture = GPU_CreateTexture;
-    renderer->UpdateTexture = GPU_UpdateTexture;
-    renderer->LockTexture = GPU_LockTexture;
-    renderer->UnlockTexture = GPU_UnlockTexture;
-    renderer->SetTextureScaleMode = GPU_SetTextureScaleMode;
-    renderer->SetRenderTarget = GPU_SetRenderTarget;
-    renderer->QueueSetViewport = GPU_QueueNoOp;
-    renderer->QueueSetDrawColor = GPU_QueueNoOp;
-    renderer->QueueDrawPoints = GPU_QueueDrawPoints;
-    renderer->QueueDrawLines = GPU_QueueDrawPoints; // lines and points queue vertices the same way.
-    renderer->QueueGeometry = GPU_QueueGeometry;
-    renderer->InvalidateCachedState = GPU_InvalidateCachedState;
-    renderer->RunCommandQueue = GPU_RunCommandQueue;
-    renderer->RenderReadPixels = GPU_RenderReadPixels;
-    renderer->RenderPresent = GPU_RenderPresent;
-    renderer->DestroyTexture = GPU_DestroyTexture;
-    renderer->DestroyRenderer = GPU_DestroyRenderer;
-    renderer->SetVSync = GPU_SetVSync;
-    GPU_InvalidateCachedState(renderer);
-    renderer->window = window;
-    renderer->name = GPU_RenderDriver.name;
-
     if (!SDL_ClaimGPUWindow(data->device, window)) {
         return false;
     }