void doneTiming() { // terminate "stuck" thread SetEvent(endStuckEvent); Real_WaitForSingleObject(stuckThread,500); CloseHandle(stuckThread); CloseHandle(stuckTimer); // make sure all currently active waits are finished ResetEvent(resyncEvent); SetEvent(nextFrameEvent); if(waitCounter) ResetEvent(noOneWaiting); else SetEvent(noOneWaiting); while(Real_WaitForSingleObject(noOneWaiting,5) == WAIT_TIMEOUT) if(!waitCounter) break; // these functions depend on critical sections that we're about to delete. UnhookFunction(&Real_timeSetEvent); UnhookFunction(&Real_timeKillEvent); UnhookFunction(&Real_SetTimer); EnterCriticalSection(&TimerAllocLock); LeaveCriticalSection(&TimerAllocLock); DeleteCriticalSection(&TimerAllocLock); EnterCriticalSection(&TimerSeedLock); TimersSeeded = true; LeaveCriticalSection(&TimerSeedLock); DeleteCriticalSection(&TimerSeedLock); // we have to remove those, because code we call on deinitilization (especially directshow related) // might be using them. UnhookFunction(&Real_Sleep); UnhookFunction(&Real_WaitForSingleObject); UnhookFunction(&Real_WaitForMultipleObjects); UnhookFunction(&Real_MsgWaitForMultipleObjects); CloseHandle(nextFrameEvent); CloseHandle(resyncEvent); CloseHandle(noOneWaiting); CloseHandle(endStuckEvent); int runTime = Real_timeGetTime() - realStartTime; timeEndPeriod(1); if(runTime) { int rate = MulDiv(currentFrame,100*1000,runTime); printLog("timing: %d.%02d frames per second on average\n",rate/100,rate%100); } }
void nextFrameTiming() { ResetEvent(resyncEvent); SetEvent(nextFrameEvent); if(waitCounter) ResetEvent(noOneWaiting); else SetEvent(noOneWaiting); while(Real_WaitForSingleObject(noOneWaiting,5) == WAIT_TIMEOUT) if(!waitCounter) break; ResetEvent(nextFrameEvent); SetEvent(resyncEvent); DWORD oldFrameTime = UMulDiv(currentFrame,1000*frameRateDenom,frameRateScaled); DWORD newFrameTime = UMulDiv(currentFrame+1,1000*frameRateDenom,frameRateScaled); ProcessEventTimers(newFrameTime - oldFrameTime); if(!currentFrame) realStartTime = Real_timeGetTime(); if(params.EnableAutoSkip) { LARGE_INTEGER due; due.QuadPart = -10*1000*__int64(params.FrameTimeout); SetWaitableTimer(stuckTimer,&due,0,0,0,FALSE); } if(exitNextFrame) { printLog("main: clean exit requested, doing my best...\n"); ExitProcess(0); } // make sure there's always a message in the queue for next frame // (some old hjb intros stop when there's no new messages) PostMessage(GetForegroundWindow(),WM_NULL,0,0); currentFrame++; timerHammeringCounter = 0; }
static void seedAllTimers() { if(!TimersSeeded) { EnterCriticalSection(&TimerSeedLock); if(!TimersSeeded) { Real_QueryPerformanceCounter(&firstTimeQPC); firstTimeTGT = Real_timeGetTime(); Real_GetSystemTimeAsFileTime(&firstTimeGSTAFT); // never actually mark timers as seeded in the first frame (i.e. before anything // was presented) - you get problems with config dialogs etc. otherweise TimersSeeded = getFrameTiming() != 0; } LeaveCriticalSection(&TimerSeedLock); } }
static DWORD WINAPI Mine_timeGetTime(void) { DWORD dwTickCount = Real_timeGetTime(); EnterCriticalSection(&g_csTimeGetTime); static DWORD dwLastCount = 0; static DWORD dwLastResult = 0; if (dwLastCount == 0) { dwLastCount = dwTickCount; dwLastResult = dwTickCount; } else { dwLastResult += (DWORD)((dwTickCount - dwLastCount) * g_fSpeed + 0.5); dwLastCount = dwTickCount; dwTickCount = dwLastResult; } LeaveCriticalSection(&g_csTimeGetTime); return dwTickCount; }