oculus1
annotate libovr/Src/Kernel/OVR_Timer.cpp @ 17:cfe4979ab3eb
ops, minor error in the last commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 21 Sep 2013 07:09:48 +0300 |
parents | e2f9e4603129 |
children |
rev | line source |
---|---|
nuclear@3 | 1 /************************************************************************************ |
nuclear@3 | 2 |
nuclear@3 | 3 Filename : OVR_Timer.cpp |
nuclear@3 | 4 Content : Provides static functions for precise timing |
nuclear@3 | 5 Created : September 19, 2012 |
nuclear@3 | 6 Notes : |
nuclear@3 | 7 |
nuclear@3 | 8 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. |
nuclear@3 | 9 |
nuclear@3 | 10 Use of this software is subject to the terms of the Oculus license |
nuclear@3 | 11 agreement provided at the time of installation or download, or which |
nuclear@3 | 12 otherwise accompanies this software in either electronic or hard copy form. |
nuclear@3 | 13 |
nuclear@3 | 14 ************************************************************************************/ |
nuclear@3 | 15 |
nuclear@3 | 16 #include "OVR_Timer.h" |
nuclear@3 | 17 |
nuclear@3 | 18 #if defined (OVR_OS_WIN32) |
nuclear@3 | 19 #include <windows.h> |
nuclear@3 | 20 |
nuclear@3 | 21 #else |
nuclear@3 | 22 #include <sys/time.h> |
nuclear@3 | 23 #endif |
nuclear@3 | 24 |
nuclear@3 | 25 namespace OVR { |
nuclear@3 | 26 |
nuclear@3 | 27 //----------------------------------------------------------------------------------- |
nuclear@3 | 28 // ***** Timer Class |
nuclear@3 | 29 |
nuclear@3 | 30 UInt64 Timer::GetProfileTicks() |
nuclear@3 | 31 { |
nuclear@3 | 32 return (GetRawTicks() * MksPerSecond) / GetRawFrequency(); |
nuclear@3 | 33 } |
nuclear@3 | 34 double Timer::GetProfileSeconds() |
nuclear@3 | 35 { |
nuclear@3 | 36 static UInt64 StartTime = GetProfileTicks(); |
nuclear@3 | 37 return TicksToSeconds(GetProfileTicks()-StartTime); |
nuclear@3 | 38 } |
nuclear@3 | 39 |
nuclear@3 | 40 |
nuclear@3 | 41 //------------------------------------------------------------------------ |
nuclear@3 | 42 // *** Win32 Specific Timer |
nuclear@3 | 43 |
nuclear@3 | 44 #if (defined (OVR_OS_WIN32)) |
nuclear@3 | 45 |
nuclear@3 | 46 CRITICAL_SECTION WinAPI_GetTimeCS; |
nuclear@3 | 47 volatile UInt32 WinAPI_OldTime = 0; |
nuclear@3 | 48 volatile UInt32 WinAPI_WrapCounter = 0; |
nuclear@3 | 49 |
nuclear@3 | 50 |
nuclear@3 | 51 UInt32 Timer::GetTicksMs() |
nuclear@3 | 52 { |
nuclear@3 | 53 return timeGetTime(); |
nuclear@3 | 54 } |
nuclear@3 | 55 |
nuclear@3 | 56 UInt64 Timer::GetTicks() |
nuclear@3 | 57 { |
nuclear@3 | 58 DWORD ticks = timeGetTime(); |
nuclear@3 | 59 UInt64 result; |
nuclear@3 | 60 |
nuclear@3 | 61 // On Win32 QueryPerformanceFrequency is unreliable due to SMP and |
nuclear@3 | 62 // performance levels, so use this logic to detect wrapping and track |
nuclear@3 | 63 // high bits. |
nuclear@3 | 64 ::EnterCriticalSection(&WinAPI_GetTimeCS); |
nuclear@3 | 65 |
nuclear@3 | 66 if (WinAPI_OldTime > ticks) |
nuclear@3 | 67 WinAPI_WrapCounter++; |
nuclear@3 | 68 WinAPI_OldTime = ticks; |
nuclear@3 | 69 |
nuclear@3 | 70 result = (UInt64(WinAPI_WrapCounter) << 32) | ticks; |
nuclear@3 | 71 ::LeaveCriticalSection(&WinAPI_GetTimeCS); |
nuclear@3 | 72 |
nuclear@3 | 73 return result * MksPerMs; |
nuclear@3 | 74 } |
nuclear@3 | 75 |
nuclear@3 | 76 UInt64 Timer::GetRawTicks() |
nuclear@3 | 77 { |
nuclear@3 | 78 LARGE_INTEGER li; |
nuclear@3 | 79 QueryPerformanceCounter(&li); |
nuclear@3 | 80 return li.QuadPart; |
nuclear@3 | 81 } |
nuclear@3 | 82 |
nuclear@3 | 83 UInt64 Timer::GetRawFrequency() |
nuclear@3 | 84 { |
nuclear@3 | 85 static UInt64 perfFreq = 0; |
nuclear@3 | 86 if (perfFreq == 0) |
nuclear@3 | 87 { |
nuclear@3 | 88 LARGE_INTEGER freq; |
nuclear@3 | 89 QueryPerformanceFrequency(&freq); |
nuclear@3 | 90 perfFreq = freq.QuadPart; |
nuclear@3 | 91 } |
nuclear@3 | 92 return perfFreq; |
nuclear@3 | 93 } |
nuclear@3 | 94 |
nuclear@3 | 95 void Timer::initializeTimerSystem() |
nuclear@3 | 96 { |
nuclear@3 | 97 timeBeginPeriod(1); |
nuclear@3 | 98 InitializeCriticalSection(&WinAPI_GetTimeCS); |
nuclear@3 | 99 |
nuclear@3 | 100 } |
nuclear@3 | 101 void Timer::shutdownTimerSystem() |
nuclear@3 | 102 { |
nuclear@3 | 103 DeleteCriticalSection(&WinAPI_GetTimeCS); |
nuclear@3 | 104 timeEndPeriod(1); |
nuclear@3 | 105 } |
nuclear@3 | 106 |
nuclear@3 | 107 #else // !OVR_OS_WIN32 |
nuclear@3 | 108 |
nuclear@3 | 109 |
nuclear@3 | 110 //------------------------------------------------------------------------ |
nuclear@3 | 111 // *** Standard OS Timer |
nuclear@3 | 112 |
nuclear@3 | 113 UInt32 Timer::GetTicksMs() |
nuclear@3 | 114 { |
nuclear@3 | 115 return (UInt32)(GetProfileTicks() / 1000); |
nuclear@3 | 116 } |
nuclear@3 | 117 // The profile ticks implementation is just fine for a normal timer. |
nuclear@3 | 118 UInt64 Timer::GetTicks() |
nuclear@3 | 119 { |
nuclear@3 | 120 return GetProfileTicks(); |
nuclear@3 | 121 } |
nuclear@3 | 122 |
nuclear@3 | 123 void Timer::initializeTimerSystem() |
nuclear@3 | 124 { |
nuclear@3 | 125 } |
nuclear@3 | 126 void Timer::shutdownTimerSystem() |
nuclear@3 | 127 { |
nuclear@3 | 128 } |
nuclear@3 | 129 |
nuclear@3 | 130 UInt64 Timer::GetRawTicks() |
nuclear@3 | 131 { |
nuclear@3 | 132 // TODO: prefer rdtsc when available? |
nuclear@3 | 133 |
nuclear@3 | 134 // Return microseconds. |
nuclear@3 | 135 struct timeval tv; |
nuclear@3 | 136 UInt64 result; |
nuclear@3 | 137 |
nuclear@3 | 138 gettimeofday(&tv, 0); |
nuclear@3 | 139 |
nuclear@3 | 140 result = (UInt64)tv.tv_sec * 1000000; |
nuclear@3 | 141 result += tv.tv_usec; |
nuclear@3 | 142 |
nuclear@3 | 143 return result; |
nuclear@3 | 144 } |
nuclear@3 | 145 |
nuclear@3 | 146 UInt64 Timer::GetRawFrequency() |
nuclear@3 | 147 { |
nuclear@3 | 148 return MksPerSecond; |
nuclear@3 | 149 } |
nuclear@3 | 150 |
nuclear@3 | 151 #endif // !OVR_OS_WIN32 |
nuclear@3 | 152 |
nuclear@3 | 153 |
nuclear@3 | 154 |
nuclear@3 | 155 } // OVR |
nuclear@3 | 156 |