src/timer/wince/SDL_systimer.c
author Sam Lantinga
Sat, 11 Mar 2006 23:46:45 +0000
changeset 1497 420b3f47806d
parent 1433 bb6839704ed6
child 1635 92947e3a18db
permissions -rw-r--r--
Fixes from Dmitry Yakimov:

fixed bugs 159 and 160:

+ added threaded timers support
! fixed restoring sdl window focus (AV in windows message handler)
! disabled forgotten cdrom and joystick in config file.
* disabled minimizing sdl window while loosing focus.
PocketPC does not have a task bar, so it is an inconvenient and unusual
behaviour for PPC users.
+ added WIN_Paint handler for GAPI
! fixed loosing focus while using GAPI videi driver

+ added TestTimer project
* removed unnecessary macros (ENABLE_WINDIB ...) from projects
icculus@1180
     1
/*
icculus@1180
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
icculus@1180
     4
icculus@1180
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
icculus@1180
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
icculus@1180
     9
icculus@1180
    10
    This library is distributed in the hope that it will be useful,
icculus@1180
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
icculus@1180
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
icculus@1180
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
icculus@1180
    18
icculus@1180
    19
    Sam Lantinga
icculus@1180
    20
    slouken@libsdl.org
icculus@1180
    21
*/
slouken@1402
    22
#include "SDL_config.h"
icculus@1180
    23
slouken@1433
    24
#define WIN32_LEAN_AND_MEAN
slouken@1433
    25
#include <windows.h>
icculus@1180
    26
#include <mmsystem.h>
icculus@1180
    27
slouken@1497
    28
#include "SDL_thread.h"
icculus@1180
    29
#include "SDL_timer.h"
slouken@1361
    30
#include "../SDL_timer_c.h"
icculus@1180
    31
icculus@1180
    32
static Uint64 start_date;
icculus@1180
    33
static Uint64 start_ticks;
icculus@1180
    34
icculus@1180
    35
static Uint64 wce_ticks(void)
icculus@1180
    36
{
icculus@1180
    37
  return((Uint64)GetTickCount());
icculus@1180
    38
}
icculus@1180
    39
icculus@1180
    40
static Uint64 wce_date(void)
icculus@1180
    41
{
icculus@1180
    42
  union
icculus@1180
    43
  {
icculus@1180
    44
	FILETIME ftime;
icculus@1180
    45
	Uint64 itime;
icculus@1180
    46
  } ftime;
icculus@1180
    47
  SYSTEMTIME stime;
icculus@1180
    48
icculus@1180
    49
  GetSystemTime(&stime);
icculus@1180
    50
  SystemTimeToFileTime(&stime,&ftime.ftime);
icculus@1180
    51
  ftime.itime/=10000; // Convert 100ns intervals to 1ms intervals
icculus@1180
    52
  // Remove ms portion, which can't be relied on
icculus@1180
    53
  ftime.itime -= (ftime.itime % 1000);
icculus@1180
    54
  return(ftime.itime);
icculus@1180
    55
}
icculus@1180
    56
icculus@1180
    57
static Sint32 wce_rel_ticks(void)
icculus@1180
    58
{
icculus@1180
    59
  return((Sint32)(wce_ticks()-start_ticks));
icculus@1180
    60
}
icculus@1180
    61
icculus@1180
    62
static Sint32 wce_rel_date(void)
icculus@1180
    63
{
icculus@1180
    64
  return((Sint32)(wce_date()-start_date));
icculus@1180
    65
}
icculus@1180
    66
icculus@1180
    67
/* Return time in ms relative to when SDL was started */
icculus@1180
    68
Uint32 SDL_GetTicks()
icculus@1180
    69
{
icculus@1180
    70
  Sint32 offset=wce_rel_date()-wce_rel_ticks();
icculus@1180
    71
  if((offset < -1000) || (offset > 1000))
icculus@1180
    72
  {
icculus@1180
    73
//    fprintf(stderr,"Time desync(%+d), resyncing\n",offset/1000);
icculus@1180
    74
	start_ticks-=offset;
icculus@1180
    75
  }
icculus@1180
    76
icculus@1180
    77
  return((Uint32)wce_rel_ticks());
icculus@1180
    78
}
icculus@1180
    79
icculus@1180
    80
/* Give up approx. givem milliseconds to the OS. */
icculus@1180
    81
void SDL_Delay(Uint32 ms)
icculus@1180
    82
{
icculus@1180
    83
  Sleep(ms);
icculus@1180
    84
}
icculus@1180
    85
icculus@1180
    86
/* Recard start-time of application for reference */
icculus@1180
    87
void SDL_StartTicks(void)
icculus@1180
    88
{
icculus@1180
    89
  start_date=wce_date();
icculus@1180
    90
  start_ticks=wce_ticks();
icculus@1180
    91
}
icculus@1180
    92
icculus@1180
    93
static UINT WIN_timer;
icculus@1180
    94
slouken@1497
    95
#if ( _WIN32_WCE <= 420 )
slouken@1497
    96
slouken@1497
    97
static HANDLE timersThread = 0;
slouken@1497
    98
static HANDLE timersQuitEvent = 0;
slouken@1497
    99
slouken@1497
   100
DWORD TimersThreadProc(void *data)
slouken@1497
   101
{
slouken@1497
   102
	while(WaitForSingleObject(timersQuitEvent, 10) == WAIT_TIMEOUT)
slouken@1497
   103
	{
slouken@1497
   104
		SDL_ThreadedTimerCheck();
slouken@1497
   105
	}
slouken@1497
   106
	return 0;
slouken@1497
   107
}
slouken@1497
   108
icculus@1180
   109
int SDL_SYS_TimerInit(void)
icculus@1180
   110
{
slouken@1497
   111
	// create a thread to process a threaded timers
slouken@1497
   112
	// SetTimer does not suit the needs because 
slouken@1497
   113
	// TimerCallbackProc will be called only when WM_TIMER occured
slouken@1497
   114
slouken@1497
   115
	timersQuitEvent = CreateEvent(0, TRUE, FALSE, 0);
slouken@1497
   116
	if( !timersQuitEvent )
slouken@1497
   117
	{
slouken@1497
   118
		SDL_SetError("Cannot create event for timers thread");
slouken@1497
   119
		return -1;
slouken@1497
   120
	}
slouken@1497
   121
	timersThread = CreateThread(NULL, 0, TimersThreadProc, 0, 0, 0);
slouken@1497
   122
	if( !timersThread )
slouken@1497
   123
	{
slouken@1497
   124
		SDL_SetError("Cannot create timers thread, check amount of RAM available");
slouken@1497
   125
		return -1;
slouken@1497
   126
	}
slouken@1497
   127
	SetThreadPriority(timersThread, THREAD_PRIORITY_HIGHEST);
slouken@1497
   128
slouken@1497
   129
	return(SDL_SetTimerThreaded(1));
icculus@1180
   130
}
icculus@1180
   131
icculus@1180
   132
void SDL_SYS_TimerQuit(void)
icculus@1180
   133
{
slouken@1497
   134
	SetEvent(timersQuitEvent);
slouken@1497
   135
	if( WaitForSingleObject(timersThread, 2000) == WAIT_TIMEOUT )
slouken@1497
   136
		TerminateThread(timersThread, 0);
slouken@1497
   137
	CloseHandle(timersThread);
slouken@1497
   138
	CloseHandle(timersQuitEvent);
icculus@1180
   139
	return;
icculus@1180
   140
}
icculus@1180
   141
slouken@1497
   142
#else
slouken@1497
   143
slouken@1497
   144
#pragma comment(lib, "mmtimer.lib")
slouken@1497
   145
slouken@1497
   146
/* Data to handle a single periodic alarm */
slouken@1497
   147
static UINT timerID = 0;
icculus@1180
   148
slouken@1497
   149
static void CALLBACK HandleAlarm(UINT uID,  UINT uMsg, DWORD dwUser,
slouken@1497
   150
						DWORD dw1, DWORD dw2)
icculus@1180
   151
{
slouken@1497
   152
	SDL_ThreadedTimerCheck();
slouken@1497
   153
}
slouken@1497
   154
slouken@1497
   155
slouken@1497
   156
int SDL_SYS_TimerInit(void)
slouken@1497
   157
{
slouken@1497
   158
	MMRESULT result;
icculus@1180
   159
slouken@1497
   160
	/* Set timer resolution */
slouken@1497
   161
	result = timeBeginPeriod(TIMER_RESOLUTION);
slouken@1497
   162
	if ( result != TIMERR_NOERROR ) {
slouken@1497
   163
		SDL_SetError("Warning: Can't set %d ms timer resolution",
slouken@1497
   164
							TIMER_RESOLUTION);
slouken@1497
   165
	}
slouken@1497
   166
	/* Allow 10 ms of drift so we don't chew on CPU */
slouken@1497
   167
	timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC);
slouken@1497
   168
	if ( ! timerID ) {
slouken@1497
   169
		SDL_SetError("timeSetEvent() failed");
slouken@1497
   170
		return(-1);
icculus@1180
   171
	}
slouken@1497
   172
	return(SDL_SetTimerThreaded(1));
icculus@1180
   173
}
icculus@1180
   174
slouken@1497
   175
void SDL_SYS_TimerQuit(void)
slouken@1497
   176
{
slouken@1497
   177
	if ( timerID ) {
slouken@1497
   178
		timeKillEvent(timerID);
slouken@1497
   179
	}
slouken@1497
   180
	timeEndPeriod(TIMER_RESOLUTION);
slouken@1497
   181
}
slouken@1497
   182
slouken@1497
   183
#endif
slouken@1497
   184
icculus@1180
   185
int SDL_SYS_StartTimer(void)
icculus@1180
   186
{
slouken@1497
   187
	SDL_SetError("Internal logic error: WinCE uses threaded timer");
slouken@1497
   188
	return(-1);
icculus@1180
   189
}
icculus@1180
   190
icculus@1180
   191
void SDL_SYS_StopTimer(void)
icculus@1180
   192
{
slouken@1497
   193
	return;
icculus@1180
   194
}