From ed463b41e15f66fe23885f12e37753b91c483199 Mon Sep 17 00:00:00 2001 From: Sam Lantinga 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 c6a9847f11..6bcba6c275 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; + if (renderer) { + /* Yay, we got one! */ + 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) { - 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 570333c7c1..b98a896f81 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 fad327c0b4..40966d181a 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_ */