Timer.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../Precompiled.h"
  4. #include "../Core/CoreEvents.h"
  5. #include "../Core/Profiler.h"
  6. #include <ctime>
  7. #ifdef _WIN32
  8. #include "../Engine/WinWrapped.h"
  9. #include <mmsystem.h>
  10. #elif __EMSCRIPTEN__
  11. #include <emscripten/emscripten.h>
  12. #else
  13. #include <sys/time.h>
  14. #include <unistd.h>
  15. #endif
  16. #include "../DebugNew.h"
  17. namespace Urho3D
  18. {
  19. bool HiresTimer::supported(false);
  20. long long HiresTimer::frequency(1000);
  21. Time::Time(Context* context) :
  22. Object(context),
  23. frameNumber_(0),
  24. timeStep_(0.0f),
  25. timerPeriod_(0)
  26. {
  27. #ifdef _WIN32
  28. LARGE_INTEGER frequency;
  29. if (QueryPerformanceFrequency(&frequency))
  30. {
  31. HiresTimer::frequency = frequency.QuadPart;
  32. HiresTimer::supported = true;
  33. }
  34. #else
  35. HiresTimer::frequency = 1000000;
  36. HiresTimer::supported = true;
  37. #endif
  38. }
  39. Time::~Time()
  40. {
  41. SetTimerPeriod(0);
  42. }
  43. static unsigned Tick()
  44. {
  45. #ifdef _WIN32
  46. return (unsigned)timeGetTime();
  47. #elif __EMSCRIPTEN__
  48. return (unsigned)emscripten_get_now();
  49. #else
  50. struct timeval time{};
  51. gettimeofday(&time, nullptr);
  52. return (unsigned)(time.tv_sec * 1000 + time.tv_usec / 1000);
  53. #endif
  54. }
  55. static long long HiresTick()
  56. {
  57. #ifdef _WIN32
  58. if (HiresTimer::IsSupported())
  59. {
  60. LARGE_INTEGER counter;
  61. QueryPerformanceCounter(&counter);
  62. return counter.QuadPart;
  63. }
  64. else
  65. return timeGetTime();
  66. #elif __EMSCRIPTEN__
  67. return (long long)(emscripten_get_now()*1000.0);
  68. #else
  69. struct timeval time{};
  70. gettimeofday(&time, nullptr);
  71. return time.tv_sec * 1000000LL + time.tv_usec;
  72. #endif
  73. }
  74. void Time::BeginFrame(float timeStep)
  75. {
  76. ++frameNumber_;
  77. if (!frameNumber_)
  78. ++frameNumber_;
  79. timeStep_ = timeStep;
  80. #ifdef URHO3D_PROFILING
  81. auto* profiler = GetSubsystem<Profiler>();
  82. if (profiler)
  83. profiler->BeginFrame();
  84. #endif
  85. {
  86. URHO3D_PROFILE(BeginFrame);
  87. // Frame begin event
  88. using namespace BeginFrame;
  89. VariantMap& eventData = GetEventDataMap();
  90. eventData[P_FRAMENUMBER] = frameNumber_;
  91. eventData[P_TIMESTEP] = timeStep_;
  92. SendEvent(E_BEGINFRAME, eventData);
  93. }
  94. }
  95. void Time::EndFrame()
  96. {
  97. {
  98. URHO3D_PROFILE(EndFrame);
  99. // Frame end event
  100. SendEvent(E_ENDFRAME);
  101. }
  102. #ifdef URHO3D_PROFILING
  103. auto* profiler = GetSubsystem<Profiler>();
  104. if (profiler)
  105. profiler->EndFrame();
  106. #endif
  107. }
  108. void Time::SetTimerPeriod(unsigned mSec)
  109. {
  110. #ifdef _WIN32
  111. if (timerPeriod_ > 0)
  112. timeEndPeriod(timerPeriod_);
  113. timerPeriod_ = mSec;
  114. if (timerPeriod_ > 0)
  115. timeBeginPeriod(timerPeriod_);
  116. #endif
  117. }
  118. float Time::GetElapsedTime()
  119. {
  120. return elapsedTime_.GetMSec(false) / 1000.0f;
  121. }
  122. unsigned Time::GetSystemTime()
  123. {
  124. return Tick();
  125. }
  126. unsigned Time::GetTimeSinceEpoch()
  127. {
  128. return (unsigned)time(nullptr);
  129. }
  130. String Time::GetTimeStamp()
  131. {
  132. time_t sysTime;
  133. time(&sysTime);
  134. const char* dateTime = ctime(&sysTime);
  135. return String(dateTime).Replaced("\n", "");
  136. }
  137. void Time::Sleep(unsigned mSec)
  138. {
  139. #ifdef _WIN32
  140. ::Sleep(mSec);
  141. #else
  142. timespec time{static_cast<time_t>(mSec / 1000), static_cast<long>((mSec % 1000) * 1000000)};
  143. nanosleep(&time, nullptr);
  144. #endif
  145. }
  146. float Time::GetFramesPerSecond() const
  147. {
  148. return 1.0f / timeStep_;
  149. }
  150. Timer::Timer()
  151. {
  152. Reset();
  153. }
  154. unsigned Timer::GetMSec(bool reset)
  155. {
  156. unsigned currentTime = Tick();
  157. unsigned elapsedTime = currentTime - startTime_;
  158. if (reset)
  159. startTime_ = currentTime;
  160. return elapsedTime;
  161. }
  162. void Timer::Reset()
  163. {
  164. startTime_ = Tick();
  165. }
  166. HiresTimer::HiresTimer()
  167. {
  168. Reset();
  169. }
  170. long long HiresTimer::GetUSec(bool reset)
  171. {
  172. long long currentTime = HiresTick();
  173. long long elapsedTime = currentTime - startTime_;
  174. // Correct for possible weirdness with changing internal frequency
  175. if (elapsedTime < 0)
  176. elapsedTime = 0;
  177. if (reset)
  178. startTime_ = currentTime;
  179. return (elapsedTime * 1000000LL) / frequency;
  180. }
  181. void HiresTimer::Reset()
  182. {
  183. startTime_ = HiresTick();
  184. }
  185. }