|
|
@ -41,10 +41,12 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
|
|
*==LICENSE==*/ |
|
|
|
*==LICENSE==*/ |
|
|
|
#include "hsTimer.h" |
|
|
|
#include "hsTimer.h" |
|
|
|
#include "HeadSpin.h" |
|
|
|
#include "HeadSpin.h" |
|
|
|
#include "hsWindows.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "plTweak.h" |
|
|
|
#include "plTweak.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef std::chrono::duration<double> dSeconds; |
|
|
|
|
|
|
|
typedef std::chrono::duration<double, std::milli> dMilliseconds; |
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// plTimerShare - the actual worker. All process spaces should share a single
|
|
|
|
// plTimerShare - the actual worker. All process spaces should share a single
|
|
|
|
// plTimerShare to keep time synchronized across spaces.
|
|
|
|
// plTimerShare to keep time synchronized across spaces.
|
|
|
@ -71,45 +73,12 @@ plTimerShare::~plTimerShare() |
|
|
|
|
|
|
|
|
|
|
|
double plTimerShare::GetSeconds() const |
|
|
|
double plTimerShare::GetSeconds() const |
|
|
|
{ |
|
|
|
{ |
|
|
|
hsWide ticks; |
|
|
|
return dSeconds(GetRawTicks()).count(); |
|
|
|
return hsTimer::GetRawTicks(&ticks)->AsDouble() / hsTimer::GetRawBase().AsDouble(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
double plTimerShare::GetMilliSeconds() const |
|
|
|
double plTimerShare::GetMilliSeconds() const |
|
|
|
{ |
|
|
|
{ |
|
|
|
return GetSeconds() * 1.e3; |
|
|
|
return dMilliseconds(GetRawTicks()).count(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hsWide plTimerShare::DSecondsToRawTicks(double secs) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
hsWide retVal; |
|
|
|
|
|
|
|
double ticks = secs * hsTimer::GetRawBase().AsDouble(); |
|
|
|
|
|
|
|
double hi = ticks / double(65536) / double(65536); |
|
|
|
|
|
|
|
ticks -= hi; |
|
|
|
|
|
|
|
retVal.fHi = int32_t(hi); |
|
|
|
|
|
|
|
retVal.fLo = int32_t(ticks); |
|
|
|
|
|
|
|
return retVal; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double plTimerShare::RawTicksToDSeconds(const hsWide& ticks) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return ticks.AsDouble() / hsTimer::GetRawBase().AsDouble(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline hsWide* plTimerShare::FactorInTimeZero(hsWide* ticks) const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( fFirstTime ) |
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fFirstTime = false; |
|
|
|
|
|
|
|
fRawTimeZero = *ticks; |
|
|
|
|
|
|
|
ticks->Set(0, 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ticks->Sub(&fRawTimeZero); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return ticks; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
double plTimerShare::IncSysSeconds() |
|
|
|
double plTimerShare::IncSysSeconds() |
|
|
@ -200,69 +169,29 @@ double plTimerShare::IncSysSeconds() |
|
|
|
void plTimerShare::SetRealTime(bool realTime) |
|
|
|
void plTimerShare::SetRealTime(bool realTime) |
|
|
|
{ |
|
|
|
{ |
|
|
|
fRunningFrameTime = !realTime; |
|
|
|
fRunningFrameTime = !realTime; |
|
|
|
if( realTime ) |
|
|
|
if (realTime) |
|
|
|
{ |
|
|
|
{ |
|
|
|
fRealSeconds = GetSeconds(); |
|
|
|
fRealSeconds = GetSeconds(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hsWide* plTimerShare::GetRawTicks(hsWide* ticks) const |
|
|
|
plTimerShare::Duration plTimerShare::GetRawTicks() const |
|
|
|
{ |
|
|
|
{ |
|
|
|
LARGE_INTEGER large; |
|
|
|
plTimerShare::TimePoint tp = Clock::now(); |
|
|
|
|
|
|
|
|
|
|
|
if (::QueryPerformanceCounter(&large)) |
|
|
|
if (fFirstTime) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ticks->Set(large.HighPart, large.LowPart); |
|
|
|
fFirstTime = false; |
|
|
|
|
|
|
|
fRawTimeZero = tp; |
|
|
|
|
|
|
|
return plTimerShare::Duration(0); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
ticks->Set(0, ::GetTickCount()); |
|
|
|
return plTimerShare::Duration(tp - fRawTimeZero); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return FactorInTimeZero(ticks); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hsWide hsTimer::IInitRawBase() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
hsWide base; |
|
|
|
|
|
|
|
LARGE_INTEGER large; |
|
|
|
|
|
|
|
if (::QueryPerformanceFrequency(&large)) |
|
|
|
|
|
|
|
base.Set(large.HighPart, large.LowPart); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
base.Set(0, 1000); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return base; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#elif HS_BUILD_FOR_UNIX |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <sys/time.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define kMicroSecondsUnit 1000000 |
|
|
|
|
|
|
|
static uint32_t gBaseTime = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hsWide* plTimerShare::GetRawTicks(hsWide* ticks) const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
timeval tv; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(void)::gettimeofday(&tv, nil); |
|
|
|
|
|
|
|
if (gBaseTime == 0) |
|
|
|
|
|
|
|
gBaseTime = tv.tv_sec; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ticks->Mul(tv.tv_sec - gBaseTime, kMicroSecondsUnit)->Add(tv.tv_usec); |
|
|
|
|
|
|
|
return ticks; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
hsWide hsTimer::IInitRawBase() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
hsWide base; |
|
|
|
|
|
|
|
base.Set(0, kMicroSecondsUnit); |
|
|
|
|
|
|
|
return base; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// hsTimer - thin static interface to plTimerShare. Also keeps a couple of
|
|
|
|
// hsTimer - thin static interface to plTimerShare. Also keeps a couple of
|
|
|
@ -270,85 +199,34 @@ hsWide hsTimer::IInitRawBase() |
|
|
|
//
|
|
|
|
//
|
|
|
|
static plTimerShare staticTimer; |
|
|
|
static plTimerShare staticTimer; |
|
|
|
plTimerShare* hsTimer::fTimer = &staticTimer; // until overridden.
|
|
|
|
plTimerShare* hsTimer::fTimer = &staticTimer; // until overridden.
|
|
|
|
const double hsTimer::fPrecTicksPerSec = hsTimer::GetPrecTicksPerSec(); |
|
|
|
|
|
|
|
const hsWide hsTimer::fRawBase = hsTimer::IInitRawBase(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void hsTimer::SetTheTimer(plTimerShare* timer) |
|
|
|
void hsTimer::SetTheTimer(plTimerShare* timer) |
|
|
|
{ |
|
|
|
{ |
|
|
|
fTimer = timer; |
|
|
|
fTimer = timer; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////
|
|
|
|
|
|
|
|
// Precision timer routines
|
|
|
|
|
|
|
|
// These remain as statics
|
|
|
|
|
|
|
|
// since they are stateless
|
|
|
|
|
|
|
|
// anyway.
|
|
|
|
|
|
|
|
///////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double hsTimer::GetPrecTicksPerSec() |
|
|
|
double hsTimer::GetPrecTicksPerSec() |
|
|
|
{ |
|
|
|
{ |
|
|
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
return double(plTimerShare::Clock::period::num) / |
|
|
|
LARGE_INTEGER freq; |
|
|
|
double(plTimerShare::Clock::period::den); |
|
|
|
if( !QueryPerformanceFrequency(&freq) ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return 1000.f; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return ((double) freq.LowPart); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uint32_t hsTimer::GetPrecTickCount() |
|
|
|
uint32_t hsTimer::GetPrecTickCount() |
|
|
|
{ |
|
|
|
{ |
|
|
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
return uint32_t(plTimerShare::Clock::now().time_since_epoch().count()); |
|
|
|
LARGE_INTEGER ti; |
|
|
|
|
|
|
|
if( !QueryPerformanceCounter(&ti) ) |
|
|
|
|
|
|
|
return GetTickCount(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ti.LowPart; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
uint32_t hsTimer::PrecSecsToTicks(float secs) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return (uint32_t)(((double)secs) * fPrecTicksPerSec); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
double hsTimer::PrecTicksToSecs(uint32_t ticks) |
|
|
|
double hsTimer::PrecTicksToSecs(uint32_t ticks) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return ((double)ticks) / fPrecTicksPerSec; |
|
|
|
return dSeconds(plTimerShare::Duration(ticks)).count(); |
|
|
|
} |
|
|
|
|
|
|
|
double hsTimer::PrecTicksToHz(uint32_t ticks) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return fPrecTicksPerSec / ((double)ticks); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uint64_t hsTimer::GetFullTickCount() |
|
|
|
uint64_t hsTimer::GetFullTickCount() |
|
|
|
{ |
|
|
|
{ |
|
|
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
return uint64_t(plTimerShare::Clock::now().time_since_epoch().count()); |
|
|
|
LARGE_INTEGER ticks; |
|
|
|
|
|
|
|
QueryPerformanceCounter(&ticks); |
|
|
|
|
|
|
|
return ticks.QuadPart; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
float hsTimer::FullTicksToMs(uint64_t ticks) |
|
|
|
float hsTimer::FullTicksToMs(uint64_t ticks) |
|
|
|
{ |
|
|
|
{ |
|
|
|
#ifdef HS_BUILD_FOR_WIN32 |
|
|
|
return float(dMilliseconds(plTimerShare::Duration(ticks)).count()); |
|
|
|
static uint64_t ticksPerTenthMs = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ticksPerTenthMs == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LARGE_INTEGER perfFreq; |
|
|
|
|
|
|
|
QueryPerformanceFrequency(&perfFreq); |
|
|
|
|
|
|
|
ticksPerTenthMs = perfFreq.QuadPart / 10000; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return float(ticks / ticksPerTenthMs) / 10.f; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
return 0.f; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|