@@ -106,8 +106,7 @@ static bool alt_grab;
106106static bool ctrl_grab ;
107107static int gui_saved_grab ;
108108static int gui_fullscreen ;
109- static int fps_selection = 3 ;
110- static float frame_deadline = (NANOSECONDS_PER_SECOND / 60 );
109+ static float min_frame_duration = (NANOSECONDS_PER_SECOND / 60 );
111110static int gui_grab_code = KMOD_LALT | KMOD_LCTRL ;
112111static SDL_Cursor * sdl_cursor_normal ;
113112static SDL_Cursor * sdl_cursor_hidden ;
@@ -134,24 +133,30 @@ void xemu_toggle_fullscreen(void)
134133 toggle_full_screen (& sdl2_console [0 ]);
135134}
136135
137- int xemu_get_frame_rate_cap (void )
138- {
139- return fps_selection ;
140- }
141136
142- void xemu_set_frame_rate_cap ( int selection )
137+ void xemu_update_frame_rate_cap ( void )
143138{
144- // FIXME: Remove redundent selection
145- fps_selection = selection ;
139+ int selection = g_config .display .window .fps_cap ;
146140
147141 // No framerate cap
148142 if (!selection ) {
149- frame_deadline = 0 ;
143+ min_frame_duration = 0 ;
144+ return ;
145+ }
146+
147+ // NOTE: Should we log in someway if the selection escaped its valid range?
148+ // For now we default to custom.
149+ float frame_rate ;
150+ const float frame_rates [5 ] = { 15 , 30 , 60 , 120 , 144 };
151+ if (selection < CONFIG_DISPLAY_WINDOW_FPS_CAP_CUSTOM ) {
152+ frame_rate = frame_rates [selection - 1 ];
153+ } else {
154+ frame_rate = g_config .display .window .custom_fps_cap ;
150155 }
151156
152- const int framerates [ 6 ] = { 60 , 15 , 30 , 60 , 120 , 144 };
153- int frame_rate = framerates [ selection ];
154- frame_deadline = (float )NANOSECONDS_PER_SECOND / frame_rate ;
157+ // Calculate the minimum time allowed between frames based on
158+ // the desired frame rate
159+ min_frame_duration = (float )NANOSECONDS_PER_SECOND / frame_rate ;
155160}
156161
157162#define SDL2_REFRESH_INTERVAL_BUSY 16
@@ -1026,29 +1031,13 @@ void sdl2_gl_switch(DisplayChangeListener *dcl,
10261031 }
10271032}
10281033
1029- float fps = 1.0 ;
1030-
1031- static void update_fps (void )
1032- {
1033- static int64_t last_update = 0 ;
1034- const float r = 0.5 ;//0.1;
1035- static float avg = 1.0 ;
1036- int64_t now = qemu_clock_get_ns (QEMU_CLOCK_REALTIME );
1037- float ms = ((float )(now - last_update )/1000000.0 );
1038- last_update = now ;
1039- if (fabs (avg - ms ) > 0.25 * avg ) avg = ms ;
1040- else avg = avg * (1.0 - r )+ ms * r ;
1041- fps = 1000.0 /avg ;
1042- }
1043-
10441034void sdl2_gl_refresh (DisplayChangeListener * dcl )
10451035{
10461036 struct sdl2_console * scon = container_of (dcl , struct sdl2_console , dcl );
10471037 assert (scon -> opengl );
10481038 bool flip_required = false;
10491039
10501040 SDL_GL_MakeCurrent (scon -> real_window , scon -> winctx );
1051- update_fps ();
10521041
10531042 /* XXX: Note that this bypasses the usual VGA path in order to quickly
10541043 * get the surface. This is simple and fast, at the cost of accuracy.
@@ -1103,10 +1092,10 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
11031092 qemu_mutex_unlock_main_loop ();
11041093
11051094 /*
1106- * Throttle to make sure swaps happen at 60Hz
1095+ * Throttle to make sure swaps happen at the desired frame rate cap
11071096 */
1108- static int64_t last_update = 0 ;
1109- int64_t deadline = last_update + frame_deadline ;
1097+ static int64_t last_frame_update = 0 ;
1098+ int64_t frame_expiration = last_frame_update + min_frame_duration ;
11101099
11111100#ifdef DEBUG_XEMU_C
11121101 int64_t sleep_acc = 0 ;
@@ -1121,8 +1110,8 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
11211110
11221111 while (1 ) {
11231112 int64_t now = qemu_clock_get_ns (QEMU_CLOCK_REALTIME );
1124- int64_t time_remaining = deadline - now ;
1125- if (now < deadline ) {
1113+ int64_t time_remaining = frame_expiration - now ;
1114+ if (now < frame_expiration ) {
11261115 if (time_remaining > sleep_threshold ) {
11271116 // Try to sleep until the until reaching the sleep threshold.
11281117 sleep_ns (time_remaining - sleep_threshold );
@@ -1139,11 +1128,10 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
11391128 }
11401129 } else {
11411130 DPRINTF ("zzZz %g %ld\n" , (double )sleep_acc /1000000.0 , spin_acc );
1142- last_update = now ;
1131+ last_frame_update = now ;
11431132 break ;
11441133 }
11451134 }
1146-
11471135}
11481136
11491137void sdl2_gl_redraw (struct sdl2_console * scon )
@@ -1413,6 +1401,9 @@ int main(int argc, char **argv)
14131401 set_full_screen (& sdl2_console [0 ], gui_fullscreen );
14141402 }
14151403
1404+ // Check settings and update the frame rate cap
1405+ xemu_update_frame_rate_cap ();
1406+
14161407 /*
14171408 * FIXME: May want to create a callback mechanism for main QEMU thread
14181409 * to just run functions to avoid TLS bugs and locking issues.
0 commit comments