mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-23 01:59:43 +01:00
Fix memory leak with ApplyFilter
The intention of the recent refactor was to make it so that the temporary surfaces would be allocated only once, when the mode is enabled, and be freed upon exit. To do this, Graphics.cpp owns the pointers, and passes them to ApplyFilter to modify. Except ApplyFilter doesn't actually modify the pointers, because it's only a single pointer, not a pointer-to-pointer. So every frame of rendering it would actually be creating a new surface and leaking memory. To fix this, they need to be pointer-to-pointer variables that get modified. I also added error logs in case the surface creation failed.
This commit is contained in:
parent
791310fa5d
commit
ea1a014145
3 changed files with 27 additions and 20 deletions
|
@ -3244,7 +3244,7 @@ void Graphics::screenshake(void)
|
||||||
{
|
{
|
||||||
if (gameScreen.badSignalEffect)
|
if (gameScreen.badSignalEffect)
|
||||||
{
|
{
|
||||||
ApplyFilter(tempFilterSrc, tempFilterDest);
|
ApplyFilter(&tempFilterSrc, &tempFilterDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_render_target(tempShakeTexture);
|
set_render_target(tempShakeTexture);
|
||||||
|
@ -3282,7 +3282,7 @@ void Graphics::render(void)
|
||||||
{
|
{
|
||||||
if (gameScreen.badSignalEffect)
|
if (gameScreen.badSignalEffect)
|
||||||
{
|
{
|
||||||
ApplyFilter(tempFilterSrc, tempFilterDest);
|
ApplyFilter(&tempFilterSrc, &tempFilterDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_render_target(NULL);
|
set_render_target(NULL);
|
||||||
|
|
|
@ -144,43 +144,50 @@ void UpdateFilter(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyFilter(SDL_Surface* src, SDL_Surface* dest)
|
void ApplyFilter(SDL_Surface** src, SDL_Surface** dest)
|
||||||
{
|
{
|
||||||
if (src == NULL)
|
|
||||||
{
|
|
||||||
src = SDL_CreateRGBSurface(0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS, 32, 0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
if (dest == NULL)
|
|
||||||
{
|
|
||||||
dest = SDL_CreateRGBSurface(0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS, 32, 0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
if (src == NULL || dest == NULL)
|
if (src == NULL || dest == NULL)
|
||||||
{
|
{
|
||||||
|
SDL_assert(0 && "NULL src or dest!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int result = SDL_RenderReadPixels(gameScreen.m_renderer, NULL, 0, src->pixels, src->pitch);
|
if (*src == NULL)
|
||||||
|
{
|
||||||
|
*src = SDL_CreateRGBSurface(0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS, 32, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
if (*dest == NULL)
|
||||||
|
{
|
||||||
|
*dest = SDL_CreateRGBSurface(0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS, 32, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
if (*src == NULL || *dest == NULL)
|
||||||
|
{
|
||||||
|
WHINE_ONCE_ARGS(("Could not create temporary surfaces: %s", SDL_GetError()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int result = SDL_RenderReadPixels(gameScreen.m_renderer, NULL, 0, (*src)->pixels, (*src)->pitch);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
SDL_FreeSurface(src);
|
SDL_FreeSurface(*src);
|
||||||
WHINE_ONCE_ARGS(("Could not read pixels from renderer: %s", SDL_GetError()));
|
WHINE_ONCE_ARGS(("Could not read pixels from renderer: %s", SDL_GetError()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int red_offset = rand() % 4;
|
const int red_offset = rand() % 4;
|
||||||
|
|
||||||
for (int x = 0; x < src->w; x++)
|
for (int x = 0; x < (*src)->w; x++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < src->h; y++)
|
for (int y = 0; y < (*src)->h; y++)
|
||||||
{
|
{
|
||||||
const int sampley = (y + (int) graphics.lerp(oldscrollamount, scrollamount)) % 240;
|
const int sampley = (y + (int) graphics.lerp(oldscrollamount, scrollamount)) % 240;
|
||||||
|
|
||||||
const SDL_Color pixel = ReadPixel(src, x, sampley);
|
const SDL_Color pixel = ReadPixel(*src, x, sampley);
|
||||||
|
|
||||||
Uint8 green = pixel.g;
|
Uint8 green = pixel.g;
|
||||||
Uint8 blue = pixel.b;
|
Uint8 blue = pixel.b;
|
||||||
|
|
||||||
const SDL_Color pixel_offset = ReadPixel(src, SDL_min(x + red_offset, 319), sampley);
|
const SDL_Color pixel_offset = ReadPixel(*src, SDL_min(x + red_offset, 319), sampley);
|
||||||
Uint8 red = pixel_offset.r;
|
Uint8 red = pixel_offset.r;
|
||||||
|
|
||||||
double mult;
|
double mult;
|
||||||
|
@ -216,9 +223,9 @@ void ApplyFilter(SDL_Surface* src, SDL_Surface* dest)
|
||||||
blue = SDL_max(blue - (distX + distY), 0);
|
blue = SDL_max(blue - (distX + distY), 0);
|
||||||
|
|
||||||
const SDL_Color color = {red, green, blue, pixel.a};
|
const SDL_Color color = {red, green, blue, pixel.a};
|
||||||
DrawPixel(dest, x, y, color);
|
DrawPixel(*dest, x, y, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UpdateTexture(graphics.gameTexture, NULL, dest->pixels, dest->pitch);
|
SDL_UpdateTexture(graphics.gameTexture, NULL, (*dest)->pixels, (*dest)->pitch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,6 @@ void DrawPixel(SDL_Surface* surface, int x, int y, SDL_Color color);
|
||||||
SDL_Color ReadPixel(const SDL_Surface* surface, int x, int y);
|
SDL_Color ReadPixel(const SDL_Surface* surface, int x, int y);
|
||||||
|
|
||||||
void UpdateFilter(void);
|
void UpdateFilter(void);
|
||||||
void ApplyFilter(SDL_Surface* src, SDL_Surface* dest);
|
void ApplyFilter(SDL_Surface** src, SDL_Surface** dest);
|
||||||
|
|
||||||
#endif /* GRAPHICSUTIL_H */
|
#endif /* GRAPHICSUTIL_H */
|
||||||
|
|
Loading…
Reference in a new issue