mirror of https://github.com/OpenTTD/OpenTTD
Codechange: use (Un)LockVideoBuffer() to manage video buffer
parent
661eb39ecc
commit
761efbb457
|
@ -801,9 +801,9 @@ void VideoDriver_SDL::LoopOnce()
|
||||||
|
|
||||||
/* The gameloop is the part that can run asynchronously. The rest
|
/* The gameloop is the part that can run asynchronously. The rest
|
||||||
* except sleeping can't. */
|
* except sleeping can't. */
|
||||||
if (_draw_mutex != nullptr) draw_lock.unlock();
|
this->UnlockVideoBuffer();
|
||||||
GameLoop();
|
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. */
|
/* 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();
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (next_tick > now) {
|
if (next_tick > now) {
|
||||||
if (_draw_mutex != nullptr) draw_lock.unlock();
|
this->UnlockVideoBuffer();
|
||||||
std::this_thread::sleep_for(next_tick - now);
|
std::this_thread::sleep_for(next_tick - now);
|
||||||
if (_draw_mutex != nullptr) draw_lock.lock();
|
this->LockVideoBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -986,3 +986,14 @@ Dimension VideoDriver_SDL::GetScreenSize() const
|
||||||
|
|
||||||
return { static_cast<uint>(mode.w), static_cast<uint>(mode.h) };
|
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();
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ public:
|
||||||
protected:
|
protected:
|
||||||
Dimension GetScreenSize() const override;
|
Dimension GetScreenSize() const override;
|
||||||
void InputLoop() override;
|
void InputLoop() override;
|
||||||
|
bool LockVideoBuffer() override;
|
||||||
|
void UnlockVideoBuffer() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int PollEvent();
|
int PollEvent();
|
||||||
|
|
|
@ -706,7 +706,6 @@ void VideoDriver_SDL::MainLoop()
|
||||||
CheckPaletteAnim();
|
CheckPaletteAnim();
|
||||||
|
|
||||||
std::thread draw_thread;
|
std::thread draw_thread;
|
||||||
std::unique_lock<std::recursive_mutex> draw_lock;
|
|
||||||
if (_draw_threaded) {
|
if (_draw_threaded) {
|
||||||
/* Initialise the mutex first, because that's the thing we *need*
|
/* Initialise the mutex first, because that's the thing we *need*
|
||||||
* directly in the newly created thread. */
|
* directly in the newly created thread. */
|
||||||
|
@ -714,7 +713,7 @@ void VideoDriver_SDL::MainLoop()
|
||||||
if (_draw_mutex == nullptr) {
|
if (_draw_mutex == nullptr) {
|
||||||
_draw_threaded = false;
|
_draw_threaded = false;
|
||||||
} else {
|
} 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_signal = new std::condition_variable_any();
|
||||||
_draw_continue = true;
|
_draw_continue = true;
|
||||||
|
|
||||||
|
@ -722,8 +721,8 @@ void VideoDriver_SDL::MainLoop()
|
||||||
|
|
||||||
/* Free the mutex if we won't be able to use it. */
|
/* Free the mutex if we won't be able to use it. */
|
||||||
if (!_draw_threaded) {
|
if (!_draw_threaded) {
|
||||||
draw_lock.unlock();
|
this->draw_lock.unlock();
|
||||||
draw_lock.release();
|
this->draw_lock.release();
|
||||||
delete _draw_mutex;
|
delete _draw_mutex;
|
||||||
delete _draw_signal;
|
delete _draw_signal;
|
||||||
_draw_mutex = nullptr;
|
_draw_mutex = nullptr;
|
||||||
|
@ -763,9 +762,9 @@ void VideoDriver_SDL::MainLoop()
|
||||||
|
|
||||||
/* The gameloop is the part that can run asynchronously. The rest
|
/* The gameloop is the part that can run asynchronously. The rest
|
||||||
* except sleeping can't. */
|
* except sleeping can't. */
|
||||||
if (_draw_mutex != nullptr) draw_lock.unlock();
|
this->UnlockVideoBuffer();
|
||||||
GameLoop();
|
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. */
|
/* 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();
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (next_tick > now) {
|
if (next_tick > now) {
|
||||||
if (_draw_mutex != nullptr) draw_lock.unlock();
|
this->UnlockVideoBuffer();
|
||||||
std::this_thread::sleep_for(next_tick - now);
|
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
|
/* Sending signal if there is no thread blocked
|
||||||
* is very valid and results in noop */
|
* is very valid and results in noop */
|
||||||
_draw_signal->notify_one();
|
_draw_signal->notify_one();
|
||||||
if (draw_lock.owns_lock()) draw_lock.unlock();
|
if (this->draw_lock.owns_lock()) this->draw_lock.unlock();
|
||||||
draw_lock.release();
|
this->draw_lock.release();
|
||||||
draw_thread.join();
|
draw_thread.join();
|
||||||
|
|
||||||
delete _draw_mutex;
|
delete _draw_mutex;
|
||||||
|
@ -858,4 +857,15 @@ void VideoDriver_SDL::ReleaseBlitterLock()
|
||||||
if (_draw_mutex != nullptr) _draw_mutex->unlock();
|
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 */
|
#endif /* WITH_SDL */
|
||||||
|
|
|
@ -39,8 +39,12 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void InputLoop() override;
|
void InputLoop() override;
|
||||||
|
bool LockVideoBuffer() override;
|
||||||
|
void UnlockVideoBuffer() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::unique_lock<std::recursive_mutex> draw_lock;
|
||||||
|
|
||||||
int PollEvent();
|
int PollEvent();
|
||||||
bool CreateMainSurface(uint w, uint h);
|
bool CreateMainSurface(uint w, uint h);
|
||||||
void SetupKeyboard();
|
void SetupKeyboard();
|
||||||
|
|
|
@ -161,6 +161,19 @@ protected:
|
||||||
*/
|
*/
|
||||||
virtual void InputLoop() {}
|
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()
|
std::chrono::steady_clock::duration GetGameInterval()
|
||||||
{
|
{
|
||||||
return std::chrono::milliseconds(MILLISECONDS_PER_TICK);
|
return std::chrono::milliseconds(MILLISECONDS_PER_TICK);
|
||||||
|
|
|
@ -1161,7 +1161,6 @@ void VideoDriver_Win32::MainLoop()
|
||||||
auto next_draw_tick = cur_ticks;
|
auto next_draw_tick = cur_ticks;
|
||||||
|
|
||||||
std::thread draw_thread;
|
std::thread draw_thread;
|
||||||
std::unique_lock<std::recursive_mutex> draw_lock;
|
|
||||||
|
|
||||||
if (_draw_threaded) {
|
if (_draw_threaded) {
|
||||||
/* Initialise the mutex first, because that's the thing we *need*
|
/* Initialise the mutex first, because that's the thing we *need*
|
||||||
|
@ -1174,15 +1173,15 @@ void VideoDriver_Win32::MainLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_draw_threaded) {
|
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_continue = true;
|
||||||
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &PaintWindowThread);
|
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &PaintWindowThread);
|
||||||
|
|
||||||
/* Free the mutex if we won't be able to use it. */
|
/* Free the mutex if we won't be able to use it. */
|
||||||
if (!_draw_threaded) {
|
if (!_draw_threaded) {
|
||||||
draw_lock.unlock();
|
this->draw_lock.unlock();
|
||||||
draw_lock.release();
|
this->draw_lock.release();
|
||||||
delete _draw_mutex;
|
delete _draw_mutex;
|
||||||
delete _draw_signal;
|
delete _draw_signal;
|
||||||
_draw_mutex = nullptr;
|
_draw_mutex = nullptr;
|
||||||
|
@ -1231,9 +1230,9 @@ void VideoDriver_Win32::MainLoop()
|
||||||
|
|
||||||
/* The game loop is the part that can run asynchronously.
|
/* The game loop is the part that can run asynchronously.
|
||||||
* The rest except sleeping can't. */
|
* The rest except sleeping can't. */
|
||||||
if (_draw_threaded) draw_lock.unlock();
|
this->UnlockVideoBuffer();
|
||||||
GameLoop();
|
GameLoop();
|
||||||
if (_draw_threaded) draw_lock.lock();
|
this->LockVideoBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
|
/* 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. */
|
/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
|
||||||
GdiFlush();
|
GdiFlush();
|
||||||
|
|
||||||
if (_draw_mutex != nullptr) draw_lock.unlock();
|
this->UnlockVideoBuffer();
|
||||||
std::this_thread::sleep_for(next_tick - now);
|
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
|
/* Sending signal if there is no thread blocked
|
||||||
* is very valid and results in noop */
|
* is very valid and results in noop */
|
||||||
_draw_signal->notify_all();
|
_draw_signal->notify_all();
|
||||||
if (draw_lock.owns_lock()) draw_lock.unlock();
|
if (this->draw_lock.owns_lock()) this->draw_lock.unlock();
|
||||||
draw_lock.release();
|
this->draw_lock.release();
|
||||||
draw_thread.join();
|
draw_thread.join();
|
||||||
|
|
||||||
delete _draw_mutex;
|
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.
|
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();
|
||||||
|
}
|
||||||
|
|
|
@ -45,9 +45,15 @@ protected:
|
||||||
Dimension GetScreenSize() const override;
|
Dimension GetScreenSize() const override;
|
||||||
float GetDPIScale() override;
|
float GetDPIScale() override;
|
||||||
void InputLoop() override;
|
void InputLoop() override;
|
||||||
|
bool LockVideoBuffer() override;
|
||||||
|
void UnlockVideoBuffer() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::unique_lock<std::recursive_mutex> draw_lock;
|
||||||
|
|
||||||
void CheckPaletteAnim();
|
void CheckPaletteAnim();
|
||||||
|
|
||||||
|
static void PaintThreadThunk(VideoDriver_Win32 *drv);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The factory for Windows' video driver. */
|
/** The factory for Windows' video driver. */
|
||||||
|
|
Loading…
Reference in New Issue