mirror of
				https://github.com/dolphin-emu/dolphin.git
				synced 2025-10-27 10:29:07 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			122 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2008 Dolphin Emulator Project
 | |
| // SPDX-License-Identifier: GPL-2.0-or-later
 | |
| 
 | |
| #include "Common/Timer.h"
 | |
| 
 | |
| #include <chrono>
 | |
| 
 | |
| #ifdef _WIN32
 | |
| #include <Windows.h>
 | |
| #include <ctime>
 | |
| #include <timeapi.h>
 | |
| #else
 | |
| #include <sys/time.h>
 | |
| #endif
 | |
| 
 | |
| #include "Common/CommonTypes.h"
 | |
| 
 | |
| namespace Common
 | |
| {
 | |
| template <typename Clock, typename Duration>
 | |
| static typename Clock::rep time_now()
 | |
| {
 | |
|   return std::chrono::time_point_cast<Duration>(Clock::now()).time_since_epoch().count();
 | |
| }
 | |
| 
 | |
| template <typename Duration>
 | |
| static auto steady_time_now()
 | |
| {
 | |
|   return time_now<std::chrono::steady_clock, Duration>();
 | |
| }
 | |
| 
 | |
| u64 Timer::NowUs()
 | |
| {
 | |
|   return steady_time_now<std::chrono::microseconds>();
 | |
| }
 | |
| 
 | |
| u64 Timer::NowMs()
 | |
| {
 | |
|   return steady_time_now<std::chrono::milliseconds>();
 | |
| }
 | |
| 
 | |
| void Timer::Start()
 | |
| {
 | |
|   m_start_ms = NowMs();
 | |
|   m_end_ms = 0;
 | |
|   m_running = true;
 | |
| }
 | |
| 
 | |
| void Timer::StartWithOffset(u64 offset)
 | |
| {
 | |
|   Start();
 | |
|   m_start_ms -= offset;
 | |
| }
 | |
| 
 | |
| void Timer::Stop()
 | |
| {
 | |
|   m_end_ms = NowMs();
 | |
|   m_running = false;
 | |
| }
 | |
| 
 | |
| u64 Timer::ElapsedMs() const
 | |
| {
 | |
|   const u64 end = m_running ? NowMs() : m_end_ms;
 | |
|   // Can handle up to 1 rollover event (underflow produces correct result)
 | |
|   // If Start() has never been called, will return 0
 | |
|   return end - m_start_ms;
 | |
| }
 | |
| 
 | |
| u64 Timer::GetLocalTimeSinceJan1970()
 | |
| {
 | |
|   // TODO Would really, really like to use std::chrono here, but Windows did not support
 | |
|   // std::chrono::current_zone() until 19H1, and other compilers don't even provide support for
 | |
|   // timezone-related parts of chrono. Someday!
 | |
|   // see https://bugs.dolphin-emu.org/issues/13007#note-4
 | |
|   time_t sysTime, tzDiff, tzDST;
 | |
|   time(&sysTime);
 | |
|   tm* gmTime = localtime(&sysTime);
 | |
| 
 | |
|   // Account for DST where needed
 | |
|   if (gmTime->tm_isdst == 1)
 | |
|     tzDST = 3600;
 | |
|   else
 | |
|     tzDST = 0;
 | |
| 
 | |
|   // Lazy way to get local time in sec
 | |
|   gmTime = gmtime(&sysTime);
 | |
|   tzDiff = sysTime - mktime(gmTime);
 | |
| 
 | |
|   return static_cast<u64>(sysTime + tzDiff + tzDST);
 | |
| }
 | |
| 
 | |
| void Timer::IncreaseResolution()
 | |
| {
 | |
| #ifdef _WIN32
 | |
|   // Disable execution speed and timer resolution throttling process-wide.
 | |
|   // This mainly will keep Dolphin marked as high performance if it's in the background. The OS
 | |
|   // should make it high performance if it's in the foreground anyway (or for some specific
 | |
|   // threads e.g. audio).
 | |
|   // This is best-effort (i.e. the call may fail on older versions of Windows, where such throttling
 | |
|   // doesn't exist, anyway), and we don't bother reverting once set.
 | |
|   // This adjusts behavior on CPUs with "performance" and "efficiency" cores
 | |
|   PROCESS_POWER_THROTTLING_STATE PowerThrottling{};
 | |
|   PowerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
 | |
|   PowerThrottling.ControlMask =
 | |
|       PROCESS_POWER_THROTTLING_EXECUTION_SPEED | PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
 | |
|   PowerThrottling.StateMask = 0;
 | |
|   SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottling,
 | |
|                         sizeof(PowerThrottling));
 | |
| 
 | |
|   // Not actually sure how useful this is these days.. :')
 | |
|   timeBeginPeriod(1);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void Timer::RestoreResolution()
 | |
| {
 | |
| #ifdef _WIN32
 | |
|   timeEndPeriod(1);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| }  // Namespace Common
 |