1 #include "core/framerate.hpp"
2 #include "core/settings.hpp"
12 #define DEFAULT_NOMINAL_RATE 60
13 #define HISTORY_FRAMES 10
17 uint64_t last_time_update
= 0;
18 uint64_t time_at_last_update
= 0;
19 bool time_frozen
= true;
20 uint64_t frame_number
= 0;
21 uint64_t frame_start_times
[HISTORY_FRAMES
];
22 double nominal_rate
= DEFAULT_NOMINAL_RATE
;
23 bool target_nominal
= true;
24 double target_fps
= DEFAULT_NOMINAL_RATE
;
25 bool target_infinite
= false;
27 uint64_t get_time(uint64_t curtime
, bool update
)
29 if(curtime
< last_time_update
|| time_frozen
)
30 return time_at_last_update
;
32 time_at_last_update
+= (curtime
- last_time_update
);
33 last_time_update
= curtime
;
34 return time_at_last_update
;
36 return time_at_last_update
+ (curtime
- last_time_update
);
39 double get_realized_fps()
43 if(frame_number
>= HISTORY_FRAMES
)
44 return (1000000.0 * (HISTORY_FRAMES
- 1)) / (frame_start_times
[0] - frame_start_times
[HISTORY_FRAMES
- 1] + 1);
45 return (1000000.0 * (frame_number
- 1)) / (frame_start_times
[0] - frame_start_times
[frame_number
- 1] + 1);
48 void add_frame(uint64_t linear_time
)
50 for(size_t i
= HISTORY_FRAMES
- 2; i
< HISTORY_FRAMES
; i
--)
51 frame_start_times
[i
+ 1] = frame_start_times
[i
];
52 frame_start_times
[0] = linear_time
;
56 struct setting_targetfps
: public setting
58 setting_targetfps() throw(std::bad_alloc
)
59 : setting("targetfps")
63 void blank() throw(std::bad_alloc
, std::runtime_error
)
65 target_nominal
= true;
66 target_infinite
= false;
67 target_fps
= nominal_rate
;
72 return !target_nominal
;
75 virtual void set(const std::string
& value
) throw(std::bad_alloc
, std::runtime_error
)
80 if(value
== "infinite") {
81 target_infinite
= true;
82 target_nominal
= false;
88 throw std::runtime_error("Invalid frame rate");
90 throw std::runtime_error("Target frame rate must be at least 0.001fps");
92 target_infinite
= false;
93 target_nominal
= false;
96 virtual std::string
get() throw(std::bad_alloc
)
100 else if(target_infinite
)
103 std::ostringstream o
;
112 void freeze_time(uint64_t curtime
)
114 get_time(curtime
, true);
118 void unfreeze_time(uint64_t curtime
)
121 last_time_update
= curtime
;
125 void set_nominal_framerate(double fps
) throw()
129 target_fps
= nominal_rate
;
130 target_infinite
= false;
134 double get_framerate() throw()
136 return 100.0 * get_realized_fps() / nominal_rate
;
139 void ack_frame_tick(uint64_t usec
) throw()
142 add_frame(get_time(usec
, true));
145 uint64_t to_wait_frame(uint64_t usec
) throw()
147 if(!frame_number
|| target_infinite
)
149 uint64_t lintime
= get_time(usec
, true);
150 uint64_t frame_lasted
= lintime
- frame_start_times
[0];
151 uint64_t frame_should_last
= 1000000 / target_fps
;
152 if(frame_lasted
>= frame_should_last
)
153 return 0; //We are late.
154 uint64_t maxwait
= frame_should_last
- frame_lasted
;
155 uint64_t history_frames
= (frame_number
< HISTORY_FRAMES
) ? frame_number
: HISTORY_FRAMES
;
156 uint64_t history_lasted
= lintime
- frame_start_times
[history_frames
- 1];
157 uint64_t history_should_last
= history_frames
* 1000000 / target_fps
;
158 if(history_lasted
>= history_should_last
)
160 uint64_t history_wait
= history_should_last
- history_lasted
;
161 if(history_wait
> maxwait
)
162 history_wait
= maxwait
;
170 gettimeofday(&tv
, NULL
);
171 return static_cast<uint64_t>(tv
.tv_sec
) * 1000000 + tv
.tv_usec
;
174 #define MAXSLEEP 500000
176 void wait_usec(uint64_t usec
)
178 uint64_t sleep_end
= get_utime() + usec
;
180 uint64_t time_now
= get_utime();
181 if(time_now
>= sleep_end
)
183 if(sleep_end
< time_now
+ MAXSLEEP
)
184 usleep(sleep_end
- time_now
);