2023-05-12 23:15:48 +02:00
|
|
|
/*
|
|
|
|
* FramerateManager.h, part of VCMI engine
|
|
|
|
*
|
|
|
|
* Authors: listed in file AUTHORS in main folder
|
|
|
|
*
|
|
|
|
* License: GNU General Public License v2.0 or later
|
|
|
|
* Full text of license available in license.txt file, in main folder
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "StdInc.h"
|
|
|
|
#include "FramerateManager.h"
|
|
|
|
|
2023-09-26 17:28:44 +02:00
|
|
|
#include "../../lib/CConfigHandler.h"
|
|
|
|
|
2023-05-13 00:12:11 +02:00
|
|
|
FramerateManager::FramerateManager(int targetFrameRate)
|
|
|
|
: targetFrameTime(Duration(boost::chrono::seconds(1)) / targetFrameRate)
|
|
|
|
, lastFrameIndex(0)
|
|
|
|
, lastFrameTimes({})
|
2023-09-26 17:28:44 +02:00
|
|
|
, lastTimePoint(Clock::now())
|
|
|
|
, vsyncEnabled(settings["video"]["vsync"].Bool())
|
2023-05-12 23:15:48 +02:00
|
|
|
{
|
2023-05-13 00:12:11 +02:00
|
|
|
boost::range::fill(lastFrameTimes, targetFrameTime);
|
2023-05-12 23:15:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FramerateManager::framerateDelay()
|
|
|
|
{
|
2023-09-26 17:28:44 +02:00
|
|
|
if(!vsyncEnabled)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2023-05-12 23:15:48 +02:00
|
|
|
|
2023-05-13 00:12:11 +02:00
|
|
|
// compute actual timeElapsed taking into account actual sleep interval
|
2023-05-12 23:15:48 +02:00
|
|
|
// limit it to 100 ms to avoid breaking animation in case of huge lag (e.g. triggered breakpoint)
|
2023-05-13 00:12:11 +02:00
|
|
|
TimePoint currentTicks = Clock::now();
|
|
|
|
Duration timeElapsed = currentTicks - lastTimePoint;
|
|
|
|
if(timeElapsed > boost::chrono::milliseconds(100))
|
|
|
|
timeElapsed = boost::chrono::milliseconds(100);
|
|
|
|
|
|
|
|
lastTimePoint = currentTicks;
|
|
|
|
lastFrameIndex = (lastFrameIndex + 1) % lastFrameTimes.size();
|
|
|
|
lastFrameTimes[lastFrameIndex] = timeElapsed;
|
|
|
|
}
|
2023-05-12 23:15:48 +02:00
|
|
|
|
2023-05-13 00:12:11 +02:00
|
|
|
ui32 FramerateManager::getElapsedMilliseconds() const
|
|
|
|
{
|
|
|
|
return lastFrameTimes[lastFrameIndex] / boost::chrono::milliseconds(1);
|
|
|
|
}
|
2023-05-12 23:15:48 +02:00
|
|
|
|
2023-05-13 00:12:11 +02:00
|
|
|
ui32 FramerateManager::getFramerate() const
|
|
|
|
{
|
|
|
|
Duration accumulatedTime = std::accumulate(lastFrameTimes.begin(), lastFrameTimes.end(), Duration());
|
2023-05-12 23:15:48 +02:00
|
|
|
|
2023-05-13 00:12:11 +02:00
|
|
|
auto actualFrameTime = accumulatedTime / lastFrameTimes.size();
|
|
|
|
if(actualFrameTime == actualFrameTime.zero())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return std::round(boost::chrono::duration<double>(1) / actualFrameTime);
|
|
|
|
};
|