You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
4.0 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://sam.zoy.org/projects/COPYING.WTFPL for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <cstdlib>
  14. #include <stdint.h>
  15. #if defined __linux__ || defined __native_client__ || defined __APPLE__
  16. # include <sys/time.h>
  17. # include <unistd.h>
  18. #elif defined _XBOX
  19. # include <xtl.h>
  20. # undef near /* Fuck Microsoft */
  21. # undef far /* Fuck Microsoft again */
  22. # include <xbox.h>
  23. #elif defined _WIN32
  24. # define WIN32_LEAN_AND_MEAN
  25. # include <windows.h>
  26. #elif defined __CELLOS_LV2__
  27. # include <sys/sys_time.h>
  28. # include <sys/timer.h>
  29. # include <sys/time_util.h>
  30. #elif defined HAVE_SDL_SDL_H
  31. # include <SDL/SDL.h>
  32. #else
  33. # include <SDL.h>
  34. #endif
  35. #include "core.h"
  36. namespace lol
  37. {
  38. /*
  39. * Timer implementation class
  40. */
  41. class TimerData
  42. {
  43. friend class Timer;
  44. private:
  45. TimerData()
  46. {
  47. #if defined __linux__ || defined __native_client__ || defined __APPLE__
  48. gettimeofday(&tv0, NULL);
  49. #elif defined _WIN32
  50. QueryPerformanceCounter(&cycles0);
  51. #elif defined __CELLOS_LV2__
  52. SYS_TIMEBASE_GET(cycles0);
  53. #else
  54. SDL_Init(SDL_INIT_TIMER);
  55. ticks0 = SDL_GetTicks();
  56. #endif
  57. }
  58. float GetOrWait(float seconds, bool update)
  59. {
  60. float secs_elapsed, secs_towait;
  61. #if defined __linux__ || defined __native_client__ || defined __APPLE__
  62. struct timeval tv;
  63. gettimeofday(&tv, NULL);
  64. secs_elapsed = 1e-6f * (tv.tv_usec - tv0.tv_usec)
  65. + (tv.tv_sec - tv0.tv_sec);
  66. if (update)
  67. tv0 = tv;
  68. secs_towait = seconds - secs_elapsed;
  69. if (secs_towait > 0.0f)
  70. usleep((int)(secs_towait * 1e6f));
  71. #elif defined _WIN32
  72. LARGE_INTEGER cycles;
  73. QueryPerformanceCounter(&cycles);
  74. static float secs_per_cycle = GetSecondsPerCycle();
  75. secs_elapsed = secs_per_cycle * (cycles.QuadPart - cycles0.QuadPart);
  76. if (update)
  77. cycles0 = cycles;
  78. secs_towait = seconds - secs_elapsed;
  79. if (secs_towait > 5e-4f)
  80. Sleep((int)(secs_towait * 1e3f + 0.5f));
  81. #elif defined __CELLOS_LV2__
  82. uint64_t cycles;
  83. SYS_TIMEBASE_GET(cycles);
  84. static float secs_per_cycle = GetSecondsPerCycle();
  85. secs_elapsed = secs_per_cycle * (cycles - cycles0);
  86. if (update)
  87. cycles0 = cycles;
  88. secs_towait = seconds - secs_elapsed;
  89. if (secs_towait > 0.0f)
  90. sys_timer_usleep((int)(secs_towait * 1e6f));
  91. #else
  92. /* The crappy SDL fallback */
  93. Uint32 ticks = SDL_GetTicks();
  94. secs_elapsed = 1e-3f * (ticks - ticks0);
  95. if (update)
  96. ticks0 = ticks;
  97. secs_towait = seconds - secs_elapsed;
  98. if (secs_towait > 5e-4f)
  99. SDL_Delay((int)(secs_towait * 1e3f + 0.5f));
  100. #endif
  101. return secs_elapsed;
  102. }
  103. static float GetSecondsPerCycle()
  104. {
  105. #if defined __linux__ || defined __native_client__ || defined __APPLE__
  106. return 1e-3f;
  107. #elif defined _WIN32
  108. LARGE_INTEGER tmp;
  109. QueryPerformanceFrequency(&tmp);
  110. return 1.f / tmp.QuadPart;
  111. #elif defined __CELLOS_LV2__
  112. return 1.f / sys_time_get_timebase_frequency();
  113. #else
  114. return 1e-3f;
  115. #endif
  116. }
  117. #if defined __linux__ || defined __native_client__ || defined __APPLE__
  118. struct timeval tv0;
  119. #elif defined _WIN32
  120. LARGE_INTEGER cycles0;
  121. #elif defined __CELLOS_LV2__
  122. uint64_t cycles0;
  123. #else
  124. Uint32 ticks0;
  125. #endif
  126. };
  127. /*
  128. * Timer public class
  129. */
  130. Timer::Timer()
  131. : data(new TimerData())
  132. {
  133. }
  134. Timer::~Timer()
  135. {
  136. delete data;
  137. }
  138. float Timer::Get()
  139. {
  140. return data->GetOrWait(0.0f, true);
  141. }
  142. float Timer::Poll()
  143. {
  144. return data->GetOrWait(0.0f, false);
  145. }
  146. void Timer::Wait(float seconds)
  147. {
  148. (void)data->GetOrWait(seconds, false);
  149. }
  150. } /* namespace lol */