1 module gfm.sdl2.framecounter;
2 
3 import std..string;
4 
5 import derelict.sdl2.sdl;
6 
7 import gfm.core.queue,
8        gfm.sdl2.sdl;
9 
10 /// Utility class which gives time delta between frames, and 
11 /// logs some framerate statistics.
12 /// Useful for a variable timestep application.
13 deprecated("FrameCounter is deprecated, it always felt out of place here."
14            " Use the tharsis-prof package or a stand-alone frame profiler instead.")
15 final class FrameCounter
16 {
17     public
18     {
19         /// Creates a FrameCounter, SDL must be initialized.
20         this(SDL2 sdl)
21         {
22             _sdl = sdl;
23             _firstFrame = true;
24             _elapsedTime = 0;
25             _frameTimes = new RingBuffer!ulong(10);
26         }
27 
28         /// Marks the beginning of a new frame.
29         /// Returns: Current time difference since last frame, in milliseconds.
30         ulong tickMs()
31         {
32             if (_firstFrame)
33             {
34                 _lastTime = SDL_GetTicks();
35                 _firstFrame = false;
36                 _frameTimes.pushBack(0);
37                 return 0; // no advance for first frame
38             }
39             else
40             {
41                 uint now = SDL_GetTicks();
42                 uint delta = now - _lastTime;
43                 _elapsedTime += delta;
44                 _lastTime = now;
45                 _frameTimes.pushBack(delta);
46                 return delta;
47             }
48         }
49 
50         /// Marks the beginning of a new frame.
51         /// Returns: Current time difference since last frame, in seconds.
52         deprecated alias tick = tickSecs;
53         double tickSecs()
54         {
55             return tickMs() * 0.001;
56         }
57 
58         /// Returns: Elapsed time since creation, in milliseconds.
59         ulong elapsedTimeMs() const
60         {
61             return _elapsedTime;
62         }
63 
64         /// Returns: Elapsed time since creation, in seconds.
65         double elapsedTime() const
66         {
67             return _elapsedTime * 0.001;
68         }
69 
70         /// Returns: Displayable framerate statistics.
71         string getFPSString()
72         {
73             double sum = 0;
74             double min = double.infinity;
75             double max = -double.infinity;
76             foreach(ulong frameTime; _frameTimes[])
77             {
78                 if (frameTime < min)
79                     min = frameTime;
80                 if (frameTime > max)
81                     max = frameTime;
82                 sum += frameTime;
83             }
84 
85             double avg = sum / cast(double)(_frameTimes[].length);
86             int avgFPS = cast(int)(0.5 + ( avg != 0 ? 1000 / avg : 0 ) );
87             int avgdt = cast(int)(0.5 + avg);
88 
89             return format("FPS: %s dt: avg %sms min %sms max %sms", avgFPS, avgdt, min, max);
90         }
91     }
92 
93     private
94     {
95         SDL2 _sdl;
96         RingBuffer!ulong _frameTimes;
97         bool _firstFrame;
98         uint _lastTime;
99         ulong _elapsedTime;
100     }
101 }
102