SDL  2.0
SDL_systimer.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 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
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 {
110  if (!hires_timer_available) {
112  SDL_TimerResolutionChanged, NULL);
113  }
114 
115  SDL_SetSystemTimerResolution(0); /* always release our timer resolution request. */
116 
117  start = 0;
118  ticks_started = SDL_FALSE;
119 }
120 
121 Uint32
122 SDL_GetTicks(void)
123 {
124  DWORD now = 0;
125  LARGE_INTEGER hires_now;
126 
127  if (!ticks_started) {
128  SDL_TicksInit();
129  }
130 
131  if (hires_timer_available) {
132  QueryPerformanceCounter(&hires_now);
133 
134  hires_now.QuadPart -= hires_start_ticks.QuadPart;
135  hires_now.QuadPart *= 1000;
136  hires_now.QuadPart /= hires_ticks_per_second.QuadPart;
137 
138  return (DWORD) hires_now.QuadPart;
139  } else {
140 #ifndef __WINRT__
141  now = timeGetTime();
142 #endif /* __WINRT__ */
143  }
144 
145  return (now - start);
146 }
147 
148 Uint64
150 {
151  LARGE_INTEGER counter;
152 
153  if (!QueryPerformanceCounter(&counter)) {
154  return SDL_GetTicks();
155  }
156  return counter.QuadPart;
157 }
158 
159 Uint64
161 {
162  LARGE_INTEGER frequency;
163 
164  if (!QueryPerformanceFrequency(&frequency)) {
165  return 1000;
166  }
167  return frequency.QuadPart;
168 }
169 
170 void
171 SDL_Delay(Uint32 ms)
172 {
173  /* Sleep() is not publicly available to apps in early versions of WinRT.
174  *
175  * Visual C++ 2013 Update 4 re-introduced Sleep() for Windows 8.1 and
176  * Windows Phone 8.1.
177  *
178  * Use the compiler version to determine availability.
179  *
180  * NOTE #1: _MSC_FULL_VER == 180030723 for Visual C++ 2013 Update 3.
181  * NOTE #2: Visual C++ 2013, when compiling for Windows 8.0 and
182  * Windows Phone 8.0, uses the Visual C++ 2012 compiler to build
183  * apps and libraries.
184  */
185 #if defined(__WINRT__) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER <= 180030723)
186  static HANDLE mutex = 0;
187  if (!mutex) {
188  mutex = CreateEventEx(0, 0, 0, EVENT_ALL_ACCESS);
189  }
190  WaitForSingleObjectEx(mutex, ms, FALSE);
191 #else
192  Sleep(ms);
193 #endif
194 }
195 
196 #endif /* SDL_TIMER_WINDOWS */
197 
198 /* vi: set ts=4 sw=4 expandtab: */
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:155
Uint64 SDL_GetPerformanceFrequency(void)
Get the count per second of the high resolution counter.
GLuint start
Definition: SDL_opengl.h:1564
GLuint const GLchar * name
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:362
uint64_t Uint64
An unsigned 64-bit integer type.
Definition: SDL_stdinc.h:164
void SDL_TicksQuit(void)
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define TRUE
Definition: edid-parse.c:31
#define SDL_atoi
#define SDL_GetPerformanceCounter
#define SDL_Delay
#define NULL
Definition: begin_code.h:143
#define SDL_AddHintCallback
#define SDL_DelHintCallback
GLuint counter
void SDL_TicksInit(void)
#define FALSE
Definition: edid-parse.c:32