summaryrefslogtreecommitdiff
path: root/src/sdl2gfx/SDL2_framerate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sdl2gfx/SDL2_framerate.cpp')
-rw-r--r--src/sdl2gfx/SDL2_framerate.cpp191
1 files changed, 191 insertions, 0 deletions
diff --git a/src/sdl2gfx/SDL2_framerate.cpp b/src/sdl2gfx/SDL2_framerate.cpp
new file mode 100644
index 000000000..bb8cc1c75
--- /dev/null
+++ b/src/sdl2gfx/SDL2_framerate.cpp
@@ -0,0 +1,191 @@
+/*
+
+SDL2_framerate.c: framerate manager
+
+Copyright (C) 2012-2014 Andreas Schiffler
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+Andreas Schiffler -- aschiffler at ferzkopp dot net
+
+Changed for ManaPlus (C) 2013-2017 ManaPlus developers
+
+*/
+
+#include "sdl2gfx/SDL2_framerate.h"
+
+/*!
+\brief Internal wrapper to SDL_GetTicks that ensures a non-zero return value.
+
+\return The tick count.
+*/
+static Uint32 _getTicks()
+{
+ Uint32 ticks = SDL_GetTicks();
+
+ /*
+ * Since baseticks!=0 is used to track initialization
+ * we need to ensure that the tick count is always >0
+ * since SDL_GetTicks may not have incremented yet and
+ * return 0 depending on the timing of the calls.
+ */
+ if (ticks == 0) {
+ return 1;
+ } else {
+ return ticks;
+ }
+}
+
+/*!
+\brief Initialize the framerate manager.
+
+Initialize the framerate manager, set default framerate of 30Hz and
+reset delay interpolation.
+
+\param manager Pointer to the framerate manager.
+*/
+void SDL_initFramerate(FPSmanager * manager)
+{
+ /*
+ * Store some sane values
+ */
+ manager->framecount = 0;
+ manager->rate = FPS_DEFAULT;
+ manager->rateticks = (1000.0f / static_cast<float>(FPS_DEFAULT));
+ manager->baseticks = _getTicks();
+ manager->lastticks = manager->baseticks;
+
+}
+
+/*!
+\brief Set the framerate in Hz
+
+Sets a new framerate for the manager and reset delay interpolation.
+Rate values must be between FPS_LOWER_LIMIT and FPS_UPPER_LIMIT inclusive to be accepted.
+
+\param manager Pointer to the framerate manager.
+\param rate The new framerate in Hz (frames per second).
+
+\return 0 for sucess and -1 for error.
+*/
+int SDL_setFramerate(FPSmanager * manager, Uint32 rate)
+{
+ if ((rate >= FPS_LOWER_LIMIT) && (rate <= FPS_UPPER_LIMIT)) {
+ manager->framecount = 0;
+ manager->rate = rate;
+ manager->rateticks = (1000.0f / static_cast<float>(rate));
+ return (0);
+ } else {
+ return (-1);
+ }
+}
+
+/*!
+\brief Return the current target framerate in Hz
+
+Get the currently set framerate of the manager.
+
+\param manager Pointer to the framerate manager.
+
+\return Current framerate in Hz or -1 for error.
+*/
+int SDL_getFramerate(FPSmanager * manager)
+{
+ if (manager == nullptr) {
+ return (-1);
+ } else {
+ return (static_cast<int>(manager->rate));
+ }
+}
+
+/*!
+\brief Return the current framecount.
+
+Get the current framecount from the framerate manager.
+A frame is counted each time SDL_framerateDelay is called.
+
+\param manager Pointer to the framerate manager.
+
+\return Current frame count or -1 for error.
+*/
+int SDL_getFramecount(FPSmanager * manager)
+{
+ if (manager == nullptr) {
+ return (-1);
+ } else {
+ return (static_cast<int>(manager->framecount));
+ }
+}
+
+/*!
+\brief Delay execution to maintain a constant framerate and calculate fps.
+
+Generate a delay to accomodate currently set framerate. Call once in the
+graphics/rendering loop. If the computer cannot keep up with the rate (i.e.
+drawing too slow), the delay is zero and the delay interpolation is reset.
+
+\param manager Pointer to the framerate manager.
+
+\return The time that passed since the last call to the function in ms. May return 0.
+*/
+Uint32 SDL_framerateDelay(FPSmanager * manager)
+{
+ Uint32 current_ticks;
+ Uint32 target_ticks;
+ Uint32 the_delay;
+ Uint32 time_passed = 0;
+
+ /*
+ * No manager, no delay
+ */
+ if (manager == nullptr) {
+ return 0;
+ }
+
+ /*
+ * Initialize uninitialized manager
+ */
+ if (manager->baseticks == 0) {
+ SDL_initFramerate(manager);
+ }
+
+ /*
+ * Next frame
+ */
+ manager->framecount++;
+
+ /*
+ * Get/calc ticks
+ */
+ current_ticks = _getTicks();
+ time_passed = current_ticks - manager->lastticks;
+ manager->lastticks = current_ticks;
+ target_ticks = manager->baseticks + static_cast<Uint32>(static_cast<float>(manager->framecount) * manager->rateticks);
+
+ if (current_ticks <= target_ticks) {
+ the_delay = target_ticks - current_ticks;
+ SDL_Delay(the_delay);
+ } else {
+ manager->framecount = 0;
+ manager->baseticks = _getTicks();
+ }
+
+ return time_passed;
+}