SDL  2.0
SDL_systimer.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #ifdef SDL_TIMER_WINDOWS
24 
25 #include "../../core/windows/SDL_windows.h"
26 #include <mmsystem.h>
27 
28 #include "SDL_timer.h"
29 #include "SDL_hints.h"
30 
31 
32 /* The first (low-resolution) ticks value of the application */
33 static DWORD start = 0;
34 static BOOL ticks_started = FALSE;
35 
36 /* Store if a high-resolution performance counter exists on the system */
37 static BOOL hires_timer_available;
38 /* The first high-resolution ticks value of the application */
39 static LARGE_INTEGER hires_start_ticks;
40 /* The number of ticks per second of the high-resolution performance counter */
41 static LARGE_INTEGER hires_ticks_per_second;
42 
43 static void
44 SDL_SetSystemTimerResolution(const UINT uPeriod)
45 {
46 #ifndef __WINRT__
47  static UINT timer_period = 0;
48 
49  if (uPeriod != timer_period) {
50  if (timer_period) {
51  timeEndPeriod(timer_period);
52  }
53 
54  timer_period = uPeriod;
55 
56  if (timer_period) {
57  timeBeginPeriod(timer_period);
58  }
59  }
60 #endif
61 }
62 
63 static void SDLCALL
64 SDL_TimerResolutionChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
65 {
66  UINT uPeriod;
67 
68  /* Unless the hint says otherwise, let's have good sleep precision */
69  if (hint && *hint) {
70  uPeriod = SDL_atoi(hint);
71  } else {
72  uPeriod = 1;
73  }
74  if (uPeriod || oldValue != hint) {
75  SDL_SetSystemTimerResolution(uPeriod);
76  }
77 }
78 
79 void
80 SDL_TicksInit(void)
81 {
82  if (ticks_started) {
83  return;
84  }
85  ticks_started = SDL_TRUE;
86 
87  /* if we didn't set a precision, set it high. This affects lots of things
88  on Windows besides the SDL timers, like audio callbacks, etc. */
90  SDL_TimerResolutionChanged, NULL);
91 
92  /* Set first ticks value */
93  /* QueryPerformanceCounter has had problems in the past, but lots of games
94  use it, so we'll rely on it here.
95  */
96  if (QueryPerformanceFrequency(&hires_ticks_per_second) == TRUE) {
97  hires_timer_available = TRUE;
98  QueryPerformanceCounter(&hires_start_ticks);
99  } else {
100  hires_timer_available = FALSE;
101 #ifndef __WINRT__
102  start = timeGetTime();
103 #endif /* __WINRT__ */
104  }
105 }
106 
107 void
108 SDL_TicksQuit(void)
109 {
111  SDL_TimerResolutionChanged, NULL);
112 
113  SDL_SetSystemTimerResolution(0); /* always release our timer resolution request. */
114 
115  start = 0;
116  ticks_started = SDL_FALSE;
117 }
118 
119 Uint32
120 SDL_GetTicks(void)
121 {
122  DWORD now = 0;
123  LARGE_INTEGER hires_now;
124 
125  if (!ticks_started) {
126  SDL_TicksInit();
127  }
128 
129  if (hires_timer_available) {
130  QueryPerformanceCounter(&hires_now);
131 
132  hires_now.QuadPart -= hires_start_ticks.QuadPart;
133  hires_now.QuadPart *= 1000;
134  hires_now.QuadPart /= hires_ticks_per_second.QuadPart;
135 
136  return (DWORD) hires_now.QuadPart;
137  } else {
138 #ifndef __WINRT__
139  now = timeGetTime();
140 #endif /* __WINRT__ */
141  }
142 
143  return (now - start);
144 }
145 
146 Uint64
148 {
149  LARGE_INTEGER counter;
150 
151  if (!QueryPerformanceCounter(&counter)) {
152  return SDL_GetTicks();
153  }
154  return counter.QuadPart;
155 }
156 
157 Uint64
159 {
160  LARGE_INTEGER frequency;
161 
162  if (!QueryPerformanceFrequency(&frequency)) {
163  return 1000;
164  }
165  return frequency.QuadPart;
166 }
167 
168 void
169 SDL_Delay(Uint32 ms)
170 {
171  /* Sleep() is not publicly available to apps in early versions of WinRT.
172  *
173  * Visual C++ 2013 Update 4 re-introduced Sleep() for Windows 8.1 and
174  * Windows Phone 8.1.
175  *
176  * Use the compiler version to determine availability.
177  *
178  * NOTE #1: _MSC_FULL_VER == 180030723 for Visual C++ 2013 Update 3.
179  * NOTE #2: Visual C++ 2013, when compiling for Windows 8.0 and
180  * Windows Phone 8.0, uses the Visual C++ 2012 compiler to build
181  * apps and libraries.
182  */
183 #if defined(__WINRT__) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER <= 180030723)
184  static HANDLE mutex = 0;
185  if (!mutex) {
186  mutex = CreateEventEx(0, 0, 0, EVENT_ALL_ACCESS);
187  }
188  WaitForSingleObjectEx(mutex, ms, FALSE);
189 #else
190  if (!ticks_started) {
191  SDL_TicksInit();
192  }
193 
194  Sleep(ms);
195 #endif
196 }
197 
198 #endif /* SDL_TIMER_WINDOWS */
199 
200 /* vi: set ts=4 sw=4 expandtab: */
Uint64 SDL_GetPerformanceFrequency(void)
Get the count per second of the high resolution counter.
GLuint start
Definition: SDL_opengl.h:1571
uint32_t Uint32
Definition: SDL_stdinc.h:181
static SDL_mutex * mutex
Definition: testlock.c:23
#define SDL_HINT_TIMER_RESOLUTION
A variable that controls the timer resolution, in milliseconds.
Definition: SDL_hints.h:492
uint64_t Uint64
Definition: SDL_stdinc.h:194
GLuint const GLchar * name
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define TRUE
Definition: edid-parse.c:33
#define SDL_atoi
#define SDL_GetPerformanceCounter
#define SDL_Delay
#define NULL
Definition: begin_code.h:164
#define SDL_AddHintCallback
void SDL_TicksInit(void)
#define SDL_DelHintCallback
GLuint counter
void SDL_TicksQuit(void)
#define FALSE
Definition: edid-parse.c:34
#define SDLCALL
Definition: SDL_internal.h:45