Changeset - r25161:560705f96b3e
[Not reviewed]
master
0 10 0
Patric Stout - 3 years ago 2021-04-10 12:53:26
truebrain@openttd.org
Feature: allow a toggle to enable/disable vsync

Vsync should be off by default, as for most players it will be
better to play without vsync. Exception exist, mainly people who
play in fullscreen mode.
10 files changed with 68 insertions and 12 deletions:
0 comments (0 inline, 0 general)
src/lang/english.txt
Show inline comments
 
@@ -1003,12 +1003,15 @@ STR_GAME_OPTIONS_RESOLUTION_OTHER       
 
STR_GAME_OPTIONS_RESOLUTION_ITEM                                :{NUM}x{NUM}
 

	
 
STR_GAME_OPTIONS_VIDEO_ACCELERATION                             :{BLACK}Hardware acceleration
 
STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP                     :{BLACK}Check this box to allow OpenTTD to try to use hardware acceleration. A changed setting will only be applied upon game restart
 
STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART                     :{WHITE}The setting will only take effect after a game restart
 

	
 
STR_GAME_OPTIONS_VIDEO_VSYNC                                    :{BLACK}VSync
 
STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP                            :{BLACK}Check this box to v-sync the screen. A changed setting will only be applied upon game restart. Only works with hardware acceleration enabled
 

	
 
STR_GAME_OPTIONS_GUI_ZOOM_FRAME                                 :{BLACK}Interface size
 
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP                      :{BLACK}Select the interface element size to use
 

	
 
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_AUTO                         :(auto-detect)
 
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL                       :Normal
 
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM                      :Double size
src/settings_gui.cpp
Show inline comments
 
@@ -455,12 +455,25 @@ struct GameOptionsWindow : Window {
 
				break;
 

	
 
			case WID_GO_VIDEO_ACCEL_BUTTON:
 
				_video_hw_accel = !_video_hw_accel;
 
				ShowErrorMessage(STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART, INVALID_STRING_ID, WL_INFO);
 
				this->SetWidgetLoweredState(WID_GO_VIDEO_ACCEL_BUTTON, _video_hw_accel);
 
#ifndef __APPLE__
 
				this->SetWidgetDisabledState(WID_GO_VIDEO_VSYNC_BUTTON, !_video_hw_accel);
 
#endif
 
				this->SetDirty();
 
				break;
 

	
 
			case WID_GO_VIDEO_VSYNC_BUTTON:
 
				if (!_video_hw_accel) break;
 

	
 
				_video_vsync = !_video_vsync;
 
				VideoDriver::GetInstance()->ToggleVsync(_video_vsync);
 

	
 
				this->SetWidgetLoweredState(WID_GO_VIDEO_VSYNC_BUTTON, _video_vsync);
 
				this->SetDirty();
 
				break;
 

	
 
			case WID_GO_BASE_SFX_VOLUME:
 
			case WID_GO_BASE_MUSIC_VOLUME: {
 
				byte &vol = (widget == WID_GO_BASE_MUSIC_VOLUME) ? _settings_client.music.music_vol : _settings_client.music.effect_vol;
 
@@ -595,12 +608,17 @@ struct GameOptionsWindow : Window {
 
	void OnInvalidateData(int data = 0, bool gui_scope = true) override
 
	{
 
		if (!gui_scope) return;
 
		this->SetWidgetLoweredState(WID_GO_FULLSCREEN_BUTTON, _fullscreen);
 
		this->SetWidgetLoweredState(WID_GO_VIDEO_ACCEL_BUTTON, _video_hw_accel);
 

	
 
#ifndef __APPLE__
 
		this->SetWidgetLoweredState(WID_GO_VIDEO_VSYNC_BUTTON, _video_vsync);
 
		this->SetWidgetDisabledState(WID_GO_VIDEO_VSYNC_BUTTON, !_video_hw_accel);
 
#endif
 

	
 
		bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
 
		this->GetWidget<NWidgetCore>(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
 

	
 
		for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
 
			this->SetWidgetDisabledState(WID_GO_BASE_GRF_TEXTFILE + tft, BaseGraphics::GetUsedSet() == nullptr || BaseGraphics::GetUsedSet()->GetTextfile(tft) == nullptr);
 
			this->SetWidgetDisabledState(WID_GO_BASE_SFX_TEXTFILE + tft, BaseSounds::GetUsedSet() == nullptr || BaseSounds::GetUsedSet()->GetTextfile(tft) == nullptr);
 
@@ -644,25 +662,34 @@ static const NWidgetPart _nested_game_op
 
		NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GRAPHICS, STR_NULL), SetPadding(0, 10, 0, 10),
 
			NWidget(NWID_HORIZONTAL),
 
				NWidget(NWID_VERTICAL),
 
					NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL), SetPadding(0, 0, 2, 0),
 
					NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_REFRESH_RATE, STR_NULL), SetPadding(0, 0, 2, 0),
 
					NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL), SetPadding(0, 0, 2, 0),
 
					NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_VIDEO_ACCELERATION, STR_NULL),
 
					NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_VIDEO_ACCELERATION, STR_NULL), SetPadding(0, 0, 2, 0),
 
#ifndef __APPLE__
 
					NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_VIDEO_VSYNC, STR_NULL),
 
#endif
 
				EndContainer(),
 
				NWidget(NWID_VERTICAL),
 
					NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_RESOLUTION_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_RESOLUTION_TOOLTIP), SetFill(1, 0), SetPadding(0, 0, 2, 0),
 
					NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_REFRESH_RATE_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP), SetFill(1, 0), SetPadding(0, 0, 2, 0),
 
					NWidget(NWID_HORIZONTAL), SetPadding(0, 0, 2, 0),
 
						NWidget(NWID_SPACER), SetMinimalSize(1, 0), SetFill(1, 0),
 
						NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
 
					EndContainer(),
 
					NWidget(NWID_HORIZONTAL),
 
					NWidget(NWID_HORIZONTAL), SetPadding(0, 0, 2, 0),
 
						NWidget(NWID_SPACER), SetMinimalSize(1, 0), SetFill(1, 0),
 
						NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_ACCEL_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP),
 
					EndContainer(),
 
#ifndef __APPLE__
 
					NWidget(NWID_HORIZONTAL),
 
						NWidget(NWID_SPACER), SetMinimalSize(1, 0), SetFill(1, 0),
 
						NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_VSYNC_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP),
 
					EndContainer(),
 
#endif
 
				EndContainer(),
 
			EndContainer(),
 
		EndContainer(),
 

	
 
		NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
 
			NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
src/table/misc_settings.ini
Show inline comments
 
@@ -74,12 +74,18 @@ cat      = SC_BASIC
 
ifdef    = WITHOUT_COCOA
 
name     = ""video_hw_accel""
 
var      = _video_hw_accel
 
def      = true
 
cat      = SC_BASIC
 

	
 
[SDTG_BOOL]
 
name     = ""video_vsync""
 
var      = _video_vsync
 
def      = false
 
cat      = SC_BASIC
 

	
 
[SDTG_OMANY]
 
name     = ""support8bpp""
 
type     = SLE_UINT8
 
var      = _support8bpp
 
def      = 0
 
max      = 2
src/video/sdl2_opengl_v.cpp
Show inline comments
 
@@ -67,14 +67,12 @@ const char *VideoDriver_SDL_OpenGL::Star
 
	/* Now we have a OpenGL context, force a client-size-changed event,
 
	 * so all buffers are allocated correctly. */
 
	int w, h;
 
	SDL_GetWindowSize(this->sdl_window, &w, &h);
 
	this->ClientSizeChanged(w, h, true);
 

	
 
	SDL_GL_SetSwapInterval(GetDriverParamBool(param, "vsync") ? 1 : 0);
 

	
 
	return nullptr;
 
}
 

	
 
void VideoDriver_SDL_OpenGL::Stop()
 
{
 
	this->DestroyContext();
 
@@ -88,12 +86,17 @@ void VideoDriver_SDL_OpenGL::DestroyCont
 
	if (this->gl_context != nullptr) {
 
		SDL_GL_DeleteContext(this->gl_context);
 
		this->gl_context = nullptr;
 
	}
 
}
 

	
 
void VideoDriver_SDL_OpenGL::ToggleVsync(bool vsync)
 
{
 
	SDL_GL_SetSwapInterval(vsync);
 
}
 

	
 
const char *VideoDriver_SDL_OpenGL::AllocateContext()
 
{
 
	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
 
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
 
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
 
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
 
@@ -104,12 +107,14 @@ const char *VideoDriver_SDL_OpenGL::Allo
 
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
 
	}
 

	
 
	this->gl_context = SDL_GL_CreateContext(this->sdl_window);
 
	if (this->gl_context == nullptr) return "SDL2: Can't active GL context";
 

	
 
	ToggleVsync(_video_vsync);
 

	
 
	return OpenGLBackend::Create(&GetOGLProcAddressCallback);
 
}
 

	
 
void VideoDriver_SDL_OpenGL::PopulateSystemSprites()
 
{
 
	OpenGLBackend::Get()->PopulateCursorCache();
src/video/sdl2_opengl_v.h
Show inline comments
 
@@ -26,12 +26,14 @@ public:
 

	
 
	void PopulateSystemSprites() override;
 

	
 
	bool HasAnimBuffer() override { return true; }
 
	uint8 *GetAnimBuffer() override { return this->anim_buffer; }
 

	
 
	void ToggleVsync(bool vsync) override;
 

	
 
	const char *GetName() const override { return "sdl-opengl"; }
 

	
 
protected:
 
	bool AllocateBackingStore(int w, int h, bool force = false) override;
 
	void *GetVideoPointer() override;
 
	void ReleaseVideoPointer() override;
src/video/video_driver.cpp
Show inline comments
 
@@ -18,12 +18,13 @@
 
#include "../progress.h"
 
#include "../thread.h"
 
#include "../window_func.h"
 
#include "video_driver.hpp"
 

	
 
bool _video_hw_accel; ///< Whether to consider hardware accelerated video drivers.
 
bool _video_vsync; ///< Whether we should use vsync (only if _video_hw_accel is enabled).
 

	
 
void VideoDriver::GameLoop()
 
{
 
	this->next_game_tick += this->GetGameInterval();
 

	
 
	/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
src/video/video_driver.hpp
Show inline comments
 
@@ -25,12 +25,13 @@
 

	
 
extern std::string _ini_videodriver;
 
extern std::vector<Dimension> _resolutions;
 
extern Dimension _cur_resolution;
 
extern bool _rightclick_emulate;
 
extern bool _video_hw_accel;
 
extern bool _video_vsync;
 

	
 
/** The base of all video drivers. */
 
class VideoDriver : public Driver {
 
	const uint DEFAULT_WINDOW_WIDTH = 640u;  ///< Default window width.
 
	const uint DEFAULT_WINDOW_HEIGHT = 480u; ///< Default window height.
 

	
 
@@ -64,12 +65,18 @@ public:
 
	 * @param fullscreen The new setting.
 
	 * @return True if the change succeeded.
 
	 */
 
	virtual bool ToggleFullscreen(bool fullscreen) = 0;
 

	
 
	/**
 
	 * Change the vsync setting.
 
	 * @param vsync The new setting.
 
	 */
 
	virtual void ToggleVsync(bool vsync) {}
 

	
 
	/**
 
	 * Callback invoked after the blitter was changed.
 
	 * @return True if no error.
 
	 */
 
	virtual bool AfterBlitterChange()
 
	{
 
		return true;
src/video/win32_v.cpp
Show inline comments
 
@@ -1287,13 +1287,12 @@ static FVideoDriver_Win32OpenGL iFVideoD
 

	
 
const char *VideoDriver_Win32OpenGL::Start(const StringList &param)
 
{
 
	if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return "Only real blitters supported";
 

	
 
	Dimension old_res = _cur_resolution; // Save current screen resolution in case of errors, as MakeWindow invalidates it.
 
	this->vsync = GetDriverParamBool(param, "vsync");
 

	
 
	LoadWGLExtensions();
 

	
 
	this->Initialize();
 
	this->MakeWindow(_fullscreen);
 

	
 
@@ -1332,12 +1331,21 @@ void VideoDriver_Win32OpenGL::DestroyCon
 
	if (this->dc != nullptr) {
 
		ReleaseDC(this->main_wnd, this->dc);
 
		this->dc = nullptr;
 
	}
 
}
 

	
 
void VideoDriver_Win32OpenGL::ToggleVsync(bool vsync)
 
{
 
	if (_wglSwapIntervalEXT != nullptr) {
 
		_wglSwapIntervalEXT(vsync);
 
	} else if (vsync) {
 
		DEBUG(driver, 0, "OpenGL: Vsync requested, but not supported by driver");
 
	}
 
}
 

	
 
const char *VideoDriver_Win32OpenGL::AllocateContext()
 
{
 
	this->dc = GetDC(this->main_wnd);
 

	
 
	const char *err = SelectPixelFormat(this->dc, this->fullscreen);
 
	if (err != nullptr) return err;
 
@@ -1360,18 +1368,13 @@ const char *VideoDriver_Win32OpenGL::All
 
		/* Old OpenGL or old driver, let's hope for the best. */
 
		rc = wglCreateContext(this->dc);
 
		if (rc == nullptr) return "Can't create OpenGL context";
 
	}
 
	if (!wglMakeCurrent(this->dc, rc)) return "Can't active GL context";
 

	
 
	/* Enable/disable Vsync if supported. */
 
	if (_wglSwapIntervalEXT != nullptr) {
 
		_wglSwapIntervalEXT(this->vsync ? 1 : 0);
 
	} else if (vsync) {
 
		DEBUG(driver, 0, "OpenGL: Vsync requested, but not supported by driver");
 
	}
 
	this->ToggleVsync(_video_vsync);
 

	
 
	this->gl_rc = rc;
 
	return OpenGLBackend::Create(&GetOGLProcAddressCallback);
 
}
 

	
 
bool VideoDriver_Win32OpenGL::ToggleFullscreen(bool full_screen)
src/video/win32_v.h
Show inline comments
 
@@ -135,18 +135,19 @@ public:
 

	
 
	void ClearSystemSprites() override;
 

	
 
	bool HasAnimBuffer() override { return true; }
 
	uint8 *GetAnimBuffer() override { return this->anim_buffer; }
 

	
 
	void ToggleVsync(bool vsync) override;
 

	
 
	const char *GetName() const override { return "win32-opengl"; }
 

	
 
protected:
 
	HDC    dc;          ///< Window device context.
 
	HGLRC  gl_rc;       ///< OpenGL context.
 
	bool   vsync;       ///< Enable VSync?
 
	uint8 *anim_buffer; ///< Animation buffer from OpenGL back-end.
 

	
 
	uint8 GetFullscreenBpp() override { return 32; } // OpenGL is always 32 bpp.
 

	
 
	void Paint() override;
 

	
src/widgets/settings_widget.h
Show inline comments
 
@@ -32,12 +32,13 @@ enum GameOptionsWidgets {
 
	WID_GO_BASE_MUSIC_VOLUME,      ///< Change music volume.
 
	WID_GO_BASE_MUSIC_STATUS,      ///< Info about corrupted files etc.
 
	WID_GO_BASE_MUSIC_TEXTFILE,    ///< Open base music readme, changelog (+1) or license (+2).
 
	WID_GO_BASE_MUSIC_DESCRIPTION = WID_GO_BASE_MUSIC_TEXTFILE + TFT_END, ///< Description of selected base music set.
 
	WID_GO_FONT_ZOOM_DROPDOWN,     ///< Dropdown for the font zoom level.
 
	WID_GO_VIDEO_ACCEL_BUTTON,     ///< Toggle for video acceleration.
 
	WID_GO_VIDEO_VSYNC_BUTTON,     ///< Toggle for video vsync.
 
	WID_GO_REFRESH_RATE_DROPDOWN,  ///< Dropdown for all available refresh rates.
 
};
 

	
 
/** Widgets of the #GameSettingsWindow class. */
 
enum GameSettingsWidgets {
 
	WID_GS_FILTER,             ///< Text filter.
0 comments (0 inline, 0 general)