1cb007542SIngo Weinhold /* 2cb007542SIngo Weinhold * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3cb007542SIngo Weinhold * Distributed under the terms of the MIT License. 4cb007542SIngo Weinhold */ 5cb007542SIngo Weinhold #include "TimeComputer.h" 6cb007542SIngo Weinhold 7*b5142f76SAugustin Cavalier #include <OS.h> 8*b5142f76SAugustin Cavalier 9cb007542SIngo Weinhold 10cb007542SIngo Weinhold TimeComputer::TimeComputer() 11cb007542SIngo Weinhold : 12cb007542SIngo Weinhold fRealTime(0), 13cb007542SIngo Weinhold fPerformanceTime(0), 14cb007542SIngo Weinhold fDrift(1), 15cb007542SIngo Weinhold fFrameRate(1000000), 16cb007542SIngo Weinhold fUsecsPerFrame(1), 17cb007542SIngo Weinhold fPerformanceTimeBase(0), 18cb007542SIngo Weinhold fFrameBase(0), 19cb007542SIngo Weinhold fResetTimeBase(true), 20cb007542SIngo Weinhold fFirstEntry(0), 21cb007542SIngo Weinhold fLastEntry(0) 22cb007542SIngo Weinhold { 23cb007542SIngo Weinhold } 24cb007542SIngo Weinhold 25cb007542SIngo Weinhold 26cb007542SIngo Weinhold void 27cb007542SIngo Weinhold TimeComputer::Init(float frameRate, bigtime_t realBaseTime) 28cb007542SIngo Weinhold { 29cb007542SIngo Weinhold fRealTime = realBaseTime; 30cb007542SIngo Weinhold fPerformanceTime = 0; 31cb007542SIngo Weinhold fDrift = 1; 32cb007542SIngo Weinhold SetFrameRate(frameRate); 33cb007542SIngo Weinhold } 34cb007542SIngo Weinhold 35cb007542SIngo Weinhold 36cb007542SIngo Weinhold void 37cb007542SIngo Weinhold TimeComputer::SetFrameRate(float frameRate) 38cb007542SIngo Weinhold { 39cb007542SIngo Weinhold if (frameRate == fFrameRate) 40cb007542SIngo Weinhold return; 41cb007542SIngo Weinhold 42cb007542SIngo Weinhold fFrameRate = frameRate; 43cb007542SIngo Weinhold fUsecsPerFrame = (double)1000000 / fFrameRate; 44cb007542SIngo Weinhold fResetTimeBase = true; 45cb007542SIngo Weinhold fFirstEntry = 0; 46cb007542SIngo Weinhold fLastEntry = 0; 47cb007542SIngo Weinhold } 48cb007542SIngo Weinhold 49cb007542SIngo Weinhold 50cb007542SIngo Weinhold void 51cb007542SIngo Weinhold TimeComputer::AddTimeStamp(bigtime_t realTime, uint64 frames) 52cb007542SIngo Weinhold { 53cb007542SIngo Weinhold bigtime_t estimatedPerformanceTime = fPerformanceTime 54cb007542SIngo Weinhold + bigtime_t((realTime - fRealTime) * fDrift); 55cb007542SIngo Weinhold 56*b5142f76SAugustin Cavalier if (realTime < fRealTime) 57*b5142f76SAugustin Cavalier debugger("TimeComputer: real time went backwards!"); 58cb007542SIngo Weinhold fRealTime = realTime; 59cb007542SIngo Weinhold 60cb007542SIngo Weinhold if (fResetTimeBase) { 61cb007542SIngo Weinhold // use the extrapolated performance time at the given real time 62cb007542SIngo Weinhold fPerformanceTime = estimatedPerformanceTime; 63cb007542SIngo Weinhold fPerformanceTimeBase = estimatedPerformanceTime; 64cb007542SIngo Weinhold fFrameBase = frames; 65cb007542SIngo Weinhold fResetTimeBase = false; 66cb007542SIngo Weinhold _AddEntry(fRealTime, fPerformanceTime); 67cf238ffcSMichael Lotz fFirstEntry = fLastEntry; 68cb007542SIngo Weinhold return; 69cb007542SIngo Weinhold } 70cb007542SIngo Weinhold 71cb007542SIngo Weinhold // add entry 72cb007542SIngo Weinhold bigtime_t performanceTime = fPerformanceTimeBase 73cb007542SIngo Weinhold + bigtime_t((frames - fFrameBase) * fUsecsPerFrame); 74cb007542SIngo Weinhold _AddEntry(realTime, performanceTime); 75cb007542SIngo Weinhold 76cb007542SIngo Weinhold // Update performance time and drift. We don't use the given 77cb007542SIngo Weinhold // performance time directly, but average it with the estimated 78cb007542SIngo Weinhold // performance time. 79cb007542SIngo Weinhold fPerformanceTime = (performanceTime + estimatedPerformanceTime) / 2; 80cb007542SIngo Weinhold 81cb007542SIngo Weinhold Entry& entry = fEntries[fFirstEntry]; 82cb007542SIngo Weinhold fDrift = double(fPerformanceTime - entry.performanceTime) 83cb007542SIngo Weinhold / double(fRealTime - entry.realTime); 84cb007542SIngo Weinhold } 85cb007542SIngo Weinhold 86cb007542SIngo Weinhold 87cb007542SIngo Weinhold void 88cb007542SIngo Weinhold TimeComputer::_AddEntry(bigtime_t realTime, bigtime_t performanceTime) 89cb007542SIngo Weinhold { 90cb007542SIngo Weinhold fLastEntry = (fLastEntry + 1) % kEntryCount; 91cb007542SIngo Weinhold Entry& entry = fEntries[fLastEntry]; 92cb007542SIngo Weinhold entry.realTime = realTime; 93cb007542SIngo Weinhold entry.performanceTime = performanceTime; 94cb007542SIngo Weinhold 95cb007542SIngo Weinhold if (fLastEntry == fFirstEntry) 96cb007542SIngo Weinhold fFirstEntry = (fFirstEntry + 1) % kEntryCount; 97cb007542SIngo Weinhold } 98