FramerateManager.cpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /*
  2. * FramerateManager.h, 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. : lastFrameIndex(0)
  16. , lastFrameTimes({})
  17. , lastTimePoint(Clock::now())
  18. {
  19. if(settings["video"]["vsync"].Bool())
  20. {
  21. static int display_in_use = settings["video"]["displayIndex"].Integer();
  22. SDL_DisplayMode mode;
  23. SDL_GetCurrentDisplayMode(display_in_use, &mode);
  24. int displayRefreshRate = mode.refresh_rate;
  25. logGlobal->info("Display refresh rate is %d", displayRefreshRate);
  26. targetFrameTime = Duration(boost::chrono::seconds(1)) / displayRefreshRate;
  27. } else
  28. {
  29. targetFrameTime = Duration(boost::chrono::seconds(1)) / targetFrameRate;
  30. }
  31. boost::range::fill(lastFrameTimes, targetFrameTime);
  32. }
  33. void FramerateManager::framerateDelay()
  34. {
  35. Duration timeSpentBusy = Clock::now() - lastTimePoint;
  36. // FPS is higher than it should be, then wait some time
  37. if(timeSpentBusy < targetFrameTime)
  38. boost::this_thread::sleep_for(targetFrameTime - timeSpentBusy);
  39. // compute actual timeElapsed taking into account actual sleep interval
  40. // limit it to 100 ms to avoid breaking animation in case of huge lag (e.g. triggered breakpoint)
  41. TimePoint currentTicks = Clock::now();
  42. Duration timeElapsed = currentTicks - lastTimePoint;
  43. if(timeElapsed > boost::chrono::milliseconds(100))
  44. timeElapsed = boost::chrono::milliseconds(100);
  45. lastTimePoint = currentTicks;
  46. lastFrameIndex = (lastFrameIndex + 1) % lastFrameTimes.size();
  47. lastFrameTimes[lastFrameIndex] = timeElapsed;
  48. }
  49. ui32 FramerateManager::getElapsedMilliseconds() const
  50. {
  51. return lastFrameTimes[lastFrameIndex] / boost::chrono::milliseconds(1);
  52. }
  53. ui32 FramerateManager::getFramerate() const
  54. {
  55. Duration accumulatedTime = std::accumulate(lastFrameTimes.begin(), lastFrameTimes.end(), Duration());
  56. auto actualFrameTime = accumulatedTime / lastFrameTimes.size();
  57. if(actualFrameTime == actualFrameTime.zero())
  58. return 0;
  59. return std::round(boost::chrono::duration<double>(1) / actualFrameTime);
  60. };