From 4fdbac72075a94c4c42e4a641d07da5b0cc921ac Mon Sep 17 00:00:00 2001
From: Ethan Lee <[EMAIL REDACTED]>
Date: Mon, 24 Nov 2025 01:04:49 -0500
Subject: [PATCH] video: Explicitly call DestroyWindowTexture when destroying a
window.
This prevents some recursion issues with hashtables, as described in #14499.
---
src/video/SDL_video.c | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 77a81143f99dd..fdb40352ce8ea 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -295,20 +295,6 @@ static Uint32 SDL_DefaultGraphicsBackends(SDL_VideoDevice *_this)
return 0;
}
-static void SDLCALL SDL_CleanupWindowTextureData(void *userdata, void *value)
-{
- SDL_WindowTextureData *data = (SDL_WindowTextureData *)value;
-
- if (data->texture) {
- SDL_DestroyTexture(data->texture);
- }
- if (data->renderer) {
- SDL_DestroyRenderer(data->renderer);
- }
- SDL_free(data->pixels);
- SDL_free(data);
-}
-
static bool SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, SDL_PixelFormat *format, void **pixels, int *pitch)
{
SDL_PropertiesID props = SDL_GetWindowProperties(window);
@@ -399,7 +385,7 @@ static bool SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window,
SDL_DestroyRenderer(renderer);
return false;
}
- if (!SDL_SetPointerPropertyWithCleanup(props, SDL_PROP_WINDOW_TEXTUREDATA_POINTER, data, SDL_CleanupWindowTextureData, NULL)) {
+ if (!SDL_SetPointerProperty(props, SDL_PROP_WINDOW_TEXTUREDATA_POINTER, data)) {
SDL_DestroyRenderer(renderer);
return false;
}
@@ -526,7 +512,21 @@ static bool SDL_UpdateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window,
static void SDL_DestroyWindowTexture(SDL_VideoDevice *_this, SDL_Window *window)
{
- SDL_ClearProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_TEXTUREDATA_POINTER);
+ SDL_PropertiesID props = SDL_GetWindowProperties(window);
+ if (SDL_HasProperty(props, SDL_PROP_WINDOW_TEXTUREDATA_POINTER)) {
+ SDL_WindowTextureData *data = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_TEXTUREDATA_POINTER, NULL);
+
+ if (data->texture) {
+ SDL_DestroyTexture(data->texture);
+ }
+ if (data->renderer) {
+ SDL_DestroyRenderer(data->renderer);
+ }
+ SDL_free(data->pixels);
+ SDL_free(data);
+
+ SDL_ClearProperty(props, SDL_PROP_WINDOW_TEXTUREDATA_POINTER);
+ }
}
static SDL_VideoDevice *_this = NULL;
@@ -4291,6 +4291,8 @@ void SDL_DestroyWindow(SDL_Window *window)
}
SDL_DestroyProperties(window->text_input_props);
+
+ SDL_DestroyWindowTexture(_this, window);
SDL_DestroyProperties(window->props);
/* Clear the modal status, but don't unset the parent just yet, as it