diff --git a/client/gui/CGuiHandler.cpp b/client/gui/CGuiHandler.cpp index ae4f9bdab..4bda96ae6 100644 --- a/client/gui/CGuiHandler.cpp +++ b/client/gui/CGuiHandler.cpp @@ -129,11 +129,10 @@ void CGuiHandler::renderFrame() CCS->curh->render(); - SDL_RenderPresent(mainRenderer); - windows().onFrameRendered(); } + SDL_RenderPresent(mainRenderer); framerate().framerateDelay(); // holds a constant FPS } diff --git a/client/gui/FramerateManager.cpp b/client/gui/FramerateManager.cpp index 59aa653e7..26757f96f 100644 --- a/client/gui/FramerateManager.cpp +++ b/client/gui/FramerateManager.cpp @@ -11,11 +11,15 @@ #include "StdInc.h" #include "FramerateManager.h" +#include "../../lib/CConfigHandler.h" +#include + FramerateManager::FramerateManager(int targetFrameRate) : targetFrameTime(Duration(boost::chrono::seconds(1)) / targetFrameRate) , lastFrameIndex(0) , lastFrameTimes({}) - , lastTimePoint (Clock::now()) + , lastTimePoint(Clock::now()) + , vsyncEnabled(settings["video"]["vsync"].Bool()) { boost::range::fill(lastFrameTimes, targetFrameTime); } @@ -24,9 +28,14 @@ void FramerateManager::framerateDelay() { Duration timeSpentBusy = Clock::now() - lastTimePoint; - // FPS is higher than it should be, then wait some time - if(timeSpentBusy < targetFrameTime) - boost::this_thread::sleep_for(targetFrameTime - timeSpentBusy); + if(!vsyncEnabled) + { + // if FPS is higher than it should be, then wait some time + if(timeSpentBusy < targetFrameTime) + { + boost::this_thread::sleep_for(targetFrameTime - timeSpentBusy); + } + } // compute actual timeElapsed taking into account actual sleep interval // limit it to 100 ms to avoid breaking animation in case of huge lag (e.g. triggered breakpoint) diff --git a/client/gui/FramerateManager.h b/client/gui/FramerateManager.h index 818e55f94..d653bd667 100644 --- a/client/gui/FramerateManager.h +++ b/client/gui/FramerateManager.h @@ -25,6 +25,8 @@ class FramerateManager /// index of last measured frome in lastFrameTimes array ui32 lastFrameIndex; + bool vsyncEnabled; + public: FramerateManager(int targetFramerate); diff --git a/client/renderSDL/ScreenHandler.cpp b/client/renderSDL/ScreenHandler.cpp index a513454b8..1371c51c7 100644 --- a/client/renderSDL/ScreenHandler.cpp +++ b/client/renderSDL/ScreenHandler.cpp @@ -274,8 +274,14 @@ void ScreenHandler::initializeWindow() handleFatalError(message, true); } - //create first available renderer if preferred not set. Use no flags, so HW accelerated will be preferred but SW renderer also will possible - mainRenderer = SDL_CreateRenderer(mainWindow, getPreferredRenderingDriver(), 0); + // create first available renderer if no preferred one is set + // use no SDL_RENDERER_SOFTWARE or SDL_RENDERER_ACCELERATED flag, so HW accelerated will be preferred but SW renderer will also be possible + uint32_t rendererFlags = 0; + if(settings["video"]["vsync"].Bool()) + { + rendererFlags |= SDL_RENDERER_PRESENTVSYNC; + } + mainRenderer = SDL_CreateRenderer(mainWindow, getPreferredRenderingDriver(), rendererFlags); if(mainRenderer == nullptr) throw std::runtime_error("Unable to create renderer\n"); @@ -570,4 +576,4 @@ bool ScreenHandler::hasFocus() { ui32 flags = SDL_GetWindowFlags(mainWindow); return flags & SDL_WINDOW_INPUT_FOCUS; -} \ No newline at end of file +} diff --git a/config/schemas/settings.json b/config/schemas/settings.json index ee7c69213..d0dedb7fe 100644 --- a/config/schemas/settings.json +++ b/config/schemas/settings.json @@ -149,7 +149,8 @@ "driver", "displayIndex", "showfps", - "targetfps" + "targetfps", + "vsync" ], "properties" : { "resolution" : { @@ -207,6 +208,10 @@ "targetfps" : { "type" : "number", "default" : 60 + }, + "vsync" : { + "type" : "boolean", + "default" : true } } }, diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index 9f00a369f..5ac6648c2 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -83,6 +83,8 @@ void CSettingsView::loadSettings() ui->spinBoxInterfaceScaling->setValue(settings["video"]["resolution"]["scaling"].Float()); ui->spinBoxFramerateLimit->setValue(settings["video"]["targetfps"].Float()); + ui->spinBoxFramerateLimit->setDisabled(settings["video"]["vsync"].Bool()); + ui->checkBoxVSync->setChecked(settings["video"]["vsync"].Bool()); ui->spinBoxReservedArea->setValue(std::round(settings["video"]["reservedWidth"].Float() * 100)); ui->comboBoxFriendlyAI->setCurrentText(QString::fromStdString(settings["server"]["friendlyAI"].String())); @@ -494,6 +496,13 @@ void CSettingsView::on_spinBoxFramerateLimit_valueChanged(int arg1) node->Float() = arg1; } +void CSettingsView::on_checkBoxVSync_stateChanged(int arg1) +{ + Settings node = settings.write["video"]["vsync"]; + node->Bool() = arg1; + ui->spinBoxFramerateLimit->setDisabled(settings["video"]["vsync"].Bool()); +} + void CSettingsView::on_comboBoxEnemyPlayerAI_currentTextChanged(const QString &arg1) { Settings node = settings.write["server"]["playerAI"]; diff --git a/launcher/settingsView/csettingsview_moc.h b/launcher/settingsView/csettingsview_moc.h index 5cc14c505..466901389 100644 --- a/launcher/settingsView/csettingsview_moc.h +++ b/launcher/settingsView/csettingsview_moc.h @@ -62,6 +62,8 @@ private slots: void on_spinBoxFramerateLimit_valueChanged(int arg1); + void on_checkBoxVSync_stateChanged(int arg1); + void on_comboBoxEnemyPlayerAI_currentTextChanged(const QString &arg1); void on_comboBoxAlliedPlayerAI_currentTextChanged(const QString &arg1); diff --git a/launcher/settingsView/csettingsview_moc.ui b/launcher/settingsView/csettingsview_moc.ui index 186689a6c..deae0833c 100644 --- a/launcher/settingsView/csettingsview_moc.ui +++ b/launcher/settingsView/csettingsview_moc.ui @@ -42,7 +42,6 @@ - 75 true @@ -107,20 +106,208 @@ 0 - -197 + -356 610 - 768 + 873 - - + + + + Heroes III Translation + + + + + + + + true + + + + General + + + + + + + Fullscreen + + + + + + + Interface Scaling + + + + + + + Autosave prefix + + + + + + + Adventure Map Allies + + + + + + + + true + + + + Video + + + + + + + 20 + + + 1000 + + + 10 + + + + + + + + true + + + + Artificial Intelligence + + + + + + + empty = map name prefix + + + + + + + true + + + + + + true + + + + + + + + + Autosave limit (0 = off) + + + + + + + + + + Additional repository + + + + + + + % + + + 0 + + + 25 + + + 1 + + + 0 + + + + + + + Show intro + + + + + + + 1 + + + + Off + + + + + On + + + + + + + + Enemy AI in battles + + + + + + VCAI + + + + VCAI + + + + + Nullkiller + + + + + false @@ -140,470 +327,13 @@ - - - - Display index - - - - - - - VCAI - - - - VCAI - - - - - Nullkiller - - - - - - - - Autosave limit (0 = off) - - - - - - - Fullscreen - - - - - - - Network port - - - - - - - - 75 - true - - - - General - - - - - - - Autosave - - - - - - - - Hardware - - - - - Software - - - - - - - - Show intro - - - - - - - - - - true - - - - - - - true - - - - - - true - - - - - - - 20 - - - 1000 - - - 10 - - - - - - - - - - Framerate Limit - - - - - - - - - - Adventure Map Enemies - - - - - - - Default repository - - - - - - - - - - 1 - - - - Off - - - - - On - - - - - - - - - 75 - true - - - - Video - - - - - - - Autosave prefix - - - - - - - Resolution - - - - + - - - - - - - true - - - - - - - Cursor - - - - - - - 1 - - - - Off - - - - - On - - - - - - - - Refresh now - - - - - - - - - - - - - - Heroes III Translation - - - - - - - 1 - - - - Off - - - - - On - - - - - - - - Enemy AI in battles - - - - - - - - 75 - true - - - - Mod Repositories - - - - - - - Additional repository - - - - - - - false - - - BattleAI - - - - BattleAI - - - - - StupidAI - - - - - - - - 50 - - - 400 - - - 10 - - - - - - - Heroes III Data Language - - - - - - - - - - Neutral AI in battles - - - - - - - Interface Scaling - - - - - - - 1024 - - - 65535 - - - 3030 - - - - - - - - - - - - - - Friendly AI in battles - - - - - - - VCMI Language - - - - - - - - - - Check on startup - - - - - - - BattleAI - - - - BattleAI - - - - - StupidAI - - - - - - - - Adventure Map Allies - - - - - - - - 75 - true - - - - Artificial Intelligence - - - - - - - VCAI - - - - VCAI - - - - - Nullkiller - - - - - - - - empty = map name prefix - - - @@ -635,6 +365,266 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use + + + + + + + Display index + + + + + + + VCAI + + + + VCAI + + + + + Nullkiller + + + + + + + + + + + + + + + Default repository + + + + + + + Heroes III Data Language + + + + + + + + + + true + + + + + + + Framerate Limit + + + + + + + Friendly AI in battles + + + + + + + VCMI Language + + + + + + + + + + true + + + + + + + + + + 50 + + + 400 + + + 10 + + + + + + + + + + + true + + + + Mod Repositories + + + + + + + + + + + + + + Resolution + + + + + + + 1024 + + + 65535 + + + 3030 + + + + + + + Autosave + + + + + + + Cursor + + + + + + + + Hardware + + + + + Software + + + + + + + + + + + Network port + + + + + + + false + + + BattleAI + + + + BattleAI + + + + + StupidAI + + + + + + + + 1 + + + + Off + + + + + On + + + + + + + + Refresh now + + + + + + + BattleAI + + + + BattleAI + + + + + StupidAI + + + + + + + + Check on startup + + + + + + + Neutral AI in battles + + + @@ -642,22 +632,41 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use - - - - % + + + + Adventure Map Enemies - - 0 - - - 25 - - + + + + + 1 - - 0 + + + Off + + + + + On + + + + + + + + VSync + + + + + + +