From e6888ab04907d1c2d480a6b3547c2a6663d21ec5 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Thu, 5 Dec 2019 09:27:06 +0100 Subject: [PATCH] gamestates: create/destroy framebuffers on start/stop Games with lots of gamestates suffered due to lots of empty framebuffers being allocated, making window resize awfully slow and pointlessly eating plenty of RAM. --- src/internal.c | 9 +-------- src/libsuperderpy.c | 10 ++++++++++ src/mainloop.c | 7 +++++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/internal.c b/src/internal.c index 648c105..cf46c6d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -169,7 +169,7 @@ SYMBOL_INTERNAL void UnfreezeGamestates(struct Game* game) { SYMBOL_INTERNAL void ResizeGamestates(struct Game* game) { struct Gamestate* tmp = game->_priv.gamestates; while (tmp) { - if (tmp->open) { + if (tmp->started) { al_destroy_bitmap(tmp->fb); if (game->_priv.params.handlers.compositor) { tmp->fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h); @@ -366,11 +366,6 @@ SYMBOL_INTERNAL bool OpenGamestate(struct Game* game, struct Gamestate* gamestat return false; } #endif - if (game->_priv.params.handlers.compositor) { - gamestate->fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h); - } else { - gamestate->fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->clip_rect.x, game->clip_rect.y, game->clip_rect.w, game->clip_rect.h); - } gamestate->open = true; return true; } @@ -457,8 +452,6 @@ SYMBOL_INTERNAL void CloseGamestate(struct Game* game, struct Gamestate* gamesta #endif } #endif - al_destroy_bitmap(gamestate->fb); - gamestate->fb = NULL; gamestate->open = false; } diff --git a/src/libsuperderpy.c b/src/libsuperderpy.c index a487a7d..dc1fa6e 100644 --- a/src/libsuperderpy.c +++ b/src/libsuperderpy.c @@ -450,6 +450,12 @@ SYMBOL_EXPORT int libsuperderpy_start(struct Game* game) { game->_priv.loading.gamestate = AllocateGamestate(game, "loading"); } if (OpenGamestate(game, game->_priv.loading.gamestate, false) && LinkGamestate(game, game->_priv.loading.gamestate)) { + if (game->_priv.params.handlers.compositor) { + game->_priv.loading.gamestate->fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h); + } else { + game->_priv.loading.gamestate->fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->clip_rect.x, game->clip_rect.y, game->clip_rect.w, game->clip_rect.h); + } + game->_priv.loading.gamestate->data = (*game->_priv.loading.gamestate->api->load)(game, ProgressStub); game->_priv.loading.gamestate->loaded = true; PrintConsole(game, "Loading screen registered."); @@ -549,6 +555,10 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) { if (game->_priv.loading.gamestate->open && game->_priv.loading.gamestate->api) { (*game->_priv.loading.gamestate->api->unload)(game, game->_priv.loading.gamestate->data); } + if (game->_priv.loading.gamestate->fb) { + al_destroy_bitmap(game->_priv.loading.gamestate->fb); + game->_priv.loading.gamestate->fb = NULL; + } CloseGamestate(game, game->_priv.loading.gamestate); free(game->_priv.loading.gamestate->name); free(game->_priv.loading.gamestate); diff --git a/src/mainloop.c b/src/mainloop.c index 0d729ee..73087d8 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -299,6 +299,8 @@ static inline bool MainloopTick(struct Game* game) { (*tmp->api->stop)(game, tmp->data); tmp->started = false; tmp->pending_stop = false; + al_destroy_bitmap(tmp->fb); + tmp->fb = NULL; PrintConsole(game, "Gamestate \"%s\" stopped successfully.", tmp->name); } @@ -459,6 +461,11 @@ static inline bool MainloopTick(struct Game* game) { game->_priv.current_gamestate = tmp; tmp->started = true; tmp->pending_start = false; + if (game->_priv.params.handlers.compositor) { + tmp->fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h); + } else { + tmp->fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->clip_rect.x, game->clip_rect.y, game->clip_rect.w, game->clip_rect.h); + } (*tmp->api->start)(game, tmp->data); game->_priv.timestamp = al_get_time();