summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video/sdl2_v.cpp19
-rw-r--r--src/video/sdl2_v.h2
-rw-r--r--src/video/sdl_v.cpp30
-rw-r--r--src/video/sdl_v.h4
-rw-r--r--src/video/video_driver.hpp13
-rw-r--r--src/video/win32_v.cpp30
-rw-r--r--src/video/win32_v.h6
7 files changed, 80 insertions, 24 deletions
diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp
index b02beacef..8bee575e2 100644
--- a/src/video/sdl2_v.cpp
+++ b/src/video/sdl2_v.cpp
@@ -801,9 +801,9 @@ void VideoDriver_SDL::LoopOnce()
/* The gameloop is the part that can run asynchronously. The rest
* except sleeping can't. */
- if (_draw_mutex != nullptr) draw_lock.unlock();
+ this->UnlockVideoBuffer();
GameLoop();
- if (_draw_mutex != nullptr) draw_lock.lock();
+ this->LockVideoBuffer();
}
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
@@ -834,9 +834,9 @@ void VideoDriver_SDL::LoopOnce()
auto now = std::chrono::steady_clock::now();
if (next_tick > now) {
- if (_draw_mutex != nullptr) draw_lock.unlock();
+ this->UnlockVideoBuffer();
std::this_thread::sleep_for(next_tick - now);
- if (_draw_mutex != nullptr) draw_lock.lock();
+ this->LockVideoBuffer();
}
}
#endif
@@ -986,3 +986,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();
+}
diff --git a/src/video/sdl2_v.h b/src/video/sdl2_v.h
index 254402905..116cef51f 100644
--- a/src/video/sdl2_v.h
+++ b/src/video/sdl2_v.h
@@ -44,6 +44,8 @@ public:
protected:
Dimension GetScreenSize() const override;
void InputLoop() override;
+ bool LockVideoBuffer() override;
+ void UnlockVideoBuffer() override;
private:
int PollEvent();
diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp
index 44391f184..8190dc4d6 100644
--- a/src/video/sdl_v.cpp
+++ b/src/video/sdl_v.cpp
@@ -706,7 +706,6 @@ void VideoDriver_SDL::MainLoop()
CheckPaletteAnim();
std::thread draw_thread;
- std::unique_lock<std::recursive_mutex> draw_lock;
if (_draw_threaded) {
/* Initialise the mutex first, because that's the thing we *need*
* directly in the newly created thread. */
@@ -714,7 +713,7 @@ void VideoDriver_SDL::MainLoop()
if (_draw_mutex == nullptr) {
_draw_threaded = false;
} else {
- draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
+ this->draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
_draw_signal = new std::condition_variable_any();
_draw_continue = true;
@@ -722,8 +721,8 @@ void VideoDriver_SDL::MainLoop()
/* Free the mutex if we won't be able to use it. */
if (!_draw_threaded) {
- draw_lock.unlock();
- draw_lock.release();
+ this->draw_lock.unlock();
+ this->draw_lock.release();
delete _draw_mutex;
delete _draw_signal;
_draw_mutex = nullptr;
@@ -763,9 +762,9 @@ void VideoDriver_SDL::MainLoop()
/* The gameloop is the part that can run asynchronously. The rest
* except sleeping can't. */
- if (_draw_mutex != nullptr) draw_lock.unlock();
+ this->UnlockVideoBuffer();
GameLoop();
- if (_draw_mutex != nullptr) draw_lock.lock();
+ this->LockVideoBuffer();
}
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
@@ -794,9 +793,9 @@ void VideoDriver_SDL::MainLoop()
auto now = std::chrono::steady_clock::now();
if (next_tick > now) {
- if (_draw_mutex != nullptr) draw_lock.unlock();
+ this->UnlockVideoBuffer();
std::this_thread::sleep_for(next_tick - now);
- if (_draw_mutex != nullptr) draw_lock.lock();
+ this->LockVideoBuffer();
}
}
}
@@ -806,8 +805,8 @@ void VideoDriver_SDL::MainLoop()
/* Sending signal if there is no thread blocked
* is very valid and results in noop */
_draw_signal->notify_one();
- if (draw_lock.owns_lock()) draw_lock.unlock();
- draw_lock.release();
+ if (this->draw_lock.owns_lock()) this->draw_lock.unlock();
+ this->draw_lock.release();
draw_thread.join();
delete _draw_mutex;
@@ -858,4 +857,15 @@ void VideoDriver_SDL::ReleaseBlitterLock()
if (_draw_mutex != nullptr) _draw_mutex->unlock();
}
+bool VideoDriver_SDL::LockVideoBuffer()
+{
+ if (_draw_threaded) this->draw_lock.lock();
+ return true;
+}
+
+void VideoDriver_SDL::UnlockVideoBuffer()
+{
+ if (_draw_threaded) this->draw_lock.unlock();
+}
+
#endif /* WITH_SDL */
diff --git a/src/video/sdl_v.h b/src/video/sdl_v.h
index 1d3da9b6a..896a6f5b8 100644
--- a/src/video/sdl_v.h
+++ b/src/video/sdl_v.h
@@ -39,8 +39,12 @@ public:
protected:
void InputLoop() override;
+ bool LockVideoBuffer() override;
+ void UnlockVideoBuffer() override;
private:
+ std::unique_lock<std::recursive_mutex> draw_lock;
+
int PollEvent();
bool CreateMainSurface(uint w, uint h);
void SetupKeyboard();
diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp
index 8ba1d2466..875125ebc 100644
--- a/src/video/video_driver.hpp
+++ b/src/video/video_driver.hpp
@@ -161,6 +161,19 @@ protected:
*/
virtual void InputLoop() {}
+ /**
+ * Make sure the video buffer is ready for drawing.
+ * @returns True if the video buffer has to be unlocked.
+ */
+ virtual bool LockVideoBuffer() {
+ return false;
+ }
+
+ /**
+ * Unlock a previously locked video buffer.
+ */
+ virtual void UnlockVideoBuffer() {}
+
std::chrono::steady_clock::duration GetGameInterval()
{
return std::chrono::milliseconds(MILLISECONDS_PER_TICK);
diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp
index f55a9c372..cca12c40c 100644
--- a/src/video/win32_v.cpp
+++ b/src/video/win32_v.cpp
@@ -1161,7 +1161,6 @@ void VideoDriver_Win32::MainLoop()
auto next_draw_tick = cur_ticks;
std::thread draw_thread;
- std::unique_lock<std::recursive_mutex> draw_lock;
if (_draw_threaded) {
/* Initialise the mutex first, because that's the thing we *need*
@@ -1174,15 +1173,15 @@ void VideoDriver_Win32::MainLoop()
}
if (_draw_threaded) {
- draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
+ this->draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
_draw_continue = true;
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &PaintWindowThread);
/* Free the mutex if we won't be able to use it. */
if (!_draw_threaded) {
- draw_lock.unlock();
- draw_lock.release();
+ this->draw_lock.unlock();
+ this->draw_lock.release();
delete _draw_mutex;
delete _draw_signal;
_draw_mutex = nullptr;
@@ -1231,9 +1230,9 @@ void VideoDriver_Win32::MainLoop()
/* The game loop is the part that can run asynchronously.
* The rest except sleeping can't. */
- if (_draw_threaded) draw_lock.unlock();
+ this->UnlockVideoBuffer();
GameLoop();
- if (_draw_threaded) draw_lock.lock();
+ this->LockVideoBuffer();
}
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
@@ -1269,9 +1268,9 @@ void VideoDriver_Win32::MainLoop()
/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
GdiFlush();
- if (_draw_mutex != nullptr) draw_lock.unlock();
+ this->UnlockVideoBuffer();
std::this_thread::sleep_for(next_tick - now);
- if (_draw_mutex != nullptr) draw_lock.lock();
+ this->LockVideoBuffer();
}
}
}
@@ -1281,8 +1280,8 @@ void VideoDriver_Win32::MainLoop()
/* Sending signal if there is no thread blocked
* is very valid and results in noop */
_draw_signal->notify_all();
- if (draw_lock.owns_lock()) draw_lock.unlock();
- draw_lock.release();
+ if (this->draw_lock.owns_lock()) this->draw_lock.unlock();
+ this->draw_lock.release();
draw_thread.join();
delete _draw_mutex;
@@ -1383,3 +1382,14 @@ float VideoDriver_Win32::GetDPIScale()
return cur_dpi > 0 ? cur_dpi / 96.0f : 1.0f; // Default Windows DPI value is 96.
}
+
+bool VideoDriver_Win32::LockVideoBuffer()
+{
+ if (_draw_threaded) this->draw_lock.lock();
+ return true;
+}
+
+void VideoDriver_Win32::UnlockVideoBuffer()
+{
+ if (_draw_threaded) this->draw_lock.unlock();
+}
diff --git a/src/video/win32_v.h b/src/video/win32_v.h
index a6219dfd0..0a80afc4d 100644
--- a/src/video/win32_v.h
+++ b/src/video/win32_v.h
@@ -45,9 +45,15 @@ protected:
Dimension GetScreenSize() const override;
float GetDPIScale() override;
void InputLoop() override;
+ bool LockVideoBuffer() override;
+ void UnlockVideoBuffer() override;
private:
+ std::unique_lock<std::recursive_mutex> draw_lock;
+
void CheckPaletteAnim();
+
+ static void PaintThreadThunk(VideoDriver_Win32 *drv);
};
/** The factory for Windows' video driver. */