2 * Copyright (C) 2016-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
15 using namespace RETRO
;
16 using namespace std::chrono_literals
;
18 #define DEFAULT_FPS 60 // In case fps is 0 (shouldn't happen)
19 #define FOREVER_MS (7 * 24 * 60 * 60 * 1000) // 1 week is large enough
21 CGameLoop::CGameLoop(IGameLoopCallback
* callback
, double fps
)
22 : CThread("GameLoop"), m_callback(callback
), m_fps(fps
? fps
: DEFAULT_FPS
), m_speedFactor(0.0)
26 CGameLoop::~CGameLoop()
31 void CGameLoop::Start()
36 void CGameLoop::Stop()
43 void CGameLoop::SetSpeed(double speedFactor
)
45 m_speedFactor
= speedFactor
;
50 void CGameLoop::PauseAsync()
55 void CGameLoop::Process(void)
59 if (m_speedFactor
== 0.0)
62 m_sleepEvent
.Wait(5000ms
);
66 if (m_speedFactor
> 0.0)
67 m_callback
->FrameEvent();
68 else if (m_speedFactor
< 0.0)
69 m_callback
->RewindEvent();
71 if (m_lastFrameMs
> 0.0)
73 m_lastFrameMs
+= FrameTimeMs();
74 m_adjustTime
= m_lastFrameMs
- NowMs();
78 m_lastFrameMs
= NowMs();
82 // Calculate sleep time
83 double sleepTimeMs
= SleepTimeMs();
85 // Sleep at least 1 ms to avoid sleeping forever
86 while (sleepTimeMs
> 1.0)
88 m_sleepEvent
.Wait(std::chrono::milliseconds(static_cast<unsigned int>(sleepTimeMs
)));
93 // Speed may have changed, update sleep time
94 sleepTimeMs
= SleepTimeMs();
100 double CGameLoop::FrameTimeMs() const
102 if (m_speedFactor
!= 0.0)
103 return 1000.0 / m_fps
/ std::abs(m_speedFactor
);
105 return 1000.0 / m_fps
/ 1.0;
108 double CGameLoop::SleepTimeMs() const
110 // Calculate next frame time
111 const double nextFrameMs
= m_lastFrameMs
+ FrameTimeMs();
113 // Calculate sleep time
114 double sleepTimeMs
= (nextFrameMs
- NowMs()) + m_adjustTime
;
120 sleepTimeMs
= (sleepTimeMs
>= 0.0 ? sleepTimeMs
: 0.0);
125 double CGameLoop::NowMs() const
127 return std::chrono::duration
<double, std::milli
>(
128 std::chrono::steady_clock::now().time_since_epoch())