GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/sdl2gfx/SDL2_framerate.cpp Lines: 9 35 25.7 %
Date: 2021-03-17 Branches: 2 20 10.0 %

Line Branch Exec Source
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
}