FS2_Open
Open source remastering of the Freespace 2 engine
timer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #ifdef _WIN32
13 #include <windows.h>
14 #else
15 #include <SDL_timer.h>
16 #include <sys/time.h>
17 #endif
18 
19 #include <limits.h>
20 
21 #include "globalincs/pstypes.h"
22 #include "io/timer.h"
23 #include "graphics/2d.h"
24 #include "globalincs/alphacolors.h"
25 
26 #define THREADED // to use the proper set of macros
27 #include "osapi/osapi.h" // for multi-thread macros
28 
29 
30 #ifdef _WIN32
31 static longlong Timer_last_value = 0, Timer_base = 0, Timer_freq = 0;
32 static const int precision = 1;
33 #endif
34 
35 static longlong Timer_perf_counter_base = 0; // perf counter start time
36 static longlong Timer_perf_counter_freq = 0; // perf counter frequency - number of ticks per second
37 
38 static int Timer_inited = 0;
39 
40 static CRITICAL_SECTION Timer_lock;
41 
42 #define MICROSECONDS_PER_SECOND 1000000
43 
45 {
46  if ( Timer_inited ) {
47  Timer_inited = 0;
48 #ifdef _WIN32
49  timeEndPeriod(precision);
50 #endif
51  DELETE_CRITICAL_SECTION( Timer_lock );
52  }
53 }
54 
55 void timer_init()
56 {
57  if ( !Timer_inited ) {
58  INITIALIZE_CRITICAL_SECTION( Timer_lock );
59 
60 #ifdef _WIN32
61  timeBeginPeriod(precision);
62  Timer_base = Timer_last_value = timeGetTime();
63 
64  // get the performance counter start time
65  LARGE_INTEGER perf_start_time;
66  QueryPerformanceCounter(&perf_start_time);
67  Timer_perf_counter_base = perf_start_time.QuadPart;
68 
69  // get the performance counter's ticks per second frequency
70  LARGE_INTEGER perf_frequency;
71  QueryPerformanceFrequency(&perf_frequency);
72  Timer_perf_counter_freq = perf_frequency.QuadPart;
73 #else
74  timeval time_value;
75 
76  // get the performance counter start time
77  gettimeofday(&time_value, NULL);
78 
79  Timer_perf_counter_base = time_value.tv_sec * MICROSECONDS_PER_SECOND + time_value.tv_usec;
80 
81  // get the performance counter's ticks per second frequency
82  Timer_perf_counter_freq = 1;
83 #endif
84 
85  Timer_inited = 1;
86 
87  atexit(timer_close);
88  }
89 }
90 
91 static uint timer_get()
92 {
93 #ifdef _WIN32
94  ENTER_CRITICAL_SECTION( Timer_lock );
95 
96  longlong time_now;
97 
98  time_now = timeGetTime();
99 
100  if ( time_now < Timer_last_value ) {
101  // the clock has rolled!
102  Timer_base = time_now;
103  mprintf(("TIMER ROLLED!\n"));
104  }
105 
106  Timer_last_value = time_now;
107 
108  LEAVE_CRITICAL_SECTION( Timer_lock );
109 
110  return (uint)(time_now - Timer_base);
111 #else
112  return SDL_GetTicks();
113 #endif
114 }
115 
117 {
118  if (!Timer_inited) {
119  Int3(); // Make sure you call timer_init before anything that uses timer functions!
120  return 0;
121  }
122 
123  longlong a = timer_get();
124 
125  a *= 65536;
126 
127  return (fix)(a / 1000);
128 }
129 
131 {
132  return timer_get_fixed_seconds();
133 }
134 
136 {
137  return timer_get_fixed_seconds();
138 }
139 
141 {
142  if (!Timer_inited) {
143  Int3();
144  return 0;
145  }
146 
147  return (timer_get() / 1000);
148 }
149 
151 {
152  if (!Timer_inited) {
153  Int3(); // Make sure you call timer_init before anything that uses timer functions!
154  return 0;
155  }
156 
157  return timer_get();
158 }
159 
161 {
162  if (!Timer_inited) {
163  Int3(); // Make sure you call timer_init before anything that uses timer functions!
164  return 0;
165  }
166 
167  return timer_get() * 1000;
168 }
169 
171 {
172  if ( !Timer_inited ) {
173  Int3();
174  return 0;
175  }
176 
177 #ifdef _WIN32
178  ENTER_CRITICAL_SECTION( Timer_lock);
179 
180  LARGE_INTEGER time;
182  longlong elapsed = time.QuadPart;// - Timer_perf_counter_base;
183 
184  LEAVE_CRITICAL_SECTION( Timer_lock);
185 
186  return (uint)(elapsed * MICROSECONDS_PER_SECOND / Timer_perf_counter_freq);
187 #else
188  timeval time_value;
189 
190  gettimeofday(&time_value, NULL);
191 
192  return time_value.tv_sec * MICROSECONDS_PER_SECOND + time_value.tv_usec;// - Timer_perf_counter_base);
193 #endif
194 }
195 
196 // 0 means invalid,
197 // 1 means always return true
198 // 2 and above actually check the time
200 
202 {
203  timestamp_ticker = 2;
204 }
205 
206 // Restrict all time values between 0 and MAX_TIME
207 // so we don't have to use UINTs to calculate rollover.
208 // For debugging & testing, you could set this to
209 // something like 1 minute (6000).
210 #define MAX_TIME (INT_MAX/2)
211 
212 void timestamp_inc(int frametime_ms)
213 {
214  timestamp_ticker += frametime_ms;
215 
216  if ( timestamp_ticker > MAX_TIME ) {
217  timestamp_ticker = 2; // Roll!
218  }
219 
220  if (timestamp_ticker < 2 ) {
221  mprintf(("Whoa!!! timestamp_ticker < 2 -- resetting to 2!!!\n"));
222  timestamp_ticker = 2;
223  }
224 }
225 
226 int timestamp(int delta_ms )
227 {
228  int t2;
229  if (delta_ms < 0 ) return 0;
230  if (delta_ms == 0 ) return 1;
231  t2 = timestamp_ticker + delta_ms;
232  if ( t2 > MAX_TIME ) {
233  // wrap!!!
234  t2 = delta_ms - (MAX_TIME-timestamp_ticker);
235  }
236  if (t2 < 2 ) t2 = 2; // hack??
237  return t2;
238 }
239 
240 // Returns milliseconds until timestamp will elapse.
241 // Negative value gives milliseconds ago that timestamp elapsed.
243 {
244  // JAS: FIX
245  // HACK!! This doesn't handle rollover!
246  // (Will it ever happen?)
247 
248  return stamp - timestamp_ticker;
249 
250 /*
251  uint delta;
252 
253  delta = stamp - timestamp_ticker;
254 
255 
256  if (delta > UINT_MAX/2)
257  delta = UINT_MAX - delta + 1;
258  else if (delta < - ( (int) (UINT_MAX/2)))
259  delta = UINT_MAX + delta + 1;
260 
261  return delta;
262 */
263 }
264 
265 // alternate timestamp functions. The way these work is you call xtimestamp() to get the
266 // current counter value, and then call
268 {
269  return timestamp_ticker;
270 }
271 
273 {
274  int t;
275 
276  if (time <= 0)
277  return 1;
278 
279  t = stamp + time;
280  if (t <= timestamp_ticker)
281  return 1; // if we are unlucky enough to have it wrap on us, this will assume time has elapsed.
282 
283  return 0;
284 }
285 
int timestamp(int delta_ms)
Definition: timer.cpp:226
#define DELETE_CRITICAL_SECTION(csc)
Definition: osapi.h:41
#define MICROSECONDS_PER_SECOND
Definition: timer.cpp:42
int timer_get_microseconds()
Definition: timer.cpp:160
#define MAX_TIME
Definition: timer.cpp:210
bool QueryPerformanceCounter(LARGE_INTEGER *pcount)
#define mprintf(args)
Definition: pstypes.h:238
int timestamp_ticker
Definition: timer.cpp:199
SDL_mutex * CRITICAL_SECTION
Definition: config.h:213
void timestamp_reset()
Definition: timer.cpp:201
fix t2
Definition: animplay.cpp:37
#define Int3()
Definition: pstypes.h:292
char stamp[STAMP_STRING_LENGTH]
Definition: fredview.cpp:74
fix timer_get_approx_seconds()
Definition: timer.cpp:135
__int64 QuadPart
Definition: config.h:118
int timer_get_seconds()
Definition: timer.cpp:140
uint timer_get_high_res_microseconds()
Definition: timer.cpp:170
unsigned int uint
Definition: pstypes.h:64
int timestamp_until(int stamp)
Definition: timer.cpp:242
GLboolean GLboolean GLboolean GLboolean a
Definition: Glext.h:5781
#define ENTER_CRITICAL_SECTION(csc)
Definition: osapi.h:42
GLenum GLint GLint * precision
Definition: Glext.h:7096
GLdouble GLdouble t
Definition: Glext.h:5329
long fix
Definition: pstypes.h:54
fix timer_get_fixed_secondsX()
Definition: timer.cpp:130
#define LEAVE_CRITICAL_SECTION(csc)
Definition: osapi.h:43
fix timer_get_fixed_seconds()
Definition: timer.cpp:116
#define INITIALIZE_CRITICAL_SECTION(csc)
Definition: osapi.h:40
__int64 longlong
Definition: pstypes.h:60
int timestamp_has_time_elapsed(int stamp, int time)
Definition: timer.cpp:272
void timestamp_inc(int frametime_ms)
Definition: timer.cpp:212
void timer_init()
Definition: timer.cpp:55
void timer_close()
Definition: timer.cpp:44
int timer_get_milliseconds()
Definition: timer.cpp:150