OpenTTD Source 20260208-master-g43af8e94d0
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#ifndef VIDEO_VIDEO_DRIVER_HPP
11#define VIDEO_VIDEO_DRIVER_HPP
12
13#include "../debug.h"
14#include "../driver.h"
16#include "../core/math_func.hpp"
17#include "../gfx_func.h"
18#include "../settings_type.h"
19#include "../zoom_type.h"
21#include <atomic>
22#include <chrono>
23#include <condition_variable>
24#include <mutex>
25#include <thread>
26
27extern std::string _ini_videodriver;
28extern std::vector<Dimension> _resolutions;
30extern bool _rightclick_emulate;
31extern bool _video_hw_accel;
32extern bool _video_vsync;
33
35class VideoDriver : public Driver {
36 const uint DEFAULT_WINDOW_WIDTH = 640u;
37 const uint DEFAULT_WINDOW_HEIGHT = 480u;
38
39public:
40 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) {}
41
49 virtual void MakeDirty(int left, int top, int width, int height) = 0;
50
54 virtual void MainLoop() = 0;
55
62 virtual bool ChangeResolution(int w, int h) = 0;
63
69 virtual bool ToggleFullscreen(bool fullscreen) = 0;
70
75 virtual void ToggleVsync([[maybe_unused]] bool vsync) {}
76
81 virtual bool AfterBlitterChange()
82 {
83 return true;
84 }
85
89 virtual void ClaimMousePointer() {}
90
95 virtual bool UseSystemCursor()
96 {
97 return false;
98 }
99
103 virtual void PopulateSystemSprites() {}
104
108 virtual void ClearSystemSprites() {}
109
118 virtual bool HasGUI() const
119 {
120 return true;
121 }
122
127 virtual bool HasEfficient8Bpp() const
128 {
129 return false;
130 }
131
136 virtual bool HasAnimBuffer()
137 {
138 return false;
139 }
140
145 virtual uint8_t *GetAnimBuffer()
146 {
147 return nullptr;
148 }
149
153 virtual void EditBoxLostFocus() {}
154
158 virtual void EditBoxGainedFocus() {}
159
164 virtual std::vector<int> GetListOfMonitorRefreshRates()
165 {
166 return {};
167 }
168
173 virtual std::string_view GetInfoString() const
174 {
175 return this->GetName();
176 }
177
184 void QueueOnMainThread(std::function<void()> &&func)
185 {
186 std::lock_guard<std::mutex> lock(this->cmd_queue_mutex);
187
188 this->cmd_queue.emplace_back(std::forward<std::function<void()>>(func));
189 }
190
191 void GameLoopPause();
192
198 virtual void SetScreensaverInhibited([[maybe_unused]] bool inhibited) {}
199
203 static VideoDriver *GetInstance()
204 {
205 return static_cast<VideoDriver *>(DriverFactoryBase::GetActiveDriver(Driver::DT_VIDEO).get());
206 }
207
208 static std::string GetCaption();
209
214 struct VideoBufferLocker {
215 VideoBufferLocker()
216 {
218 }
219
220 ~VideoBufferLocker()
221 {
223 }
224
225 private:
226 bool unlock;
227 };
228
229protected:
230 const uint ALLOWED_DRIFT = 5;
231
236
241 {
242 if (_cur_resolution.width == 0 || _cur_resolution.height == 0) {
243 /* Auto-detect a good resolution. We aim for 75% of the screen size.
244 * Limit width times height times bytes per pixel to fit a 32 bit
245 * integer, This way all internal drawing routines work correctly. */
246 Dimension res = this->GetScreenSize();
247 _cur_resolution.width = ClampU(res.width * 3 / 4, DEFAULT_WINDOW_WIDTH, UINT16_MAX / 2);
248 _cur_resolution.height = ClampU(res.height * 3 / 4, DEFAULT_WINDOW_HEIGHT, UINT16_MAX / 2);
249 }
250 }
251
255 virtual void InputLoop() {}
256
261 virtual bool LockVideoBuffer()
262 {
263 return false;
264 }
265
269 virtual void UnlockVideoBuffer() {}
270
274 virtual void Paint() {}
275
279 virtual void CheckPaletteAnim() {}
280
285 virtual bool PollEvent() { return false; };
286
290 void StartGameThread();
291
295 void StopGameThread();
296
302 void Tick();
303
307 void SleepTillNextTick();
308
309 std::chrono::steady_clock::duration GetGameInterval()
310 {
311#ifdef DEBUG_DUMP_COMMANDS
312 /* When replaying, run as fast as we can. */
313 extern bool _ddc_fastforward;
314 if (_ddc_fastforward) return std::chrono::microseconds(0);
315#endif /* DEBUG_DUMP_COMMANDS */
316
317 TicToc::Tick("GameTick");
318
319 /* If we are paused, run on normal speed. */
320 if (_pause_mode.Any()) return std::chrono::milliseconds(MILLISECONDS_PER_TICK);
321 /* Infinite speed, as quickly as you can. */
322 if (_game_speed == 0) return std::chrono::microseconds(0);
323
324 return std::chrono::microseconds(MILLISECONDS_PER_TICK * 1000 * 100 / _game_speed);
325 }
326
327 std::chrono::steady_clock::duration GetDrawInterval()
328 {
329 TicToc::Tick("DrawTick");
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
369private:
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 */
static std::unique_ptr< Driver > & GetActiveDriver(Driver::Type type)
Get the active driver for the given type.
Definition driver.h:84
A driver for communicating with the user.
Definition driver.h:21
virtual std::string_view GetName() const =0
Get the name of this driver.
@ DT_VIDEO
A video driver.
Definition driver.h:42
virtual void InputLoop()
Handle input logic, is CTRL pressed, should we fast-forward, etc.
virtual bool ToggleFullscreen(bool fullscreen)=0
Change the full screen setting.
virtual Dimension GetScreenSize() const
Get the resolution of the main screen.
virtual void PopulateSystemSprites()
Populate all sprites in cache.
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.
virtual std::string_view GetInfoString() const
Get some information about the selected driver/backend to be shown to the user.
const uint DEFAULT_WINDOW_WIDTH
Default window width.
bool fast_forward_key_pressed
The fast-forward key is being pressed.
virtual void ClearSystemSprites()
Clear all cached sprites.
virtual bool UseSystemCursor()
Get whether the mouse cursor is drawn by the video driver.
virtual void SetScreensaverInhibited(bool inhibited)
Prevents the system from going to sleep.
void Tick()
Give the video-driver a tick.
const uint DEFAULT_WINDOW_HEIGHT
Default window height.
virtual void MakeDirty(int left, int top, int width, int height)=0
Mark a particular area dirty.
void SleepTillNextTick()
Sleep till the next tick is about to happen.
void StartGameThread()
Start the loop for game-tick.
virtual void EditBoxLostFocus()
An edit box lost the input focus.
virtual bool HasAnimBuffer()
Does this video driver support a separate animation buffer in addition to the colour buffer?
virtual bool ChangeResolution(int w, int h)=0
Change the resolution of the window.
virtual bool HasGUI() const
Whether the driver has a graphical user interface with the end user.
static std::string GetCaption()
Get the caption to use for the game's title bar.
virtual void ToggleVsync(bool vsync)
Change the vsync setting.
virtual bool AfterBlitterChange()
Callback invoked after the blitter was changed.
void StopGameThread()
Stop the loop for the game-tick.
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
const uint ALLOWED_DRIFT
How many times videodriver can miss deadlines without it being overly compensated.
virtual void MainLoop()=0
Perform the actual drawing.
virtual void EditBoxGainedFocus()
An edit box gained the input focus.
virtual bool PollEvent()
Process a single system event.
virtual bool HasEfficient8Bpp() const
Has this video driver an efficient code path for palette animated 8-bpp sprites?
virtual void Paint()
Paint the window.
virtual void UnlockVideoBuffer()
Unlock a previously locked video buffer.
bool fast_forward_via_key
The fast-forward was enabled by key press.
virtual void ClaimMousePointer()
Claim the exclusive rights for the mouse pointer.
virtual uint8_t * GetAnimBuffer()
Get a pointer to the animation buffer of the video back-end.
virtual std::vector< int > GetListOfMonitorRefreshRates()
Get a list of refresh rates of each available monitor.
virtual void CheckPaletteAnim()
Process any pending palette animation.
virtual bool LockVideoBuffer()
Make sure the video buffer is ready for drawing.
void GameLoopPause()
Pause the game-loop for a bit, releasing the game-state lock.
void DrainCommandQueue()
Execute all queued commands.
void UpdateAutoResolution()
Apply resolution auto-detection and clamp to sensible defaults.
Functions related to debugging.
std::string _ini_videodriver
The video driver a stored in the configuration file.
Definition driver.cpp:27
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
Base for all drivers (video, sound, music, etc).
All geometry types in OpenTTD.
uint16_t _game_speed
Current game-speed; 100 is 1x, 0 is infinite.
Definition gfx.cpp:41
PauseModes _pause_mode
The current pause mode.
Definition gfx.cpp:51
Functions related to the gfx engine.
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
Definition gfx_type.h:370
Integer math functions.
constexpr uint ClampU(const uint a, const uint min, const uint max)
Clamp an unsigned integer between an interval.
Network functions used by other parts of OpenTTD.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
Types related to global configuration settings.
GUISettings gui
settings related to the GUI
Dimensions (a width and height) of a rectangle in 2D.
uint16_t refresh_rate
How often we refresh the screen (time between draw-ticks).
bool unlock
Stores if the lock did anything that has to be undone.
bool _video_vsync
Whether we should use vsync (only if active video driver supports HW acceleration).
bool _video_hw_accel
Whether to consider hardware accelerated video drivers on startup.
bool _video_vsync
Whether we should use vsync (only if active video driver supports HW acceleration).
Dimension _cur_resolution
The current resolution.
Definition driver.cpp:29
std::mutex lock
synchronization for playback status fields
Definition win32_m.cpp:35
Types related to zooming in and out.