FramerateManager.cpp 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. /*
  2. * FramerateManager.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "FramerateManager.h"
  12. #include "../../lib/CConfigHandler.h"
  13. #include <SDL_video.h>
  14. FramerateManager::FramerateManager(int targetFrameRate)
  15. : targetFrameTime(Duration(std::chrono::seconds(1)) / targetFrameRate)
  16. , lastFrameIndex(0)
  17. , lastFrameTimes({})
  18. , lastTimePoint(Clock::now())
  19. , vsyncEnabled(settings["video"]["vsync"].Bool())
  20. {
  21. boost::range::fill(lastFrameTimes, targetFrameTime);
  22. }
  23. void FramerateManager::framerateDelay()
  24. {
  25. Duration timeSpentBusy = Clock::now() - lastTimePoint;
  26. if(!vsyncEnabled && timeSpentBusy < targetFrameTime)
  27. {
  28. // if FPS is higher than it should be, then wait some time
  29. std::this_thread::sleep_for(targetFrameTime - timeSpentBusy);
  30. }
  31. // compute actual timeElapsed taking into account actual sleep interval
  32. // limit it to 100 ms to avoid breaking animation in case of huge lag (e.g. triggered breakpoint)
  33. TimePoint currentTicks = Clock::now();
  34. Duration timeElapsed = currentTicks - lastTimePoint;
  35. if(timeElapsed > std::chrono::milliseconds(100))
  36. timeElapsed = std::chrono::milliseconds(100);
  37. lastTimePoint = currentTicks;
  38. lastFrameIndex = (lastFrameIndex + 1) % lastFrameTimes.size();
  39. lastFrameTimes[lastFrameIndex] = timeElapsed;
  40. }
  41. ui32 FramerateManager::getElapsedMilliseconds() const
  42. {
  43. return lastFrameTimes[lastFrameIndex] / std::chrono::milliseconds(1);
  44. }
  45. ui32 FramerateManager::getFramerate() const
  46. {
  47. Duration accumulatedTime = std::accumulate(lastFrameTimes.begin(), lastFrameTimes.end(), Duration());
  48. auto actualFrameTime = accumulatedTime / lastFrameTimes.size();
  49. if(actualFrameTime == actualFrameTime.zero())
  50. return 0;
  51. return std::round(std::chrono::duration<double>(1) / actualFrameTime);
  52. };