OpenTTD Source  14.0-beta1
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"
11 #include "debug.h"
12 #include "error.h"
13 #include "error_func.h"
14 #include "sound/sound_driver.hpp"
15 #include "music/music_driver.hpp"
16 #include "video/video_driver.hpp"
17 #include "string_func.h"
18 #include "table/strings.h"
19 #include "fileio_func.h"
20 #include <sstream>
21 
22 #ifdef _WIN32
23 # include <windows.h>
24 #else
25 # include <unistd.h>
26 #endif /* _WIN32 */
27 
28 #include "safeguards.h"
29 
30 std::string _ini_videodriver;
31 std::vector<Dimension> _resolutions;
34 
35 std::string _ini_sounddriver;
36 
37 std::string _ini_musicdriver;
38 
39 std::string _ini_blitter;
41 
42 static const std::string HWACCELERATION_TEST_FILE = "hwaccel.dat";
43 
50 const char *GetDriverParam(const StringList &parm, const char *name)
51 {
52  if (parm.empty()) return nullptr;
53 
54  size_t len = strlen(name);
55  for (auto &p : parm) {
56  if (p.compare(0, len, name) == 0) {
57  if (p.length() == len) return "";
58  if (p[len] == '=') return p.c_str() + len + 1;
59  }
60  }
61  return nullptr;
62 }
63 
70 bool GetDriverParamBool(const StringList &parm, const char *name)
71 {
72  return GetDriverParam(parm, name) != nullptr;
73 }
74 
82 int GetDriverParamInt(const StringList &parm, const char *name, int def)
83 {
84  const char *p = GetDriverParam(parm, name);
85  return p != nullptr ? atoi(p) : def;
86 }
87 
94 void 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 
110 bool 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 
124  if (type == Driver::DT_VIDEO && !_video_hw_accel && d->UsesHardwareAcceleration()) continue;
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  unlink(filename.c_str());
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(STR_VIDEO_DRIVER_ERROR, STR_VIDEO_DRIVER_ERROR_HARDWARE_ACCELERATION_CRASH, true);
139  continue;
140  }
141 
142  /* Write empty file to note we are attempting hardware acceleration. */
144  FioFCloseFile(f);
145  }
146 
147  Driver *oldd = *GetActiveDriver(type);
148  Driver *newd = d->CreateInstance();
149  *GetActiveDriver(type) = newd;
150 
151  const char *err = newd->Start({});
152  if (err == nullptr) {
153  Debug(driver, 1, "Successfully probed {} driver '{}'", GetDriverTypeName(type), d->name);
154  delete oldd;
155  return true;
156  }
157 
158  *GetActiveDriver(type) = oldd;
159  Debug(driver, 1, "Probing {} driver '{}' failed with error: {}", GetDriverTypeName(type), d->name, err);
160  delete newd;
161 
163  _video_hw_accel = false;
164  ErrorMessageData msg(STR_VIDEO_DRIVER_ERROR, STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION, true);
166  }
167  }
168  }
169  UserError("Couldn't find any suitable {} driver", GetDriverTypeName(type));
170  } else {
171  /* Extract the driver name and put parameter list in parm */
172  std::istringstream buffer(name);
173  std::string dname;
174  std::getline(buffer, dname, ':');
175 
176  std::string param;
177  std::vector<std::string> parms;
178  while (std::getline(buffer, param, ',')) {
179  parms.push_back(param);
180  }
181 
182  /* Find this driver */
183  for (auto &it : GetDrivers()) {
184  DriverFactoryBase *d = it.second;
185 
186  /* Check driver type */
187  if (d->type != type) continue;
188 
189  /* Check driver name */
190  if (!StrEqualsIgnoreCase(dname, d->name)) continue;
191 
192  /* Found our driver, let's try it */
193  Driver *newd = d->CreateInstance();
194 
195  const char *err = newd->Start(parms);
196  if (err != nullptr) {
197  delete newd;
198  UserError("Unable to load driver '{}'. The error was: {}", d->name, err);
199  }
200 
201  Debug(driver, 1, "Successfully loaded {} driver '{}'", GetDriverTypeName(type), d->name);
202  delete *GetActiveDriver(type);
203  *GetActiveDriver(type) = newd;
204  return true;
205  }
206  UserError("No such {} driver: {}\n", GetDriverTypeName(type), dname);
207  }
208 }
209 
214 {
215  /* As part of the detection whether the GPU driver crashes the game,
216  * and as we are operational now, remove the hardware acceleration
217  * test-file. */
219  if (!filename.empty()) unlink(filename.c_str());
220 }
221 
226 void DriverFactoryBase::GetDriversInfo(std::back_insert_iterator<std::string> &output_iterator)
227 {
229  fmt::format_to(output_iterator, "List of {} drivers:\n", GetDriverTypeName(type));
230 
231  for (int priority = 10; priority >= 0; priority--) {
232  for (auto &it : GetDrivers()) {
233  DriverFactoryBase *d = it.second;
234  if (d->type != type) continue;
235  if (d->priority != priority) continue;
236  fmt::format_to(output_iterator, "{:>18}: {}\n", d->name, d->GetDescription());
237  }
238  }
239 
240  fmt::format_to(output_iterator, "\n");
241  }
242 }
243 
251 DriverFactoryBase::DriverFactoryBase(Driver::Type type, int priority, const char *name, const char *description) :
252  type(type), priority(priority), name(name), description(description)
253 {
254  /* Prefix the name with driver type to make it unique */
255  std::string typed_name = fmt::format("{}{}", GetDriverTypeName(type), name);
256 
257  Drivers &drivers = GetDrivers();
258  assert(drivers.find(typed_name) == drivers.end());
259  drivers.insert(Drivers::value_type(typed_name, this));
260 }
261 
266 {
267  /* Prefix the name with driver type to make it unique */
268  std::string typed_name = fmt::format("{}{}", GetDriverTypeName(type), name);
269 
270  Drivers::iterator it = GetDrivers().find(typed_name);
271  assert(it != GetDrivers().end());
272 
273  GetDrivers().erase(it);
274  if (GetDrivers().empty()) delete &GetDrivers();
275 }
DriverFactoryBase::GetDriverTypeName
static const char * GetDriverTypeName(Driver::Type type)
Get the driver type name.
Definition: driver.h:95
DriverFactoryBase::SelectDriverImpl
static bool SelectDriverImpl(const std::string &name, Driver::Type type)
Find the requested driver and return its class.
Definition: driver.cpp:110
DriverFactoryBase::GetActiveDriver
static Driver ** GetActiveDriver(Driver::Type type)
Get the active driver for the given type.
Definition: driver.h:84
Dimension
Dimensions (a width and height) of a rectangle in 2D.
Definition: geometry_type.hpp:30
ScheduleErrorMessage
void ScheduleErrorMessage(ErrorList &datas)
Schedule a list of errors.
Definition: error_gui.cpp:452
DriverFactoryBase::name
const char * name
The name of the drivers of this factory.
Definition: driver.h:65
FioFindFullPath
std::string FioFindFullPath(Subdirectory subdir, const std::string &filename)
Find a path to the filename in one of the search directories.
Definition: fileio.cpp:159
_ini_blitter
std::string _ini_blitter
The blitter as stored in the configuration file.
Definition: driver.cpp:39
DriverFactoryBase::DriverFactoryBase
DriverFactoryBase(Driver::Type type, int priority, const char *name, const char *description)
Construct a new DriverFactory.
Definition: driver.cpp:251
DriverFactoryBase::CreateInstance
virtual Driver * CreateInstance() const =0
Create an instance of this driver-class.
DriverFactoryBase::~DriverFactoryBase
virtual ~DriverFactoryBase()
Frees memory used for this->name.
Definition: driver.cpp:265
DriverFactoryBase::GetDriversInfo
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:226
fileio_func.h
GetDriverParam
const char * GetDriverParam(const StringList &parm, const char *name)
Get a string parameter the list of parameters.
Definition: driver.cpp:50
DriverFactoryBase::GetDrivers
static Drivers & GetDrivers()
Get the map with drivers.
Definition: driver.h:73
Debug
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
_ini_musicdriver
std::string _ini_musicdriver
The music driver a stored in the configuration file.
Definition: driver.cpp:37
BASE_DIR
@ BASE_DIR
Base directory for all subdirectories.
Definition: fileio_type.h:109
error_func.h
DriverFactoryBase::priority
int priority
The priority of this factory.
Definition: driver.h:64
DriverFactoryBase::Drivers
std::map< std::string, DriverFactoryBase * > Drivers
Type for a map of drivers.
Definition: driver.h:68
FioFOpenFile
FILE * FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
Definition: fileio.cpp:263
Driver::Start
virtual const char * Start(const StringList &parm)=0
Start this driver.
DriverFactoryBase::type
Driver::Type type
The type of driver.
Definition: driver.h:63
StringList
std::vector< std::string > StringList
Type for a list of strings.
Definition: string_type.h:60
safeguards.h
music_driver.hpp
_resolutions
std::vector< Dimension > _resolutions
List of resolutions.
Definition: driver.cpp:31
ErrorMessageData
The data of the error message.
Definition: error.h:31
error.h
stdafx.h
Driver::Type
Type
The type of driver.
Definition: driver.h:38
Driver::DT_END
@ DT_END
Helper for iteration.
Definition: driver.h:43
GetDriverParamInt
int GetDriverParamInt(const StringList &parm, const char *name, int def)
Get an integer parameter the list of parameters.
Definition: driver.cpp:82
sound_driver.hpp
_rightclick_emulate
bool _rightclick_emulate
Whether right clicking is emulated.
Definition: driver.cpp:33
string_func.h
Driver::DT_BEGIN
@ DT_BEGIN
Helper for iteration.
Definition: driver.h:39
video_driver.hpp
Driver::DT_VIDEO
@ DT_VIDEO
A video driver.
Definition: driver.h:42
_blitter_autodetected
bool _blitter_autodetected
Was the blitter autodetected or specified by the user?
Definition: driver.cpp:40
_ini_sounddriver
std::string _ini_sounddriver
The sound driver a stored in the configuration file.
Definition: driver.cpp:35
_video_hw_accel
bool _video_hw_accel
Whether to consider hardware accelerated video drivers.
Definition: video_driver.cpp:25
DriverFactoryBase::UsesHardwareAcceleration
virtual bool UsesHardwareAcceleration() const
Does the driver use hardware acceleration (video-drivers only).
Definition: driver.h:114
DriverFactoryBase::GetDescription
const char * GetDescription() const
Get a nice description of the driver-class.
Definition: driver.h:138
StrEqualsIgnoreCase
bool StrEqualsIgnoreCase(const std::string_view str1, const std::string_view str2)
Compares two string( view)s for equality, while ignoring the case of the characters.
Definition: string.cpp:366
DriverFactoryBase::SelectDriver
static void SelectDriver(const std::string &name, Driver::Type type)
Find the requested driver and return its class.
Definition: driver.cpp:94
Driver
A driver for communicating with the user.
Definition: driver.h:21
GetDriverParamBool
bool GetDriverParamBool(const StringList &parm, const char *name)
Get a boolean parameter the list of parameters.
Definition: driver.cpp:70
_cur_resolution
Dimension _cur_resolution
The current resolution.
Definition: driver.cpp:32
DriverFactoryBase
Base for all driver factories.
Definition: driver.h:57
_ini_videodriver
std::string _ini_videodriver
The video driver a stored in the configuration file.
Definition: driver.cpp:30
DriverFactoryBase::MarkVideoDriverOperational
static void MarkVideoDriverOperational()
Mark the current video driver as operational.
Definition: driver.cpp:213
FioFCloseFile
void FioFCloseFile(FILE *f)
Close a file in a safe way.
Definition: fileio.cpp:148
debug.h
HWACCELERATION_TEST_FILE
static const std::string HWACCELERATION_TEST_FILE
Filename to test if we crashed last time we tried to use hardware acceleration.
Definition: driver.cpp:42