From 5f36ee14ed8285db3c9e65f9b168930418c8c009 Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Wed, 28 Apr 2021 15:46:29 +0200 Subject: [PATCH] winsys: lazy initialize sfml to prevent global ctor races --- src/winsys.cpp | 50 ++++++++++++++++++++++++++++++++------------------ src/winsys.h | 19 ++++++++++--------- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/winsys.cpp b/src/winsys.cpp index 657b705..d29d878 100644 --- a/src/winsys.cpp +++ b/src/winsys.cpp @@ -36,6 +36,7 @@ CWinsys Winsys; CWinsys::CWinsys() : numJoysticks(0) , sfmlRenders(false) + , window(nullptr) , auto_resolution(800, 600) , scale(1.f) { for (unsigned int i = 0; i < sf::Joystick::Count; i++) { @@ -44,18 +45,6 @@ CWinsys::CWinsys() else break; } - - sf::VideoMode desktopMode = sf::VideoMode::getDesktopMode(); - resolutions[0] = TScreenRes(desktopMode.width, desktopMode.height); - resolutions[1] = TScreenRes(800, 600); - resolutions[2] = TScreenRes(1024, 768); - resolutions[3] = TScreenRes(1152, 864); - resolutions[4] = TScreenRes(1280, 960); - resolutions[5] = TScreenRes(1280, 1024); - resolutions[6] = TScreenRes(1360, 768); - resolutions[7] = TScreenRes(1400, 1050); - resolutions[8] = TScreenRes(1440, 900); - resolutions[9] = TScreenRes(1680, 1050); } const TScreenRes& CWinsys::GetResolution(std::size_t idx) const { @@ -63,6 +52,13 @@ const TScreenRes& CWinsys::GetResolution(std::size_t idx) const { return resolutions[idx]; } +sf::RenderWindow &CWinsys::getWindow() { + if (window == nullptr) { + window = std::make_unique(); + } + return *window; +} + std::string CWinsys::GetResName(std::size_t idx) const { if (idx >= NUM_RESOLUTIONS) return "800 x 600"; if (idx == 0) return (Trans.Text(110)); @@ -96,15 +92,16 @@ void CWinsys::SetupVideoMode(const TScreenRes& res) { resolution = res; ResetRenderMode(); + auto w = &getWindow(); #ifdef USE_STENCIL_BUFFER sf::ContextSettings ctx(bpp, 8, 0, 1, 2); #else sf::ContextSettings ctx(bpp, 0, 0, 1, 2); #endif - window.create(sf::VideoMode(resolution.width, resolution.height, bpp), WINDOW_TITLE, style, ctx); + w->create(sf::VideoMode(resolution.width, resolution.height, bpp), WINDOW_TITLE, style, ctx); if (param.framerate) - window.setFramerateLimit(param.framerate); + w->setFramerateLimit(param.framerate); #ifdef _WIN32 HICON icon = LoadIcon(GetModuleHandle(NULL), (LPCWSTR)IDI_APPLICATION); SendMessageW(window.getSystemHandle(), WM_SETICON, ICON_BIG, (LPARAM)icon); @@ -124,18 +121,32 @@ void CWinsys::SetupVideoMode(int width, int height) { } void CWinsys::Init() { + sf::VideoMode desktopMode = sf::VideoMode::getDesktopMode(); + resolutions[0] = TScreenRes(desktopMode.width, desktopMode.height); + resolutions[1] = TScreenRes(800, 600); + resolutions[2] = TScreenRes(1024, 768); + resolutions[3] = TScreenRes(1152, 864); + resolutions[4] = TScreenRes(1280, 960); + resolutions[5] = TScreenRes(1280, 1024); + resolutions[6] = TScreenRes(1360, 768); + resolutions[7] = TScreenRes(1400, 1050); + resolutions[8] = TScreenRes(1440, 900); + resolutions[9] = TScreenRes(1680, 1050); + SetupVideoMode(GetResolution(param.res_type)); } void CWinsys::KeyRepeat(bool repeat) { - window.setKeyRepeatEnabled(repeat); + if (window != nullptr) + window->setKeyRepeatEnabled(repeat); } void CWinsys::Quit() { Score.SaveHighScore(); SaveMessages(); if (g_game.argument < 1) Players.SavePlayers(); - window.close(); + if (window != nullptr) + window->close(); } void CWinsys::Terminate() { @@ -165,9 +176,12 @@ void CWinsys::PrintJoystickInfo() const { } void CWinsys::TakeScreenshot() const { + if (window == nullptr) { + return; + } sf::Texture tex; - tex.create(window.getSize().x, window.getSize().y); - tex.update(window); + tex.create(window->getSize().x, window->getSize().y); + tex.update(*window); sf::Image img = tex.copyToImage(); std::string path = param.screenshot_dir; diff --git a/src/winsys.h b/src/winsys.h index 2957c75..bfd2799 100644 --- a/src/winsys.h +++ b/src/winsys.h @@ -36,10 +36,12 @@ private: // sfml window bool sfmlRenders; - sf::RenderWindow window; + std::unique_ptr window; TScreenRes resolutions[NUM_RESOLUTIONS]; TScreenRes auto_resolution; float CalcScreenScale() const; + + sf::RenderWindow &getWindow(); public: TScreenRes resolution; float scale; // scale factor for screen, see 'use_quad_scale' @@ -54,16 +56,15 @@ public: void SetupVideoMode(int width, int height); void KeyRepeat(bool repeat); void PrintJoystickInfo() const; - void ShowCursor(bool visible) { window.setMouseCursorVisible(visible); } - void SwapBuffers() { window.display(); } + void ShowCursor(bool visible) { getWindow().setMouseCursorVisible(visible); } + void SwapBuffers() { getWindow().display(); } void Quit(); void Terminate(); - void draw(const sf::Drawable& drawable, const sf::RenderStates& states = sf::RenderStates::Default) { window.draw(drawable, states); } - void clear() { window.clear(colBackgr); } - void beginSFML() { if (!sfmlRenders) window.pushGLStates(); sfmlRenders = true; } - void endSFML() { if (sfmlRenders) window.popGLStates(); sfmlRenders = false; } - bool PollEvent(sf::Event& event) { return window.pollEvent(event); } - const sf::Window& getWindow() const { return window; } + void draw(const sf::Drawable& drawable, const sf::RenderStates& states = sf::RenderStates::Default) { getWindow().draw(drawable, states); } + void clear() { getWindow().clear(colBackgr); } + void beginSFML() { if (!sfmlRenders) getWindow().pushGLStates(); sfmlRenders = true; } + void endSFML() { if (sfmlRenders) getWindow().popGLStates(); sfmlRenders = false; } + bool PollEvent(sf::Event& event) { return getWindow().pollEvent(event); } void TakeScreenshot() const; };