OpenTTD Source 20251116-master-g21329071df
driver.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
12#include "debug.h"
13#include "error.h"
14#include "error_func.h"
17#include "strings_func.h"
19#include "string_func.h"
20#include "fileio_func.h"
22
23#include "table/strings.h"
24
25#include "safeguards.h"
26
27std::string _ini_videodriver;
28std::vector<Dimension> _resolutions;
31
32std::string _ini_sounddriver;
33
34std::string _ini_musicdriver;
35
36std::string _ini_blitter;
38
39static const std::string HWACCELERATION_TEST_FILE = "hwaccel.dat";
40
47std::optional<std::string_view> GetDriverParam(const StringList &parm, std::string_view name)
48{
49 if (parm.empty()) return std::nullopt;
50
51 for (auto &p : parm) {
52 StringConsumer consumer{p};
53 if (consumer.ReadIf(name)) {
54 if (!consumer.AnyBytesLeft()) return "";
55 if (consumer.ReadIf("=")) return consumer.GetLeftData();
56 }
57 }
58 return std::nullopt;
59}
60
67bool GetDriverParamBool(const StringList &parm, std::string_view name)
68{
69 return GetDriverParam(parm, name).has_value();
70}
71
79int GetDriverParamInt(const StringList &parm, std::string_view name, int def)
80{
81 auto p = GetDriverParam(parm, name);
82 if (!p.has_value()) return def;
83 auto value = ParseInteger<int>(*p);
84 if (value.has_value()) return *value;
85 UserError("Invalid value for driver parameter {}: {}", name, *p);
86}
87
94void DriverFactoryBase::SelectDriver(const std::string &name, Driver::Type type)
95{
97 name.empty() ?
98 UserError("Failed to autoprobe {} driver", GetDriverTypeName(type)) :
99 UserError("Failed to select requested {} driver '{}'", GetDriverTypeName(type), name);
100 }
101}
102
110bool DriverFactoryBase::SelectDriverImpl(const std::string &name, Driver::Type type)
111{
112 if (GetDrivers().empty()) return false;
113
114 if (name.empty()) {
115 /* Probe for this driver, but do not fall back to dedicated/null! */
116 for (int priority = 10; priority > 0; priority--) {
117 for (auto &it : GetDrivers()) {
118 DriverFactoryBase *d = it.second;
119
120 /* Check driver type */
121 if (d->type != type) continue;
122 if (d->priority != priority) continue;
123
125
127 /* Check if we have already tried this driver in last run.
128 * If it is here, it most likely means we crashed. So skip
129 * hardware acceleration. */
131 if (!filename.empty()) {
132 FioRemove(filename);
133
134 Debug(driver, 1, "Probing {} driver '{}' skipped due to earlier crash", GetDriverTypeName(type), d->name);
135
136 _video_hw_accel = false;
137 ErrorMessageData msg(GetEncodedString(STR_VIDEO_DRIVER_ERROR), GetEncodedString(STR_VIDEO_DRIVER_ERROR_HARDWARE_ACCELERATION_CRASH), true);
138 ScheduleErrorMessage(std::move(msg));
139 continue;
140 }
141
142 /* Write empty file to note we are attempting hardware acceleration. */
144 }
145
146 /* Keep old driver in case we need to switch back, or may still need to process an OS callback. */
147 auto oldd = std::move(GetActiveDriver(type));
148 auto newd = d->CreateInstance();
149
150 auto err = newd->Start({});
151 if (!err) {
152 Debug(driver, 1, "Successfully probed {} driver '{}'", GetDriverTypeName(type), d->name);
153 GetActiveDriver(type) = std::move(newd);
154 return true;
155 }
156
157 GetActiveDriver(type) = std::move(oldd);
158 Debug(driver, 1, "Probing {} driver '{}' failed with error: {}", GetDriverTypeName(type), d->name, *err);
159
161 _video_hw_accel = false;
162 ErrorMessageData msg(GetEncodedString(STR_VIDEO_DRIVER_ERROR), GetEncodedString(STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION), true);
163 ScheduleErrorMessage(std::move(msg));
164 }
165 }
166 }
167 UserError("Couldn't find any suitable {} driver", GetDriverTypeName(type));
168 } else {
169 /* Extract the driver name and put parameter list in parm */
170 std::istringstream buffer(name);
171 std::string dname;
172 std::getline(buffer, dname, ':');
173
174 std::string param;
175 std::vector<std::string> parms;
176 while (std::getline(buffer, param, ',')) {
177 parms.push_back(param);
178 }
179
180 /* Find this driver */
181 for (auto &it : GetDrivers()) {
182 DriverFactoryBase *d = it.second;
183
184 /* Check driver type */
185 if (d->type != type) continue;
186
187 /* Check driver name */
188 if (!StrEqualsIgnoreCase(dname, d->name)) continue;
189
190 /* Found our driver, let's try it */
191 auto newd = d->CreateInstance();
192 auto err = newd->Start(parms);
193 if (err) {
194 UserError("Unable to load driver '{}'. The error was: {}", d->name, *err);
195 }
196
197 Debug(driver, 1, "Successfully loaded {} driver '{}'", GetDriverTypeName(type), d->name);
198 GetActiveDriver(type) = std::move(newd);
199 return true;
200 }
201 UserError("No such {} driver: {}\n", GetDriverTypeName(type), dname);
202 }
203}
204
209{
210 /* As part of the detection whether the GPU driver crashes the game,
211 * and as we are operational now, remove the hardware acceleration
212 * test-file. */
214 if (!filename.empty()) FioRemove(filename);
215}
216
221void DriverFactoryBase::GetDriversInfo(std::back_insert_iterator<std::string> &output_iterator)
222{
224 fmt::format_to(output_iterator, "List of {} drivers:\n", GetDriverTypeName(type));
225
226 for (int priority = 10; priority >= 0; priority--) {
227 for (auto &it : GetDrivers()) {
228 DriverFactoryBase *d = it.second;
229 if (d->type != type) continue;
230 if (d->priority != priority) continue;
231 fmt::format_to(output_iterator, "{:>18}: {}\n", d->name, d->GetDescription());
232 }
233 }
234
235 fmt::format_to(output_iterator, "\n");
236 }
237}
238
246DriverFactoryBase::DriverFactoryBase(Driver::Type type, int priority, std::string_view name, std::string_view description) :
247 type(type), priority(priority), name(name), description(description)
248{
249 /* Prefix the name with driver type to make it unique */
250 std::string typed_name = fmt::format("{}{}", GetDriverTypeName(type), name);
251
252 Drivers &drivers = GetDrivers();
253 assert(drivers.find(typed_name) == drivers.end());
254 drivers.insert(Drivers::value_type(typed_name, this));
255}
256
261{
262 /* Prefix the name with driver type to make it unique */
263 std::string typed_name = fmt::format("{}{}", GetDriverTypeName(type), name);
264
265 Drivers::iterator it = GetDrivers().find(typed_name);
266 assert(it != GetDrivers().end());
267
268 GetDrivers().erase(it);
269 if (GetDrivers().empty()) delete &GetDrivers();
270}
Base for all driver factories.
Definition driver.h:57
static void MarkVideoDriverOperational()
Mark the current video driver as operational.
Definition driver.cpp:208
std::string_view name
The name of the drivers of this factory.
Definition driver.h:65
std::string_view GetDescription() const
Get a nice description of the driver-class.
Definition driver.h:138
std::map< std::string, DriverFactoryBase * > Drivers
Type for a map of drivers.
Definition driver.h:68
static Drivers & GetDrivers()
Get the map with drivers.
Definition driver.h:73
virtual bool UsesHardwareAcceleration() const
Does the driver use hardware acceleration (video-drivers only).
Definition driver.h:114
static std::unique_ptr< Driver > & GetActiveDriver(Driver::Type type)
Get the active driver for the given type.
Definition driver.h:84
DriverFactoryBase(Driver::Type type, int priority, std::string_view name, std::string_view description)
Construct a new DriverFactory.
Definition driver.cpp:246
static void SelectDriver(const std::string &name, Driver::Type type)
Find the requested driver and return its class.
Definition driver.cpp:94
static std::string_view GetDriverTypeName(Driver::Type type)
Get the driver type name.
Definition driver.h:95
static bool SelectDriverImpl(const std::string &name, Driver::Type type)
Find the requested driver and return its class.
Definition driver.cpp:110
virtual std::unique_ptr< Driver > CreateInstance() const =0
Create an instance of this driver-class.
static void GetDriversInfo(std::back_insert_iterator< std::string > &output_iterator)
Build a human readable list of available drivers, grouped by type.
Definition driver.cpp:221
Driver::Type type
The type of driver.
Definition driver.h:63
virtual ~DriverFactoryBase()
Frees memory used for this->name.
Definition driver.cpp:260
int priority
The priority of this factory.
Definition driver.h:64
Type
The type of driver.
Definition driver.h:38
@ DT_END
Helper for iteration.
Definition driver.h:43
@ DT_VIDEO
A video driver.
Definition driver.h:42
@ DT_BEGIN
Helper for iteration.
Definition driver.h:39
The data of the error message.
Definition error.h:31
Parse data from a string / buffer.
std::string_view GetLeftData() const noexcept
Get data left to read.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
int GetDriverParamInt(const StringList &parm, std::string_view name, int def)
Get an integer parameter the list of parameters.
Definition driver.cpp:79
std::optional< std::string_view > GetDriverParam(const StringList &parm, std::string_view name)
Get a string parameter the list of parameters.
Definition driver.cpp:47
bool _blitter_autodetected
Was the blitter autodetected or specified by the user?
Definition driver.cpp:37
bool GetDriverParamBool(const StringList &parm, std::string_view name)
Get a boolean parameter the list of parameters.
Definition driver.cpp:67
std::string _ini_videodriver
The video driver a stored in the configuration file.
Definition driver.cpp:27
std::string _ini_musicdriver
The music driver a stored in the configuration file.
Definition driver.cpp:34
std::vector< Dimension > _resolutions
List of resolutions.
Definition driver.cpp:28
Dimension _cur_resolution
The current resolution.
Definition driver.cpp:29
bool _rightclick_emulate
Whether right clicking is emulated.
Definition driver.cpp:30
std::string _ini_blitter
The blitter as stored in the configuration file.
Definition driver.cpp:36
std::string _ini_sounddriver
The sound driver a stored in the configuration file.
Definition driver.cpp:32
static const std::string HWACCELERATION_TEST_FILE
Filename to test if we crashed last time we tried to use hardware acceleration.
Definition driver.cpp:39
Functions related to errors.
void ScheduleErrorMessage(ErrorList &datas)
Schedule a list of errors.
Error reporting related functions.
bool FioRemove(const std::string &filename)
Remove a file.
Definition fileio.cpp:327
std::optional< FileHandle > FioFOpenFile(std::string_view filename, std::string_view mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
Definition fileio.cpp:242
std::string FioFindFullPath(Subdirectory subdir, std::string_view filename)
Find a path to the filename in one of the search directories.
Definition fileio.cpp:144
Functions for Standard In/Out file operations.
@ BASE_DIR
Base directory for all subdirectories.
Definition fileio_type.h:89
Base for all music playback.
A number of safeguards to prevent using unsafe methods.
Base for all sound drivers.
Definition of base types and functions in a cross-platform compatible way.
bool StrEqualsIgnoreCase(std::string_view str1, std::string_view str2)
Compares two string( view)s for equality, while ignoring the case of the characters.
Definition string.cpp:324
Parse strings.
Functions related to low-level strings.
std::vector< std::string > StringList
Type for a list of strings.
Definition string_type.h:60
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
Functions related to OTTD's strings.
Dimensions (a width and height) of a rectangle in 2D.
bool _video_hw_accel
Whether to consider hardware accelerated video drivers on startup.
Base of all video drivers.