OpenTTD Source  20240917-master-g9ab0a47812
video_driver.hpp
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 #ifndef VIDEO_VIDEO_DRIVER_HPP
11 #define VIDEO_VIDEO_DRIVER_HPP
12 
13 #include "../driver.h"
14 #include "../core/geometry_type.hpp"
15 #include "../core/math_func.hpp"
16 #include "../gfx_func.h"
17 #include "../settings_type.h"
18 #include "../zoom_type.h"
19 #include "../network/network_func.h"
20 #include <atomic>
21 #include <chrono>
22 #include <condition_variable>
23 #include <mutex>
24 #include <thread>
25 
26 extern std::string _ini_videodriver;
27 extern std::vector<Dimension> _resolutions;
29 extern bool _rightclick_emulate;
30 extern bool _video_hw_accel;
31 extern bool _video_vsync;
32 
34 class VideoDriver : public Driver {
35  const uint DEFAULT_WINDOW_WIDTH = 640u;
36  const uint DEFAULT_WINDOW_HEIGHT = 480u;
37 
38 public:
39  VideoDriver(bool uses_hardware_acceleration = false) : fast_forward_key_pressed(false), fast_forward_via_key(false), is_game_threaded(true), uses_hardware_acceleration(uses_hardware_acceleration) {}
40 
48  virtual void MakeDirty(int left, int top, int width, int height) = 0;
49 
53  virtual void MainLoop() = 0;
54 
61  virtual bool ChangeResolution(int w, int h) = 0;
62 
68  virtual bool ToggleFullscreen(bool fullscreen) = 0;
69 
74  virtual void ToggleVsync([[maybe_unused]] bool vsync) {}
75 
80  virtual bool AfterBlitterChange()
81  {
82  return true;
83  }
84 
85  virtual bool ClaimMousePointer()
86  {
87  return true;
88  }
89 
94  virtual bool UseSystemCursor()
95  {
96  return false;
97  }
98 
102  virtual void PopulateSystemSprites() {}
103 
107  virtual void ClearSystemSprites() {}
108 
117  virtual bool HasGUI() const
118  {
119  return true;
120  }
121 
126  virtual bool HasEfficient8Bpp() const
127  {
128  return false;
129  }
130 
135  virtual bool HasAnimBuffer()
136  {
137  return false;
138  }
139 
144  virtual uint8_t *GetAnimBuffer()
145  {
146  return nullptr;
147  }
148 
152  virtual void EditBoxLostFocus() {}
153 
157  virtual void EditBoxGainedFocus() {}
158 
163  virtual std::vector<int> GetListOfMonitorRefreshRates()
164  {
165  return {};
166  }
167 
171  virtual int GetSuggestedUIScale()
172  {
173  float dpi_scale = this->GetDPIScale();
174 
175  return Clamp(dpi_scale * 100, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE);
176  }
177 
178  virtual std::string_view GetInfoString() const
179  {
180  return this->GetName();
181  }
182 
189  void QueueOnMainThread(std::function<void()> &&func)
190  {
191  std::lock_guard<std::mutex> lock(this->cmd_queue_mutex);
192 
193  this->cmd_queue.emplace_back(std::forward<std::function<void()>>(func));
194  }
195 
196  void GameLoopPause();
197 
202  {
204  }
205 
206  static std::string GetCaption();
207 
214  {
216  }
217 
219  {
221  }
222 
223  private:
224  bool unlock;
225  };
226 
227 protected:
228  const uint ALLOWED_DRIFT = 5;
229 
234 
239  virtual float GetDPIScale() { return 1.0f; }
240 
245  {
246  if (_cur_resolution.width == 0 || _cur_resolution.height == 0) {
247  /* Auto-detect a good resolution. We aim for 75% of the screen size.
248  * Limit width times height times bytes per pixel to fit a 32 bit
249  * integer, This way all internal drawing routines work correctly. */
250  Dimension res = this->GetScreenSize();
251  _cur_resolution.width = ClampU(res.width * 3 / 4, DEFAULT_WINDOW_WIDTH, UINT16_MAX / 2);
252  _cur_resolution.height = ClampU(res.height * 3 / 4, DEFAULT_WINDOW_HEIGHT, UINT16_MAX / 2);
253  }
254  }
255 
259  virtual void InputLoop() {}
260 
265  virtual bool LockVideoBuffer()
266  {
267  return false;
268  }
269 
273  virtual void UnlockVideoBuffer() {}
274 
278  virtual void Paint() {}
279 
283  virtual void CheckPaletteAnim() {}
284 
289  virtual bool PollEvent() { return false; };
290 
294  void StartGameThread();
295 
299  void StopGameThread();
300 
306  void Tick();
307 
311  void SleepTillNextTick();
312 
313  std::chrono::steady_clock::duration GetGameInterval()
314  {
315 #ifdef DEBUG_DUMP_COMMANDS
316  /* When replaying, run as fast as we can. */
317  extern bool _ddc_fastforward;
318  if (_ddc_fastforward) return std::chrono::microseconds(0);
319 #endif /* DEBUG_DUMP_COMMANDS */
320 
321  /* If we are paused, run on normal speed. */
322  if (_pause_mode) return std::chrono::milliseconds(MILLISECONDS_PER_TICK);
323  /* Infinite speed, as quickly as you can. */
324  if (_game_speed == 0) return std::chrono::microseconds(0);
325 
326  return std::chrono::microseconds(MILLISECONDS_PER_TICK * 1000 * 100 / _game_speed);
327  }
328 
329  std::chrono::steady_clock::duration GetDrawInterval()
330  {
331  /* If vsync, draw interval is decided by the display driver */
332  if (_video_vsync && this->uses_hardware_acceleration) return std::chrono::microseconds(0);
333  return std::chrono::microseconds(1000000 / _settings_client.gui.refresh_rate);
334  }
335 
338  {
339  std::vector<std::function<void()>> cmds{};
340 
341  {
342  /* Exchange queue with an empty one to limit the time we
343  * hold the mutex. This also ensures that queued functions can
344  * add new functions to the queue without everything blocking. */
345  std::lock_guard<std::mutex> lock(this->cmd_queue_mutex);
346  cmds.swap(this->cmd_queue);
347  }
348 
349  for (auto &f : cmds) {
350  f();
351  }
352  }
353 
354  std::chrono::steady_clock::time_point next_game_tick;
355  std::chrono::steady_clock::time_point next_draw_tick;
356 
359 
360  bool is_game_threaded;
361  std::thread game_thread;
362  std::mutex game_state_mutex;
363  std::mutex game_thread_wait_mutex;
364 
365  bool uses_hardware_acceleration;
366 
367  static void GameThreadThunk(VideoDriver *drv);
368 
369 private:
370  std::mutex cmd_queue_mutex;
371  std::vector<std::function<void()>> cmd_queue;
372 
373  void GameLoop();
374  void GameThread();
375 };
376 
377 #endif /* VIDEO_VIDEO_DRIVER_HPP */
VideoDriver::Tick
void Tick()
Give the video-driver a tick.
Definition: video_driver.cpp:102
VideoDriver::HasAnimBuffer
virtual bool HasAnimBuffer()
Does this video driver support a separate animation buffer in addition to the colour buffer?
Definition: video_driver.hpp:135
DriverFactoryBase::GetActiveDriver
static Driver ** GetActiveDriver(Driver::Type type)
Get the active driver for the given type.
Definition: driver.h:84
VideoDriver
The base of all video drivers.
Definition: video_driver.hpp:34
Dimension
Dimensions (a width and height) of a rectangle in 2D.
Definition: geometry_type.hpp:30
lock
std::mutex lock
synchronization for playback status fields
Definition: win32_m.cpp:35
VideoDriver::CheckPaletteAnim
virtual void CheckPaletteAnim()
Process any pending palette animation.
Definition: video_driver.hpp:283
VideoDriver::ToggleVsync
virtual void ToggleVsync([[maybe_unused]] bool vsync)
Change the vsync setting.
Definition: video_driver.hpp:74
VideoDriver::MakeDirty
virtual void MakeDirty(int left, int top, int width, int height)=0
Mark a particular area dirty.
VideoDriver::ToggleFullscreen
virtual bool ToggleFullscreen(bool fullscreen)=0
Change the full screen setting.
_cur_resolution
Dimension _cur_resolution
The current resolution.
Definition: driver.cpp:26
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:56
ClampU
constexpr uint ClampU(const uint a, const uint min, const uint max)
Clamp an unsigned integer between an interval.
Definition: math_func.hpp:150
VideoDriver::HasGUI
virtual bool HasGUI() const
Whether the driver has a graphical user interface with the end user.
Definition: video_driver.hpp:117
VideoDriver::StartGameThread
void StartGameThread()
Start the loop for game-tick.
Definition: video_driver.cpp:86
VideoDriver::ClearSystemSprites
virtual void ClearSystemSprites()
Clear all cached sprites.
Definition: video_driver.hpp:107
_video_vsync
bool _video_vsync
Whether we should use vsync (only if active video driver supports HW acceleration).
Definition: video_driver.cpp:26
VideoDriver::GetDPIScale
virtual float GetDPIScale()
Get DPI scaling factor of the screen OTTD is displayed on.
Definition: video_driver.hpp:239
GUISettings::refresh_rate
uint16_t refresh_rate
How often we refresh the screen (time between draw-ticks).
Definition: settings_type.h:209
VideoDriver::DEFAULT_WINDOW_HEIGHT
const uint DEFAULT_WINDOW_HEIGHT
Default window height.
Definition: video_driver.hpp:36
VideoDriver::InputLoop
virtual void InputLoop()
Handle input logic, is CTRL pressed, should we fast-forward, etc.
Definition: video_driver.hpp:259
VideoDriver::GetListOfMonitorRefreshRates
virtual std::vector< int > GetListOfMonitorRefreshRates()
Get a list of refresh rates of each available monitor.
Definition: video_driver.hpp:163
VideoDriver::Paint
virtual void Paint()
Paint the window.
Definition: video_driver.hpp:278
_rightclick_emulate
bool _rightclick_emulate
Whether right clicking is emulated.
Definition: driver.cpp:27
VideoDriver::ALLOWED_DRIFT
const uint ALLOWED_DRIFT
How many times videodriver can miss deadlines without it being overly compensated.
Definition: video_driver.hpp:228
_pause_mode
PauseMode _pause_mode
The current pause mode.
Definition: gfx.cpp:50
VideoDriver::GetAnimBuffer
virtual uint8_t * GetAnimBuffer()
Get a pointer to the animation buffer of the video back-end.
Definition: video_driver.hpp:144
VideoDriver::ChangeResolution
virtual bool ChangeResolution(int w, int h)=0
Change the resolution of the window.
VideoDriver::QueueOnMainThread
void QueueOnMainThread(std::function< void()> &&func)
Queue a function to be called on the main thread with game state lock held and video buffer locked.
Definition: video_driver.hpp:189
_game_speed
uint16_t _game_speed
Current game-speed; 100 is 1x, 0 is infinite.
Definition: gfx.cpp:40
VideoDriver::GetInstance
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
Definition: video_driver.hpp:201
VideoDriver::UnlockVideoBuffer
virtual void UnlockVideoBuffer()
Unlock a previously locked video buffer.
Definition: video_driver.hpp:273
VideoDriver::UseSystemCursor
virtual bool UseSystemCursor()
Get whether the mouse cursor is drawn by the video driver.
Definition: video_driver.hpp:94
VideoDriver::GameLoopPause
void GameLoopPause()
Pause the game-loop for a bit, releasing the game-state lock.
Definition: video_driver.cpp:66
VideoDriver::StopGameThread
void StopGameThread()
Stop the loop for the game-tick.
Definition: video_driver.cpp:95
VideoDriver::PopulateSystemSprites
virtual void PopulateSystemSprites()
Populate all sprites in cache.
Definition: video_driver.hpp:102
Driver::GetName
virtual std::string_view GetName() const =0
Get the name of this driver.
VideoDriver::GetCaption
static std::string GetCaption()
Get the caption to use for the game's title bar.
Definition: video_driver.cpp:189
VideoDriver::UpdateAutoResolution
void UpdateAutoResolution()
Apply resolution auto-detection and clamp to sensible defaults.
Definition: video_driver.hpp:244
Driver::DT_VIDEO
@ DT_VIDEO
A video driver.
Definition: driver.h:42
VideoDriver::VideoBufferLocker::unlock
bool unlock
Stores if the lock did anything that has to be undone.
Definition: video_driver.hpp:224
VideoDriver::DrainCommandQueue
void DrainCommandQueue()
Execute all queued commands.
Definition: video_driver.hpp:337
_ini_videodriver
std::string _ini_videodriver
The video driver a stored in the configuration file.
Definition: driver.cpp:24
VideoDriver::fast_forward_via_key
bool fast_forward_via_key
The fast-forward was enabled by key press.
Definition: video_driver.hpp:358
VideoDriver::GetSuggestedUIScale
virtual int GetSuggestedUIScale()
Get a suggested default GUI scale taking screen DPI into account.
Definition: video_driver.hpp:171
_video_hw_accel
bool _video_hw_accel
Whether to consider hardware accelerated video drivers on startup.
Definition: video_driver.cpp:25
MILLISECONDS_PER_TICK
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
Definition: gfx_type.h:327
VideoDriver::SleepTillNextTick
void SleepTillNextTick()
Sleep till the next tick is about to happen.
Definition: video_driver.cpp:171
VideoDriver::MainLoop
virtual void MainLoop()=0
Perform the actual drawing.
VideoDriver::fast_forward_key_pressed
bool fast_forward_key_pressed
The fast-forward key is being pressed.
Definition: video_driver.hpp:357
VideoDriver::HasEfficient8Bpp
virtual bool HasEfficient8Bpp() const
Has this video driver an efficient code path for palette animated 8-bpp sprites?
Definition: video_driver.hpp:126
VideoDriver::LockVideoBuffer
virtual bool LockVideoBuffer()
Make sure the video buffer is ready for drawing.
Definition: video_driver.hpp:265
VideoDriver::EditBoxLostFocus
virtual void EditBoxLostFocus()
An edit box lost the input focus.
Definition: video_driver.hpp:152
VideoDriver::DEFAULT_WINDOW_WIDTH
const uint DEFAULT_WINDOW_WIDTH
Default window width.
Definition: video_driver.hpp:35
Clamp
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:79
Driver
A driver for communicating with the user.
Definition: driver.h:21
_resolutions
std::vector< Dimension > _resolutions
List of resolutions.
Definition: driver.cpp:25
VideoDriver::PollEvent
virtual bool PollEvent()
Process a single system event.
Definition: video_driver.hpp:289
VideoDriver::VideoBufferLocker
Helper struct to ensure the video buffer is locked and ready for drawing.
Definition: video_driver.hpp:212
ClientSettings::gui
GUISettings gui
settings related to the GUI
Definition: settings_type.h:611
VideoDriver::GetScreenSize
virtual Dimension GetScreenSize() const
Get the resolution of the main screen.
Definition: video_driver.hpp:233
VideoDriver::EditBoxGainedFocus
virtual void EditBoxGainedFocus()
An edit box gained the input focus.
Definition: video_driver.hpp:157
VideoDriver::AfterBlitterChange
virtual bool AfterBlitterChange()
Callback invoked after the blitter was changed.
Definition: video_driver.hpp:80