SDL: Fixed color scale when rendering to an sRGB render target

From 4d135fb696df2f84bca89b6e08ce3bd1a7327d6f Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 11 Sep 2024 13:59:14 -0700
Subject: [PATCH] Fixed color scale when rendering to an sRGB render target

---
 src/render/SDL_render.c    | 23 +++++++++++++++++------
 src/render/SDL_sysrender.h |  2 +-
 2 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 993e07b7604a7..f4752d6974fd3 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -326,7 +326,6 @@ static bool FlushRenderCommands(SDL_Renderer *renderer)
     renderer->vertex_data_used = 0;
     renderer->render_command_generation++;
     renderer->color_queued = false;
-    renderer->color_scale_queued = false;
     renderer->viewport_queued = false;
     renderer->cliprect_queued = false;
     return result;
@@ -748,6 +747,17 @@ static void UpdateMainViewDimensions(SDL_Renderer *renderer)
     UpdatePixelViewport(renderer, &renderer->main_view);
 }
 
+static void UpdateColorScale(SDL_Renderer *renderer)
+{
+    float SDR_white_point;
+    if (renderer->target) {
+        SDR_white_point = renderer->target->SDR_white_point;
+    } else {
+        SDR_white_point = renderer->SDR_white_point;
+    }
+    renderer->color_scale = renderer->desired_color_scale * SDR_white_point;
+}
+
 static void UpdateHDRProperties(SDL_Renderer *renderer)
 {
     SDL_PropertiesID window_props;
@@ -763,8 +773,6 @@ static void UpdateHDRProperties(SDL_Renderer *renderer)
         return;
     }
 
-    renderer->color_scale /= renderer->SDR_white_point;
-
     if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
         renderer->SDR_white_point = SDL_GetFloatProperty(window_props, SDL_PROP_WINDOW_SDR_WHITE_LEVEL_FLOAT, 1.0f);
         renderer->HDR_headroom = SDL_GetFloatProperty(window_props, SDL_PROP_WINDOW_HDR_HEADROOM_FLOAT, 1.0f);
@@ -781,7 +789,7 @@ static void UpdateHDRProperties(SDL_Renderer *renderer)
     SDL_SetFloatProperty(renderer_props, SDL_PROP_RENDERER_SDR_WHITE_POINT_FLOAT, renderer->SDR_white_point);
     SDL_SetFloatProperty(renderer_props, SDL_PROP_RENDERER_HDR_HEADROOM_FLOAT, renderer->HDR_headroom);
 
-    renderer->color_scale *= renderer->SDR_white_point;
+    UpdateColorScale(renderer);
 }
 
 static bool UpdateLogicalPresentation(SDL_Renderer *renderer);
@@ -1072,6 +1080,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
 
     renderer->SDR_white_point = 1.0f;
     renderer->HDR_headroom = 1.0f;
+    renderer->desired_color_scale = 1.0f;
     renderer->color_scale = 1.0f;
 
     if (window) {
@@ -2502,6 +2511,7 @@ static bool SDL_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *tex
     } else {
         renderer->view = &renderer->main_view;
     }
+    UpdateColorScale(renderer);
 
     if (!renderer->SetRenderTarget(renderer, texture)) {
         SDL_UnlockMutex(renderer->target_mutex);
@@ -3262,7 +3272,8 @@ SDL_bool SDL_SetRenderColorScale(SDL_Renderer *renderer, float scale)
 {
     CHECK_RENDERER_MAGIC(renderer, false);
 
-    renderer->color_scale = scale * renderer->SDR_white_point;
+    renderer->desired_color_scale = scale;
+    UpdateColorScale(renderer);
     return true;
 }
 
@@ -3275,7 +3286,7 @@ SDL_bool SDL_GetRenderColorScale(SDL_Renderer *renderer, float *scale)
     CHECK_RENDERER_MAGIC(renderer, false);
 
     if (scale) {
-        *scale = renderer->color_scale / renderer->SDR_white_point;
+        *scale = renderer->desired_color_scale;
     }
     return true;
 }
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index 7afe44b32bd66..dcd0604bd84c4 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -267,6 +267,7 @@ struct SDL_Renderer
     float SDR_white_point;
     float HDR_headroom;
 
+    float desired_color_scale;
     float color_scale;
     SDL_FColor color;        /**< Color for drawing operations values */
     SDL_BlendMode blendMode; /**< The drawing blend mode */
@@ -282,7 +283,6 @@ struct SDL_Renderer
     SDL_Rect last_queued_cliprect;
     bool last_queued_cliprect_enabled;
     bool color_queued;
-    bool color_scale_queued;
     bool viewport_queued;
     bool cliprect_queued;