1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 #ifdef SDL_TIMER_WIN32 25 26 #define WIN32_LEAN_AND_MEAN 27 #include <windows.h> 28 #include <mmsystem.h> 29 30 #include "SDL_timer.h" 31 #include "../SDL_timer_c.h" 32 33 #ifdef _WIN32_WCE 34 #error This is WinCE. Please use src/timer/wince/SDL_systimer.c instead. 35 #endif 36 37 #define TIME_WRAP_VALUE (~(DWORD)0) 38 39 /* The first (low-resolution) ticks value of the application */ 40 static DWORD start; 41 42 #ifndef USE_GETTICKCOUNT 43 /* Store if a high-resolution performance counter exists on the system */ 44 static BOOL hires_timer_available; 45 /* The first high-resolution ticks value of the application */ 46 static LARGE_INTEGER hires_start_ticks; 47 /* The number of ticks per second of the high-resolution performance counter */ 48 static LARGE_INTEGER hires_ticks_per_second; 49 #endif 50 51 void SDL_StartTicks(void) 52 { 53 /* Set first ticks value */ 54 #ifdef USE_GETTICKCOUNT 55 start = GetTickCount(); 56 #else 57 #if 0 /* Apparently there are problems with QPC on Win2K */ 58 if (QueryPerformanceFrequency(&hires_ticks_per_second) == TRUE) 59 { 60 hires_timer_available = TRUE; 61 QueryPerformanceCounter(&hires_start_ticks); 62 } 63 else 64 #endif 65 { 66 hires_timer_available = FALSE; 67 timeBeginPeriod(1); /* use 1 ms timer precision */ 68 start = timeGetTime(); 69 } 70 #endif 71 } 72 73 Uint32 SDL_GetTicks(void) 74 { 75 DWORD now, ticks; 76 #ifndef USE_GETTICKCOUNT 77 LARGE_INTEGER hires_now; 78 #endif 79 80 #ifdef USE_GETTICKCOUNT 81 now = GetTickCount(); 82 #else 83 if (hires_timer_available) 84 { 85 QueryPerformanceCounter(&hires_now); 86 87 hires_now.QuadPart -= hires_start_ticks.QuadPart; 88 hires_now.QuadPart *= 1000; 89 hires_now.QuadPart /= hires_ticks_per_second.QuadPart; 90 91 return (DWORD)hires_now.QuadPart; 92 } 93 else 94 { 95 now = timeGetTime(); 96 } 97 #endif 98 99 if ( now < start ) { 100 ticks = (TIME_WRAP_VALUE-start) + now; 101 } else { 102 ticks = (now - start); 103 } 104 return(ticks); 105 } 106 107 void SDL_Delay(Uint32 ms) 108 { 109 Sleep(ms); 110 } 111 112 /* Data to handle a single periodic alarm */ 113 static UINT timerID = 0; 114 115 static void CALLBACK HandleAlarm(UINT uID, UINT uMsg, DWORD_PTR dwUser, 116 DWORD_PTR dw1, DWORD_PTR dw2) 117 { 118 SDL_ThreadedTimerCheck(); 119 } 120 121 122 int SDL_SYS_TimerInit(void) 123 { 124 MMRESULT result; 125 126 /* Set timer resolution */ 127 result = timeBeginPeriod(TIMER_RESOLUTION); 128 if ( result != TIMERR_NOERROR ) { 129 SDL_SetError("Warning: Can't set %d ms timer resolution", 130 TIMER_RESOLUTION); 131 } 132 /* Allow 10 ms of drift so we don't chew on CPU */ 133 timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC); 134 if ( ! timerID ) { 135 SDL_SetError("timeSetEvent() failed"); 136 return(-1); 137 } 138 return(SDL_SetTimerThreaded(1)); 139 } 140 141 void SDL_SYS_TimerQuit(void) 142 { 143 if ( timerID ) { 144 timeKillEvent(timerID); 145 } 146 timeEndPeriod(TIMER_RESOLUTION); 147 } 148 149 int SDL_SYS_StartTimer(void) 150 { 151 SDL_SetError("Internal logic error: Win32 uses threaded timer"); 152 return(-1); 153 } 154 155 void SDL_SYS_StopTimer(void) 156 { 157 return; 158 } 159 160 #endif /* SDL_TIMER_WIN32 */ 161