summaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/Kernel/OVR_Timer.cpp
blob: 599c614ae4a9dcf13d319a8745e625e32d9d7f95 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/************************************************************************************

Filename    :   OVR_Timer.cpp
Content     :   Provides static functions for precise timing
Created     :   September 19, 2012
Notes       : 

Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.

Use of this software is subject to the terms of the Oculus license
agreement provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.

************************************************************************************/

#include "OVR_Timer.h"

#if defined (OVR_OS_WIN32)
#include <windows.h>
#pragma comment(lib, "winmm.lib")

#else
#include <sys/time.h>
#endif


namespace OVR {

//-----------------------------------------------------------------------------------
// ***** Timer Class

UInt64 Timer::GetProfileTicks()
{
    return (GetRawTicks() * MksPerSecond) / GetRawFrequency();
}
double Timer::GetProfileSeconds()
{
    static UInt64 StartTime = GetProfileTicks();
    return TicksToSeconds(GetProfileTicks()-StartTime);
}


//------------------------------------------------------------------------
// *** Win32 Specific Timer

#if (defined (OVR_OS_WIN32))

CRITICAL_SECTION WinAPI_GetTimeCS;
volatile UInt32  WinAPI_OldTime = 0;
volatile UInt32  WinAPI_WrapCounter = 0;


UInt32 Timer::GetTicksMs()
{
    return timeGetTime();
}

UInt64 Timer::GetTicks()
{
    DWORD  ticks = timeGetTime();
    UInt64 result;

    // On Win32 QueryPerformanceFrequency is unreliable due to SMP and
    // performance levels, so use this logic to detect wrapping and track
    // high bits.
    ::EnterCriticalSection(&WinAPI_GetTimeCS);

    if (WinAPI_OldTime > ticks)
        WinAPI_WrapCounter++;
    WinAPI_OldTime = ticks;

    result = (UInt64(WinAPI_WrapCounter) << 32) | ticks;
    ::LeaveCriticalSection(&WinAPI_GetTimeCS);

    return result * MksPerMs;
}

UInt64 Timer::GetRawTicks()
{
    LARGE_INTEGER li;
    QueryPerformanceCounter(&li);
    return li.QuadPart;
}

UInt64 Timer::GetRawFrequency()
{
    static UInt64 perfFreq = 0;
    if (perfFreq == 0)
    {
        LARGE_INTEGER freq;
        QueryPerformanceFrequency(&freq);
        perfFreq = freq.QuadPart;
    }
    return perfFreq;
}

void Timer::initializeTimerSystem()
{
    timeBeginPeriod(1);
    InitializeCriticalSection(&WinAPI_GetTimeCS);

}
void Timer::shutdownTimerSystem()
{
    DeleteCriticalSection(&WinAPI_GetTimeCS);
    timeEndPeriod(1);
}

#else   // !OVR_OS_WIN32


//------------------------------------------------------------------------
// *** Standard OS Timer     

UInt32 Timer::GetTicksMs()
{
    return (UInt32)(GetProfileTicks() / 1000);
}
// The profile ticks implementation is just fine for a normal timer.
UInt64 Timer::GetTicks()
{
    return GetProfileTicks();
}

void Timer::initializeTimerSystem()
{
}
void Timer::shutdownTimerSystem()
{
}

UInt64  Timer::GetRawTicks()
{
    // TODO: prefer rdtsc when available?

    // Return microseconds.
    struct timeval tv;
    UInt64 result;

    gettimeofday(&tv, 0);

    result = (UInt64)tv.tv_sec * 1000000;
    result += tv.tv_usec;

    return result;
}

UInt64 Timer::GetRawFrequency()
{
    return MksPerSecond;
}

#endif  // !OVR_OS_WIN32



} // OVR