winsys: lazy initialize sfml to prevent global ctor races

master
q3k 2021-04-28 15:46:29 +02:00
parent e9debff163
commit 5f36ee14ed
2 changed files with 42 additions and 27 deletions

View File

@ -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<sf::RenderWindow>();
}
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;

View File

@ -36,10 +36,12 @@ private:
// sfml window
bool sfmlRenders;
sf::RenderWindow window;
std::unique_ptr<sf::RenderWindow> 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;
};