Merge branch 'fix_frame_rate_limit' into 'master'

Fix frame rate limit (#5686)

See merge request OpenMW/openmw!603
pull/3047/head
AnyOldName3 3 years ago
commit 2b144ff3dd

@ -38,6 +38,8 @@
#include <components/detournavigator/navigator.hpp>
#include <components/misc/frameratelimiter.hpp>
#include "mwinput/inputmanagerimp.hpp"
#include "mwgui/windowmanagerimp.hpp"
@ -918,13 +920,15 @@ void OMW::Engine::go()
}
// Start the main rendering loop
osg::Timer frameTimer;
double simulationTime = 0.0;
Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(mEnvironment.getFrameRateLimit());
const std::chrono::steady_clock::duration maxSimulationInterval(std::chrono::milliseconds(200));
while (!mViewer->done() && !mEnvironment.getStateManager()->hasQuitRequest())
{
double dt = frameTimer.time_s();
frameTimer.setStartTick();
dt = std::min(dt, 0.2);
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(std::min(
frameRateLimiter.getLastFrameDuration(),
maxSimulationInterval
)).count();
mViewer->advance(simulationTime);
@ -960,7 +964,7 @@ void OMW::Engine::go()
}
}
mEnvironment.limitFrameRate(frameTimer.time_s());
frameRateLimiter.limit();
}
// Save user settings

@ -1,8 +1,6 @@
#include "environment.hpp"
#include <cassert>
#include <chrono>
#include <thread>
#include <components/resource/resourcesystem.hpp>
@ -98,19 +96,6 @@ float MWBase::Environment::getFrameRateLimit() const
return mFrameRateLimit;
}
void MWBase::Environment::limitFrameRate(double dt) const
{
if (mFrameRateLimit > 0.f)
{
double thisFrameTime = dt;
double minFrameTime = 1.0 / static_cast<double>(mFrameRateLimit);
if (thisFrameTime < minFrameTime)
{
std::this_thread::sleep_for(std::chrono::duration<double>(minFrameTime - thisFrameTime));
}
}
}
MWBase::World *MWBase::Environment::getWorld() const
{
assert (mWorld);

@ -83,7 +83,6 @@ namespace MWBase
void setFrameRateLimit(float frameRateLimit);
float getFrameRateLimit() const;
void limitFrameRate(double dt) const;
World *getWorld() const;

@ -50,6 +50,7 @@
#include <components/widgets/tags.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/misc/frameratelimiter.hpp>
#include "../mwbase/inputmanager.hpp"
#include "../mwbase/statemanager.hpp"
@ -710,12 +711,11 @@ namespace MWGui
if (block)
{
osg::Timer frameTimer;
Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(MWBase::Environment::get().getFrameRateLimit());
while (mMessageBoxManager->readPressedButton(false) == -1
&& !MWBase::Environment::get().getStateManager()->hasQuitRequest())
{
double dt = frameTimer.time_s();
frameTimer.setStartTick();
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(frameRateLimiter.getLastFrameDuration()).count();
mKeyboardNavigation->onFrame();
mMessageBoxManager->onFrame(dt);
@ -734,7 +734,7 @@ namespace MWGui
// refer to the advance() and frame() order in Engine::go()
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
MWBase::Environment::get().limitFrameRate(frameTimer.time_s());
frameRateLimiter.limit();
}
}
}
@ -1750,11 +1750,10 @@ namespace MWGui
~MWSound::Type::Movie & MWSound::Type::Mask
);
osg::Timer frameTimer;
Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(MWBase::Environment::get().getFrameRateLimit());
while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest())
{
double dt = frameTimer.time_s();
frameTimer.setStartTick();
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(frameRateLimiter.getLastFrameDuration()).count();
MWBase::Environment::get().getInputManager()->update(dt, true, false);
@ -1777,7 +1776,7 @@ namespace MWGui
// refer to the advance() and frame() order in Engine::go()
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
MWBase::Environment::get().limitFrameRate(frameTimer.time_s());
frameRateLimiter.limit();
}
mVideoWidget->stop();

@ -0,0 +1,56 @@
#ifndef OPENMW_COMPONENTS_MISC_FRAMERATELIMITER_H
#define OPENMW_COMPONENTS_MISC_FRAMERATELIMITER_H
#include <chrono>
#include <thread>
namespace Misc
{
class FrameRateLimiter
{
public:
template <class Rep, class Ratio>
explicit FrameRateLimiter(std::chrono::duration<Rep, Ratio> maxFrameDuration,
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now())
: mMaxFrameDuration(std::chrono::duration_cast<std::chrono::steady_clock::duration>(maxFrameDuration))
, mLastMeasurement(now)
{}
std::chrono::steady_clock::duration getLastFrameDuration() const
{
return mLastFrameDuration;
}
void limit(std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now())
{
const auto passed = now - mLastMeasurement;
const auto left = mMaxFrameDuration - passed;
if (left > left.zero())
{
std::this_thread::sleep_for(left);
mLastMeasurement = now + left;
mLastFrameDuration = mMaxFrameDuration;
}
else
{
mLastMeasurement = now;
mLastFrameDuration = passed;
}
}
private:
std::chrono::steady_clock::duration mMaxFrameDuration;
std::chrono::steady_clock::time_point mLastMeasurement;
std::chrono::steady_clock::duration mLastFrameDuration;
};
inline Misc::FrameRateLimiter makeFrameRateLimiter(float frameRateLimit)
{
if (frameRateLimit > 0.0f)
return Misc::FrameRateLimiter(std::chrono::duration<float>(1.0f / frameRateLimit));
else
return Misc::FrameRateLimiter(std::chrono::steady_clock::duration::zero());
}
}
#endif
Loading…
Cancel
Save