Compare commits

...

10 Commits

Author SHA1 Message Date
LeRoyce Pearson 72dfb4f05a feat: add build.zig 2024-04-20 01:21:58 -06:00
Frank Praznik fb4c15319e pipewire: Raise minimum build version to 0.3.44 2024-04-19 12:34:22 -04:00
Frank Praznik 566d142938 tests: Clean up the renderer in the video test suite since it isn't automatic anymore. 2024-04-19 12:23:40 -04:00
Frank Praznik bede245395 Remove references to renderers being destroyed with windows in the documentation 2024-04-19 12:23:40 -04:00
Ryan C. Gordon cab3defc18 render: SDL_DestroyWindow hollows out its renderer but doesn't free it.
This allows apps to destroy the window and renderer in either order, but
makes sure that the renderer can properly clean up its resources while OpenGL
contexts and libraries are still loaded, etc.

If the window is destroyed first, the renderer is (mostly) destroyed but its
pointer remains valid. Attempts to use the renderer will return an error,
but it can still be explicitly destroyed, at which time the struct is free'd.

If the renderer is destroyed first, everything works as before, and a new
renderer can still be created on the existing window.

Fixes #9540.
2024-04-19 00:25:59 -04:00
Ryan C. Gordon 39c8434f5f render: Manage memory for SDL_Renderer* at higher level.
Previously, each backend would allocate and free the renderer struct. Now
the higher level does it, so the backends only manage their private resources.

This removes some boilerplate and avoids some potential accidents.
2024-04-19 00:25:59 -04:00
Frank Praznik 09e32faa68 x11: Ensure that a configure event was received before sending the final window size and coordinates
Headless display servers might not send an initial configure event, so don't assume that one has arrived and send garbage size/position values when showing a window.
2024-04-18 14:28:16 -04:00
SDL Wiki Bot 64d5fb6ab6 Sync SDL3 wiki -> header 2024-04-18 17:41:14 +00:00
Anonymous Maarten 911fc9b17e testffmpeg: treat Khronos headers as system headers 2024-04-18 09:10:15 -07:00
devon-artmeier 9c65738926
dialog: Use size_t for length variables (#9572)
Shuts up a warning about size differences.
2024-04-18 09:09:10 -07:00
26 changed files with 399 additions and 345 deletions

169
build.zig Normal file
View File

@ -0,0 +1,169 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const lib = b.addStaticLibrary(.{
.name = "SDL",
.target = target,
.optimize = optimize,
});
lib.addIncludePath(.{ .path = "include" });
lib.addIncludePath(.{ .path = "src" });
lib.installHeadersDirectoryOptions(.{
.source_dir = .{ .path = "include/SDL3" },
.install_dir = .header,
.install_subdir = "SDL3",
});
lib.addCSourceFiles(.{
.files = &.{
"src/SDL.c",
"src/SDL_assert.c",
"src/SDL_error.c",
"src/SDL_guid.c",
"src/SDL_hashtable.c",
"src/SDL_hints.c",
"src/SDL_list.c",
"src/SDL_log.c",
"src/SDL_properties.c",
"src/SDL_utils.c",
"src/atomic/SDL_atomic.c",
"src/atomic/SDL_spinlock.c",
"src/audio/SDL_audio.c",
"src/audio/SDL_audiocvt.c",
"src/audio/SDL_audiodev.c",
"src/audio/SDL_audioqueue.c",
"src/audio/SDL_audioresample.c",
"src/audio/SDL_audiotypecvt.c",
"src/audio/SDL_mixer.c",
"src/audio/SDL_wave.c",
"src/camera/SDL_camera.c",
"src/core/SDL_core_unsupported.c",
"src/core/SDL_runapp.c",
"src/cpuinfo/SDL_cpuinfo.c",
"src/dynapi/SDL_dynapi.c",
"src/events/SDL_clipboardevents.c",
"src/events/SDL_displayevents.c",
"src/events/SDL_dropevents.c",
"src/events/SDL_events.c",
"src/events/SDL_keyboard.c",
"src/events/SDL_keysym_to_scancode.c",
"src/events/SDL_mouse.c",
"src/events/SDL_pen.c",
"src/events/SDL_quit.c",
"src/events/SDL_scancode_tables.c",
"src/events/SDL_touch.c",
"src/events/SDL_windowevents.c",
"src/events/imKStoUCS.c",
"src/file/SDL_iostream.c",
"src/filesystem/SDL_filesystem.c",
"src/joystick/SDL_gamepad.c",
"src/joystick/SDL_joystick.c",
"src/joystick/SDL_steam_virtual_gamepad.c",
"src/joystick/controller_type.c",
"src/haptic/SDL_haptic.c",
"src/hidapi/SDL_hidapi.c",
"src/libm/e_atan2.c",
"src/libm/e_exp.c",
"src/libm/e_fmod.c",
"src/libm/e_log.c",
"src/libm/e_log10.c",
"src/libm/e_pow.c",
"src/libm/e_rem_pio2.c",
"src/libm/e_sqrt.c",
"src/libm/k_cos.c",
"src/libm/k_rem_pio2.c",
"src/libm/k_sin.c",
"src/libm/k_tan.c",
"src/libm/s_atan.c",
"src/libm/s_copysign.c",
"src/libm/s_cos.c",
"src/libm/s_fabs.c",
"src/libm/s_floor.c",
"src/libm/s_modf.c",
"src/libm/s_scalbn.c",
"src/libm/s_sin.c",
"src/libm/s_tan.c",
"src/locale/SDL_locale.c",
"src/main/SDL_main_callbacks.c",
"src/misc/SDL_url.c",
"src/power/SDL_power.c",
"src/render/SDL_d3dmath.c",
"src/render/SDL_render.c",
"src/render/SDL_render_unsupported.c",
"src/render/SDL_yuv_sw.c",
"src/sensor/SDL_sensor.c",
"src/stdlib/SDL_crc16.c",
"src/stdlib/SDL_crc32.c",
"src/stdlib/SDL_getenv.c",
"src/stdlib/SDL_iconv.c",
"src/stdlib/SDL_malloc.c",
"src/stdlib/SDL_memcpy.c",
"src/stdlib/SDL_memmove.c",
"src/stdlib/SDL_memset.c",
"src/stdlib/SDL_mslibc.c",
"src/stdlib/SDL_qsort.c",
"src/stdlib/SDL_stdlib.c",
"src/stdlib/SDL_string.c",
"src/stdlib/SDL_strtokr.c",
"src/storage/SDL_storage.c",
"src/thread/SDL_thread.c",
"src/time/SDL_time.c",
"src/timer/SDL_timer.c",
"src/video/SDL_RLEaccel.c",
"src/video/SDL_blit.c",
"src/video/SDL_blit_0.c",
"src/video/SDL_blit_1.c",
"src/video/SDL_blit_A.c",
"src/video/SDL_blit_N.c",
"src/video/SDL_blit_auto.c",
"src/video/SDL_blit_copy.c",
"src/video/SDL_blit_slow.c",
"src/video/SDL_bmp.c",
"src/video/SDL_clipboard.c",
"src/video/SDL_egl.c",
"src/video/SDL_fillrect.c",
"src/video/SDL_pixels.c",
"src/video/SDL_rect.c",
"src/video/SDL_stretch.c",
"src/video/SDL_surface.c",
"src/video/SDL_video.c",
"src/video/SDL_video_unsupported.c",
"src/video/SDL_vulkan_utils.c",
"src/video/SDL_yuv.c",
"src/video/yuv2rgb/yuv_rgb_lsx.c",
"src/video/yuv2rgb/yuv_rgb_sse.c",
"src/video/yuv2rgb/yuv_rgb_std.c",
},
});
lib.linkLibC();
b.installArtifact(lib);
}

62
build.zig.zon Normal file
View File

@ -0,0 +1,62 @@
.{
.name = "SDL",
// This is a [Semantic Version](https://semver.org/).
// In a future version of Zig it will be used for package deduplication.
.version = "3.1.1",
// This field is optional.
// This is currently advisory only; Zig does not yet do anything
// with this value.
//.minimum_zig_version = "0.11.0",
// This field is optional.
// Each dependency must either provide a `url` and `hash`, or a `path`.
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
// Once all dependencies are fetched, `zig build` no longer requires
// internet connectivity.
.dependencies = .{
// See `zig fetch --save <url>` for a command-line interface for adding dependencies.
//.example = .{
// // When updating this field to a new URL, be sure to delete the corresponding
// // `hash`, otherwise you are communicating that you expect to find the old hash at
// // the new URL.
// .url = "https://example.com/foo.tar.gz",
//
// // This is computed from the file contents of the directory of files that is
// // obtained after fetching `url` and applying the inclusion rules given by
// // `paths`.
// //
// // This field is the source of truth; packages do not come from a `url`; they
// // come from a `hash`. `url` is just one of many possible mirrors for how to
// // obtain a package matching this `hash`.
// //
// // Uses the [multihash](https://multiformats.io/multihash/) format.
// .hash = "...",
//
// // When this is provided, the package is found in a directory relative to the
// // build root. In this case the package's hash is irrelevant and therefore not
// // computed. This field and `url` are mutually exclusive.
// .path = "foo",
//},
},
// Specifies the set of files and directories that are included in this package.
// Only files and directories listed here are included in the `hash` that
// is computed for this package.
// Paths are relative to the build root. Use the empty string (`""`) to refer to
// the build root itself.
// A directory listed here means that all files within, recursively, are included.
.paths = .{
// This makes *all* files, recursively, included in this package. It is generally
// better to explicitly list the files and directories instead, to insure that
// fetching from tarballs, file system paths, and version control all result
// in the same contents hash.
"",
// For example...
//"build.zig",
//"build.zig.zon",
//"src",
//"LICENSE",
//"README.md",
},
}

View File

@ -134,7 +134,7 @@ endmacro()
# - HAVE_SDL_LOADSO opt # - HAVE_SDL_LOADSO opt
macro(CheckPipewire) macro(CheckPipewire)
if(SDL_PIPEWIRE) if(SDL_PIPEWIRE)
set(PipeWire_PKG_CONFIG_SPEC libpipewire-0.3>=0.3.20) set(PipeWire_PKG_CONFIG_SPEC libpipewire-0.3>=0.3.44)
pkg_check_modules(PC_PIPEWIRE IMPORTED_TARGET ${PipeWire_PKG_CONFIG_SPEC}) pkg_check_modules(PC_PIPEWIRE IMPORTED_TARGET ${PipeWire_PKG_CONFIG_SPEC})
if(PC_PIPEWIRE_FOUND) if(PC_PIPEWIRE_FOUND)
set(HAVE_PIPEWIRE TRUE) set(HAVE_PIPEWIRE TRUE)

View File

@ -22,7 +22,7 @@ Using the Simple DirectMedia Layer for iOS
5. Select the project in the main view, go to the "Build Settings" tab, select "All", and edit "Header Search Path" and drag over the SDL "Public Headers" folder from the left 5. Select the project in the main view, go to the "Build Settings" tab, select "All", and edit "Header Search Path" and drag over the SDL "Public Headers" folder from the left
6. Select the project in the main view, go to the "Build Phases" tab, select "Link Binary With Libraries", and add SDL3.framework from "Framework-iOS" 6. Select the project in the main view, go to the "Build Phases" tab, select "Link Binary With Libraries", and add SDL3.framework from "Framework-iOS"
7. Select the project in the main view, go to the "General" tab, scroll down to "Frameworks, Libraries, and Embedded Content", and select "Embed & Sign" for the SDL library. 7. Select the project in the main view, go to the "General" tab, scroll down to "Frameworks, Libraries, and Embedded Content", and select "Embed & Sign" for the SDL library.
8. Add the source files that you would normally have for an SDL program, making sure to have #include "SDL.h" at the top of the file containing your main() function. 8. Add the source files that you would normally have for an SDL program, making sure to have #include <SDL3/SDL_main.h> at the top of the file containing your main() function.
9. Add any assets that your application needs. 9. Add any assets that your application needs.
10. Enjoy! 10. Enjoy!

View File

@ -2031,10 +2031,6 @@ extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture *texture);
* If `renderer` is NULL, this function will return immediately after setting * If `renderer` is NULL, this function will return immediately after setting
* the SDL error message to "Invalid renderer". See SDL_GetError(). * the SDL error message to "Invalid renderer". See SDL_GetError().
* *
* Note that destroying a window implicitly destroys the associated renderer,
* so this should not be called if the window associated with the renderer has
* already been destroyed.
*
* \param renderer the rendering context * \param renderer the rendering context
* *
* \since This function is available since SDL 3.0.0. * \since This function is available since SDL 3.0.0.

View File

@ -2179,9 +2179,6 @@ extern DECLSPEC int SDLCALL SDL_FlashWindow(SDL_Window *window, SDL_FlashOperati
/** /**
* Destroy a window. * Destroy a window.
* *
* If the window has an associated SDL_Renderer, it will be implicitly
* destroyed as well.
*
* If `window` is NULL, this function will return immediately after setting * If `window` is NULL, this function will return immediately after setting
* the SDL error message to "Invalid window". See SDL_GetError(). * the SDL error message to "Invalid window". See SDL_GetError().
* *

View File

@ -29,38 +29,6 @@
#include <spa/param/audio/format-utils.h> #include <spa/param/audio/format-utils.h>
#include <spa/utils/json.h> #include <spa/utils/json.h>
#include "../../core/linux/SDL_dbus.h"
/*
* The following keys are defined for compatibility when building against older versions of Pipewire
* prior to their introduction and can be removed if the minimum required Pipewire build version is
* increased to or beyond their point of introduction.
*/
/*
* Introduced in 0.3.22
* Taken from /src/pipewire/keys.h
*/
#ifndef PW_KEY_CONFIG_NAME
#define PW_KEY_CONFIG_NAME "config.name"
#endif
/*
* Introduced in 0.3.33
* Taken from src/pipewire/keys.h
*/
#ifndef PW_KEY_NODE_RATE
#define PW_KEY_NODE_RATE "node.rate"
#endif
/*
* Introduced in 0.3.44
* Taken from src/pipewire/keys.h
*/
#ifndef PW_KEY_TARGET_OBJECT
#define PW_KEY_TARGET_OBJECT "target.object"
#endif
/* /*
* This seems to be a sane lower limit as Pipewire * This seems to be a sane lower limit as Pipewire
* uses it in several of it's own modules. * uses it in several of it's own modules.
@ -121,10 +89,6 @@ static struct pw_properties *(*PIPEWIRE_pw_properties_new)(const char *, ...)SPA
static int (*PIPEWIRE_pw_properties_set)(struct pw_properties *, const char *, const char *); static int (*PIPEWIRE_pw_properties_set)(struct pw_properties *, const char *, const char *);
static int (*PIPEWIRE_pw_properties_setf)(struct pw_properties *, const char *, const char *, ...) SPA_PRINTF_FUNC(3, 4); static int (*PIPEWIRE_pw_properties_setf)(struct pw_properties *, const char *, const char *, ...) SPA_PRINTF_FUNC(3, 4);
static int pipewire_library_version_major;
static int pipewire_library_version_minor;
static int pipewire_library_version_patch;
#ifdef SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC #ifdef SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC
static const char *pipewire_library = SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC; static const char *pipewire_library = SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC;
@ -215,13 +179,6 @@ static int load_pipewire_syms(void)
return 0; return 0;
} }
static SDL_bool pipewire_library_version_at_least(int major, int minor, int patch)
{
return (pipewire_library_version_major >= major) &&
(pipewire_library_version_major > major || pipewire_library_version_minor >= minor) &&
(pipewire_library_version_major > major || pipewire_library_version_minor > minor || pipewire_library_version_patch >= patch);
}
/* When in a container, the library version can differ from the underlying core version, /* When in a container, the library version can differ from the underlying core version,
* so make sure the underlying Pipewire implementation meets the version requirement. * so make sure the underlying Pipewire implementation meets the version requirement.
*/ */
@ -310,20 +267,10 @@ static int init_pipewire_library(SDL_bool check_preferred_version)
{ {
if (!load_pipewire_library()) { if (!load_pipewire_library()) {
if (!load_pipewire_syms()) { if (!load_pipewire_syms()) {
int nargs; PIPEWIRE_pw_init(NULL, NULL);
const char *version = PIPEWIRE_pw_get_library_version();
nargs = SDL_sscanf(version, "%d.%d.%d", &pipewire_library_version_major, &pipewire_library_version_minor, &pipewire_library_version_patch);
if (nargs < 3) {
return -1;
}
// SDL can build against 0.3.20, but requires 0.3.24 at minimum if (!check_preferred_version || pipewire_core_version_at_least(1, 0, 0)) {
if (pipewire_library_version_at_least(0, 3, 24)) { return 0;
PIPEWIRE_pw_init(NULL, NULL);
if (!check_preferred_version || pipewire_core_version_at_least(1, 0, 0)) {
return 0;
}
} }
} }
} }
@ -1253,25 +1200,13 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true"); PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true");
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true"); // Requesting a specific device, don't migrate to new default hardware. PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true"); // Requesting a specific device, don't migrate to new default hardware.
/* if (node_id != PW_ID_ANY) {
* Pipewire 0.3.44 introduced PW_KEY_TARGET_OBJECT that takes either a path PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
* (PW_KEY_NODE_NAME) or node serial number (PE_KEY_OBJECT_SERIAL) to connect const struct io_node *node = io_list_get_by_id(node_id);
* the stream to its target. The target_id parameter in pw_stream_connect() is if (node) {
* now deprecated and should always be PW_ID_ANY. PIPEWIRE_pw_properties_set(props, PW_KEY_TARGET_OBJECT, node->path);
*/
if (pipewire_library_version_at_least(0, 3, 44)) {
if (node_id != PW_ID_ANY) {
const struct io_node *node;
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
node = io_list_get_by_id(node_id);
if (node) {
PIPEWIRE_pw_properties_set(props, PW_KEY_TARGET_OBJECT, node->path);
}
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
node_id = PW_ID_ANY;
} }
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
} }
// Create the new stream // Create the new stream
@ -1281,7 +1216,8 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
return SDL_SetError("Pipewire: Failed to create stream (%i)", errno); return SDL_SetError("Pipewire: Failed to create stream (%i)", errno);
} }
res = PIPEWIRE_pw_stream_connect(priv->stream, iscapture ? PW_DIRECTION_INPUT : PW_DIRECTION_OUTPUT, node_id, STREAM_FLAGS, // The target node is passed via PW_KEY_TARGET_OBJECT; target_id is a legacy parameter and must be PW_ID_ANY.
res = PIPEWIRE_pw_stream_connect(priv->stream, iscapture ? PW_DIRECTION_INPUT : PW_DIRECTION_OUTPUT, PW_ID_ANY, STREAM_FLAGS,
&params, 1); &params, 1);
if (res != 0) { if (res != 0) {
return SDL_SetError("Pipewire: Failed to connect stream"); return SDL_SetError("Pipewire: Failed to connect stream");

View File

@ -33,7 +33,7 @@ char *convert_filters(const SDL_DialogFileFilter *filters, NameTransform ntf,
char *new_combined; char *new_combined;
char *converted; char *converted;
const char *terminator; const char *terminator;
int new_length; size_t new_length;
combined = SDL_strdup(prefix); combined = SDL_strdup(prefix);
@ -82,7 +82,7 @@ char *convert_filter(const SDL_DialogFileFilter filter, NameTransform ntf,
{ {
char *converted; char *converted;
char *name_filtered; char *name_filtered;
int total_length; size_t total_length;
char *list; char *list;
list = convert_ext_list(filter.pattern, ext_prefix, ext_separator, list = convert_ext_list(filter.pattern, ext_prefix, ext_separator,
@ -131,7 +131,7 @@ char *convert_ext_list(const char *list, const char *prefix,
{ {
char *converted; char *converted;
int semicolons; int semicolons;
int total_length; size_t total_length;
semicolons = 0; semicolons = 0;

View File

@ -46,12 +46,19 @@ this should probably be removed at some point in the future. --ryan. */
#define SDL_PROP_WINDOW_RENDERER_POINTER "SDL.internal.window.renderer" #define SDL_PROP_WINDOW_RENDERER_POINTER "SDL.internal.window.renderer"
#define SDL_PROP_TEXTURE_PARENT_POINTER "SDL.internal.texture.parent" #define SDL_PROP_TEXTURE_PARENT_POINTER "SDL.internal.texture.parent"
#define CHECK_RENDERER_MAGIC(renderer, retval) \ #define CHECK_RENDERER_MAGIC_BUT_NOT_DESTROYED_FLAG(renderer, retval) \
if (!(renderer) || (renderer)->magic != &SDL_renderer_magic) { \ if (!(renderer) || (renderer)->magic != &SDL_renderer_magic) { \
SDL_InvalidParamError("renderer"); \ SDL_InvalidParamError("renderer"); \
return retval; \ return retval; \
} }
#define CHECK_RENDERER_MAGIC(renderer, retval) \
CHECK_RENDERER_MAGIC_BUT_NOT_DESTROYED_FLAG(renderer, retval); \
if ((renderer)->destroyed) { \
SDL_SetError("Renderer's window has been destroyed, can't use further"); \
return retval; \
}
#define CHECK_TEXTURE_MAGIC(texture, retval) \ #define CHECK_TEXTURE_MAGIC(texture, retval) \
if (!(texture) || (texture)->magic != &SDL_texture_magic) { \ if (!(texture) || (texture)->magic != &SDL_texture_magic) { \
SDL_InvalidParamError("texture"); \ SDL_InvalidParamError("texture"); \
@ -900,12 +907,18 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
SDL_Window *window = (SDL_Window *)SDL_GetProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER, NULL); SDL_Window *window = (SDL_Window *)SDL_GetProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER, NULL);
SDL_Surface *surface = (SDL_Surface *)SDL_GetProperty(props, SDL_PROP_RENDERER_CREATE_SURFACE_POINTER, NULL); SDL_Surface *surface = (SDL_Surface *)SDL_GetProperty(props, SDL_PROP_RENDERER_CREATE_SURFACE_POINTER, NULL);
const char *name = SDL_GetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING, NULL); const char *name = SDL_GetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING, NULL);
SDL_Renderer *renderer = NULL;
const int n = SDL_GetNumRenderDrivers(); const int n = SDL_GetNumRenderDrivers();
const char *hint; const char *hint;
int i, attempted = 0; int i, attempted = 0;
SDL_PropertiesID new_props; SDL_PropertiesID new_props;
SDL_Renderer *renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
#ifdef SDL_PLATFORM_ANDROID #ifdef SDL_PLATFORM_ANDROID
Android_ActivityMutex_Lock_Running(); Android_ActivityMutex_Lock_Running();
#endif #endif
@ -932,15 +945,15 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
if (surface) { if (surface) {
#if SDL_VIDEO_RENDER_SW #if SDL_VIDEO_RENDER_SW
renderer = SW_CreateRendererForSurface(surface, props); const int rc = SW_CreateRendererForSurface(renderer, surface, props);
#else #else
renderer = NULL; const int rc = SDL_SetError("SDL not built with software renderer");
SDL_SetError("SDL not built with software renderer");
#endif #endif
if (!renderer) { if (rc == -1) {
goto error; goto error;
} }
} else { } else {
int rc = -1;
if (!name) { if (!name) {
name = SDL_GetHint(SDL_HINT_RENDER_DRIVER); name = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
} }
@ -949,26 +962,27 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
const SDL_RenderDriver *driver = render_drivers[i]; const SDL_RenderDriver *driver = render_drivers[i];
if (SDL_strcasecmp(name, driver->info.name) == 0) { if (SDL_strcasecmp(name, driver->info.name) == 0) {
/* Create a new renderer instance */ // Create a new renderer instance
++attempted; ++attempted;
renderer = driver->CreateRenderer(window, props); rc = driver->CreateRenderer(renderer, window, props);
break; break;
} }
} }
} else { } else {
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
const SDL_RenderDriver *driver = render_drivers[i]; const SDL_RenderDriver *driver = render_drivers[i];
/* Create a new renderer instance */ // Create a new renderer instance
++attempted; ++attempted;
renderer = driver->CreateRenderer(window, props); rc = driver->CreateRenderer(renderer, window, props);
if (renderer) { if (rc == 0) {
/* Yay, we got one! */ break; // Yay, we got one!
break;
} }
SDL_zerop(renderer); // make sure we don't leave function pointers from a previous CreateRenderer() in this struct.
renderer->magic = &SDL_renderer_magic;
} }
} }
if (!renderer) { if (rc == -1) {
if (!name || !attempted) { if (!name || !attempted) {
SDL_SetError("Couldn't find matching render driver"); SDL_SetError("Couldn't find matching render driver");
} }
@ -1072,6 +1086,7 @@ error:
#ifdef SDL_PLATFORM_ANDROID #ifdef SDL_PLATFORM_ANDROID
Android_ActivityMutex_Unlock(); Android_ActivityMutex_Unlock();
#endif #endif
SDL_free(renderer);
return NULL; return NULL;
#else #else
@ -4509,9 +4524,12 @@ static void SDL_DiscardAllCommands(SDL_Renderer *renderer)
} }
} }
void SDL_DestroyRenderer(SDL_Renderer *renderer) void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer)
{ {
CHECK_RENDERER_MAGIC(renderer,); SDL_assert(renderer != NULL);
SDL_assert(!renderer->destroyed);
renderer->destroyed = SDL_TRUE;
SDL_DestroyProperties(renderer->props); SDL_DestroyProperties(renderer->props);
@ -4522,7 +4540,6 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer)
/* Free existing textures for this renderer */ /* Free existing textures for this renderer */
while (renderer->textures) { while (renderer->textures) {
SDL_Texture *tex = renderer->textures; SDL_Texture *tex = renderer->textures;
(void)tex;
SDL_DestroyTextureInternal(renderer->textures, SDL_TRUE /* is_destroying */); SDL_DestroyTextureInternal(renderer->textures, SDL_TRUE /* is_destroying */);
SDL_assert(tex != renderer->textures); /* satisfy static analysis. */ SDL_assert(tex != renderer->textures); /* satisfy static analysis. */
} }
@ -4533,17 +4550,29 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer)
SDL_ClearProperty(SDL_GetWindowProperties(renderer->window), SDL_PROP_WINDOW_RENDERER_POINTER); SDL_ClearProperty(SDL_GetWindowProperties(renderer->window), SDL_PROP_WINDOW_RENDERER_POINTER);
} }
/* It's no longer magical... */
renderer->magic = NULL;
/* Free the target mutex */ /* Free the target mutex */
SDL_DestroyMutex(renderer->target_mutex); SDL_DestroyMutex(renderer->target_mutex);
renderer->target_mutex = NULL; renderer->target_mutex = NULL;
/* Free the renderer instance */ /* Clean up renderer-specific resources */
renderer->DestroyRenderer(renderer); renderer->DestroyRenderer(renderer);
} }
void SDL_DestroyRenderer(SDL_Renderer *renderer)
{
CHECK_RENDERER_MAGIC_BUT_NOT_DESTROYED_FLAG(renderer,);
// if we've already destroyed the renderer through SDL_DestroyWindow, we just need
// to free the renderer pointer. This lets apps destroy the window and renderer
// in either order.
if (!renderer->destroyed) {
SDL_DestroyRendererWithoutFreeing(renderer);
renderer->magic = NULL; // It's no longer magical...
}
SDL_free(renderer);
}
void *SDL_GetRenderMetalLayer(SDL_Renderer *renderer) void *SDL_GetRenderMetalLayer(SDL_Renderer *renderer)
{ {
CHECK_RENDERER_MAGIC(renderer, NULL); CHECK_RENDERER_MAGIC(renderer, NULL);

View File

@ -289,13 +289,15 @@ struct SDL_Renderer
SDL_PropertiesID props; SDL_PropertiesID props;
SDL_bool destroyed; // already destroyed by SDL_DestroyWindow; just free this struct in SDL_DestroyRenderer.
void *driverdata; void *driverdata;
}; };
/* Define the SDL render driver structure */ /* Define the SDL render driver structure */
struct SDL_RenderDriver struct SDL_RenderDriver
{ {
SDL_Renderer *(*CreateRenderer)(SDL_Window *window, SDL_PropertiesID props); int (*CreateRenderer)(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID props);
/* Info about the renderer capabilities */ /* Info about the renderer capabilities */
SDL_RendererInfo info; SDL_RendererInfo info;
@ -335,6 +337,9 @@ extern SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode
the next call, because it might be in an array that gets realloc()'d. */ the next call, because it might be in an array that gets realloc()'d. */
extern void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset); extern void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset);
// Let the video subsystem destroy a renderer without making its pointer invalid.
extern void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer);
/* Ends C function definitions when using C++ */ /* Ends C function definitions when using C++ */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1469,7 +1469,6 @@ static void D3D_DestroyRenderer(SDL_Renderer *renderer)
} }
SDL_free(data); SDL_free(data);
} }
SDL_free(renderer);
} }
static int D3D_Reset(SDL_Renderer *renderer) static int D3D_Reset(SDL_Renderer *renderer)
@ -1567,9 +1566,8 @@ static int D3D_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0; return 0;
} }
SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) int D3D_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
SDL_Renderer *renderer;
D3D_RenderData *data; D3D_RenderData *data;
HRESULT result; HRESULT result;
D3DPRESENT_PARAMETERS pparams; D3DPRESENT_PARAMETERS pparams;
@ -1580,31 +1578,20 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro
SDL_DisplayID displayID; SDL_DisplayID displayID;
const SDL_DisplayMode *fullscreen_mode = NULL; const SDL_DisplayMode *fullscreen_mode = NULL;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
SDL_SetError("Unsupported output colorspace"); return SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
return NULL;
} }
data = (D3D_RenderData *)SDL_calloc(1, sizeof(*data)); data = (D3D_RenderData *)SDL_calloc(1, sizeof(*data));
if (!data) { if (!data) {
SDL_free(renderer); return -1;
return NULL;
} }
if (!D3D_LoadDLL(&data->d3dDLL, &data->d3d)) { if (!D3D_LoadDLL(&data->d3dDLL, &data->d3d)) {
SDL_SetError("Unable to create Direct3D interface");
SDL_free(renderer);
SDL_free(data); SDL_free(data);
return NULL; return SDL_SetError("Unable to create Direct3D interface");
} }
renderer->WindowEvent = D3D_WindowEvent; renderer->WindowEvent = D3D_WindowEvent;
@ -1685,23 +1672,20 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro
&pparams, &data->device); &pparams, &data->device);
if (FAILED(result)) { if (FAILED(result)) {
D3D_DestroyRenderer(renderer); D3D_DestroyRenderer(renderer);
D3D_SetError("CreateDevice()", result); return D3D_SetError("CreateDevice()", result);
return NULL;
} }
/* Get presentation parameters to fill info */ /* Get presentation parameters to fill info */
result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain); result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
if (FAILED(result)) { if (FAILED(result)) {
D3D_DestroyRenderer(renderer); D3D_DestroyRenderer(renderer);
D3D_SetError("GetSwapChain()", result); return D3D_SetError("GetSwapChain()", result);
return NULL;
} }
result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams); result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
if (FAILED(result)) { if (FAILED(result)) {
IDirect3DSwapChain9_Release(chain); IDirect3DSwapChain9_Release(chain);
D3D_DestroyRenderer(renderer); D3D_DestroyRenderer(renderer);
D3D_SetError("GetPresentParameters()", result); return D3D_SetError("GetPresentParameters()", result);
return NULL;
} }
IDirect3DSwapChain9_Release(chain); IDirect3DSwapChain9_Release(chain);
if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) { if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
@ -1741,7 +1725,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro
SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_D3D9_DEVICE_POINTER, data->device); SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_D3D9_DEVICE_POINTER, data->device);
return renderer; return 0;
} }
SDL_RenderDriver D3D_RenderDriver = { SDL_RenderDriver D3D_RenderDriver = {

View File

@ -413,7 +413,6 @@ static void D3D11_DestroyRenderer(SDL_Renderer *renderer)
if (data) { if (data) {
SDL_free(data); SDL_free(data);
} }
SDL_free(renderer);
} }
static D3D11_BLEND GetBlendFunc(SDL_BlendFactor factor) static D3D11_BLEND GetBlendFunc(SDL_BlendFactor factor)
@ -2741,31 +2740,21 @@ static int D3D11_SetVSync(SDL_Renderer *renderer, const int vsync)
} }
#endif #endif
SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) static int D3D11_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
SDL_Renderer *renderer;
D3D11_RenderData *data; D3D11_RenderData *data;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB && if (renderer->output_colorspace != SDL_COLORSPACE_SRGB &&
renderer->output_colorspace != SDL_COLORSPACE_SRGB_LINEAR renderer->output_colorspace != SDL_COLORSPACE_SRGB_LINEAR
/*&& renderer->output_colorspace != SDL_COLORSPACE_HDR10*/) { /*&& renderer->output_colorspace != SDL_COLORSPACE_HDR10*/) {
SDL_SetError("Unsupported output colorspace"); return SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
return NULL;
} }
data = (D3D11_RenderData *)SDL_calloc(1, sizeof(*data)); data = (D3D11_RenderData *)SDL_calloc(1, sizeof(*data));
if (!data) { if (!data) {
SDL_free(renderer); return -1;
return NULL;
} }
data->identity = MatrixIdentity(); data->identity = MatrixIdentity();
@ -2825,14 +2814,14 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p
/* Initialize Direct3D resources */ /* Initialize Direct3D resources */
if (FAILED(D3D11_CreateDeviceResources(renderer))) { if (FAILED(D3D11_CreateDeviceResources(renderer))) {
D3D11_DestroyRenderer(renderer); D3D11_DestroyRenderer(renderer);
return NULL; return -1;
} }
if (FAILED(D3D11_CreateWindowSizeDependentResources(renderer))) { if (FAILED(D3D11_CreateWindowSizeDependentResources(renderer))) {
D3D11_DestroyRenderer(renderer); D3D11_DestroyRenderer(renderer);
return NULL; return -1;
} }
return renderer; return 0;
} }
SDL_RenderDriver D3D11_RenderDriver = { SDL_RenderDriver D3D11_RenderDriver = {

View File

@ -587,7 +587,6 @@ static void D3D12_DestroyRenderer(SDL_Renderer *renderer)
if (data) { if (data) {
SDL_free(data); SDL_free(data);
} }
SDL_free(renderer);
} }
static D3D12_BLEND GetBlendFunc(SDL_BlendFactor factor) static D3D12_BLEND GetBlendFunc(SDL_BlendFactor factor)
@ -3173,37 +3172,26 @@ static int D3D12_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0; return 0;
} }
SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) int D3D12_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
SDL_Renderer *renderer;
D3D12_RenderData *data; D3D12_RenderData *data;
if (SDL_GetWindowFlags(window) & SDL_WINDOW_TRANSPARENT) { if (SDL_GetWindowFlags(window) & SDL_WINDOW_TRANSPARENT) {
/* D3D12 removed the swap effect needed to support transparent windows, use D3D11 instead */ /* D3D12 removed the swap effect needed to support transparent windows, use D3D11 instead */
SDL_SetError("The direct3d12 renderer doesn't work with transparent windows"); return SDL_SetError("The direct3d12 renderer doesn't work with transparent windows");
return NULL;
} }
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB && if (renderer->output_colorspace != SDL_COLORSPACE_SRGB &&
renderer->output_colorspace != SDL_COLORSPACE_SRGB_LINEAR renderer->output_colorspace != SDL_COLORSPACE_SRGB_LINEAR
/*&& renderer->output_colorspace != SDL_COLORSPACE_HDR10*/) { /*&& renderer->output_colorspace != SDL_COLORSPACE_HDR10*/) {
SDL_SetError("Unsupported output colorspace"); return SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
return NULL;
} }
data = (D3D12_RenderData *)SDL_calloc(1, sizeof(*data)); data = (D3D12_RenderData *)SDL_calloc(1, sizeof(*data));
if (!data) { if (!data) {
SDL_free(renderer); return -1;
return NULL;
} }
data->identity = MatrixIdentity(); data->identity = MatrixIdentity();
@ -3248,14 +3236,14 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p
/* Initialize Direct3D resources */ /* Initialize Direct3D resources */
if (FAILED(D3D12_CreateDeviceResources(renderer))) { if (FAILED(D3D12_CreateDeviceResources(renderer))) {
D3D12_DestroyRenderer(renderer); D3D12_DestroyRenderer(renderer);
return NULL; return -1;
} }
if (FAILED(D3D12_CreateWindowSizeDependentResources(renderer))) { if (FAILED(D3D12_CreateWindowSizeDependentResources(renderer))) {
D3D12_DestroyRenderer(renderer); D3D12_DestroyRenderer(renderer);
return NULL; return -1;
} }
return renderer; return 0;
} }
SDL_RenderDriver D3D12_RenderDriver = { SDL_RenderDriver D3D12_RenderDriver = {

View File

@ -1800,8 +1800,6 @@ static void METAL_DestroyRenderer(SDL_Renderer *renderer)
/* SDL_Metal_DestroyView(data.mtlview); */ /* SDL_Metal_DestroyView(data.mtlview); */
CFBridgingRelease(data.mtlview); CFBridgingRelease(data.mtlview);
} }
SDL_free(renderer);
} }
} }
@ -1874,10 +1872,9 @@ static SDL_MetalView GetWindowView(SDL_Window *window)
return nil; return nil;
} }
static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) static int METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
@autoreleasepool { @autoreleasepool {
SDL_Renderer *renderer = NULL;
METAL_RenderData *data = NULL; METAL_RenderData *data = NULL;
id<MTLDevice> mtldevice = nil; id<MTLDevice> mtldevice = nil;
SDL_MetalView view = NULL; SDL_MetalView view = NULL;
@ -1939,15 +1936,9 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
const size_t YCbCr_shader_matrix_size = 4 * 4 * sizeof(float); const size_t YCbCr_shader_matrix_size = 4 * 4 * sizeof(float);
if (!IsMetalAvailable()) { if (!IsMetalAvailable()) {
return NULL; return -1;
} }
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
#ifndef SDL_PLATFORM_TVOS #ifndef SDL_PLATFORM_TVOS
@ -1959,9 +1950,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR && scRGB_supported) { if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR && scRGB_supported) {
/* This colorspace is supported */ /* This colorspace is supported */
} else { } else {
SDL_SetError("Unsupported output colorspace"); return SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
return NULL;
} }
} }
@ -1983,9 +1972,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
} }
if (mtldevice == nil) { if (mtldevice == nil) {
SDL_free(renderer); return SDL_SetError("Failed to obtain Metal device");
SDL_SetError("Failed to obtain Metal device");
return NULL;
} }
view = GetWindowView(window); view = GetWindowView(window);
@ -1994,8 +1981,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
} }
if (view == NULL) { if (view == NULL) {
SDL_free(renderer); return -1;
return NULL;
} }
// !!! FIXME: error checking on all of this. // !!! FIXME: error checking on all of this.
@ -2007,8 +1993,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
*/ */
/* SDL_Metal_DestroyView(view); */ /* SDL_Metal_DestroyView(view); */
CFBridgingRelease(view); CFBridgingRelease(view);
SDL_free(renderer); return SDL_SetError("METAL_RenderData alloc/init failed");
return NULL;
} }
renderer->driverdata = (void *)CFBridgingRetain(data); renderer->driverdata = (void *)CFBridgingRetain(data);
@ -2205,7 +2190,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
renderer->info.max_texture_width = maxtexsize; renderer->info.max_texture_width = maxtexsize;
renderer->info.max_texture_height = maxtexsize; renderer->info.max_texture_height = maxtexsize;
return renderer; return 0;
} }
} }

View File

@ -1583,7 +1583,6 @@ static void GL_DestroyRenderer(SDL_Renderer *renderer)
} }
SDL_free(data); SDL_free(data);
} }
SDL_free(renderer);
} }
static int GL_SetVSync(SDL_Renderer *renderer, const int vsync) static int GL_SetVSync(SDL_Renderer *renderer, const int vsync)
@ -1612,10 +1611,9 @@ static int GL_SetVSync(SDL_Renderer *renderer, const int vsync)
return retval; return retval;
} }
static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) static int GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
SDL_Renderer *renderer; GL_RenderData *data = NULL;
GL_RenderData *data;
GLint value; GLint value;
SDL_WindowFlags window_flags; SDL_WindowFlags window_flags;
int profile_mask = 0, major = 0, minor = 0; int profile_mask = 0, major = 0, minor = 0;
@ -1644,22 +1642,15 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
} }
#endif #endif
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
goto error;
}
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
SDL_SetError("Unsupported output colorspace"); SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
goto error; goto error;
} }
data = (GL_RenderData *)SDL_calloc(1, sizeof(*data)); data = (GL_RenderData *)SDL_calloc(1, sizeof(*data));
if (!data) { if (!data) {
SDL_free(renderer);
goto error; goto error;
} }
@ -1695,21 +1686,15 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
data->context = SDL_GL_CreateContext(window); data->context = SDL_GL_CreateContext(window);
if (!data->context) { if (!data->context) {
SDL_free(renderer);
SDL_free(data);
goto error; goto error;
} }
if (SDL_GL_MakeCurrent(window, data->context) < 0) { if (SDL_GL_MakeCurrent(window, data->context) < 0) {
SDL_GL_DeleteContext(data->context); SDL_GL_DeleteContext(data->context);
SDL_free(renderer);
SDL_free(data);
goto error; goto error;
} }
if (GL_LoadFunctions(data) < 0) { if (GL_LoadFunctions(data) < 0) {
SDL_GL_DeleteContext(data->context); SDL_GL_DeleteContext(data->context);
SDL_free(renderer);
SDL_free(data);
goto error; goto error;
} }
@ -1844,8 +1829,6 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
} else { } else {
SDL_SetError("Can't create render targets, GL_EXT_framebuffer_object not available"); SDL_SetError("Can't create render targets, GL_EXT_framebuffer_object not available");
SDL_GL_DeleteContext(data->context); SDL_GL_DeleteContext(data->context);
SDL_free(renderer);
SDL_free(data);
goto error; goto error;
} }
@ -1870,9 +1853,10 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
data->drawstate.clear_color.b = 1.0f; data->drawstate.clear_color.b = 1.0f;
data->drawstate.clear_color.a = 1.0f; data->drawstate.clear_color.a = 1.0f;
return renderer; return 0;
error: error:
SDL_free(data);
if (changed_window) { if (changed_window) {
/* Uh oh, better try to put it back... */ /* Uh oh, better try to put it back... */
char *error = SDL_strdup(SDL_GetError()); char *error = SDL_strdup(SDL_GetError());
@ -1883,7 +1867,7 @@ error:
SDL_SetError("%s", error); SDL_SetError("%s", error);
SDL_free(error); SDL_free(error);
} }
return NULL; return -1;
} }
SDL_RenderDriver GL_RenderDriver = { SDL_RenderDriver GL_RenderDriver = {

View File

@ -1445,7 +1445,6 @@ static void GLES2_DestroyRenderer(SDL_Renderer *renderer)
SDL_free(data); SDL_free(data);
} }
SDL_free(renderer);
} }
static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
@ -2041,10 +2040,9 @@ static int GLES2_SetVSync(SDL_Renderer *renderer, const int vsync)
* Renderer instantiation * * Renderer instantiation *
*************************************************************************************************/ *************************************************************************************************/
static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) static int GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
SDL_Renderer *renderer; GLES2_RenderData *data = NULL;
GLES2_RenderData *data;
SDL_WindowFlags window_flags = 0; /* -Wconditional-uninitialized */ SDL_WindowFlags window_flags = 0; /* -Wconditional-uninitialized */
GLint window_framebuffer; GLint window_framebuffer;
GLint value; GLint value;
@ -2078,24 +2076,15 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
} }
} }
/* Create the renderer struct */
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
if (!renderer) {
goto error;
}
renderer->magic = &SDL_renderer_magic;
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
SDL_SetError("Unsupported output colorspace"); SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
goto error; goto error;
} }
data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData)); data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData));
if (!data) { if (!data) {
SDL_free(renderer);
goto error; goto error;
} }
renderer->info = GLES2_RenderDriver.info; renderer->info = GLES2_RenderDriver.info;
@ -2106,28 +2095,20 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
/* Create an OpenGL ES 2.0 context */ /* Create an OpenGL ES 2.0 context */
data->context = SDL_GL_CreateContext(window); data->context = SDL_GL_CreateContext(window);
if (!data->context) { if (!data->context) {
SDL_free(renderer);
SDL_free(data);
goto error; goto error;
} }
if (SDL_GL_MakeCurrent(window, data->context) < 0) { if (SDL_GL_MakeCurrent(window, data->context) < 0) {
SDL_GL_DeleteContext(data->context); SDL_GL_DeleteContext(data->context);
SDL_free(renderer);
SDL_free(data);
goto error; goto error;
} }
if (GLES2_LoadFunctions(data) < 0) { if (GLES2_LoadFunctions(data) < 0) {
SDL_GL_DeleteContext(data->context); SDL_GL_DeleteContext(data->context);
SDL_free(renderer);
SDL_free(data);
goto error; goto error;
} }
if (GLES2_CacheShaders(data) < 0) { if (GLES2_CacheShaders(data) < 0) {
SDL_GL_DeleteContext(data->context); SDL_GL_DeleteContext(data->context);
SDL_free(renderer);
SDL_free(data);
goto error; goto error;
} }
@ -2244,9 +2225,10 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
GL_CheckError("", renderer); GL_CheckError("", renderer);
return renderer; return 0;
error: error:
SDL_free(data);
if (changed_window) { if (changed_window) {
/* Uh oh, better try to put it back... */ /* Uh oh, better try to put it back... */
char *error = SDL_strdup(SDL_GetError()); char *error = SDL_strdup(SDL_GetError());
@ -2257,7 +2239,7 @@ error:
SDL_SetError("%s", error); SDL_SetError("%s", error);
SDL_free(error); SDL_free(error);
} }
return NULL; return -1;
} }
SDL_RenderDriver GLES2_RenderDriver = { SDL_RenderDriver GLES2_RenderDriver = {

View File

@ -602,8 +602,6 @@ static void PS2_DestroyRenderer(SDL_Renderer *renderer)
if (vsync_sema_id >= 0) { if (vsync_sema_id >= 0) {
DeleteSema(vsync_sema_id); DeleteSema(vsync_sema_id);
} }
SDL_free(renderer);
} }
static int PS2_SetVSync(SDL_Renderer *renderer, const int vsync) static int PS2_SetVSync(SDL_Renderer *renderer, const int vsync)
@ -614,32 +612,23 @@ static int PS2_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0; return 0;
} }
static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) static int PS2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
SDL_Renderer *renderer;
PS2_RenderData *data; PS2_RenderData *data;
GSGLOBAL *gsGlobal; GSGLOBAL *gsGlobal;
ee_sema_t sema; ee_sema_t sema;
SDL_bool dynamicVsync; SDL_bool dynamicVsync;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
SDL_SetError("Unsupported output colorspace");
SDL_free(renderer); SDL_free(renderer);
return NULL; return SDL_SetError("Unsupported output colorspace");
} }
data = (PS2_RenderData *)SDL_calloc(1, sizeof(*data)); data = (PS2_RenderData *)SDL_calloc(1, sizeof(*data));
if (!data) { if (!data) {
PS2_DestroyRenderer(renderer); return -1;
return NULL;
} }
/* Specific gsKit init */ /* Specific gsKit init */
@ -711,7 +700,7 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID cre
if (data->vsync) { if (data->vsync) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} }
return renderer; return 0;
} }
SDL_RenderDriver PS2_RenderDriver = { SDL_RenderDriver PS2_RenderDriver = {

View File

@ -1277,7 +1277,6 @@ static void PSP_DestroyRenderer(SDL_Renderer *renderer)
data->displayListAvail = SDL_FALSE; data->displayListAvail = SDL_FALSE;
SDL_free(data); SDL_free(data);
} }
SDL_free(renderer);
} }
static int PSP_SetVSync(SDL_Renderer *renderer, const int vsync) static int PSP_SetVSync(SDL_Renderer *renderer, const int vsync)
@ -1287,31 +1286,21 @@ static int PSP_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0; return 0;
} }
SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) static int PSP_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
SDL_Renderer *renderer;
PSP_RenderData *data; PSP_RenderData *data;
int pixelformat; int pixelformat;
void *doublebuffer = NULL; void *doublebuffer = NULL;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
SDL_SetError("Unsupported output colorspace"); return SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
return NULL;
} }
data = (PSP_RenderData *)SDL_calloc(1, sizeof(*data)); data = (PSP_RenderData *)SDL_calloc(1, sizeof(*data));
if (!data) { if (!data) {
PSP_DestroyRenderer(renderer); return -1;
return NULL;
} }
renderer->WindowEvent = PSP_WindowEvent; renderer->WindowEvent = PSP_WindowEvent;
@ -1406,7 +1395,7 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro
if (data->vsync) { if (data->vsync) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} }
return renderer; return 0;
} }
SDL_RenderDriver PSP_RenderDriver = { SDL_RenderDriver PSP_RenderDriver = {

View File

@ -1018,7 +1018,6 @@ static void SW_DestroyRenderer(SDL_Renderer *renderer)
SDL_DestroyWindowSurface(window); SDL_DestroyWindowSurface(window);
} }
SDL_free(data); SDL_free(data);
SDL_free(renderer);
} }
static void SW_SelectBestFormats(SDL_Renderer *renderer, SDL_PixelFormatEnum format) static void SW_SelectBestFormats(SDL_Renderer *renderer, SDL_PixelFormatEnum format)
@ -1116,27 +1115,20 @@ static void SW_SelectBestFormats(SDL_Renderer *renderer, SDL_PixelFormatEnum for
} }
} }
SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface, SDL_PropertiesID create_props) int SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, SDL_PropertiesID create_props)
{ {
SDL_Renderer *renderer;
SW_RenderData *data; SW_RenderData *data;
if (!surface) { if (!surface) {
SDL_InvalidParamError("surface"); return SDL_InvalidParamError("surface");
return NULL;
} }
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
renderer->software = SDL_TRUE; renderer->software = SDL_TRUE;
data = (SW_RenderData *)SDL_calloc(1, sizeof(*data)); data = (SW_RenderData *)SDL_calloc(1, sizeof(*data));
if (!data) { if (!data) {
SW_DestroyRenderer(renderer); SW_DestroyRenderer(renderer);
return NULL; return -1;
} }
data->surface = surface; data->surface = surface;
data->window = surface; data->window = surface;
@ -1172,27 +1164,18 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface, SDL_PropertiesID
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
SDL_SetError("Unsupported output colorspace");
SW_DestroyRenderer(renderer); SW_DestroyRenderer(renderer);
return NULL; return SDL_SetError("Unsupported output colorspace");
} }
return renderer; return 0;
} }
static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) static int SW_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
const char *hint;
SDL_Surface *surface;
SDL_bool no_hint_set;
/* Set the vsync hint based on our flags, if it's not already set */ /* Set the vsync hint based on our flags, if it's not already set */
hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC); const char *hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC);
if (!hint || !*hint) { const SDL_bool no_hint_set = (!hint || !*hint);
no_hint_set = SDL_TRUE;
} else {
no_hint_set = SDL_FALSE;
}
if (no_hint_set) { if (no_hint_set) {
if (SDL_GetBooleanProperty(create_props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { if (SDL_GetBooleanProperty(create_props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
@ -1202,7 +1185,7 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
} }
} }
surface = SDL_GetWindowSurface(window); SDL_Surface *surface = SDL_GetWindowSurface(window);
/* Reset the vsync hint if we set it above */ /* Reset the vsync hint if we set it above */
if (no_hint_set) { if (no_hint_set) {
@ -1210,10 +1193,10 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
} }
if (!surface) { if (!surface) {
return NULL; return -1;
} }
return SW_CreateRendererForSurface(surface, create_props); return SW_CreateRendererForSurface(renderer, surface, create_props);
} }
SDL_RenderDriver SW_RenderDriver = { SDL_RenderDriver SW_RenderDriver = {

View File

@ -22,6 +22,6 @@
#ifndef SDL_render_sw_c_h_ #ifndef SDL_render_sw_c_h_
#define SDL_render_sw_c_h_ #define SDL_render_sw_c_h_
extern SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface, SDL_PropertiesID create_props); extern int SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, SDL_PropertiesID create_props);
#endif /* SDL_render_sw_c_h_ */ #endif /* SDL_render_sw_c_h_ */

View File

@ -42,7 +42,7 @@
#include <psp2/sysmodule.h> #include <psp2/sysmodule.h>
#endif #endif
static SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props); static int VITA_GXM_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props);
static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event); static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event);
@ -210,29 +210,19 @@ static int VITA_GXM_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0; return 0;
} }
SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) static int VITA_GXM_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
SDL_Renderer *renderer;
VITA_GXM_RenderData *data; VITA_GXM_RenderData *data;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
SDL_SetError("Unsupported output colorspace"); return SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
return NULL;
} }
data = (VITA_GXM_RenderData *)SDL_calloc(1, sizeof(VITA_GXM_RenderData)); data = (VITA_GXM_RenderData *)SDL_calloc(1, sizeof(VITA_GXM_RenderData));
if (!data) { if (!data) {
SDL_free(renderer); return -1;
return NULL;
} }
renderer->WindowEvent = VITA_GXM_WindowEvent; renderer->WindowEvent = VITA_GXM_WindowEvent;
@ -281,11 +271,10 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID creat
if (gxm_init(renderer) != 0) { if (gxm_init(renderer) != 0) {
SDL_free(data); SDL_free(data);
SDL_free(renderer); return SDL_SetError("gxm_init failed");
return NULL;
} }
return renderer; return 0;
} }
static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event) static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
@ -1230,7 +1219,6 @@ static void VITA_GXM_DestroyRenderer(SDL_Renderer *renderer)
data->drawing = SDL_FALSE; data->drawing = SDL_FALSE;
SDL_free(data); SDL_free(data);
} }
SDL_free(renderer);
} }
#endif /* SDL_VIDEO_RENDER_VITA_GXM */ #endif /* SDL_VIDEO_RENDER_VITA_GXM */

View File

@ -1061,14 +1061,13 @@ static VkResult VULKAN_IssueBatch(VULKAN_RenderData *rendererData)
static void VULKAN_DestroyRenderer(SDL_Renderer *renderer) static void VULKAN_DestroyRenderer(SDL_Renderer *renderer)
{ {
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->driverdata; VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->driverdata;
if (rendererData->device != VK_NULL_HANDLE) {
vkDeviceWaitIdle(rendererData->device);
VULKAN_DestroyAll(renderer);
}
if (rendererData) { if (rendererData) {
if (rendererData->device != VK_NULL_HANDLE) {
vkDeviceWaitIdle(rendererData->device);
VULKAN_DestroyAll(renderer);
}
SDL_free(rendererData); SDL_free(rendererData);
} }
SDL_free(renderer);
} }
static VkBlendFactor GetBlendFactor(SDL_BlendFactor factor) static VkBlendFactor GetBlendFactor(SDL_BlendFactor factor)
@ -4037,30 +4036,21 @@ static int VULKAN_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0; return 0;
} }
SDL_Renderer *VULKAN_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) static int VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
SDL_Renderer *renderer;
VULKAN_RenderData *rendererData; VULKAN_RenderData *rendererData;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
SDL_SetupRendererColorspace(renderer, create_props); SDL_SetupRendererColorspace(renderer, create_props);
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB && if (renderer->output_colorspace != SDL_COLORSPACE_SRGB &&
renderer->output_colorspace != SDL_COLORSPACE_SRGB_LINEAR && renderer->output_colorspace != SDL_COLORSPACE_SRGB_LINEAR &&
renderer->output_colorspace != SDL_COLORSPACE_HDR10) { renderer->output_colorspace != SDL_COLORSPACE_HDR10) {
SDL_SetError("Unsupported output colorspace"); return SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
return NULL;
} }
rendererData = (VULKAN_RenderData *)SDL_calloc(1, sizeof(*rendererData)); rendererData = (VULKAN_RenderData *)SDL_calloc(1, sizeof(*rendererData));
if (!rendererData) { if (!rendererData) {
SDL_free(renderer); return -1;
return NULL;
} }
rendererData->identity = MatrixIdentity(); rendererData->identity = MatrixIdentity();
@ -4110,11 +4100,10 @@ SDL_Renderer *VULKAN_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_
/* Initialize Vulkan resources */ /* Initialize Vulkan resources */
if (VULKAN_CreateDeviceResources(renderer, create_props) != VK_SUCCESS) { if (VULKAN_CreateDeviceResources(renderer, create_props) != VK_SUCCESS) {
VULKAN_DestroyRenderer(renderer); VULKAN_DestroyRenderer(renderer);
return NULL; return -1;
} } else if (VULKAN_CreateWindowSizeDependentResources(renderer) != VK_SUCCESS) {
if (VULKAN_CreateWindowSizeDependentResources(renderer) != VK_SUCCESS) {
VULKAN_DestroyRenderer(renderer); VULKAN_DestroyRenderer(renderer);
return NULL; return -1;
} }
#if SDL_HAVE_YUV #if SDL_HAVE_YUV
@ -4127,7 +4116,7 @@ SDL_Renderer *VULKAN_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_
} }
#endif #endif
return renderer; return 0;
} }
SDL_RenderDriver VULKAN_RenderDriver = { SDL_RenderDriver VULKAN_RenderDriver = {

View File

@ -34,6 +34,7 @@
#include "../SDL_properties_c.h" #include "../SDL_properties_c.h"
#include "../timer/SDL_timer_c.h" #include "../timer/SDL_timer_c.h"
#include "../camera/SDL_camera_c.h" #include "../camera/SDL_camera_c.h"
#include "../render/SDL_sysrender.h"
#ifdef SDL_VIDEO_OPENGL #ifdef SDL_VIDEO_OPENGL
#include <SDL3/SDL_opengl.h> #include <SDL3/SDL_opengl.h>
@ -3649,7 +3650,7 @@ void SDL_DestroyWindow(SDL_Window *window)
SDL_Renderer *renderer = SDL_GetRenderer(window); SDL_Renderer *renderer = SDL_GetRenderer(window);
if (renderer) { if (renderer) {
SDL_DestroyRenderer(renderer); SDL_DestroyRendererWithoutFreeing(renderer);
} }
SDL_DestroyProperties(window->props); SDL_DestroyProperties(window->props);

View File

@ -1369,18 +1369,23 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
X11_XSync(display, False); X11_XSync(display, False);
X11_PumpEvents(_this); X11_PumpEvents(_this);
int x = data->last_xconfigure.x; /* If a configure event was received (type is non-zero), send the final window size and coordinates. */
int y = data->last_xconfigure.y; if (data->last_xconfigure.type) {
SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y); int x = data->last_xconfigure.x;
int y = data->last_xconfigure.y;
SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y);
/* If the borders appeared, this happened automatically in the event system, otherwise, set the position now. */ /* If the borders appeared, this happened automatically in the event system, otherwise, set the position now. */
if (data->disable_size_position_events && (window->x != x || window->y != y)) { if (data->disable_size_position_events && (window->x != x || window->y != y)) {
data->pending_operation = X11_PENDING_OP_MOVE; data->pending_operation = X11_PENDING_OP_MOVE;
X11_XMoveWindow(display, data->xwindow, window->x, window->y); X11_XMoveWindow(display, data->xwindow, window->x, window->y);
}
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, data->last_xconfigure.width, data->last_xconfigure.height);
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y);
} }
data->disable_size_position_events = SDL_FALSE; data->disable_size_position_events = SDL_FALSE;
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, data->last_xconfigure.width, data->last_xconfigure.height);
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y);
} }
void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)

View File

@ -247,7 +247,7 @@ if(FFmpeg_FOUND AND LIBAVUTIL_AVFRAME_HAS_CH_LAYOUT)
target_link_libraries(testffmpeg PRIVATE OpenGL::EGL) target_link_libraries(testffmpeg PRIVATE OpenGL::EGL)
target_compile_definitions(testffmpeg PRIVATE HAVE_EGL) target_compile_definitions(testffmpeg PRIVATE HAVE_EGL)
endif() endif()
target_include_directories(testffmpeg BEFORE PRIVATE ${SDL3_SOURCE_DIR}/src/video/khronos) target_include_directories(testffmpeg SYSTEM BEFORE PRIVATE ${SDL3_SOURCE_DIR}/src/video/khronos)
target_link_libraries(testffmpeg PRIVATE ${FFMPEG_LIBRARIES}) target_link_libraries(testffmpeg PRIVATE ${FFMPEG_LIBRARIES})
else() else()
message(STATUS "Can't find ffmpeg 5.1.3 or newer, skipping testffmpeg") message(STATUS "Can't find ffmpeg 5.1.3 or newer, skipping testffmpeg")

View File

@ -75,6 +75,10 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title)
static void destroyVideoSuiteTestWindow(SDL_Window *window) static void destroyVideoSuiteTestWindow(SDL_Window *window)
{ {
if (window != NULL) { if (window != NULL) {
SDL_Renderer *renderer = SDL_GetRenderer(window);
if (renderer) {
SDL_DestroyRenderer(renderer);
}
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
window = NULL; window = NULL;
SDLTest_AssertPass("Call to SDL_DestroyWindow()"); SDLTest_AssertPass("Call to SDL_DestroyWindow()");