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@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 */ 40static DWORD start; 41 42#ifndef USE_GETTICKCOUNT 43/* Store if a high-resolution performance counter exists on the system */ 44static BOOL hires_timer_available; 45/* The first high-resolution ticks value of the application */ 46static LARGE_INTEGER hires_start_ticks; 47/* The number of ticks per second of the high-resolution performance counter */ 48static LARGE_INTEGER hires_ticks_per_second; 49#endif 50 51void 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 73Uint32 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 107void SDL_Delay(Uint32 ms) 108{ 109 Sleep(ms); 110} 111 112/* Data to handle a single periodic alarm */ 113static UINT timerID = 0; 114 115static void CALLBACK HandleAlarm(UINT uID, UINT uMsg, DWORD_PTR dwUser, 116 DWORD_PTR dw1, DWORD_PTR dw2) 117{ 118 SDL_ThreadedTimerCheck(); 119} 120 121 122int 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 141void SDL_SYS_TimerQuit(void) 142{ 143 if ( timerID ) { 144 timeKillEvent(timerID); 145 } 146 timeEndPeriod(TIMER_RESOLUTION); 147} 148 149int SDL_SYS_StartTimer(void) 150{ 151 SDL_SetError("Internal logic error: Win32 uses threaded timer"); 152 return(-1); 153} 154 155void SDL_SYS_StopTimer(void) 156{ 157 return; 158} 159 160#endif /* SDL_TIMER_WIN32 */ 161