oculus1

annotate libovr/Src/Kernel/OVR_Timer.cpp @ 29:9a973ef0e2a3

fixed the performance issue under MacOSX by replacing glutSolidTeapot (which uses glEvalMesh) with my own teapot generator.
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 27 Oct 2013 06:31:18 +0200
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