diff --git a/src/driver.cpp b/src/driver.cpp index c4efd35692..42520648f2 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -9,10 +9,12 @@ #include "stdafx.h" #include "debug.h" +#include "error.h" #include "sound/sound_driver.hpp" #include "music/music_driver.hpp" #include "video/video_driver.hpp" #include "string_func.h" +#include "table/strings.h" #include #include @@ -111,6 +113,8 @@ bool DriverFactoryBase::SelectDriverImpl(const std::string &name, Driver::Type t if (d->type != type) continue; if (d->priority != priority) continue; + if (type == Driver::DT_VIDEO && !_video_hw_accel && d->UsesHardwareAcceleration()) continue; + Driver *oldd = *GetActiveDriver(type); Driver *newd = d->CreateInstance(); *GetActiveDriver(type) = newd; @@ -125,6 +129,12 @@ bool DriverFactoryBase::SelectDriverImpl(const std::string &name, Driver::Type t *GetActiveDriver(type) = oldd; DEBUG(driver, 1, "Probing %s driver '%s' failed with error: %s", GetDriverTypeName(type), d->name, err); delete newd; + + if (type == Driver::DT_VIDEO && _video_hw_accel && d->UsesHardwareAcceleration()) { + _video_hw_accel = false; + ErrorMessageData msg(STR_VIDEO_DRIVER_ERROR, STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION); + ScheduleErrorMessage(msg); + } } } usererror("Couldn't find any suitable %s driver", GetDriverTypeName(type)); diff --git a/src/driver.h b/src/driver.h index 68d9fac929..93aaf61550 100644 --- a/src/driver.h +++ b/src/driver.h @@ -107,6 +107,15 @@ protected: virtual ~DriverFactoryBase(); + /** + * Does the driver use hardware acceleration (video-drivers only). + * @return True if the driver uses hardware acceleration. + */ + virtual bool UsesHardwareAcceleration() const + { + return false; + } + public: /** * Shuts down all active drivers diff --git a/src/lang/english.txt b/src/lang/english.txt index e47914fc04..1b47ec8ded 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1001,6 +1001,10 @@ STR_GAME_OPTIONS_RESOLUTION :{BLACK}Screen r STR_GAME_OPTIONS_RESOLUTION_TOOLTIP :{BLACK}Select the screen resolution to use STR_GAME_OPTIONS_RESOLUTION_OTHER :other +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_GUI_ZOOM_FRAME :{BLACK}Interface size STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Select the interface element size to use @@ -1787,6 +1791,10 @@ STR_CONFIG_ERROR_INVALID_BASE_MUSIC_NOT_FOUND :{WHITE}... igno STR_CONFIG_ERROR_OUT_OF_MEMORY :{WHITE}Out of memory STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}Allocating {BYTES} of spritecache failed. The spritecache was reduced to {BYTES}. This will reduce the performance of OpenTTD. To reduce memory requirements you can try to disable 32bpp graphics and/or zoom-in levels +# Video initalization errors +STR_VIDEO_DRIVER_ERROR :{WHITE}Error with video settings... +STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION :{WHITE}... no compatible GPU found. Hardware acceleration disabled + # Intro window STR_INTRO_CAPTION :{WHITE}OpenTTD {REV} diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index f89b3f7187..0ef8176bc9 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -35,6 +35,7 @@ #include "querystring_gui.h" #include "fontcache.h" #include "zoom_func.h" +#include "video/video_driver.hpp" #include @@ -381,6 +382,13 @@ struct GameOptionsWindow : Window { this->SetDirty(); 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); + this->SetDirty(); + break; + default: { int selected; DropDownList list = this->BuildDropDownList(widget, &selected); @@ -493,6 +501,7 @@ struct GameOptionsWindow : Window { { if (!gui_scope) return; this->SetWidgetLoweredState(WID_GO_FULLSCREEN_BUTTON, _fullscreen); + this->SetWidgetLoweredState(WID_GO_VIDEO_ACCEL_BUTTON, _video_hw_accel); bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0; this->GetWidget(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL); @@ -521,14 +530,16 @@ static const NWidgetPart _nested_game_options_widgets[] = { EndContainer(), NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_RESOLUTION_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_RESOLUTION_TOOLTIP), SetFill(1, 0), SetPadding(0, 0, 3, 0), - NWidget(NWID_HORIZONTAL), + NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0), SetPadding(0, 0, 3, 0), NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP), EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_VIDEO_ACCELERATION, STR_NULL), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_ACCEL_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP), + EndContainer(), EndContainer(), - NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_GUI_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0), - EndContainer(), + NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1), EndContainer(), NWidget(NWID_VERTICAL), SetPIP(0, 6, 0), @@ -538,7 +549,9 @@ static const NWidgetPart _nested_game_options_widgets[] = { NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_CURRENCY_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP), SetFill(1, 0), EndContainer(), - NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1), + NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_GUI_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0), + EndContainer(), NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_FONT_ZOOM, STR_NULL), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_FONT_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0), EndContainer(), diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 9d2f76cc06..9286d1c959 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -12,6 +12,9 @@ static const char *_support8bppmodes = "no|system|hardware"; #ifdef WITH_COCOA extern bool _allow_hidpi_window; #endif +#ifndef WITH_COCOA +#define WITHOUT_COCOA +#endif static const SettingDescGlobVarList _misc_settings[] = { [post-amble] @@ -60,6 +63,20 @@ var = _fullscreen def = false cat = SC_BASIC +[SDTG_BOOL] +ifdef = WITH_COCOA +name = ""video_hw_accel"" +var = _video_hw_accel +def = false +cat = SC_BASIC + +[SDTG_BOOL] +ifdef = WITHOUT_COCOA +name = ""video_hw_accel"" +var = _video_hw_accel +def = true +cat = SC_BASIC + [SDTG_OMANY] name = ""support8bpp"" type = SLE_UINT8 diff --git a/src/video/cocoa/cocoa_ogl.h b/src/video/cocoa/cocoa_ogl.h index be5d731136..9d95cd6066 100644 --- a/src/video/cocoa/cocoa_ogl.h +++ b/src/video/cocoa/cocoa_ogl.h @@ -54,6 +54,9 @@ class FVideoDriver_CocoaOpenGL : public DriverFactoryBase { public: FVideoDriver_CocoaOpenGL() : DriverFactoryBase(Driver::DT_VIDEO, 9, "cocoa-opengl", "Cocoa OpenGL Video Driver") {} Driver *CreateInstance() const override { return new VideoDriver_CocoaOpenGL(); } + +protected: + bool UsesHardwareAcceleration() const override { return true; } }; #endif /* VIDEO_COCOA_OGL_H */ diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index a32c7065d9..371e4b5bc7 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -122,7 +122,7 @@ protected: class FVideoDriver_CocoaQuartz : public DriverFactoryBase { public: - FVideoDriver_CocoaQuartz() : DriverFactoryBase(Driver::DT_VIDEO, 10, "cocoa", "Cocoa Video Driver") {} + FVideoDriver_CocoaQuartz() : DriverFactoryBase(Driver::DT_VIDEO, 8, "cocoa", "Cocoa Video Driver") {} Driver *CreateInstance() const override { return new VideoDriver_CocoaQuartz(); } }; diff --git a/src/video/sdl2_opengl_v.h b/src/video/sdl2_opengl_v.h index a59233db6d..71bc4373a2 100644 --- a/src/video/sdl2_opengl_v.h +++ b/src/video/sdl2_opengl_v.h @@ -51,4 +51,7 @@ class FVideoDriver_SDL_OpenGL : public DriverFactoryBase { public: FVideoDriver_SDL_OpenGL() : DriverFactoryBase(Driver::DT_VIDEO, 8, "sdl-opengl", "SDL OpenGL Video Driver") {} /* virtual */ Driver *CreateInstance() const override { return new VideoDriver_SDL_OpenGL(); } + +protected: + bool UsesHardwareAcceleration() const override { return true; } }; diff --git a/src/video/video_driver.cpp b/src/video/video_driver.cpp index 5e25184357..cb81f857d8 100644 --- a/src/video/video_driver.cpp +++ b/src/video/video_driver.cpp @@ -17,6 +17,8 @@ #include "../window_func.h" #include "video_driver.hpp" +bool _video_hw_accel; ///< Whether to consider hardware accelerated video drivers. + bool VideoDriver::Tick() { auto cur_ticks = std::chrono::steady_clock::now(); diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp index 938dd84bf3..58802efab1 100644 --- a/src/video/video_driver.hpp +++ b/src/video/video_driver.hpp @@ -23,6 +23,7 @@ extern std::string _ini_videodriver; extern std::vector _resolutions; extern Dimension _cur_resolution; extern bool _rightclick_emulate; +extern bool _video_hw_accel; /** The base of all video drivers. */ class VideoDriver : public Driver { diff --git a/src/video/win32_v.h b/src/video/win32_v.h index 0174671181..6dec59300f 100644 --- a/src/video/win32_v.h +++ b/src/video/win32_v.h @@ -175,6 +175,9 @@ class FVideoDriver_Win32OpenGL : public DriverFactoryBase { public: FVideoDriver_Win32OpenGL() : DriverFactoryBase(Driver::DT_VIDEO, 10, "win32-opengl", "Win32 OpenGL Video Driver") {} /* virtual */ Driver *CreateInstance() const override { return new VideoDriver_Win32OpenGL(); } + +protected: + bool UsesHardwareAcceleration() const override { return true; } }; #endif /* WITH_OPENGL */ diff --git a/src/widgets/settings_widget.h b/src/widgets/settings_widget.h index 2eb6180f5c..0b816ee1fe 100644 --- a/src/widgets/settings_widget.h +++ b/src/widgets/settings_widget.h @@ -32,6 +32,7 @@ enum GameOptionsWidgets { 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. }; /** Widgets of the #GameSettingsWindow class. */