src/timer/wince/SDL_systimer.c
author Sam Lantinga
Sat, 19 Sep 2009 13:29:40 +0000
changeset 3280 00cace2d9080
parent 2859 99210400e8b9
child 3697 f7b03b6838cb
permissions -rw-r--r--
Merged a cleaned up version of Jiang's code changes from Google Summer of Code 2009
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 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_WINCE
    25 
    26 #define WIN32_LEAN_AND_MEAN
    27 #include <windows.h>
    28 #include <mmsystem.h>
    29 
    30 #include "SDL_thread.h"
    31 #include "SDL_timer.h"
    32 #include "../SDL_timer_c.h"
    33 
    34 static Uint64 start_date;
    35 static Uint64 start_ticks;
    36 
    37 static Uint64
    38 wce_ticks(void)
    39 {
    40     return ((Uint64) GetTickCount());
    41 }
    42 
    43 static Uint64
    44 wce_date(void)
    45 {
    46     union
    47     {
    48         FILETIME ftime;
    49         Uint64 itime;
    50     } ftime;
    51     SYSTEMTIME stime;
    52 
    53     GetSystemTime(&stime);
    54     SystemTimeToFileTime(&stime, &ftime.ftime);
    55     ftime.itime /= 10000;       // Convert 100ns intervals to 1ms intervals
    56     // Remove ms portion, which can't be relied on
    57     ftime.itime -= (ftime.itime % 1000);
    58     return (ftime.itime);
    59 }
    60 
    61 static Sint32
    62 wce_rel_ticks(void)
    63 {
    64     return ((Sint32) (wce_ticks() - start_ticks));
    65 }
    66 
    67 static Sint32
    68 wce_rel_date(void)
    69 {
    70     return ((Sint32) (wce_date() - start_date));
    71 }
    72 
    73 /* Return time in ms relative to when SDL was started */
    74 Uint32
    75 SDL_GetTicks()
    76 {
    77     Sint32 offset = wce_rel_date() - wce_rel_ticks();
    78     if ((offset < -1000) || (offset > 1000)) {
    79 //    fprintf(stderr,"Time desync(%+d), resyncing\n",offset/1000);
    80         start_ticks -= offset;
    81     }
    82 
    83     return ((Uint32) wce_rel_ticks());
    84 }
    85 
    86 /* Give up approx. givem milliseconds to the OS. */
    87 void
    88 SDL_Delay(Uint32 ms)
    89 {
    90     Sleep(ms);
    91 }
    92 
    93 /* Recard start-time of application for reference */
    94 void
    95 SDL_StartTicks(void)
    96 {
    97     start_date = wce_date();
    98     start_ticks = wce_ticks();
    99 }
   100 
   101 static UINT WIN_timer;
   102 
   103 #if ( _WIN32_WCE <= 420 )
   104 
   105 static HANDLE timersThread = 0;
   106 static HANDLE timersQuitEvent = 0;
   107 
   108 DWORD
   109 TimersThreadProc(void *data)
   110 {
   111     while (WaitForSingleObject(timersQuitEvent, 10) == WAIT_TIMEOUT) {
   112         SDL_ThreadedTimerCheck();
   113     }
   114     return 0;
   115 }
   116 
   117 int
   118 SDL_SYS_TimerInit(void)
   119 {
   120     // create a thread to process a threaded timers
   121     // SetTimer does not suit the needs because 
   122     // TimerCallbackProc will be called only when WM_TIMER occured
   123 
   124     timersQuitEvent = CreateEvent(0, TRUE, FALSE, 0);
   125     if (!timersQuitEvent) {
   126         SDL_SetError("Cannot create event for timers thread");
   127         return -1;
   128     }
   129     timersThread = CreateThread(NULL, 0, TimersThreadProc, 0, 0, 0);
   130     if (!timersThread) {
   131         SDL_SetError
   132             ("Cannot create timers thread, check amount of RAM available");
   133         return -1;
   134     }
   135     SetThreadPriority(timersThread, THREAD_PRIORITY_HIGHEST);
   136 
   137     return (SDL_SetTimerThreaded(1));
   138 }
   139 
   140 void
   141 SDL_SYS_TimerQuit(void)
   142 {
   143     SetEvent(timersQuitEvent);
   144     if (WaitForSingleObject(timersThread, 2000) == WAIT_TIMEOUT)
   145         TerminateThread(timersThread, 0);
   146     CloseHandle(timersThread);
   147     CloseHandle(timersQuitEvent);
   148     return;
   149 }
   150 
   151 #else
   152 
   153 #pragma comment(lib, "mmtimer.lib")
   154 
   155 /* Data to handle a single periodic alarm */
   156 static UINT timerID = 0;
   157 
   158 static void CALLBACK
   159 HandleAlarm(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
   160 {
   161     SDL_ThreadedTimerCheck();
   162 }
   163 
   164 
   165 int
   166 SDL_SYS_TimerInit(void)
   167 {
   168     MMRESULT result;
   169 
   170     /* Set timer resolution */
   171     result = timeBeginPeriod(TIMER_RESOLUTION);
   172     if (result != TIMERR_NOERROR) {
   173         SDL_SetError("Warning: Can't set %d ms timer resolution",
   174                      TIMER_RESOLUTION);
   175     }
   176     /* Allow 10 ms of drift so we don't chew on CPU */
   177     timerID =
   178         timeSetEvent(TIMER_RESOLUTION, 1, HandleAlarm, 0, TIME_PERIODIC);
   179     if (!timerID) {
   180         SDL_SetError("timeSetEvent() failed");
   181         return (-1);
   182     }
   183     return (SDL_SetTimerThreaded(1));
   184 }
   185 
   186 void
   187 SDL_SYS_TimerQuit(void)
   188 {
   189     if (timerID) {
   190         timeKillEvent(timerID);
   191     }
   192     timeEndPeriod(TIMER_RESOLUTION);
   193 }
   194 
   195 #endif
   196 
   197 int
   198 SDL_SYS_StartTimer(void)
   199 {
   200     SDL_SetError("Internal logic error: WinCE uses threaded timer");
   201     return (-1);
   202 }
   203 
   204 void
   205 SDL_SYS_StopTimer(void)
   206 {
   207     return;
   208 }
   209 
   210 #endif /* SDL_TIMER_WINCE */
   211 /* vi: set ts=4 sw=4 expandtab: */