Browse Source

Async loading

Does the loading on a separate thread, so we're
now loading while fading in and while updating
the progress bar.
pull/7523/head
Gleb Mazovetskiy 1 year ago committed by Anders Jenbo
parent
commit
f15fbcf61a
  1. 129
      Source/controls/touch/renderers.cpp
  2. 79
      Source/controls/touch/renderers.h
  3. 6
      Source/diablo.cpp
  4. 14
      Source/gamemenu.cpp
  5. 341
      Source/interfac.cpp
  6. 8
      Source/interfac.h
  7. 1
      Source/loadsave.cpp
  8. 4
      test/timedemo_test.cpp

129
Source/controls/touch/renderers.cpp

@ -90,7 +90,7 @@ VirtualGamepadButtonType GetStandButtonType(bool isPressed)
return isPressed ? GAMEPAD_STANDDOWN : GAMEPAD_STAND;
}
void LoadButtonArt(ButtonTexture *buttonArt, SDL_Renderer *renderer)
void LoadButtonArt(ButtonTexture *buttonArt)
{
constexpr unsigned Sprites = 13;
constexpr unsigned Frames = 2;
@ -100,14 +100,9 @@ void LoadButtonArt(ButtonTexture *buttonArt, SDL_Renderer *renderer)
buttonArt->numSprites = Sprites;
buttonArt->numFrames = Frames;
if (renderer != nullptr) {
buttonArt->texture.reset(SDL_CreateTextureFromSurface(renderer, buttonArt->surface.get()));
buttonArt->surface = nullptr;
}
}
void LoadPotionArt(ButtonTexture *potionArt, SDL_Renderer *renderer)
void LoadPotionArt(ButtonTexture *potionArt)
{
item_cursor_graphic potionGraphics[] {
ICURS_POTION_OF_HEALING,
@ -149,12 +144,7 @@ void LoadPotionArt(ButtonTexture *potionArt, SDL_Renderer *renderer)
potionArt->numFrames = sizeof(potionGraphics);
if (renderer == nullptr) {
potionArt->surface.reset(SDL_ConvertSurfaceFormat(surface.get(), SDL_PIXELFORMAT_ARGB8888, 0));
} else {
potionArt->texture.reset(SDL_CreateTextureFromSurface(renderer, surface.get()));
potionArt->surface = nullptr;
}
potionArt->surface.reset(SDL_ConvertSurfaceFormat(surface.get(), SDL_PIXELFORMAT_ARGB8888, 0));
}
bool InteractsWithCharButton(Point point)
@ -223,39 +213,24 @@ void RenderVirtualGamepad(SDL_Surface *surface)
Renderer.Render(renderFunction);
}
void VirtualGamepadRenderer::LoadArt(SDL_Renderer *renderer)
void VirtualGamepadRenderer::LoadArt()
{
menuPanelRenderer.LoadArt(renderer);
directionPadRenderer.LoadArt(renderer);
LoadButtonArt(&buttonArt, renderer);
LoadPotionArt(&potionArt, renderer);
menuPanelRenderer.LoadArt();
directionPadRenderer.LoadArt();
LoadButtonArt(&buttonArt);
LoadPotionArt(&potionArt);
}
void VirtualMenuPanelRenderer::LoadArt(SDL_Renderer *renderer)
void VirtualMenuPanelRenderer::LoadArt()
{
menuArt.surface.reset(LoadPNG("ui_art\\menu.png"));
menuArtLevelUp.surface.reset(LoadPNG("ui_art\\menu-levelup.png"));
if (renderer != nullptr) {
menuArt.texture.reset(SDL_CreateTextureFromSurface(renderer, menuArt.surface.get()));
menuArt.surface = nullptr;
menuArtLevelUp.texture.reset(SDL_CreateTextureFromSurface(renderer, menuArtLevelUp.surface.get()));
menuArtLevelUp.surface = nullptr;
}
}
void VirtualDirectionPadRenderer::LoadArt(SDL_Renderer *renderer)
void VirtualDirectionPadRenderer::LoadArt()
{
padArt.surface.reset(LoadPNG("ui_art\\directions.png"));
knobArt.surface.reset(LoadPNG("ui_art\\directions2.png"));
if (renderer != nullptr) {
padArt.texture.reset(SDL_CreateTextureFromSurface(renderer, padArt.surface.get()));
padArt.surface = nullptr;
knobArt.texture.reset(SDL_CreateTextureFromSurface(renderer, knobArt.surface.get()));
knobArt.surface = nullptr;
}
}
void VirtualGamepadRenderer::Render(RenderFunction renderFunction)
@ -516,25 +491,25 @@ void VirtualGamepadRenderer::UnloadArt()
{
menuPanelRenderer.UnloadArt();
directionPadRenderer.UnloadArt();
buttonArt.clear();
potionArt.clear();
buttonArt.clearSurface();
potionArt.clearSurface();
}
void VirtualMenuPanelRenderer::UnloadArt()
{
menuArt.clear();
menuArtLevelUp.clear();
menuArt.clearSurface();
menuArtLevelUp.clearSurface();
}
void VirtualDirectionPadRenderer::UnloadArt()
{
padArt.clear();
knobArt.clear();
padArt.clearSurface();
knobArt.clearSurface();
}
void InitVirtualGamepadGFX(SDL_Renderer *renderer)
void InitVirtualGamepadGFX()
{
Renderer.LoadArt(renderer);
Renderer.LoadArt();
}
void FreeVirtualGamepadGFX()
@ -542,4 +517,72 @@ void FreeVirtualGamepadGFX()
Renderer.UnloadArt();
}
void VirtualGamepadRenderer::createTextures(SDL_Renderer &renderer)
{
menuPanelRenderer.createTextures(renderer);
directionPadRenderer.createTextures(renderer);
if (buttonArt.surface != nullptr) {
buttonArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, buttonArt.surface.get()));
buttonArt.surface = nullptr;
}
if (potionArt.surface != nullptr) {
potionArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, potionArt.surface.get()));
potionArt.surface = nullptr;
}
}
void VirtualMenuPanelRenderer::createTextures(SDL_Renderer &renderer)
{
if (menuArt.surface != nullptr) {
menuArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, menuArt.surface.get()));
menuArt.surface = nullptr;
}
if (menuArtLevelUp.surface != nullptr) {
menuArtLevelUp.texture.reset(SDL_CreateTextureFromSurface(&renderer, menuArtLevelUp.surface.get()));
menuArtLevelUp.surface = nullptr;
}
}
void VirtualDirectionPadRenderer::createTextures(SDL_Renderer &renderer)
{
if (padArt.surface != nullptr) {
padArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, padArt.surface.get()));
padArt.surface = nullptr;
}
if (knobArt.surface != nullptr) {
knobArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, knobArt.surface.get()));
knobArt.surface = nullptr;
}
}
void VirtualGamepadRenderer::destroyTextures()
{
menuPanelRenderer.destroyTextures();
directionPadRenderer.destroyTextures();
buttonArt.destroyTexture();
potionArt.destroyTexture();
}
void VirtualMenuPanelRenderer::destroyTextures()
{
menuArt.destroyTexture();
menuArtLevelUp.destroyTexture();
}
void VirtualDirectionPadRenderer::destroyTextures()
{
padArt.destroyTexture();
knobArt.destroyTexture();
}
void InitVirtualGamepadTextures(SDL_Renderer &renderer)
{
Renderer.createTextures(renderer);
}
void FreeVirtualGamepadTextures()
{
Renderer.destroyTextures();
}
} // namespace devilution

79
Source/controls/touch/renderers.h

@ -61,12 +61,16 @@ struct ButtonTexture {
Size size() const;
void clear()
void clearSurface()
{
surface = nullptr;
texture = nullptr;
numFrames = 1;
}
void destroyTexture()
{
texture = nullptr;
}
};
typedef std::function<void(const ButtonTexture &art, SDL_Rect *src, SDL_Rect *dst)> RenderFunction;
@ -78,7 +82,23 @@ public:
{
}
void LoadArt(SDL_Renderer *renderer);
void LoadArt();
/**
* @brief Converts surfaces to textures.
*
* Must be called from the main thread.
*
* Per https://wiki.libsdl.org/SDL3/CategoryRender:
* > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986
*/
void createTextures(SDL_Renderer &renderer);
/**
* @brief Must be called from the main thread.
*/
void destroyTextures();
void Render(RenderFunction renderFunction);
void UnloadArt();
@ -95,7 +115,23 @@ public:
{
}
void LoadArt(SDL_Renderer *renderer);
void LoadArt();
/**
* @brief Converts surfaces to textures.
*
* Must be called from the main thread.
*
* Per https://wiki.libsdl.org/SDL3/CategoryRender:
* > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986
*/
void createTextures(SDL_Renderer &renderer);
/**
* @brief Must be called from the main thread.
*/
void destroyTextures();
void Render(RenderFunction renderFunction);
void UnloadArt();
@ -213,7 +249,23 @@ public:
{
}
void LoadArt(SDL_Renderer *renderer);
void LoadArt();
/**
* @brief Converts surfaces to textures.
*
* Must be called from the main thread.
*
* Per https://wiki.libsdl.org/SDL3/CategoryRender:
* > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986
*/
void createTextures(SDL_Renderer &renderer);
/**
* @brief Must be called from the main thread.
*/
void destroyTextures();
void Render(RenderFunction renderFunction);
void UnloadArt();
@ -234,7 +286,22 @@ private:
ButtonTexture potionArt;
};
void InitVirtualGamepadGFX(SDL_Renderer *renderer);
void InitVirtualGamepadGFX();
/**
* @brief Creates textures for the virtual gamepad.
*
* Must be called after `InitVirtualGamepadGFX`.
* Must be called from the main thread.
*
* Per https://wiki.libsdl.org/SDL3/CategoryRender:
* > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986
*/
void InitVirtualGamepadTextures(SDL_Renderer &renderer);
/** @brief Must be called from the main thread. */
void FreeVirtualGamepadTextures();
void RenderVirtualGamepad(SDL_Renderer *renderer);
void RenderVirtualGamepad(SDL_Surface *surface);
void FreeVirtualGamepadGFX();

6
Source/diablo.cpp

@ -1324,7 +1324,7 @@ void LoadAllGFX()
{
IncProgress();
#if !defined(USE_SDL1) && !defined(__vita__)
InitVirtualGamepadGFX(renderer);
InitVirtualGamepadGFX();
#endif
IncProgress();
InitObjectGFX();
@ -3044,7 +3044,7 @@ void LoadGameLevelSetLevel(bool firstflag, lvl_entry lvldir, const Player &myPla
IncProgress();
if (!HeadlessMode) {
#if !defined(USE_SDL1) && !defined(__vita__)
InitVirtualGamepadGFX(renderer);
InitVirtualGamepadGFX();
#endif
InitMissileGFX(gbIsHellfire);
IncProgress();
@ -3101,7 +3101,7 @@ void LoadGameLevelStandardLevel(bool firstflag, lvl_entry lvldir, const Player &
IncProgress();
#if !defined(USE_SDL1) && !defined(__vita__)
InitVirtualGamepadGFX(renderer);
InitVirtualGamepadGFX();
#endif
IncProgress();

14
Source/gamemenu.cpp

@ -19,6 +19,10 @@
#include "qol/floatingnumbers.h"
#include "utils/language.h"
#ifndef USE_SDL1
#include "controls/touch/renderers.h"
#endif
namespace devilution {
bool isGameMenuOpen = false;
@ -302,7 +306,17 @@ void gamemenu_load_game(bool /*bActivate*/)
InitDiabloMsg(EMSG_LOADING);
RedrawEverything();
DrawAndBlit();
#ifndef USE_SDL1
DeactivateVirtualGamepad();
FreeVirtualGamepadTextures();
#endif
LoadGame(false);
#if !defined(USE_SDL1) && !defined(__vita__)
if (renderer != nullptr) {
InitVirtualGamepadTextures(*renderer);
}
#endif
NewCursor(CURSOR_HAND);
ClrDiabloMsg();
CornerStone.activated = false;
PaletteFadeOut(8);

341
Source/interfac.cpp

@ -12,12 +12,10 @@
#include "control.h"
#include "engine.h"
#include "engine/clx_sprite.hpp"
#include "engine/demomode.h"
#include "engine/dx.h"
#include "engine/events.hpp"
#include "engine/load_cel.hpp"
#include "engine/load_clx.hpp"
#include "engine/load_pcx.hpp"
#include "engine/palette.h"
#include "engine/render/clx_render.hpp"
#include "hwcursor.hpp"
@ -26,12 +24,18 @@
#include "pfile.h"
#include "plrmsg.h"
#include "utils/sdl_geometry.h"
#include "utils/sdl_thread.h"
#ifndef USE_SDL1
#include "controls/touch/renderers.h"
#endif
namespace devilution {
namespace {
constexpr uint32_t MaxProgress = 534;
constexpr uint32_t ProgressStepSize = 23;
OptionalOwnedClxSpriteList sgpBackCel;
@ -225,118 +229,18 @@ void DrawCutsceneForeground()
RenderPresent();
}
} // namespace
void RegisterCustomEvents()
{
#ifndef USE_SDL1
CustomEventsBegin = SDL_RegisterEvents(NumCustomEvents);
#endif
}
bool IsCustomEvent(SdlEventType eventType)
{
return eventType >= CustomEventsBegin && eventType < CustomEventsBegin + NumCustomEvents;
}
interface_mode GetCustomEvent(SdlEventType eventType)
{
return static_cast<interface_mode>(eventType - CustomEventsBegin);
}
SdlEventType CustomEventToSdlEvent(interface_mode eventType)
void DoLoad(interface_mode uMsg)
{
return CustomEventsBegin + eventType;
}
void interface_msg_pump()
{
SDL_Event event;
uint16_t modState;
while (FetchMessage(&event, &modState)) {
if (event.type != SDL_QUIT) {
HandleMessage(event, modState);
}
}
}
void IncProgress()
{
if (!HeadlessMode && !demo::IsRunning())
interface_msg_pump();
if (!IsProgress)
return;
sgdwProgress += 23;
if (sgdwProgress > MaxProgress)
sgdwProgress = MaxProgress;
if (!HeadlessMode && !demo::IsRunning())
DrawCutsceneForeground();
}
void CompleteProgress()
{
if (HeadlessMode)
return;
if (!IsProgress)
return;
while (sgdwProgress < MaxProgress)
IncProgress();
}
void ShowProgress(interface_mode uMsg)
{
IsProgress = true;
gbSomebodyWonGameKludge = false;
uint32_t delayStart = SDL_GetTicks();
EventHandler previousHandler = SetEventHandler(DisableInputEventHandler);
if (!HeadlessMode) {
assert(ghMainWnd);
interface_msg_pump();
ClearScreenBuffer();
scrollrt_draw_game_screen();
if (IsHardwareCursor())
SetHardwareCursorVisible(false);
BlackPalette();
// Blit the background once and then free it.
LoadCutsceneBackground(uMsg);
DrawCutsceneBackground();
if (RenderDirectlyToOutputSurface && PalSurface != nullptr) {
// Render into all the backbuffers if there are multiple.
const void *initialPixels = PalSurface->pixels;
if (DiabloUiSurface() == PalSurface)
BltFast(nullptr, nullptr);
RenderPresent();
while (PalSurface->pixels != initialPixels) {
DrawCutsceneBackground();
if (DiabloUiSurface() == PalSurface)
BltFast(nullptr, nullptr);
RenderPresent();
}
}
FreeCutsceneBackground();
PaletteFadeIn(8);
IncProgress();
sound_init();
IncProgress();
}
IncProgress();
sound_init();
IncProgress();
Player &myPlayer = *MyPlayer;
switch (uMsg) {
case WM_DIABLOADGAME:
IncProgress();
IncProgress();
IncProgress(2);
LoadGame(true);
IncProgress();
IncProgress();
IncProgress(2);
break;
case WM_DIABNEWGAME:
myPlayer.pOriginalCathedral = !gbIsHellfire;
@ -477,37 +381,228 @@ void ShowProgress(interface_mode uMsg)
LoadGameLevel(false, ENTRY_MAIN);
IncProgress();
break;
default:
app_fatal("Unknown progress mode");
}
SDL_Event event;
event.type = CustomEventToSdlEvent(WM_DONE);
SDL_PushEvent(&event);
}
struct {
uint32_t delayStart;
EventHandler prevHandler;
bool done;
std::array<SDL_Color, 256> palette;
} ProgressEventHandlerState;
void ProgressEventHandler(const SDL_Event &event, uint16_t modState)
{
DisableInputEventHandler(event, modState);
if (!IsCustomEvent(event.type)) return;
static uint32_t drawnProgress;
drawnProgress = 0;
const interface_mode customEvent = GetCustomEvent(event.type);
switch (customEvent) {
case WM_PROGRESS:
if (!HeadlessMode && drawnProgress != sgdwProgress) {
DrawCutsceneForeground();
drawnProgress = sgdwProgress;
}
break;
case WM_DONE: {
// We may have loaded a new palette.
// Temporarily switch back to the load screen palette for fade out.
std::array<SDL_Color, 256> prevPalette;
if (!HeadlessMode) {
prevPalette = orig_palette;
orig_palette = ProgressEventHandlerState.palette;
ApplyGamma(logical_palette, orig_palette, 256);
}
NewCursor(CURSOR_HAND);
if (!HeadlessMode) {
assert(ghMainWnd);
if (RenderDirectlyToOutputSurface && PalSurface != nullptr) {
// Ensure that all back buffers have the full progress bar.
const void *initialPixels = PalSurface->pixels;
do {
DrawCutsceneForeground();
if (DiabloUiSurface() == PalSurface)
BltFast(nullptr, nullptr);
RenderPresent();
} while (PalSurface->pixels != initialPixels);
}
PaletteFadeOut(8);
orig_palette = prevPalette;
ApplyGamma(logical_palette, orig_palette, 256);
}
[[maybe_unused]] EventHandler prevHandler = SetEventHandler(ProgressEventHandlerState.prevHandler);
assert(prevHandler == ProgressEventHandler);
ProgressEventHandlerState.prevHandler = nullptr;
IsProgress = false;
Player &myPlayer = *MyPlayer;
NetSendCmdLocParam2(true, CMD_PLAYER_JOINLEVEL, myPlayer.position.tile, myPlayer.plrlevel, myPlayer.plrIsOnSetLevel ? 1 : 0);
DelayPlrMessages(SDL_GetTicks() - ProgressEventHandlerState.delayStart);
if (gbSomebodyWonGameKludge && myPlayer.isOnLevel(16)) {
PrepDoEnding();
}
gbSomebodyWonGameKludge = false;
ProgressEventHandlerState.done = true;
#if !defined(USE_SDL1) && !defined(__vita__)
if (renderer != nullptr) {
InitVirtualGamepadTextures(*renderer);
}
#endif
} break;
default:
app_fatal("Unknown progress mode");
break;
}
}
} // namespace
void RegisterCustomEvents()
{
#ifndef USE_SDL1
CustomEventsBegin = SDL_RegisterEvents(NumCustomEvents);
#endif
}
bool IsCustomEvent(SdlEventType eventType)
{
return eventType >= CustomEventsBegin && eventType < CustomEventsBegin + NumCustomEvents;
}
interface_mode GetCustomEvent(SdlEventType eventType)
{
return static_cast<interface_mode>(eventType - CustomEventsBegin);
}
SdlEventType CustomEventToSdlEvent(interface_mode eventType)
{
return CustomEventsBegin + eventType;
}
void interface_msg_pump()
{
SDL_Event event;
uint16_t modState;
while (FetchMessage(&event, &modState)) {
if (event.type != SDL_QUIT) {
HandleMessage(event, modState);
}
}
}
void IncProgress(uint32_t steps)
{
if (!IsProgress)
return;
const uint32_t prevProgress = sgdwProgress;
sgdwProgress += ProgressStepSize * steps;
if (sgdwProgress > MaxProgress)
sgdwProgress = MaxProgress;
if (!HeadlessMode && sgdwProgress != prevProgress) {
SDL_Event event;
event.type = CustomEventToSdlEvent(WM_PROGRESS);
SDL_PushEvent(&event);
}
}
void CompleteProgress()
{
if (HeadlessMode)
return;
if (!IsProgress)
return;
if (sgdwProgress < MaxProgress) {
IncProgress((MaxProgress - sgdwProgress) / ProgressStepSize);
}
}
void ShowProgress(interface_mode uMsg)
{
IsProgress = true;
gbSomebodyWonGameKludge = false;
ProgressEventHandlerState.delayStart = SDL_GetTicks();
ProgressEventHandlerState.prevHandler = SetEventHandler(ProgressEventHandler);
ProgressEventHandlerState.done = false;
#ifndef USE_SDL1
DeactivateVirtualGamepad();
FreeVirtualGamepadTextures();
#endif
if (!HeadlessMode) {
assert(ghMainWnd);
interface_msg_pump();
ClearScreenBuffer();
scrollrt_draw_game_screen();
if (IsHardwareCursor())
SetHardwareCursorVisible(false);
BlackPalette();
// Blit the background once and then free it.
LoadCutsceneBackground(uMsg);
DrawCutsceneBackground();
ProgressEventHandlerState.palette = orig_palette;
if (RenderDirectlyToOutputSurface && PalSurface != nullptr) {
// Ensure that all back buffers have the full progress bar.
// Render into all the backbuffers if there are multiple.
const void *initialPixels = PalSurface->pixels;
do {
DrawCutsceneForeground();
if (DiabloUiSurface() == PalSurface)
BltFast(nullptr, nullptr);
RenderPresent();
while (PalSurface->pixels != initialPixels) {
DrawCutsceneBackground();
if (DiabloUiSurface() == PalSurface)
BltFast(nullptr, nullptr);
RenderPresent();
} while (PalSurface->pixels != initialPixels);
}
}
PaletteFadeOut(8);
FreeCutsceneBackground();
}
previousHandler = SetEventHandler(previousHandler);
assert(previousHandler == DisableInputEventHandler);
IsProgress = false;
NetSendCmdLocParam2(true, CMD_PLAYER_JOINLEVEL, myPlayer.position.tile, myPlayer.plrlevel, myPlayer.plrIsOnSetLevel ? 1 : 0);
DelayPlrMessages(SDL_GetTicks() - delayStart);
// Begin loading
static interface_mode loadTarget;
loadTarget = uMsg;
SdlThread loadThread = SdlThread([]() {
DoLoad(loadTarget);
});
if (gbSomebodyWonGameKludge && myPlayer.isOnLevel(16)) {
PrepDoEnding();
if (!HeadlessMode) {
PaletteFadeIn(8);
}
gbSomebodyWonGameKludge = false;
while (true) {
SDL_Event event;
// We use the real `SDL_PollEvent` here instead of `FetchEvent`
// to process real events rather than the recorded ones in demo mode.
while (SDL_PollEvent(&event)) {
if (event.type != SDL_QUIT) {
HandleMessage(event, SDL_GetModState());
}
if (ProgressEventHandlerState.done) {
loadThread.join();
return;
}
}
}
}
} // namespace devilution

8
Source/interfac.h

@ -26,8 +26,12 @@ enum interface_mode : uint8_t {
WM_DIABNEWGAME,
WM_DIABLOADGAME,
// Asynchronous loading events.
WM_PROGRESS,
WM_DONE,
WM_FIRST = WM_DIABNEXTLVL,
WM_LAST = WM_DIABLOADGAME,
WM_LAST = WM_DONE,
};
void RegisterCustomEvents();
@ -59,7 +63,7 @@ enum Cutscenes : uint8_t {
};
void interface_msg_pump();
void IncProgress();
void IncProgress(uint32_t steps = 1);
void CompleteProgress();
void ShowProgress(interface_mode uMsg);

1
Source/loadsave.cpp

@ -2552,7 +2552,6 @@ void LoadGame(bool firstflag)
SetUpMissileAnimationData();
RedoMissileFlags();
NewCursor(CURSOR_HAND);
gbProcessPlayers = IsDiabloAlive(!firstflag);
if (gbIsHellfireSaveGame != gbIsHellfire) {

4
test/timedemo_test.cpp

@ -23,6 +23,9 @@ bool Dummy_GetHeroInfo(_uiheroinfo *pInfo)
void RunTimedemo(std::string timedemoFolderName)
{
if (SDL_Init(SDL_INIT_EVENTS) <= -1) {
ErrSdl();
}
std::string unitTestFolderCompletePath = paths::BasePath() + "/test/fixtures/timedemo/" + timedemoFolderName;
paths::SetPrefPath(unitTestFolderCompletePath);
paths::SetConfigPath(unitTestFolderCompletePath);
@ -72,6 +75,7 @@ void RunTimedemo(std::string timedemoFolderName)
ASSERT_FALSE(gbRunGame);
gbRunGame = false;
init_cleanup();
SDL_Quit();
}
} // namespace

Loading…
Cancel
Save