src/timer/win32/SDL_systimer.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 07 Oct 2002 15:19:17 +0000
changeset 517 621ab54c1dde
parent 453 a6fa62b1be09
child 769 b8d311d90021
permissions -rw-r--r--
Fixed building timer code on Windows CE
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 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     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 #include <windows.h>
    29 #include <mmsystem.h>
    30 
    31 #include "SDL_timer.h"
    32 #include "SDL_timer_c.h"
    33 #include "SDL_error.h"
    34 
    35 #ifdef _WIN32_WCE
    36 #define USE_GETTICKCOUNT
    37 #define USE_SETTIMER
    38 #endif
    39 
    40 #define TIME_WRAP_VALUE	(~(DWORD)0)
    41 
    42 /* The first (low-resolution) ticks value of the application */
    43 static DWORD start;
    44 
    45 #ifndef USE_GETTICKCOUNT
    46 /* Store if a high-resolution performance counter exists on the system */
    47 static BOOL hires_timer_available;
    48 /* The first high-resolution ticks value of the application */
    49 static LARGE_INTEGER hires_start_ticks;
    50 /* The number of ticks per second of the high-resolution performance counter */
    51 static LARGE_INTEGER hires_ticks_per_second;
    52 #endif
    53 
    54 void SDL_StartTicks(void)
    55 {
    56 	/* Set first ticks value */
    57 #ifdef USE_GETTICKCOUNT
    58 	start = GetTickCount();
    59 #else
    60 #if 0 /* Apparently there are problems with QPC on Win2K */
    61 	if (QueryPerformanceFrequency(&hires_ticks_per_second) == TRUE)
    62 	{
    63 		hires_timer_available = TRUE;
    64 		QueryPerformanceCounter(&hires_start_ticks);
    65 	}
    66 	else
    67 #endif
    68 	{
    69 		hires_timer_available = FALSE;
    70 		timeBeginPeriod(1);		/* use 1 ms timer precision */
    71 		start = timeGetTime();
    72 	}
    73 #endif
    74 }
    75 
    76 Uint32 SDL_GetTicks(void)
    77 {
    78 	DWORD now, ticks;
    79 #ifndef USE_GETTICKCOUNT
    80 	LARGE_INTEGER hires_now;
    81 #endif
    82 
    83 #ifdef USE_GETTICKCOUNT
    84 	now = GetTickCount();
    85 #else
    86 	if (hires_timer_available)
    87 	{
    88 		QueryPerformanceCounter(&hires_now);
    89 
    90 		hires_now.QuadPart -= hires_start_ticks.QuadPart;
    91 		hires_now.QuadPart *= 1000;
    92 		hires_now.QuadPart /= hires_ticks_per_second.QuadPart;
    93 
    94 		return (DWORD)hires_now.QuadPart;
    95 	}
    96 	else
    97 	{
    98 		now = timeGetTime();
    99 	}
   100 #endif
   101 
   102 	if ( now < start ) {
   103 		ticks = (TIME_WRAP_VALUE-start) + now;
   104 	} else {
   105 		ticks = (now - start);
   106 	}
   107 	return(ticks);
   108 }
   109 
   110 void SDL_Delay(Uint32 ms)
   111 {
   112 	Sleep(ms);
   113 }
   114 
   115 #ifdef USE_SETTIMER
   116 
   117 static UINT WIN_timer;
   118 
   119 int SDL_SYS_TimerInit(void)
   120 {
   121 	return(0);
   122 }
   123 
   124 void SDL_SYS_TimerQuit(void)
   125 {
   126 	return;
   127 }
   128 
   129 /* Forward declaration because this is called by the timer callback */
   130 int SDL_SYS_StartTimer(void);
   131 
   132 static VOID CALLBACK TimerCallbackProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
   133 {
   134 	Uint32 ms;
   135 
   136 	ms = SDL_alarm_callback(SDL_alarm_interval);
   137 	if ( ms != SDL_alarm_interval ) {
   138 		KillTimer(NULL, idEvent);
   139 		if ( ms ) {
   140 			SDL_alarm_interval = ROUND_RESOLUTION(ms);
   141 			SDL_SYS_StartTimer();
   142 		} else {
   143 			SDL_alarm_interval = 0;
   144 		}
   145 	}
   146 }
   147 
   148 int SDL_SYS_StartTimer(void)
   149 {
   150 	int retval;
   151 
   152 	WIN_timer = SetTimer(NULL, 0, SDL_alarm_interval, TimerCallbackProc);
   153 	if ( WIN_timer ) {
   154 		retval = 0;
   155 	} else {
   156 		retval = -1;
   157 	}
   158 	return retval;
   159 }
   160 
   161 void SDL_SYS_StopTimer(void)
   162 {
   163 	if ( WIN_timer ) {
   164 		KillTimer(NULL, WIN_timer);
   165 		WIN_timer = 0;
   166 	}
   167 }
   168 
   169 #else /* !USE_SETTIMER */
   170 
   171 /* Data to handle a single periodic alarm */
   172 static UINT timerID = 0;
   173 
   174 static void CALLBACK HandleAlarm(UINT uID,  UINT uMsg, DWORD dwUser,
   175 						DWORD dw1, DWORD dw2)
   176 {
   177 	SDL_ThreadedTimerCheck();
   178 }
   179 
   180 
   181 int SDL_SYS_TimerInit(void)
   182 {
   183 	MMRESULT result;
   184 
   185 	/* Set timer resolution */
   186 	result = timeBeginPeriod(TIMER_RESOLUTION);
   187 	if ( result != TIMERR_NOERROR ) {
   188 		SDL_SetError("Warning: Can't set %d ms timer resolution",
   189 							TIMER_RESOLUTION);
   190 	}
   191 	/* Allow 10 ms of drift so we don't chew on CPU */
   192 	timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC);
   193 	if ( ! timerID ) {
   194 		SDL_SetError("timeSetEvent() failed");
   195 		return(-1);
   196 	}
   197 	return(SDL_SetTimerThreaded(1));
   198 }
   199 
   200 void SDL_SYS_TimerQuit(void)
   201 {
   202 	if ( timerID ) {
   203 		timeKillEvent(timerID);
   204 	}
   205 	timeEndPeriod(TIMER_RESOLUTION);
   206 }
   207 
   208 int SDL_SYS_StartTimer(void)
   209 {
   210 	SDL_SetError("Internal logic error: Win32 uses threaded timer");
   211 	return(-1);
   212 }
   213 
   214 void SDL_SYS_StopTimer(void)
   215 {
   216 	return;
   217 }
   218 
   219 #endif /* USE_SETTIMER */