Changeset - r24836:1b90bc77ac1d
[Not reviewed]
master
0 10 0
Patric Stout - 4 years ago 2021-02-17 14:31:09
truebrain@openttd.org
Feature: configurable refresh-rate and change default to 60fps

Most modern games run on 60 fps, and for good reason. This gives
a much smoother experiences.

As some people have monitors that can do 144Hz or even 240Hz, allow
people to configure the refresh rate. Of course, the higher you
set the value, the more time the game spends on drawing pixels
instead of simulating the game, which has an effect on simulation
speed.

The simulation will still always run at 33.33 fps, and is not
influences by this setting.
10 files changed with 50 insertions and 27 deletions:
0 comments (0 inline, 0 general)
src/framerate_gui.cpp
Show inline comments
 
@@ -186,13 +186,13 @@ namespace {
 
		PerformanceData(1),                     // PFE_ACC_GL_TRAINS
 
		PerformanceData(1),                     // PFE_ACC_GL_ROADVEHS
 
		PerformanceData(1),                     // PFE_ACC_GL_SHIPS
 
		PerformanceData(1),                     // PFE_ACC_GL_AIRCRAFT
 
		PerformanceData(1),                     // PFE_GL_LANDSCAPE
 
		PerformanceData(1),                     // PFE_GL_LINKGRAPH
 
		PerformanceData(GL_RATE),               // PFE_DRAWING
 
		PerformanceData(1000.0 / 30),           // PFE_DRAWING
 
		PerformanceData(1),                     // PFE_ACC_DRAWWORLD
 
		PerformanceData(60.0),                  // PFE_VIDEO
 
		PerformanceData(1000.0 * 8192 / 44100), // PFE_SOUND
 
		PerformanceData(1),                     // PFE_ALLSCRIPTS
 
		PerformanceData(1),                     // PFE_GAMESCRIPT
 
		PerformanceData(1),                     // PFE_AI0 ...
 
@@ -465,13 +465,13 @@ struct FramerateWindow : Window {
 
		double gl_rate = _pf_data[PFE_GAMELOOP].GetRate();
 
		bool have_script = false;
 
		this->rate_gameloop.SetRate(gl_rate, _pf_data[PFE_GAMELOOP].expected_rate);
 
		this->speed_gameloop.SetRate(gl_rate / _pf_data[PFE_GAMELOOP].expected_rate, 1.0);
 
		if (this->small) return; // in small mode, this is everything needed
 

	
 
		this->rate_drawing.SetRate(_pf_data[PFE_DRAWING].GetRate(), _pf_data[PFE_DRAWING].expected_rate);
 
		this->rate_drawing.SetRate(_pf_data[PFE_DRAWING].GetRate(), _settings_client.gui.refresh_rate);
 

	
 
		int new_active = 0;
 
		for (PerformanceElement e = PFE_FIRST; e < PFE_MAX; e++) {
 
			this->times_shortterm[e].SetTime(_pf_data[e].GetAverageDurationMilliseconds(8), MILLISECONDS_PER_TICK);
 
			this->times_longterm[e].SetTime(_pf_data[e].GetAverageDurationMilliseconds(NUM_FRAMERATE_POINTS), MILLISECONDS_PER_TICK);
 
			if (_pf_data[e].num_valid > 0) {
src/settings_type.h
Show inline comments
 
@@ -144,12 +144,13 @@ struct GUISettings {
 
	byte   missing_strings_threshold;        ///< the number of missing strings before showing the warning
 
	uint8  graph_line_thickness;             ///< the thickness of the lines in the various graph guis
 
	uint8  osk_activation;                   ///< Mouse gesture to trigger the OSK.
 
	byte   starting_colour;                  ///< default color scheme for the company to start a new game with
 
	bool   show_newgrf_name;                 ///< Show the name of the NewGRF in the build vehicle window
 
	bool   auto_remove_signals;              ///< automatically remove signals when in the way during rail construction
 
	uint16 refresh_rate;                     ///< How often we refresh the screen (time between draw-ticks).
 

	
 
	uint16 console_backlog_timeout;          ///< the minimum amount of time items should be in the console backlog before they will be removed in ~3 seconds granularity.
 
	uint16 console_backlog_length;           ///< the minimum amount of items in the console backlog before items will be removed.
 

	
 
	uint8  station_gui_group_order;          ///< the order of grouping cargo entries in the station gui
 
	uint8  station_gui_sort_by;              ///< sort cargo entries in the station gui by station name or amount
src/table/settings.ini
Show inline comments
 
@@ -3351,12 +3351,22 @@ var      = gui.console_backlog_length
 
type     = SLE_UINT16
 
flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
 
def      = 100
 
min      = 10
 
max      = 65500
 

	
 
[SDTC_VAR]
 
var      = gui.refresh_rate
 
type     = SLE_UINT16
 
flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
 
def      = 60
 
min      = 10
 
max      = 1000
 
cat      = SC_EXPERT
 
startup  = true
 

	
 
[SDTC_BOOL]
 
var      = sound.news_ticker
 
flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
 
def      = true
 
str      = STR_CONFIG_SETTING_SOUND_TICKER
 
strhelp  = STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT
src/video/allegro_v.cpp
Show inline comments
 
@@ -482,26 +482,26 @@ void VideoDriver_Allegro::MainLoop()
 
			_realtime_tick += delta.count();
 
			last_realtime_tick += delta;
 
		}
 

	
 
		if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
 
			if (_fast_forward && !_pause_mode) {
 
				next_game_tick = cur_ticks + std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
				next_game_tick = cur_ticks + this->GetGameInterval();
 
			} else {
 
				next_game_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
				next_game_tick += this->GetGameInterval();
 
				/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
 
				if (next_game_tick < cur_ticks - std::chrono::milliseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_game_tick = cur_ticks;
 
				if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
 
			}
 

	
 
			GameLoop();
 
		}
 

	
 
		if (cur_ticks >= next_draw_tick) {
 
			next_draw_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
			next_draw_tick += this->GetDrawInterval();
 
			/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
 
			if (next_draw_tick < cur_ticks - std::chrono::microseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_draw_tick = cur_ticks;
 
			if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
 

	
 
			bool old_ctrl_pressed = _ctrl_pressed;
 

	
 
			_ctrl_pressed  = !!(key_shifts & KB_CTRL_FLAG);
 
			_shift_pressed = !!(key_shifts & KB_SHIFT_FLAG);
 

	
src/video/cocoa/cocoa_v.mm
Show inline comments
 
@@ -672,26 +672,26 @@ void VideoDriver_Cocoa::GameLoop()
 
				_realtime_tick += delta.count();
 
				last_realtime_tick += delta;
 
			}
 

	
 
			if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
 
				if (_fast_forward && !_pause_mode) {
 
					next_game_tick = cur_ticks + std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
					next_game_tick = cur_ticks + this->GetGameInterval();
 
				} else {
 
					next_game_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
					next_game_tick += this->GetGameInterval();
 
					/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
 
					if (next_game_tick < cur_ticks - std::chrono::milliseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_game_tick = cur_ticks;
 
					if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
 
				}
 

	
 
				::GameLoop();
 
			}
 

	
 
			if (cur_ticks >= next_draw_tick) {
 
				next_draw_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
				next_draw_tick += this->GetDrawInterval();
 
				/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
 
				if (next_draw_tick < cur_ticks - std::chrono::microseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_draw_tick = cur_ticks;
 
				if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
 

	
 
				bool old_ctrl_pressed = _ctrl_pressed;
 

	
 
				_ctrl_pressed = (cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)) != 0;
 
				_shift_pressed = (cur_mods & NSShiftKeyMask) != 0;
 

	
src/video/dedicated_v.cpp
Show inline comments
 
@@ -291,17 +291,17 @@ void VideoDriver_Dedicated::MainLoop()
 
			_realtime_tick += delta.count();
 
			last_realtime_tick += delta;
 
		}
 

	
 
		if (cur_ticks >= next_game_tick || _ddc_fastforward) {
 
			if (_ddc_fastforward) {
 
				next_game_tick = cur_ticks + std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
				next_game_tick = cur_ticks + this->GetGameInterval();
 
			} else {
 
				next_game_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
				next_game_tick += this->GetGameInterval();
 
				/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
 
				if (next_game_tick < cur_ticks - std::chrono::milliseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_game_tick = cur_ticks;
 
				if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
 
			}
 

	
 
			GameLoop();
 
			InputLoop();
 
			UpdateWindows();
 
		}
src/video/sdl2_v.cpp
Show inline comments
 
@@ -790,15 +790,15 @@ void VideoDriver_SDL::LoopOnce()
 
		if (_draw_mutex != nullptr) draw_lock.unlock();
 
		GameLoop();
 
		if (_draw_mutex != nullptr) draw_lock.lock();
 
	}
 

	
 
	if (cur_ticks >= next_draw_tick) {
 
		next_draw_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
		next_draw_tick += this->GetDrawInterval();
 
		/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
 
		if (next_draw_tick < cur_ticks - std::chrono::microseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_draw_tick = cur_ticks;
 
		if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
 

	
 
		bool old_ctrl_pressed = _ctrl_pressed;
 

	
 
		_ctrl_pressed  = !!(mod & KMOD_CTRL);
 
		_shift_pressed = !!(mod & KMOD_SHIFT);
 

	
src/video/sdl_v.cpp
Show inline comments
 
@@ -728,30 +728,30 @@ void VideoDriver_SDL::MainLoop()
 
			_realtime_tick += delta.count();
 
			last_realtime_tick += delta;
 
		}
 

	
 
		if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
 
			if (_fast_forward && !_pause_mode) {
 
				next_game_tick = cur_ticks + std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
				next_game_tick = cur_ticks + this->GetGameInterval();
 
			} else {
 
				next_game_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
				next_game_tick += this->GetGameInterval();
 
				/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
 
				if (next_game_tick < cur_ticks - std::chrono::milliseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_game_tick = cur_ticks;
 
				if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
 
			}
 

	
 
			/* The gameloop is the part that can run asynchronously. The rest
 
			 * except sleeping can't. */
 
			if (_draw_mutex != nullptr) draw_lock.unlock();
 
			GameLoop();
 
			if (_draw_mutex != nullptr) draw_lock.lock();
 
		}
 

	
 
		if (cur_ticks >= next_draw_tick) {
 
			next_draw_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
			next_draw_tick += this->GetDrawInterval();
 
			/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
 
			if (next_draw_tick < cur_ticks - std::chrono::microseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_draw_tick = cur_ticks;
 
			if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
 

	
 
			bool old_ctrl_pressed = _ctrl_pressed;
 

	
 
			_ctrl_pressed  = !!(mod & KMOD_CTRL);
 
			_shift_pressed = !!(mod & KMOD_SHIFT);
 

	
src/video/video_driver.hpp
Show inline comments
 
@@ -10,13 +10,15 @@
 
#ifndef VIDEO_VIDEO_DRIVER_HPP
 
#define VIDEO_VIDEO_DRIVER_HPP
 

	
 
#include "../driver.h"
 
#include "../core/geometry_type.hpp"
 
#include "../core/math_func.hpp"
 
#include "../settings_type.h"
 
#include "../zoom_type.h"
 
#include <chrono>
 
#include <vector>
 

	
 
extern std::string _ini_videodriver;
 
extern std::vector<Dimension> _resolutions;
 
extern Dimension _cur_resolution;
 
extern bool _rightclick_emulate;
 
@@ -150,9 +152,19 @@ protected:
 
			 * integer, This way all internal drawing routines work correctly. */
 
			Dimension res = this->GetScreenSize();
 
			_cur_resolution.width  = ClampU(res.width  * 3 / 4, DEFAULT_WINDOW_WIDTH, UINT16_MAX / 2);
 
			_cur_resolution.height = ClampU(res.height * 3 / 4, DEFAULT_WINDOW_HEIGHT, UINT16_MAX / 2);
 
		}
 
	}
 

	
 
	std::chrono::steady_clock::duration GetGameInterval()
 
	{
 
		return std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
	}
 

	
 
	std::chrono::steady_clock::duration GetDrawInterval()
 
	{
 
		return std::chrono::microseconds(1000000 / _settings_client.gui.refresh_rate);
 
	}
 
};
 

	
 
#endif /* VIDEO_VIDEO_DRIVER_HPP */
src/video/win32_v.cpp
Show inline comments
 
@@ -1205,17 +1205,17 @@ void VideoDriver_Win32::MainLoop()
 
			_realtime_tick += delta.count();
 
			last_realtime_tick += delta;
 
		}
 

	
 
		if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
 
			if (_fast_forward && !_pause_mode) {
 
				next_game_tick = cur_ticks + std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
				next_game_tick = cur_ticks + this->GetGameInterval();
 
			} else {
 
				next_game_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
				next_game_tick += this->GetGameInterval();
 
				/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
 
				if (next_game_tick < cur_ticks - std::chrono::milliseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_game_tick = cur_ticks;
 
				if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
 
			}
 

	
 
			/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
 
			GdiFlush();
 

	
 
			/* The game loop is the part that can run asynchronously.
 
@@ -1223,15 +1223,15 @@ void VideoDriver_Win32::MainLoop()
 
			if (_draw_threaded) draw_lock.unlock();
 
			GameLoop();
 
			if (_draw_threaded) draw_lock.lock();
 
		}
 

	
 
		if (cur_ticks >= next_draw_tick) {
 
			next_draw_tick += std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
			next_draw_tick += this->GetDrawInterval();
 
			/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
 
			if (next_draw_tick < cur_ticks - std::chrono::microseconds(ALLOWED_DRIFT * MILLISECONDS_PER_TICK)) next_draw_tick = cur_ticks;
 
			if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
 

	
 
			bool old_ctrl_pressed = _ctrl_pressed;
 

	
 
			_ctrl_pressed = _wnd.has_focus && GetAsyncKeyState(VK_CONTROL)<0;
 
			_shift_pressed = _wnd.has_focus && GetAsyncKeyState(VK_SHIFT)<0;
 

	
0 comments (0 inline, 0 general)