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.
This commit is contained in:
Sebastian Krzyszkowiak 2019-12-05 09:27:06 +01:00
parent 3dd72ec389
commit e6888ab049
No known key found for this signature in database
GPG key ID: E8F235CF3BDBC3FF
3 changed files with 18 additions and 8 deletions

View file

@ -169,7 +169,7 @@ SYMBOL_INTERNAL void UnfreezeGamestates(struct Game* game) {
SYMBOL_INTERNAL void ResizeGamestates(struct Game* game) { SYMBOL_INTERNAL void ResizeGamestates(struct Game* game) {
struct Gamestate* tmp = game->_priv.gamestates; struct Gamestate* tmp = game->_priv.gamestates;
while (tmp) { while (tmp) {
if (tmp->open) { if (tmp->started) {
al_destroy_bitmap(tmp->fb); al_destroy_bitmap(tmp->fb);
if (game->_priv.params.handlers.compositor) { if (game->_priv.params.handlers.compositor) {
tmp->fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h); 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; return false;
} }
#endif #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; gamestate->open = true;
return true; return true;
} }
@ -457,8 +452,6 @@ SYMBOL_INTERNAL void CloseGamestate(struct Game* game, struct Gamestate* gamesta
#endif #endif
} }
#endif #endif
al_destroy_bitmap(gamestate->fb);
gamestate->fb = NULL;
gamestate->open = false; gamestate->open = false;
} }

View file

@ -450,6 +450,12 @@ SYMBOL_EXPORT int libsuperderpy_start(struct Game* game) {
game->_priv.loading.gamestate = AllocateGamestate(game, "loading"); game->_priv.loading.gamestate = AllocateGamestate(game, "loading");
} }
if (OpenGamestate(game, game->_priv.loading.gamestate, false) && LinkGamestate(game, game->_priv.loading.gamestate)) { 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->data = (*game->_priv.loading.gamestate->api->load)(game, ProgressStub);
game->_priv.loading.gamestate->loaded = true; game->_priv.loading.gamestate->loaded = true;
PrintConsole(game, "Loading screen registered."); 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) { if (game->_priv.loading.gamestate->open && game->_priv.loading.gamestate->api) {
(*game->_priv.loading.gamestate->api->unload)(game, game->_priv.loading.gamestate->data); (*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); CloseGamestate(game, game->_priv.loading.gamestate);
free(game->_priv.loading.gamestate->name); free(game->_priv.loading.gamestate->name);
free(game->_priv.loading.gamestate); free(game->_priv.loading.gamestate);

View file

@ -299,6 +299,8 @@ static inline bool MainloopTick(struct Game* game) {
(*tmp->api->stop)(game, tmp->data); (*tmp->api->stop)(game, tmp->data);
tmp->started = false; tmp->started = false;
tmp->pending_stop = false; tmp->pending_stop = false;
al_destroy_bitmap(tmp->fb);
tmp->fb = NULL;
PrintConsole(game, "Gamestate \"%s\" stopped successfully.", tmp->name); PrintConsole(game, "Gamestate \"%s\" stopped successfully.", tmp->name);
} }
@ -459,6 +461,11 @@ static inline bool MainloopTick(struct Game* game) {
game->_priv.current_gamestate = tmp; game->_priv.current_gamestate = tmp;
tmp->started = true; tmp->started = true;
tmp->pending_start = false; 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); (*tmp->api->start)(game, tmp->data);
game->_priv.timestamp = al_get_time(); game->_priv.timestamp = al_get_time();