void WCFrameRateMonitor::operator()(void) { //Start the timer if counter = 0 if (this->_frameCounter == 0) #ifdef __APPLE__ //Use OSX frameworks to get time this->_start = UpTime(); #elif __WIN32__ //Use MFC frameworks to get time this->_start = GetTickCount(); #endif //Calculate FPS every 100 frames if (this->_frameCounter == 100) { #ifdef __APPLE__ Nanoseconds elapsed = AbsoluteDeltaToNanoseconds(UpTime(), this->_start); this->_fps = 100.0 / UnsignedWideToUInt64(elapsed) * 1000000000; #elif __WIN32__ //Determine how much time has elapsed since start of 100 frame block WPFloat elapsed = (WPFloat)(GetTickCount() - this->_start); this->_fps = 100.0 / elapsed * 1000.0; #endif if (this->_fps > 1000.0) this->_fps = -1.0f; //Reset the counter to 0 this->_frameCounter = 0; //Make sure the layer/scene know to redraw this->MarkDirty(); } //Otherwise increment the counter else this->_frameCounter++; }
void PsychGetPrecisionTimerSeconds(double *secs) { double timeDouble; AbsoluteTime timeAbsTime; Nanoseconds timeNanoseconds; UInt64 timeUInt64; //Get the time in an AbsolulteTime structure which expresses time as a ratio. timeAbsTime=UpTime(); //Convert the AbsoluteTime structure to nanoseconds stored in an UnsignedWide. //UnsignedWide is an opaque type. Depending on the compiler it is //implemented either as structure holding holding 32-bit high and low parts //or as a native long long. timeNanoseconds=AbsoluteToNanoseconds(timeAbsTime); //convert the opaque unsigned wide type into a UInt64. Variant forms //of the UnsignedWide type is why we need to use the UnsignedWideToUInt64() //macro instead of a cast. If GCC then UnsignedWideToUInt64 resolves to a type recast. timeUInt64=UnsignedWideToUInt64(timeNanoseconds); //cast nanoseconds in unsigned wide type to a double timeDouble=(double)timeUInt64; //divide down to seconds *secs= timeDouble / 1000000000; }
double Timer::EndTimer() { #ifdef OS_MAC AbsoluteTime stopTime = UpTime(); Nanoseconds diff = AbsoluteDeltaToNanoseconds(stopTime, startTime); uint64_t nanosecs = UnsignedWideToUInt64(diff); //cout << nanosecs << " ns elapsed (" << (double)nanosecs/1000000.0 << " ms)" << endl; return elapsedTime = (double)(nanosecs/1000000000.0); #elif defined( TIMER_USE_CYCLE_COUNTER ) Timer::CycleCounter c; double diffTime = (double)(c.count() - startTime); const static double ClocksPerSecond = getCPUSpeed() * 1000000.0; elapsedTime = diffTime / ClocksPerSecond; return elapsedTime; #else #ifdef WIN32 elapsedTime=(timeGetTime()-startTime)*0.001; #else struct timeval stopTime; gettimeofday( &stopTime, NULL ); uint64_t microsecs = stopTime.tv_sec - startTime.tv_sec; microsecs = microsecs * 1000000 + stopTime.tv_usec - startTime.tv_usec; elapsedTime = (double)microsecs / 1000000.0; #endif return elapsedTime; #endif }
GHOST_TUns64 GHOST_SystemCarbon::getMilliSeconds() const { UnsignedWide micros; ::Microseconds(µs); UInt64 millis; millis = UnsignedWideToUInt64(micros); return (millis / 1000) - m_start_time; }
GHOST_SystemCarbon::GHOST_SystemCarbon() : m_modifierMask(0) { m_displayManager = new GHOST_DisplayManagerCarbon(); GHOST_ASSERT(m_displayManager, "GHOST_SystemCarbon::GHOST_SystemCarbon(): m_displayManager==0\n"); m_displayManager->initialize(); UnsignedWide micros; ::Microseconds(µs); m_start_time = UnsignedWideToUInt64(micros) / 1000; m_ignoreWindowSizedMessages = false; }
void Display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, options[OPTION_DISPLAY_WIREFRAME] ? GL_LINE : GL_FILL); //Wireframe control glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /*** Frame Rate Counter ***/ static int frameCounter = 0; static AbsoluteTime start; static WPFloat fps = 0.0; char str[12]; sprintf(str, "%4.2f fps", fps); glRasterPos2f(-1.8, -1.8); glColor4f(1.0, 1.0, 1.0, 1.0); for (int i = 0; i < 10; i++) glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, str[i]); //Timer stuff if (frameCounter == 0) start = UpTime(); if (frameCounter == 100) { Nanoseconds elapsed = AbsoluteDeltaToNanoseconds(UpTime(), start); fps = 100.0 / UnsignedWideToUInt64(elapsed) * 1000000000; frameCounter = 0; } else frameCounter++; /*** ***/ //Now go to viewing perspeective manipulator.applyTransform(); //Render the surface curve->Render(0); if (options[OPTION_TANGENT]) { WCRay tangent = curve->Tangent(_tangentVal); tangent.Render(0); } if (options[OPTION_INVERSION]) { WCVector4 inv = curve->PointInversion(*_ipt); glColor4f(0.0, 1.0, 1.0, 1.0); glPointSize(4.0); _ipt->Render(0); glBegin(GL_POINTS); glVertex3f(inv.I(), inv.J(), inv.K()); glEnd(); pt = _ipt; } //Swap buffers and start over glutSwapBuffers(); glutReportErrors(); }
MWTime StandardClock::getCurrentTimeNS() { // first things first /*uint64_t now = mach_absolute_time(); return (MWTime)(now * tTBI.numer / tTBI.denom);*/ AbsoluteTime uptime; Nanoseconds nano; uptime = UpTime(); nano = AbsoluteToNanoseconds(uptime); return (MWTime)(UnsignedWideToUInt64( nano ) - baseTime); }
double getTicks() { //return 40; #ifdef _WIN32 return (double) GetTickCount(); #else Nanoseconds nano = AbsoluteToNanoseconds( UpTime() ); // if you want that in (floating point) seconds: double seconds = ((double) UnsignedWideToUInt64( nano )) * 1e-9; return seconds * 1000.0; #endif }
nglTime::nglTime() { #ifdef _POSIX_WORLD_ struct timeval tv; gettimeofday (&tv, NULL); mValue = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0); #endif // _POSIX_WORLD_ #if macintosh Nanoseconds t = AbsoluteToNanoseconds(UpTime()); mValue = ((double)UnsignedWideToUInt64(t)) / 1000000.0; #endif // macintosh #ifdef _WIN32_ mValue = GetTime(); #endif // _WIN32_ }
/* Should this be public? */ prng_error_status prngForceReseed(PRNG *p, LONGLONG ticks) { int i; #ifdef WIN_NT FILETIME a,b,c,usertime; #endif BYTE buf[64]; BYTE dig[20]; #if defined(macintosh) || defined(__APPLE__) #if (defined(TARGET_API_MAC_OSX) || defined(KERNEL_BUILD)) struct timeval tv; int64_t endTime, curTime; #else /* TARGET_API_MAC_CARBON */ UnsignedWide uwide; /* struct needed for Microseconds() */ LONGLONG start; LONGLONG now; #endif #endif CHECKSTATE(p); POOLCHECK(p); ZCHECK(ticks); /* Set up start and end times */ #if defined(macintosh) || defined(__APPLE__) #if (defined(TARGET_API_MAC_OSX) || defined(KERNEL_BUILD)) /* note we can't loop for more than a million microseconds */ #ifdef KERNEL_BUILD microuptime (&tv); #else gettimeofday(&tv, NULL); #endif endTime = (int64_t)tv.tv_sec*1000000LL + (int64_t)tv.tv_usec + ticks; #else /* TARGET_API_MAC_OSX */ Microseconds(&uwide); start = UnsignedWideToUInt64(uwide); #endif /* TARGET_API_xxx */ #endif /* macintosh */ do { /* Do a couple of iterations between time checks */ prngOutput(p, buf,64); YSHA1Update(&p->pool,buf,64); prngOutput(p, buf,64); YSHA1Update(&p->pool,buf,64); prngOutput(p, buf,64); YSHA1Update(&p->pool,buf,64); prngOutput(p, buf,64); YSHA1Update(&p->pool,buf,64); prngOutput(p, buf,64); YSHA1Update(&p->pool,buf,64); #if defined(macintosh) || defined(__APPLE__) #if defined(TARGET_API_MAC_OSX) || defined(KERNEL_BUILD) #ifdef TARGET_API_MAC_OSX gettimeofday(&tv, NULL); #else microuptime (&tv); curTime = (int64_t)tv.tv_sec*1000000LL + (int64_t)tv.tv_usec; #endif } while(curTime < endTime); #else Microseconds(&uwide); now = UnsignedWideToUInt64(uwide); } while ( (now-start) < ticks) ;
PsychError PSYCHHIDKbTriggerWait(void) { pRecDevice deviceRecord; int i, deviceIndex, numDeviceIndices; long KeysUsagePage=0x07; // This is the keyboard usage page long KeysUsage; // This will contain the key code of the trigger key long KbDeviceUsagePages[NUMDEVICEUSAGES]= {0x01,0x01}, KbDeviceUsages[NUMDEVICEUSAGES]={0x06,0x07}; // Generic Desktop page (0x01), keyboard (0x06), keypad (0x07) int numDeviceUsages=NUMDEVICEUSAGES; int deviceIndices[PSYCH_HID_MAX_KEYBOARD_DEVICES]; pRecDevice deviceRecords[PSYCH_HID_MAX_KEYBOARD_DEVICES]; psych_bool isDeviceSpecified, foundUserSpecifiedDevice; double *timeValueOutput; IOHIDQueueInterface **queue; HRESULT result; IOHIDDeviceInterface122** interface=NULL; // This requires Mac OS X 10.3 or higher IOReturn success; IOHIDElementCookie triggerCookie; PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(2)); //Specify trigger key code and the deviceNumber of the keyboard or keypad to scan. PsychHIDVerifyInit(); if(hidDataRef!=NULL) PsychErrorExitMsg(PsychError_user, "A queue is already running, you must call KbQueueRelease() before invoking KbTriggerWait."); //Identify the trigger { int KeysUsageInteger; if(!PsychCopyInIntegerArg(1, TRUE, &KeysUsageInteger)){ PsychErrorExitMsg(PsychError_user, "Keycode is required."); } KeysUsage=KeysUsageInteger; } //Choose the device index and its record PsychHIDGetDeviceListByUsages(numDeviceUsages, KbDeviceUsagePages, KbDeviceUsages, &numDeviceIndices, deviceIndices, deviceRecords); isDeviceSpecified=PsychCopyInIntegerArg(2, FALSE, &deviceIndex); if(isDeviceSpecified){ //make sure that the device number provided by the user is really a keyboard or keypad. for(i=0;i<numDeviceIndices;i++){ if(foundUserSpecifiedDevice=(deviceIndices[i]==deviceIndex)) break; } if(!foundUserSpecifiedDevice) PsychErrorExitMsg(PsychError_user, "Specified device number is not a keyboard or keypad device."); }else{ // set the keyboard or keypad device to be the first keyboard device or, if no keyboard, the first keypad i=0; if(numDeviceIndices==0) PsychErrorExitMsg(PsychError_user, "No keyboard or keypad devices detected."); else{ deviceIndex=deviceIndices[i]; } } deviceRecord=deviceRecords[i]; //Allocate and init out return arguments. PsychAllocOutDoubleArg(1, FALSE, &timeValueOutput); if(!timeValueOutput) PsychErrorExitMsg(PsychError_system, "Failed to allocate memory for output."); interface=deviceRecord->interface; if(!interface) PsychErrorExitMsg(PsychError_system, "Could not get interface to device."); // The following bracketed clause will get a cookie corresponding to the // trigger. If multiple keys were of interest, the code could be modified // trivially to iterate over an array of KeysUsage to generate an array of // corresponding cookies { CFArrayRef elements; psych_bool usedDictionary=FALSE; { CFDictionaryRef dict=NULL; // The next few lines define a dictionary describing the key of interest // If they are omitted, the code will still work, but all elements will match // initially rather than just the one key of interest, so the code will be // slower since it will iterate through hundreds of keys CFStringRef keys[2] = {CFSTR("UsagePage"), CFSTR("Usage")}; CFNumberRef values[2]; values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &KeysUsagePage); values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &KeysUsage); if(values[0]!=NULL && values[1]!=NULL){ // Even if they are NULL, it will be ok since dict can be NULL at the expense of some loss of efficiency dict = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, 2, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } // copyMatchinfElements requires IOHIDDeviceInterface122, thus Mac OS X 10.3 or higher // elements would have to be obtained directly from IORegistry for 10.2 or earlier // If dict==NULL, all elements will match, leading to some inefficiency success = (*interface)->copyMatchingElements(interface, dict, &elements); if(dict){ usedDictionary=TRUE; CFRelease(dict); } if(values[0]) CFRelease(values[0]); if(values[1]) CFRelease(values[1]); if(!elements){ PsychErrorExitMsg(PsychError_user, "Specified key code not found on device."); } } { // elements will only contain one element in this implementation, but has the // advantage of generalizing to future derived implementations that listen // for multiple keys CFIndex i; for (i=0; i<CFArrayGetCount(elements); i++) { long number; CFDictionaryRef element= CFArrayGetValueAtIndex(elements, i); CFTypeRef object; if(!element) continue; if(!usedDictionary){ // Verify tht we are dealing with a keypad or keyboard object = CFDictionaryGetValue(element, CFSTR(kIOHIDElementUsageKey)); if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) continue; if (!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType,&number)) continue; if(number!=KeysUsage) continue; // See if element corresponds to the desired key object = CFDictionaryGetValue(element, CFSTR(kIOHIDElementUsagePageKey)); if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) continue; if (!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, &number)) continue; if(number!=KeysUsagePage) continue; } // Get the cookie for this element object= (CFDictionaryGetValue(element, CFSTR(kIOHIDElementCookieKey))); if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) continue; if(!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, &number)) continue; triggerCookie = (IOHIDElementCookie) number; break; } if(CFArrayGetCount(elements)==i){ CFRelease(elements); PsychErrorExitMsg(PsychError_user, "Specified key code not found on device."); } CFRelease(elements); } } // Allocate for the queue queue=(*interface)->allocQueue(interface); if(!queue){ PsychErrorExitMsg(PsychError_system, "Failed to allocate event queue for detecting key press."); } // Create the queue result = (*queue)->create(queue, 0, 8); // 8 events can be stored before the earliest event is lost if (kIOReturnSuccess != result){ (*queue)->Release(queue); (*queue)=NULL; PsychErrorExitMsg(PsychError_system, "Failed to create event queue for detecting key press."); } // Add the trigger to the queue // If multiple keys were of interest, their cookies could be added in turn result = (*queue)->addElement(queue, triggerCookie, 0); if (kIOReturnSuccess != result){ result = (*queue)->dispose(queue); (*queue)->Release(queue); (*queue)=NULL; PsychErrorExitMsg(PsychError_system, "Failed to add trigger key to event queues."); } // Start the queue result = (*queue)->start(queue); if (kIOReturnSuccess != result){ result = (*queue)->dispose(queue); (*queue)->Release(queue); (*queue)=NULL; PsychErrorExitMsg(PsychError_system, "Failed to start event queues."); } // Watch for the trigger { IOHIDEventStruct event; while(1){ AbsoluteTime zeroTime = {0,0}; result = (*queue)->getNextEvent(queue, &event, zeroTime, 0); if(kIOReturnSuccess==result) break; PsychWaitIntervalSeconds((double)0.004); //surrender some time to other processes // If it were of interest to trigger selectively on key press or key release, // this could be evaluated by checking event.value (zero versus non-zero) // but this would put more code inside the loop // If multiple keys are registered via addElement (not the case here), the // cookie for the key responsible for the event can be obtained from // event.elementCookie } // If event.longValue is not NULL, the documentation indicates that it is up // to the caller to deallocate it. The circumstances under which a non-NULL // value would be generated are not specified. My guess is that some devices // might return a 64-bit value (e.g., a tracking device coordinate). // Keys, having only two states, shouldn't need this, but check and free to // be safe if ((event.longValueSize != 0) && (event.longValue != NULL)) free(event.longValue); // Set the time, using the same strategy as PsychTimeGlue's PsychGetPrecisionTimerSeconds // For code maintainability, it would be better if this conversion were performed // by a function in PsychTimeGlue { Nanoseconds timeNanoseconds=AbsoluteToNanoseconds(event.timestamp); UInt64 timeUInt64=UnsignedWideToUInt64(timeNanoseconds); double timeDouble=(double)timeUInt64; *timeValueOutput=timeDouble / 1000000000; } } // Clean up result = (*queue)->stop(queue); // Code from Apple sometimes removes elements from queue before disposing and sometimes does not // I can't see any reason to do so for a queue that's one line of code away from destruction // and therefore haven't result = (*queue)->dispose(queue); (*queue)->Release(queue); (*queue)=NULL; // Just in case queue is redefined as static in the future // PsychGetPrecisionTimerSeconds(timeValueOutput); // Less precise strategy than using event.timestamp return(PsychError_none); }
// ----------------------------------------------------------------------------- UInt64 usecs_since_startup() { UnsignedWide usecs = {0, 0}; Microseconds(&usecs); return UnsignedWideToUInt64(usecs); }