Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OVR_Timer.cpp
Go to the documentation of this file.
1 /************************************************************************************
2 
3 Filename : OVR_Timer.cpp
4 Content : Provides static functions for precise timing
5 Created : September 19, 2012
6 Notes :
7 
8 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
9 
10 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
12 which is provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
14 
15 You may obtain a copy of the License at
16 
17 http://www.oculusvr.com/licenses/LICENSE-3.1
18 
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24 
25 ************************************************************************************/
26 
27 #include "OVR_Timer.h"
28 #include "OVR_Log.h"
29 
30 #if defined (OVR_OS_WIN32)
31 #include <windows.h>
32 #elif defined(OVR_OS_ANDROID)
33 #include <time.h>
34 #include <android/log.h>
35 
36 #else
37 #include <sys/time.h>
38 #endif
39 
40 namespace OVR {
41 
42 // For recorded data playback
43 bool Timer::useFakeSeconds = false;
44 double Timer::FakeSeconds = 0;
45 
46 
47 //------------------------------------------------------------------------
48 // *** Timer - Platform Independent functions
49 
50 // Returns global high-resolution application timer in seconds.
52 {
53  if(useFakeSeconds)
54  return FakeSeconds;
55 
56  return double(Timer::GetTicksNanos()) * 0.000000001;
57 }
58 
59 
60 #ifndef OVR_OS_WIN32
61 
62 // Unused on OSs other then Win32.
64 {
65 }
67 {
68 }
69 
70 #endif
71 
72 
73 
74 //------------------------------------------------------------------------
75 // *** Android Specific Timer
76 
77 #if defined(OVR_OS_ANDROID)
78 
80 {
81  if (useFakeSeconds)
82  return (UInt64) (FakeSeconds * NanosPerSecond);
83 
84  // Choreographer vsync timestamp is based on.
85  struct timespec tp;
86  const int status = clock_gettime(CLOCK_MONOTONIC, &tp);
87 
88  if (status != 0)
89  {
90  OVR_DEBUG_LOG(("clock_gettime status=%i", status ));
91  }
92  const UInt64 result = (UInt64)tp.tv_sec * (UInt64)(1000 * 1000 * 1000) + UInt64(tp.tv_nsec);
93  return result;
94 }
95 
96 
97 //------------------------------------------------------------------------
98 // *** Win32 Specific Timer
99 
100 #elif defined (OVR_OS_WIN32)
101 
102 
103 // This helper class implements high-resolution wrapper that combines timeGetTime() output
104 // with QueryPerformanceCounter. timeGetTime() is lower precision but drives the high bits,
105 // as it's tied to the system clock.
106 struct PerformanceTimer
107 {
108  PerformanceTimer()
109  : OldMMTimeMs(0), MMTimeWrapCounter(0), PrefFrequency(0),
110  LastResultNanos(0), PerfMinusTicksDeltaNanos(0)
111  { }
112 
113  enum {
114  MMTimerResolutionNanos = 1000000
115  };
116 
117  void Initialize();
118  void Shutdown();
119 
120  UInt64 GetTimeNanos();
121 
122 
123  UINT64 getFrequency()
124  {
125  if (PrefFrequency == 0)
126  {
127  LARGE_INTEGER freq;
128  QueryPerformanceFrequency(&freq);
129  PrefFrequency = freq.QuadPart;
130  }
131  return PrefFrequency;
132  }
133 
134 
135  CRITICAL_SECTION TimeCS;
136  // timeGetTime() support with wrap.
137  UInt32 OldMMTimeMs;
138  UInt32 MMTimeWrapCounter;
139  // Cached performance frequency result.
140  UInt64 PrefFrequency;
141 
142  // Computed as (perfCounterNanos - ticksCounterNanos) initially,
143  // and used to adjust timing.
144  UInt64 PerfMinusTicksDeltaNanos;
145  // Last returned value in nanoseconds, to ensure we don't back-step in time.
146  UInt64 LastResultNanos;
147 };
148 
149 PerformanceTimer Win32_PerfTimer;
150 
151 
152 void PerformanceTimer::Initialize()
153 {
154  timeBeginPeriod(1);
155  InitializeCriticalSection(&TimeCS);
156  MMTimeWrapCounter = 0;
157  getFrequency();
158 }
159 
160 void PerformanceTimer::Shutdown()
161 {
162  DeleteCriticalSection(&TimeCS);
163  timeEndPeriod(1);
164 }
165 
166 UInt64 PerformanceTimer::GetTimeNanos()
167 {
168  UInt64 resultNanos;
169  LARGE_INTEGER li;
170  DWORD mmTimeMs;
171 
172  // On Win32 QueryPerformanceFrequency is unreliable due to SMP and
173  // performance levels, so use this logic to detect wrapping and track
174  // high bits.
175  ::EnterCriticalSection(&TimeCS);
176 
177  // Get raw value and perf counter "At the same time".
178  mmTimeMs = timeGetTime();
179  QueryPerformanceCounter(&li);
180 
181  if (OldMMTimeMs > mmTimeMs)
182  MMTimeWrapCounter++;
183  OldMMTimeMs = mmTimeMs;
184 
185  // Normalize to nanoseconds.
186  UInt64 mmCounterNanos = ((UInt64(MMTimeWrapCounter) << 32) | mmTimeMs) * 1000000;
187  UInt64 frequency = getFrequency();
188  UInt64 perfCounterSeconds = UInt64(li.QuadPart) / frequency;
189  UInt64 perfRemainderNanos = ( (UInt64(li.QuadPart) - perfCounterSeconds * frequency) *
190  Timer::NanosPerSecond ) / frequency;
191  UInt64 perfCounterNanos = perfCounterSeconds * Timer::NanosPerSecond + perfRemainderNanos;
192 
193  if (PerfMinusTicksDeltaNanos == 0)
194  PerfMinusTicksDeltaNanos = perfCounterNanos - mmCounterNanos;
195 
196 
197  // Compute result before snapping.
198  //
199  // On first call, this evaluates to:
200  // resultNanos = mmCounterNanos.
201  // Next call, assuming no wrap:
202  // resultNanos = prev_mmCounterNanos + (perfCounterNanos - prev_perfCounterNanos).
203  // After wrap, this would be:
204  // resultNanos = snapped(prev_mmCounterNanos +/- 1ms) + (perfCounterNanos - prev_perfCounterNanos).
205  //
206  resultNanos = perfCounterNanos - PerfMinusTicksDeltaNanos;
207 
208  // Snap the range so that resultNanos never moves further apart then its target resolution.
209  // It's better to allow more slack on the high side as timeGetTime() may be updated at sporadically
210  // larger then 1 ms intervals even when 1 ms resolution is requested.
211  if (resultNanos > (mmCounterNanos + MMTimerResolutionNanos*2))
212  {
213  resultNanos = mmCounterNanos + MMTimerResolutionNanos*2;
214  if (resultNanos < LastResultNanos)
215  resultNanos = LastResultNanos;
216  PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos;
217  }
218  else if (resultNanos < (mmCounterNanos - MMTimerResolutionNanos))
219  {
220  resultNanos = mmCounterNanos - MMTimerResolutionNanos;
221  if (resultNanos < LastResultNanos)
222  resultNanos = LastResultNanos;
223  PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos;
224  }
225 
226  LastResultNanos = resultNanos;
227  ::LeaveCriticalSection(&TimeCS);
228 
229  //Tom's addition, to keep precision
230  static UInt64 initial_time = 0;
231  if (!initial_time) initial_time = resultNanos;
232  resultNanos -= initial_time;
233 
234 
235  return resultNanos;
236 }
237 
238 
239 // Delegate to PerformanceTimer.
241 {
242  if (useFakeSeconds)
243  return (UInt64) (FakeSeconds * NanosPerSecond);
244 
245  return Win32_PerfTimer.GetTimeNanos();
246 }
248 {
249  Win32_PerfTimer.Initialize();
250 
251 }
253 {
254  Win32_PerfTimer.Shutdown();
255 }
256 
257 #else // !OVR_OS_WIN32 && !OVR_OS_ANDROID
258 
259 
260 //------------------------------------------------------------------------
261 // *** Standard OS Timer
262 
264 {
265  if (useFakeSeconds)
266  return (UInt64) (FakeSeconds * NanosPerSecond);
267 
268  // TODO: prefer rdtsc when available?
269  UInt64 result;
270 
271  // Return microseconds.
272  struct timeval tv;
273 
274  gettimeofday(&tv, 0);
275 
276  result = (UInt64)tv.tv_sec * 1000000;
277  result += tv.tv_usec;
278 
279  return result * 1000;
280 }
281 
282 #endif // OS-specific
283 
284 
285 
286 } // OVR
287 
static UInt64 OVR_STDCALL GetTicksNanos()
Definition: OVR_Timer.cpp:263
uint64_t UInt64
Definition: OVR_Types.h:255
static bool useFakeSeconds
Definition: OVR_Timer.h:82
__time_t tv_sec
Definition: OVR_Types.h:32
uint32_t UInt32
Definition: OVR_Types.h:253
static void initializeTimerSystem()
Definition: OVR_Timer.cpp:63
static double FakeSeconds
Definition: OVR_Timer.h:81
static double OVR_STDCALL GetSeconds()
Definition: OVR_Timer.cpp:51
#define OVR_DEBUG_LOG(args)
Definition: OVR_Log.h:196
static void shutdownTimerSystem()
Definition: OVR_Timer.cpp:66
__suseconds_t tv_usec
Definition: OVR_Types.h:33