aboutsummaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/Kernel/OVR_Timer.cpp
diff options
context:
space:
mode:
authorBrad Davis <[email protected]>2014-07-24 16:47:31 -0700
committerBrad Davis <[email protected]>2014-07-24 16:47:31 -0700
commit0f49ce8fc6aa54224e4c0d6fda8c4527ad39cce1 (patch)
treeda07ebc6a7f75185bda857dd5f1c34710b416a93 /LibOVR/Src/Kernel/OVR_Timer.cpp
parentca79271759ff7eecd22ec5c4db438370fe51d687 (diff)
0.4 Win-Beta0.4.0
Diffstat (limited to 'LibOVR/Src/Kernel/OVR_Timer.cpp')
-rw-r--r--LibOVR/Src/Kernel/OVR_Timer.cpp104
1 files changed, 69 insertions, 35 deletions
diff --git a/LibOVR/Src/Kernel/OVR_Timer.cpp b/LibOVR/Src/Kernel/OVR_Timer.cpp
index a8de47d..5269106 100644
--- a/LibOVR/Src/Kernel/OVR_Timer.cpp
+++ b/LibOVR/Src/Kernel/OVR_Timer.cpp
@@ -27,8 +27,10 @@ limitations under the License.
#include "OVR_Timer.h"
#include "OVR_Log.h"
-#if defined (OVR_OS_WIN32)
+#if defined (OVR_OS_WIN32)
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+#include <MMSystem.h>
#elif defined(OVR_OS_ANDROID)
#include <time.h>
#include <android/log.h>
@@ -57,7 +59,7 @@ double Timer::GetSeconds()
}
-#ifndef OVR_OS_WIN32
+#if !defined(OVR_OS_WIN32)
// Unused on OSs other then Win32.
void Timer::initializeTimerSystem()
@@ -76,10 +78,10 @@ void Timer::shutdownTimerSystem()
#if defined(OVR_OS_ANDROID)
-UInt64 Timer::GetTicksNanos()
+uint64_t Timer::GetTicksNanos()
{
if (useFakeSeconds)
- return (UInt64) (FakeSeconds * NanosPerSecond);
+ return (uint64_t) (FakeSeconds * NanosPerSecond);
// Choreographer vsync timestamp is based on.
struct timespec tp;
@@ -89,7 +91,7 @@ UInt64 Timer::GetTicksNanos()
{
OVR_DEBUG_LOG(("clock_gettime status=%i", status ));
}
- const UInt64 result = (UInt64)tp.tv_sec * (UInt64)(1000 * 1000 * 1000) + UInt64(tp.tv_nsec);
+ const uint64_t result = (uint64_t)tp.tv_sec * (uint64_t)(1000 * 1000 * 1000) + uint64_t(tp.tv_nsec);
return result;
}
@@ -97,7 +99,7 @@ UInt64 Timer::GetTicksNanos()
//------------------------------------------------------------------------
// *** Win32 Specific Timer
-#elif defined (OVR_OS_WIN32)
+#elif defined (OVR_OS_WIN32)
// This helper class implements high-resolution wrapper that combines timeGetTime() output
@@ -117,7 +119,7 @@ struct PerformanceTimer
void Initialize();
void Shutdown();
- UInt64 GetTimeNanos();
+ uint64_t GetTimeNanos();
UINT64 getFrequency()
@@ -131,19 +133,20 @@ struct PerformanceTimer
return PrefFrequency;
}
+ bool UsingVista;
CRITICAL_SECTION TimeCS;
// timeGetTime() support with wrap.
- UInt32 OldMMTimeMs;
- UInt32 MMTimeWrapCounter;
+ uint32_t OldMMTimeMs;
+ uint32_t MMTimeWrapCounter;
// Cached performance frequency result.
- UInt64 PrefFrequency;
+ uint64_t PrefFrequency;
// Computed as (perfCounterNanos - ticksCounterNanos) initially,
// and used to adjust timing.
- UInt64 PerfMinusTicksDeltaNanos;
+ uint64_t PerfMinusTicksDeltaNanos;
// Last returned value in nanoseconds, to ensure we don't back-step in time.
- UInt64 LastResultNanos;
+ uint64_t LastResultNanos;
};
PerformanceTimer Win32_PerfTimer;
@@ -151,23 +154,55 @@ PerformanceTimer Win32_PerfTimer;
void PerformanceTimer::Initialize()
{
- timeBeginPeriod(1);
+
+ MMRESULT mmr = timeBeginPeriod(1);
+ OVR_ASSERT(TIMERR_NOERROR == mmr);
+ OVR_UNUSED(mmr);
+
InitializeCriticalSection(&TimeCS);
MMTimeWrapCounter = 0;
getFrequency();
+
+ // Set Vista flag. On Vista, we can just use QPC() without all the extra work
+ UsingVista = false;
+ OSVERSIONINFOA vi;
+ vi.dwOSVersionInfoSize = sizeof(vi);
+ if (GetVersionExA(&vi))
+ {
+ UsingVista = vi.dwMajorVersion >= 6;
+ }
+
+ OVR_DEBUG_LOG(("Performance timer Vista flag = %d", (int)UsingVista));
}
void PerformanceTimer::Shutdown()
{
DeleteCriticalSection(&TimeCS);
- timeEndPeriod(1);
+
+ MMRESULT mmr = timeEndPeriod(1);
+ OVR_ASSERT(TIMERR_NOERROR == mmr);
+ OVR_UNUSED(mmr);
}
-UInt64 PerformanceTimer::GetTimeNanos()
+uint64_t PerformanceTimer::GetTimeNanos()
{
- UInt64 resultNanos;
+ uint64_t resultNanos;
LARGE_INTEGER li;
- DWORD mmTimeMs;
+
+ // If on Vista,
+ if (UsingVista)
+ {
+ // Then we can use QPC() directly without all that extra work
+ QueryPerformanceCounter(&li);
+
+ uint64_t frequency = getFrequency();
+ uint64_t perfCounterSeconds = (uint64_t)li.QuadPart / frequency;
+ uint64_t perfRemainderNanos = (((uint64_t)li.QuadPart - perfCounterSeconds * frequency) *
+ Timer::NanosPerSecond) / frequency;
+ resultNanos = perfCounterSeconds * Timer::NanosPerSecond + perfRemainderNanos;
+ }
+ else
+ {
// On Win32 QueryPerformanceFrequency is unreliable due to SMP and
// performance levels, so use this logic to detect wrapping and track
@@ -175,25 +210,23 @@ UInt64 PerformanceTimer::GetTimeNanos()
::EnterCriticalSection(&TimeCS);
// Get raw value and perf counter "At the same time".
- mmTimeMs = timeGetTime();
QueryPerformanceCounter(&li);
-
+ DWORD mmTimeMs = timeGetTime();
if (OldMMTimeMs > mmTimeMs)
MMTimeWrapCounter++;
OldMMTimeMs = mmTimeMs;
// Normalize to nanoseconds.
- UInt64 mmCounterNanos = ((UInt64(MMTimeWrapCounter) << 32) | mmTimeMs) * 1000000;
- UInt64 frequency = getFrequency();
- UInt64 perfCounterSeconds = UInt64(li.QuadPart) / frequency;
- UInt64 perfRemainderNanos = ( (UInt64(li.QuadPart) - perfCounterSeconds * frequency) *
+ uint64_t frequency = getFrequency();
+ uint64_t perfCounterSeconds = uint64_t(li.QuadPart) / frequency;
+ uint64_t perfRemainderNanos = ( (uint64_t(li.QuadPart) - perfCounterSeconds * frequency) *
Timer::NanosPerSecond ) / frequency;
- UInt64 perfCounterNanos = perfCounterSeconds * Timer::NanosPerSecond + perfRemainderNanos;
+ uint64_t perfCounterNanos = perfCounterSeconds * Timer::NanosPerSecond + perfRemainderNanos;
+ uint64_t mmCounterNanos = ((uint64_t(MMTimeWrapCounter) << 32) | mmTimeMs) * 1000000;
if (PerfMinusTicksDeltaNanos == 0)
PerfMinusTicksDeltaNanos = perfCounterNanos - mmCounterNanos;
-
// Compute result before snapping.
//
// On first call, this evaluates to:
@@ -225,22 +258,23 @@ UInt64 PerformanceTimer::GetTimeNanos()
LastResultNanos = resultNanos;
::LeaveCriticalSection(&TimeCS);
+ }
//Tom's addition, to keep precision
- static UInt64 initial_time = 0;
- if (!initial_time) initial_time = resultNanos;
- resultNanos -= initial_time;
-
+ //static uint64_t initial_time = 0;
+ //if (!initial_time) initial_time = resultNanos;
+ //resultNanos -= initial_time;
+ // FIXME: This cannot be used for cross-process timestamps
return resultNanos;
}
// Delegate to PerformanceTimer.
-UInt64 Timer::GetTicksNanos()
+uint64_t Timer::GetTicksNanos()
{
if (useFakeSeconds)
- return (UInt64) (FakeSeconds * NanosPerSecond);
+ return (uint64_t) (FakeSeconds * NanosPerSecond);
return Win32_PerfTimer.GetTimeNanos();
}
@@ -260,20 +294,20 @@ void Timer::shutdownTimerSystem()
//------------------------------------------------------------------------
// *** Standard OS Timer
-UInt64 Timer::GetTicksNanos()
+uint64_t Timer::GetTicksNanos()
{
if (useFakeSeconds)
- return (UInt64) (FakeSeconds * NanosPerSecond);
+ return (uint64_t) (FakeSeconds * NanosPerSecond);
// TODO: prefer rdtsc when available?
- UInt64 result;
+ uint64_t result;
// Return microseconds.
struct timeval tv;
gettimeofday(&tv, 0);
- result = (UInt64)tv.tv_sec * 1000000;
+ result = (uint64_t)tv.tv_sec * 1000000;
result += tv.tv_usec;
return result * 1000;