1 |
|
|
/* |
2 |
|
|
|
3 |
|
|
SDL2_framerate.c: framerate manager |
4 |
|
|
|
5 |
|
|
Copyright (C) 2012-2014 Andreas Schiffler |
6 |
|
|
|
7 |
|
|
This software is provided 'as-is', without any express or implied |
8 |
|
|
warranty. In no event will the authors be held liable for any damages |
9 |
|
|
arising from the use of this software. |
10 |
|
|
|
11 |
|
|
Permission is granted to anyone to use this software for any purpose, |
12 |
|
|
including commercial applications, and to alter it and redistribute it |
13 |
|
|
freely, subject to the following restrictions: |
14 |
|
|
|
15 |
|
|
1. The origin of this software must not be misrepresented; you must not |
16 |
|
|
claim that you wrote the original software. If you use this software |
17 |
|
|
in a product, an acknowledgment in the product documentation would be |
18 |
|
|
appreciated but is not required. |
19 |
|
|
|
20 |
|
|
2. Altered source versions must be plainly marked as such, and must not be |
21 |
|
|
misrepresented as being the original software. |
22 |
|
|
|
23 |
|
|
3. This notice may not be removed or altered from any source |
24 |
|
|
distribution. |
25 |
|
|
|
26 |
|
|
Andreas Schiffler -- aschiffler at ferzkopp dot net |
27 |
|
|
|
28 |
|
|
Changed for ManaPlus (C) 2013-2017 ManaPlus developers |
29 |
|
|
|
30 |
|
|
*/ |
31 |
|
|
|
32 |
|
|
#include "sdl2gfx/SDL2_framerate.h" |
33 |
|
|
|
34 |
|
|
#include "debug.h" |
35 |
|
|
|
36 |
|
|
/*! |
37 |
|
|
\brief Internal wrapper to SDL_GetTicks that ensures a non-zero return value. |
38 |
|
|
|
39 |
|
|
\return The tick count. |
40 |
|
|
*/ |
41 |
|
|
static Uint32 _getTicks() |
42 |
|
|
{ |
43 |
|
|
Uint32 ticks = SDL_GetTicks(); |
44 |
|
|
|
45 |
|
|
/* |
46 |
|
|
* Since baseticks!=0 is used to track initialization |
47 |
|
|
* we need to ensure that the tick count is always >0 |
48 |
|
|
* since SDL_GetTicks may not have incremented yet and |
49 |
|
|
* return 0 depending on the timing of the calls. |
50 |
|
|
*/ |
51 |
|
|
if (ticks == 0) |
52 |
|
|
{ |
53 |
|
|
return 1; |
54 |
|
|
} |
55 |
|
|
else |
56 |
|
|
{ |
57 |
|
|
return ticks; |
58 |
|
|
} |
59 |
|
|
} |
60 |
|
|
|
61 |
|
|
/*! |
62 |
|
|
\brief Initialize the framerate manager. |
63 |
|
|
|
64 |
|
|
Initialize the framerate manager, set default framerate of 30Hz and |
65 |
|
|
reset delay interpolation. |
66 |
|
|
|
67 |
|
|
\param manager Pointer to the framerate manager. |
68 |
|
|
*/ |
69 |
|
|
void SDL_initFramerate(FPSmanager * manager) |
70 |
|
|
{ |
71 |
|
|
/* |
72 |
|
|
* Store some sane values |
73 |
|
|
*/ |
74 |
|
|
manager->framecount = 0; |
75 |
|
|
manager->rate = FPS_DEFAULT; |
76 |
|
|
manager->rateticks = (1000.0F / static_cast<float>(FPS_DEFAULT)); |
77 |
|
|
manager->baseticks = _getTicks(); |
78 |
|
|
manager->lastticks = manager->baseticks; |
79 |
|
|
|
80 |
|
|
} |
81 |
|
|
|
82 |
|
|
/*! |
83 |
|
|
\brief Set the framerate in Hz |
84 |
|
|
|
85 |
|
|
Sets a new framerate for the manager and reset delay interpolation. |
86 |
|
|
Rate values must be between FPS_LOWER_LIMIT and FPS_UPPER_LIMIT inclusive to be accepted. |
87 |
|
|
|
88 |
|
|
\param manager Pointer to the framerate manager. |
89 |
|
|
\param rate The new framerate in Hz (frames per second). |
90 |
|
|
|
91 |
|
|
\return 0 for sucess and -1 for error. |
92 |
|
|
*/ |
93 |
|
2 |
int SDL_setFramerate(FPSmanager * manager, Uint32 rate) |
94 |
|
|
{ |
95 |
✓✗ |
2 |
if ((rate >= FPS_LOWER_LIMIT) && (rate <= FPS_UPPER_LIMIT)) |
96 |
|
|
{ |
97 |
|
2 |
manager->framecount = 0; |
98 |
|
2 |
manager->rate = rate; |
99 |
|
2 |
manager->rateticks = (1000.0F / static_cast<float>(rate)); |
100 |
|
2 |
return (0); |
101 |
|
|
} |
102 |
|
|
else |
103 |
|
|
{ |
104 |
|
|
return (-1); |
105 |
|
|
} |
106 |
|
|
} |
107 |
|
|
|
108 |
|
|
/*! |
109 |
|
|
\brief Return the current target framerate in Hz |
110 |
|
|
|
111 |
|
|
Get the currently set framerate of the manager. |
112 |
|
|
|
113 |
|
|
\param manager Pointer to the framerate manager. |
114 |
|
|
|
115 |
|
|
\return Current framerate in Hz or -1 for error. |
116 |
|
|
*/ |
117 |
|
3 |
int SDL_getFramerate(FPSmanager * manager) |
118 |
|
|
{ |
119 |
✓✗ |
3 |
if (manager == nullptr) |
120 |
|
|
{ |
121 |
|
|
return (-1); |
122 |
|
|
} |
123 |
|
|
else |
124 |
|
|
{ |
125 |
|
3 |
return (static_cast<int>(manager->rate)); |
126 |
|
|
} |
127 |
|
|
} |
128 |
|
|
|
129 |
|
|
/*! |
130 |
|
|
\brief Return the current framecount. |
131 |
|
|
|
132 |
|
|
Get the current framecount from the framerate manager. |
133 |
|
|
A frame is counted each time SDL_framerateDelay is called. |
134 |
|
|
|
135 |
|
|
\param manager Pointer to the framerate manager. |
136 |
|
|
|
137 |
|
|
\return Current frame count or -1 for error. |
138 |
|
|
*/ |
139 |
|
|
int SDL_getFramecount(FPSmanager * manager) |
140 |
|
|
{ |
141 |
|
|
if (manager == nullptr) |
142 |
|
|
{ |
143 |
|
|
return (-1); |
144 |
|
|
} |
145 |
|
|
else |
146 |
|
|
{ |
147 |
|
|
return (static_cast<int>(manager->framecount)); |
148 |
|
|
} |
149 |
|
|
} |
150 |
|
|
|
151 |
|
|
/*! |
152 |
|
|
\brief Delay execution to maintain a constant framerate and calculate fps. |
153 |
|
|
|
154 |
|
|
Generate a delay to accomodate currently set framerate. Call once in the |
155 |
|
|
graphics/rendering loop. If the computer cannot keep up with the rate (i.e. |
156 |
|
|
drawing too slow), the delay is zero and the delay interpolation is reset. |
157 |
|
|
|
158 |
|
|
\param manager Pointer to the framerate manager. |
159 |
|
|
|
160 |
|
|
\return The time that passed since the last call to the function in ms. May return 0. |
161 |
|
|
*/ |
162 |
|
|
Uint32 SDL_framerateDelay(FPSmanager * manager) |
163 |
|
|
{ |
164 |
|
|
Uint32 current_ticks; |
165 |
|
|
Uint32 target_ticks; |
166 |
|
|
Uint32 the_delay; |
167 |
|
|
Uint32 time_passed = 0; |
168 |
|
|
|
169 |
|
|
/* |
170 |
|
|
* No manager, no delay |
171 |
|
|
*/ |
172 |
|
|
if (manager == nullptr) |
173 |
|
|
{ |
174 |
|
|
return 0; |
175 |
|
|
} |
176 |
|
|
|
177 |
|
|
/* |
178 |
|
|
* Initialize uninitialized manager |
179 |
|
|
*/ |
180 |
|
|
if (manager->baseticks == 0) |
181 |
|
|
{ |
182 |
|
|
SDL_initFramerate(manager); |
183 |
|
|
} |
184 |
|
|
|
185 |
|
|
/* |
186 |
|
|
* Next frame |
187 |
|
|
*/ |
188 |
|
|
manager->framecount++; |
189 |
|
|
|
190 |
|
|
/* |
191 |
|
|
* Get/calc ticks |
192 |
|
|
*/ |
193 |
|
|
current_ticks = _getTicks(); |
194 |
|
|
time_passed = current_ticks - manager->lastticks; |
195 |
|
|
manager->lastticks = current_ticks; |
196 |
|
|
target_ticks = manager->baseticks + static_cast<Uint32>(static_cast<float>( |
197 |
|
|
manager->framecount) * manager->rateticks); |
198 |
|
|
|
199 |
|
|
if (current_ticks <= target_ticks) |
200 |
|
|
{ |
201 |
|
|
the_delay = target_ticks - current_ticks; |
202 |
|
|
SDL_Delay(the_delay); |
203 |
|
|
} |
204 |
|
|
else |
205 |
|
|
{ |
206 |
|
|
manager->framecount = 0; |
207 |
|
|
manager->baseticks = _getTicks(); |
208 |
|
|
} |
209 |
|
|
|
210 |
|
|
return time_passed; |
211 |
|
|
} |