#ifndef OPENMW_COMPONENTS_MISC_FRAMERATELIMITER_H #define OPENMW_COMPONENTS_MISC_FRAMERATELIMITER_H #include #include namespace Misc { class FrameRateLimiter { public: template explicit FrameRateLimiter(std::chrono::duration maxFrameDuration, std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now()) : mMaxFrameDuration(std::chrono::duration_cast(maxFrameDuration)) , mLastMeasurement(now) , mLastFrameDuration(0) {} 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(1.0f / frameRateLimit)); else return Misc::FrameRateLimiter(std::chrono::steady_clock::duration::zero()); } } #endif