mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-29 16:09:13 +00:00
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.
This commit is contained in:
parent
39c8434f5f
commit
cab3defc18
3 changed files with 33 additions and 7 deletions
|
@ -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_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) { \
|
||||
SDL_InvalidParamError("renderer"); \
|
||||
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) \
|
||||
if (!(texture) || (texture)->magic != &SDL_texture_magic) { \
|
||||
SDL_InvalidParamError("texture"); \
|
||||
|
@ -4517,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);
|
||||
|
||||
|
@ -4540,15 +4550,25 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer)
|
|||
SDL_ClearProperty(SDL_GetWindowProperties(renderer->window), SDL_PROP_WINDOW_RENDERER_POINTER);
|
||||
}
|
||||
|
||||
/* It's no longer magical... */
|
||||
renderer->magic = NULL;
|
||||
|
||||
/* Free the target mutex */
|
||||
SDL_DestroyMutex(renderer->target_mutex);
|
||||
renderer->target_mutex = NULL;
|
||||
|
||||
/* Clean up renderer-specific resources */
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue