Fix #1223 (analogue mode segfault)

When `SDL_RenderReadPixels` fails for some reason, the game tries to
free the temporary source surface it creates. Unfortunately, it never
sets it to `NULL` after, so the next time the game tries to render the
filter, it'll try to work with a memory region that was already freed.

To fix this, I just replaced `SDL_FreeSurface(*src);` with
`VVV_freefunc(SDL_FreeSurface, *src);` which is a helper macro which
sets the pointer to NULL after freeing.

Now, there's a new issue -- since the temporary buffer is now NULL,
next frame we'll try to remake it! So I've introduced a static bool
which disables the filter entirely if `SDL_RenderReadPixels` fails.
Without this, it'd create and destroy a surface every frame, which
could lead to slowdown. (Not as slow as the filter when it DOES work,
but still...)

I also added a line which frees the second temporary surface... it's
weird that was missing in the first place, but I think reimplementing
analogue mode was one of the last things I did for the renderer
rewrite anyways.

Resolves #1223.
This commit is contained in:
NyakoFox 2025-04-28 01:03:17 -03:00 committed by Ethan Lee
parent 2ee5aef3fa
commit 6810c5fa8c

View file

@ -189,8 +189,15 @@ void UpdateFilter(void)
}
}
static bool disabled_filter = false;
void ApplyFilter(SDL_Surface** src, SDL_Surface** dest)
{
if (disabled_filter)
{
return;
}
if (src == NULL || dest == NULL)
{
SDL_assert(0 && "NULL src or dest!");
@ -214,7 +221,9 @@ void ApplyFilter(SDL_Surface** src, SDL_Surface** dest)
const int result = SDL_RenderReadPixels(gameScreen.m_renderer, NULL, 0, (*src)->pixels, (*src)->pitch);
if (result != 0)
{
SDL_FreeSurface(*src);
disabled_filter = true;
VVV_freefunc(SDL_FreeSurface, *src);
VVV_freefunc(SDL_FreeSurface, *dest);
WHINE_ONCE_ARGS(("Could not read pixels from renderer: %s", SDL_GetError()));
return;
}