Merge branch 'master' into jgrpp

# Conflicts:
#	src/dock_gui.cpp
#	src/rail_gui.cpp
#	src/road_gui.cpp
#	src/terraform_gui.cpp
#	src/vehicle.cpp
#	src/video/allegro_v.cpp
#	src/video/cocoa/cocoa_v.mm
#	src/video/dedicated_v.cpp
#	src/video/sdl2_v.cpp
#	src/video/sdl_v.cpp
#	src/video/win32_v.cpp
This commit is contained in:
Jonathan G Rennison
2021-02-21 11:49:54 +00:00
42 changed files with 885 additions and 1005 deletions

View File

@@ -338,7 +338,7 @@ void VideoDriver_SDL::CheckPaletteAnim()
this->MakeDirty(0, 0, _screen.width, _screen.height);
}
static void Paint()
void VideoDriver_SDL::Paint()
{
PerformanceMeasurer framerate(PFE_VIDEO);
@@ -372,10 +372,10 @@ static void Paint()
}
SDL_UpdateWindowSurfaceRects(_sdl_window, &r, 1);
MemSetT(&_dirty_rect, 0);
_dirty_rect = {};
}
static void PaintThread()
void VideoDriver_SDL::PaintThread()
{
/* First tell the main thread we're started */
std::unique_lock<std::recursive_mutex> lock(*_draw_mutex);
@@ -386,11 +386,16 @@ static void PaintThread()
while (_draw_continue) {
/* Then just draw and wait till we stop */
Paint();
this->Paint();
_draw_signal->wait(lock);
}
}
/* static */ void VideoDriver_SDL::PaintThreadThunk(VideoDriver_SDL *drv)
{
drv->PaintThread();
}
static const Dimension default_resolutions[] = {
{ 640, 480 },
{ 800, 600 },
@@ -556,7 +561,7 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
* gotten smaller, reset our dirty rects. GameSizeChanged() a bit lower
* will mark the whole screen dirty again anyway, but this time with the
* new dimensions. */
MemSetT(&_dirty_rect, 0);
_dirty_rect = {};
_screen.width = _sdl_surface->w;
_screen.height = _sdl_surface->h;
@@ -1059,11 +1064,43 @@ void VideoDriver_SDL::Stop()
}
}
void VideoDriver_SDL::InputLoop()
{
uint32 mod = SDL_GetModState();
const Uint8 *keys = SDL_GetKeyboardState(NULL);
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
_ctrl_pressed = !!(mod & KMOD_CTRL) != _invert_ctrl;
_shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift;
#if defined(_DEBUG)
if (_shift_pressed)
#else
/* Speedup when pressing tab, except when using ALT+TAB
* to switch to another application. */
if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0)
#endif /* defined(_DEBUG) */
{
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
/* Determine which directional keys are down. */
_dirkeys =
(keys[SDL_SCANCODE_LEFT] ? 1 : 0) |
(keys[SDL_SCANCODE_UP] ? 2 : 0) |
(keys[SDL_SCANCODE_RIGHT] ? 4 : 0) |
(keys[SDL_SCANCODE_DOWN] ? 8 : 0);
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
}
void VideoDriver_SDL::LoopOnce()
{
uint32 mod;
int numkeys;
const Uint8 *keys;
InteractiveRandom(); // randomness
while (PollEvent() == -1) {}
@@ -1081,106 +1118,23 @@ void VideoDriver_SDL::LoopOnce()
return;
}
mod = SDL_GetModState();
keys = SDL_GetKeyboardState(&numkeys);
#if defined(_DEBUG)
if (_shift_pressed)
#else
/* Speedup when pressing tab, except when using ALT+TAB
* to switch to another application */
if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0)
#endif /* defined(_DEBUG) */
{
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
cur_ticks = std::chrono::steady_clock::now();
/* If more than a millisecond has passed, increase the _realtime_tick. */
if (cur_ticks - last_realtime_tick > std::chrono::milliseconds(1)) {
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(cur_ticks - last_realtime_tick);
IncreaseRealtimeTick(delta.count());
last_realtime_tick += delta;
}
if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}
/* The gameloop is the part that can run asynchronously. The rest
* except sleeping can't. */
if (_draw_mutex != nullptr) draw_lock.unlock();
GameLoop();
if (_draw_mutex != nullptr) draw_lock.lock();
GameLoopPaletteAnimations();
}
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
if (cur_ticks >= next_draw_tick && (_switch_mode == SM_NONE || HasModalProgress())) {
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
_ctrl_pressed = !!(mod & KMOD_CTRL) != _invert_ctrl;
_shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift;
/* determine which directional keys are down */
_dirkeys =
(keys[SDL_SCANCODE_LEFT] ? 1 : 0) |
(keys[SDL_SCANCODE_UP] ? 2 : 0) |
(keys[SDL_SCANCODE_RIGHT] ? 4 : 0) |
(keys[SDL_SCANCODE_DOWN] ? 8 : 0);
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
InputLoop();
UpdateWindows();
this->CheckPaletteAnim();
if (VideoDriver::Tick()) {
if (_draw_mutex != nullptr && !HasModalProgress()) {
_draw_signal->notify_one();
} else {
Paint();
this->Paint();
}
}
/* Emscripten is running an event-based mainloop; there is already some
* downtime between each iteration, so no need to sleep. */
#ifndef __EMSCRIPTEN__
/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
if (!_fast_forward || _pause_mode) {
/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
auto next_tick = std::min(next_draw_tick, next_game_tick);
auto now = std::chrono::steady_clock::now();
if (next_tick > now) {
if (_draw_mutex != nullptr) draw_lock.unlock();
std::this_thread::sleep_for(next_tick - now);
if (_draw_mutex != nullptr) draw_lock.lock();
}
}
this->SleepTillNextTick();
#endif
}
void VideoDriver_SDL::MainLoop()
{
cur_ticks = std::chrono::steady_clock::now();
last_realtime_tick = cur_ticks;
next_game_tick = cur_ticks;
this->CheckPaletteAnim();
if (_draw_threaded) {
/* Initialise the mutex first, because that's the thing we *need*
* directly in the newly created thread. */
@@ -1192,7 +1146,7 @@ void VideoDriver_SDL::MainLoop()
_draw_signal = new std::condition_variable_any();
_draw_continue = true;
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &PaintThread);
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &VideoDriver_SDL::PaintThreadThunk, this);
/* Free the mutex if we won't be able to use it. */
if (!_draw_threaded) {
@@ -1317,3 +1271,14 @@ Dimension VideoDriver_SDL::GetScreenSize() const
return { static_cast<uint>(mode.w), static_cast<uint>(mode.h) };
}
bool VideoDriver_SDL::LockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.lock();
return true;
}
void VideoDriver_SDL::UnlockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.unlock();
}