From ed463b41e15f66fe23885f12e37753b91c483199 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 10 Mar 2024 11:05:26 -0700
Subject: [PATCH] Unified the software renderer creation path
Previously there were two different paths for renderer creation, and the HDR metadata initialization was missing when creating a software renderer for a surface. Now all the cases are handled in a single path, so regardless of whether you create a software renderer by name, a software renderer for a surface, or fall back to a software renderer, you'll get the correct initialization in all cases.
Fixes https://github.com/libsdl-org/SDL/issues/9221
---
src/render/SDL_render.c | 113 ++++++++++++--------------
src/render/software/SDL_render_sw.c | 26 +++---
src/render/software/SDL_render_sw_c.h | 2 +-
3 files changed, 65 insertions(+), 76 deletions(-)
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index c6a9847f11c56..6bcba6c2756ad 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -906,25 +906,21 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
int i, attempted = 0;
SDL_PropertiesID new_props;
- if (!window && surface) {
- return SDL_CreateSoftwareRenderer(surface);
- }
-
#ifdef SDL_PLATFORM_ANDROID
Android_ActivityMutex_Lock_Running();
#endif
- if (!window) {
+ if ((!window && !surface) || (window && surface)) {
SDL_InvalidParamError("window");
goto error;
}
- if (SDL_WindowHasSurface(window)) {
+ if (window && SDL_WindowHasSurface(window)) {
SDL_SetError("Surface already associated with window");
goto error;
}
- if (SDL_GetRenderer(window)) {
+ if (window && SDL_GetRenderer(window)) {
SDL_SetError("Renderer already associated with window");
goto error;
}
@@ -934,38 +930,45 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
SDL_SetBooleanProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE));
}
- if (!name) {
- name = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
- }
+ if (surface) {
+ renderer = SW_CreateRendererForSurface(surface, props);
+ if (!renderer) {
+ goto error;
+ }
+ } else {
+ 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->info.name) == 0) {
+ if (name) {
+ for (i = 0; i < n; i++) {
+ const SDL_RenderDriver *driver = render_drivers[i];
+ if (SDL_strcasecmp(name, driver->info.name) == 0) {
+ /* Create a new renderer instance */
+ ++attempted;
+ renderer = driver->CreateRenderer(window, props);
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < n; i++) {
+ const SDL_RenderDriver *driver = render_drivers[i];
/* Create a new renderer instance */
++attempted;
renderer = driver->CreateRenderer(window, props);
- break;
- }
- }
- } else {
- for (i = 0; i < n; i++) {
- const SDL_RenderDriver *driver = render_drivers[i];
- /* Create a new renderer instance */
- ++attempted;
- renderer = driver->CreateRenderer(window, props);
- if (renderer) {
- /* Yay, we got one! */
- break;
+ if (renderer) {
+ /* Yay, we got one! */
+ break;
+ }
}
}
- }
- if (!renderer) {
- if (!name || !attempted) {
- SDL_SetError("Couldn't find matching render driver");
+ if (!renderer) {
+ if (!name || !attempted) {
+ SDL_SetError("Couldn't find matching render driver");
+ }
+ goto error;
}
- goto error;
}
if (SDL_GetBooleanProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
@@ -983,6 +986,10 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
renderer->magic = &SDL_renderer_magic;
renderer->window = window;
renderer->target_mutex = SDL_CreateMutex();
+ if (surface) {
+ renderer->main_view.pixel_w = surface->w;
+ renderer->main_view.pixel_h = surface->h;
+ }
renderer->main_view.viewport.w = -1;
renderer->main_view.viewport.h = -1;
renderer->main_view.scale.x = 1.0f;
@@ -1005,7 +1012,12 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
/* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */
renderer->render_command_generation = 1;
- renderer->line_method = SDL_GetRenderLineMethod();
+ if (renderer->info.flags & SDL_RENDERER_SOFTWARE) {
+ /* Software renderer always uses line method, for speed */
+ renderer->line_method = SDL_RENDERLINEMETHOD_LINES;
+ } else {
+ renderer->line_method = SDL_GetRenderLineMethod();
+ }
renderer->SDR_white_point = 1.0f;
renderer->HDR_headroom = 1.0f;
@@ -1032,11 +1044,15 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
SDL_SetNumberProperty(new_props, SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER, renderer->output_colorspace);
UpdateHDRProperties(renderer);
- SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_RENDERER_POINTER, renderer);
+ if (window) {
+ SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_RENDERER_POINTER, renderer);
+ }
SDL_SetRenderViewport(renderer, NULL);
- SDL_AddEventWatch(SDL_RendererEventWatch, renderer);
+ if (window) {
+ SDL_AddEventWatch(SDL_RendererEventWatch, renderer);
+ }
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER,
"Created renderer: %s", renderer->info.name);
@@ -1081,31 +1097,10 @@ SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface)
{
#if SDL_VIDEO_RENDER_SW
SDL_Renderer *renderer;
-
- renderer = SW_CreateRendererForSurface(surface);
-
- if (renderer) {
- VerifyDrawQueueFunctions(renderer);
- renderer->magic = &SDL_renderer_magic;
- renderer->target_mutex = SDL_CreateMutex();
- renderer->main_view.pixel_w = surface->w;
- renderer->main_view.pixel_h = surface->h;
- renderer->main_view.viewport.w = -1;
- renderer->main_view.viewport.h = -1;
- renderer->main_view.scale.x = 1.0f;
- renderer->main_view.scale.y = 1.0f;
- renderer->view = &renderer->main_view;
- renderer->dpi_scale.x = 1.0f;
- renderer->dpi_scale.y = 1.0f;
-
- /* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */
- renderer->render_command_generation = 1;
-
- /* Software renderer always uses line method, for speed */
- renderer->line_method = SDL_RENDERLINEMETHOD_LINES;
-
- SDL_SetRenderViewport(renderer, NULL);
- }
+ SDL_PropertiesID props = SDL_CreateProperties();
+ SDL_SetProperty(props, SDL_PROP_RENDERER_CREATE_SURFACE_POINTER, surface);
+ renderer = SDL_CreateRendererWithProperties(props);
+ SDL_DestroyProperties(props);
return renderer;
#else
SDL_SetError("SDL not built with rendering support");
diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c
index 570333c7c1646..b98a896f81a64 100644
--- a/src/render/software/SDL_render_sw.c
+++ b/src/render/software/SDL_render_sw.c
@@ -1116,7 +1116,7 @@ static void SW_SelectBestFormats(SDL_Renderer *renderer, SDL_PixelFormatEnum for
}
}
-SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface)
+SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface, SDL_PropertiesID create_props)
{
SDL_Renderer *renderer;
SW_RenderData *data;
@@ -1168,12 +1168,19 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface)
SW_SelectBestFormats(renderer, surface->format->format);
+ SDL_SetupRendererColorspace(renderer, create_props);
+
+ if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
+ SDL_SetError("Unsupported output colorspace");
+ SW_DestroyRenderer(renderer);
+ return NULL;
+ }
+
return renderer;
}
static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
- SDL_Renderer *renderer;
const char *hint;
SDL_Surface *surface;
SDL_bool no_hint_set;
@@ -1205,20 +1212,7 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
return NULL;
}
- renderer = SW_CreateRendererForSurface(surface);
- if (!renderer) {
- return NULL;
- }
-
- SDL_SetupRendererColorspace(renderer, create_props);
-
- if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
- SDL_SetError("Unsupported output colorspace");
- SW_DestroyRenderer(renderer);
- return NULL;
- }
-
- return renderer;
+ return SW_CreateRendererForSurface(surface, create_props);
}
SDL_RenderDriver SW_RenderDriver = {
diff --git a/src/render/software/SDL_render_sw_c.h b/src/render/software/SDL_render_sw_c.h
index fad327c0b4929..40966d181adbf 100644
--- a/src/render/software/SDL_render_sw_c.h
+++ b/src/render/software/SDL_render_sw_c.h
@@ -22,6 +22,6 @@
#ifndef SDL_render_sw_c_h_
#define SDL_render_sw_c_h_
-extern SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface);
+extern SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface, SDL_PropertiesID create_props);
#endif /* SDL_render_sw_c_h_ */