diff --git a/panda/src/express/clockObject.I b/panda/src/express/clockObject.I index 6ecd7b77bb..f6a57262c3 100644 --- a/panda/src/express/clockObject.I +++ b/panda/src/express/clockObject.I @@ -113,47 +113,6 @@ reset() { set_frame_count(0); } -//////////////////////////////////////////////////////////////////// -// Function: ClockObject::set_real_time -// Access: Published -// Description: Resets the clock to the indicated time. This -// changes only the real time of the clock as reported -// by get_real_time(), but does not immediately change -// the time reported by get_frame_time()--that will -// change after the next call to tick(). Also see -// reset(), set_frame_time(), and set_frame_count(). -//////////////////////////////////////////////////////////////////// -INLINE void ClockObject:: -set_real_time(double time) { - _start_time = _true_clock->get_real_time() - time; -} - -//////////////////////////////////////////////////////////////////// -// Function: ClockObject::set_frame_time -// Access: Published -// Description: Changes the time as reported for the current frame to -// the indicated time. Normally, the way to adjust the -// frame time is via tick(); this function is provided -// only for occasional special adjustments. -//////////////////////////////////////////////////////////////////// -INLINE void ClockObject:: -set_frame_time(double time) { - _actual_frame_time = time; - _reported_frame_time = time; -} - -//////////////////////////////////////////////////////////////////// -// Function: ClockObject::set_frame_count -// Access: Published -// Description: Resets the number of frames counted to the indicated -// number. Also see reset(), set_real_time(), and -// set_frame_time(). -//////////////////////////////////////////////////////////////////// -INLINE void ClockObject:: -set_frame_count(int frame_count) { - _frame_count = frame_count; -} - //////////////////////////////////////////////////////////////////// // Function: ClockObject::get_frame_count // Access: Published diff --git a/panda/src/express/clockObject.cxx b/panda/src/express/clockObject.cxx index dae16fdc41..0024b0e032 100644 --- a/panda/src/express/clockObject.cxx +++ b/panda/src/express/clockObject.cxx @@ -18,6 +18,7 @@ #include "clockObject.h" +#include "config_express.h" ClockObject *ClockObject::_global_clock = (ClockObject *)NULL; @@ -39,6 +40,64 @@ ClockObject() { _max_dt = -1.0; } +//////////////////////////////////////////////////////////////////// +// Function: ClockObject::set_real_time +// Access: Published +// Description: Resets the clock to the indicated time. This +// changes only the real time of the clock as reported +// by get_real_time(), but does not immediately change +// the time reported by get_frame_time()--that will +// change after the next call to tick(). Also see +// reset(), set_frame_time(), and set_frame_count(). +//////////////////////////////////////////////////////////////////// +void ClockObject:: +set_real_time(double time) { +#ifndef NDEBUG + if (this == _global_clock) { + express_cat.warning() + << "Adjusting global clock's real time by " << time - get_real_time() + << " seconds.\n"; + } +#endif // NDEBUG + _start_time = _true_clock->get_real_time() - time; +} + +//////////////////////////////////////////////////////////////////// +// Function: ClockObject::set_frame_time +// Access: Published +// Description: Changes the time as reported for the current frame to +// the indicated time. Normally, the way to adjust the +// frame time is via tick(); this function is provided +// only for occasional special adjustments. +//////////////////////////////////////////////////////////////////// +void ClockObject:: +set_frame_time(double time) { + if (this == _global_clock) { + express_cat.warning() + << "Adjusting global clock's frame time by " << time - get_frame_time() + << " seconds.\n"; + } + _actual_frame_time = time; + _reported_frame_time = time; +} + +//////////////////////////////////////////////////////////////////// +// Function: ClockObject::set_frame_count +// Access: Published +// Description: Resets the number of frames counted to the indicated +// number. Also see reset(), set_real_time(), and +// set_frame_time(). +//////////////////////////////////////////////////////////////////// +void ClockObject:: +set_frame_count(int frame_count) { + if (this == _global_clock) { + express_cat.warning() + << "Adjusting global clock's frame count by " + << frame_count - get_frame_count() << " frames.\n"; + } + _frame_count = frame_count; +} + //////////////////////////////////////////////////////////////////// // Function: ClockObject::tick // Access: Published diff --git a/panda/src/express/clockObject.h b/panda/src/express/clockObject.h index 4996401734..0e20629c41 100644 --- a/panda/src/express/clockObject.h +++ b/panda/src/express/clockObject.h @@ -81,9 +81,9 @@ PUBLISHED: INLINE double get_real_time() const; INLINE void reset(); - INLINE void set_real_time(double time); - INLINE void set_frame_time(double time); - INLINE void set_frame_count(int frame_count); + void set_real_time(double time); + void set_frame_time(double time); + void set_frame_count(int frame_count); INLINE int get_frame_count() const; INLINE double get_frame_rate() const; diff --git a/panda/src/express/config_express.cxx b/panda/src/express/config_express.cxx index 946cf1d023..d0db7b1ad5 100644 --- a/panda/src/express/config_express.cxx +++ b/panda/src/express/config_express.cxx @@ -88,15 +88,15 @@ get_never_destruct() { // it is available. bool get_use_high_res_clock() { - static bool got_use_high_res_clock = false; - static bool use_high_res_clock; + return config_express.GetBool("use-high-res-clock", true); +} - if (!got_use_high_res_clock) { - use_high_res_clock = config_express.GetBool("use-high-res-clock", true); - got_use_high_res_clock = true; - } - - return use_high_res_clock; +// Set this to true to double-check the results of the high-resolution +// clock against the system clock. This has no effect if NDEBUG is +// defined. +bool +get_paranoid_clock() { + return config_express.GetBool("paranoid-clock", false); } const int patchfile_window_size = diff --git a/panda/src/express/config_express.h b/panda/src/express/config_express.h index 93599bd4f6..a26ee8f506 100644 --- a/panda/src/express/config_express.h +++ b/panda/src/express/config_express.h @@ -36,6 +36,7 @@ NotifyCategoryDecl(express, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS); bool EXPCL_PANDAEXPRESS get_leak_memory(); bool EXPCL_PANDAEXPRESS get_never_destruct(); bool EXPCL_PANDAEXPRESS get_use_high_res_clock(); +bool EXPCL_PANDAEXPRESS get_paranoid_clock(); extern const int patchfile_window_size; extern const int patchfile_increment_size; diff --git a/panda/src/express/trueClock.cxx b/panda/src/express/trueClock.cxx index 21a84708f1..64c3978f20 100644 --- a/panda/src/express/trueClock.cxx +++ b/panda/src/express/trueClock.cxx @@ -21,6 +21,8 @@ #include "config_express.h" #include "numeric_types.h" +#include "math.h" // for fabs() + TrueClock *TrueClock::_global_ptr = NULL; #if defined(WIN32_VC) @@ -41,6 +43,7 @@ static BOOL _has_high_res; static PN_int64 _frequency; static PN_int64 _init_count; static long _init_sec; +static bool _paranoid_clock; void get_true_time_of_day(ulong &sec, ulong &usec) { struct timeb tb; @@ -55,7 +58,30 @@ get_real_time() const { LARGE_INTEGER count; QueryPerformanceCounter(&count); - return (double)(count.QuadPart - _init_count) / (double)_frequency; + double time = (double)(count.QuadPart - _init_count) / (double)_frequency; + +#ifndef NDEBUG + if (_paranoid_clock) { + // Now double-check the high-resolution clock against the system + // clock. + struct timeb tb; + ftime(&tb); + double sys_time = (double)(tb.time - _init_sec) + (double)tb.millitm / 1000.0; + if (fabs(time - sys_time) > 0.5) { + // Too much variance! + express_cat.error() + << "Clock error! High resolution clock reads " << time + << " while system clock reads " << sys_time << ".\n"; + _init_count = + (PN_int64)(count.QuadPart - sys_time * (double)_frequency); + time = (double)(count.QuadPart - _init_count) / (double)_frequency; + express_cat.error() + << "High resolution clock reset to " << time << ".\n"; + } + } +#endif // NDEBUG + + return time; } else { // No high-resolution clock; return the best information we have. @@ -72,6 +98,8 @@ TrueClock() { _has_high_res = QueryPerformanceFrequency((LARGE_INTEGER *)&_frequency); } + _paranoid_clock = get_paranoid_clock(); + if (_has_high_res) { LARGE_INTEGER count; QueryPerformanceCounter(&count); @@ -93,6 +121,25 @@ TrueClock() { ftime(&tb); _init_sec = tb.time; } +#ifndef NDEBUG + else if (_paranoid_clock) { + express_cat.warning() + << "Not trusting the high resolution clock." << endl; + + struct timeb tb; + ftime(&tb); + _init_sec = tb.time; + + // Also set the QueryPerformance counter to exactly match the sys + // time, before we get started. + double sys_time = (double)(tb.time - _init_sec) + (double)tb.millitm / 1000.0; + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + _init_count = + (PN_int64)(count.QuadPart - sys_time * (double)_frequency); + } +#endif + }