summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPatric Stout <truebrain@openttd.org>2021-03-08 14:50:06 +0100
committerPatric Stout <github@truebrain.nl>2021-03-08 19:18:55 +0100
commit8946b41d20d6be59da23b98add273955b43450fd (patch)
tree59efe6e340339a68f4355a0c19cda5695755e49c /src
parente56d2c63c306dd087de26088729d09233b1122c2 (diff)
downloadopenttd-8946b41d20d6be59da23b98add273955b43450fd.tar.xz
Fix: ensure switching blitter happens in the main thread
This because video-drivers might need to make changes to their context, which for most video-drivers has to be done in the same thread as the window was created; main thread in our case.
Diffstat (limited to 'src')
-rw-r--r--src/gfxinit.cpp11
-rw-r--r--src/video/video_driver.cpp29
-rw-r--r--src/video/video_driver.hpp14
3 files changed, 44 insertions, 10 deletions
diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp
index 2883d3ee3..7e2c2cc62 100644
--- a/src/gfxinit.cpp
+++ b/src/gfxinit.cpp
@@ -308,18 +308,11 @@ static bool SwitchNewGRFBlitter()
}
if (BlitterFactory::GetBlitterFactory(repl_blitter) == nullptr) continue;
- DEBUG(misc, 1, "Switching blitter from '%s' to '%s'... ", cur_blitter, repl_blitter);
- Blitter *new_blitter = BlitterFactory::SelectBlitter(repl_blitter);
- if (new_blitter == nullptr) NOT_REACHED();
- DEBUG(misc, 1, "Successfully switched to %s.", repl_blitter);
+ /* Inform the video driver we want to switch blitter as soon as possible. */
+ VideoDriver::GetInstance()->ChangeBlitter(repl_blitter);
break;
}
- if (!VideoDriver::GetInstance()->AfterBlitterChange()) {
- /* Failed to switch blitter, let's hope we can return to the old one. */
- if (BlitterFactory::SelectBlitter(cur_blitter) == nullptr || !VideoDriver::GetInstance()->AfterBlitterChange()) usererror("Failed to reinitialize video driver. Specify a fixed blitter in the config");
- }
-
return true;
}
diff --git a/src/video/video_driver.cpp b/src/video/video_driver.cpp
index e313329d5..1b7fc6a4b 100644
--- a/src/video/video_driver.cpp
+++ b/src/video/video_driver.cpp
@@ -10,8 +10,11 @@
#include "../stdafx.h"
#include "../core/random_func.hpp"
#include "../network/network.h"
+#include "../blitter/factory.hpp"
#include "../debug.h"
+#include "../fontcache.h"
#include "../gfx_func.h"
+#include "../gfxinit.h"
#include "../progress.h"
#include "../thread.h"
#include "../window_func.h"
@@ -74,6 +77,27 @@ void VideoDriver::StopGameThread()
this->game_thread.join();
}
+void VideoDriver::RealChangeBlitter(const char *repl_blitter)
+{
+ const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName();
+
+ DEBUG(driver, 1, "Switching blitter from '%s' to '%s'... ", cur_blitter, repl_blitter);
+ Blitter *new_blitter = BlitterFactory::SelectBlitter(repl_blitter);
+ if (new_blitter == nullptr) NOT_REACHED();
+ DEBUG(driver, 1, "Successfully switched to %s.", repl_blitter);
+
+ if (!this->AfterBlitterChange()) {
+ /* Failed to switch blitter, let's hope we can return to the old one. */
+ if (BlitterFactory::SelectBlitter(cur_blitter) == nullptr || !this->AfterBlitterChange()) usererror("Failed to reinitialize video driver. Specify a fixed blitter in the config");
+ }
+
+ /* Clear caches that might have sprites for another blitter. */
+ this->ClearSystemSprites();
+ ClearFontCache();
+ GfxClearSpriteCache();
+ ReInitAllWindows();
+}
+
void VideoDriver::Tick()
{
if (!this->is_game_threaded && std::chrono::steady_clock::now() >= this->next_game_tick) {
@@ -115,6 +139,11 @@ void VideoDriver::Tick()
this->LockVideoBuffer();
+ if (this->change_blitter != nullptr) {
+ this->RealChangeBlitter(this->change_blitter);
+ this->change_blitter = nullptr;
+ }
+
while (this->PollEvent()) {}
::InputLoop();
diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp
index 423e46436..4b2de253a 100644
--- a/src/video/video_driver.hpp
+++ b/src/video/video_driver.hpp
@@ -35,7 +35,7 @@ class VideoDriver : public Driver {
const uint DEFAULT_WINDOW_HEIGHT = 480u; ///< Default window height.
public:
- VideoDriver() : is_game_threaded(true) {}
+ VideoDriver() : is_game_threaded(true), change_blitter(nullptr) {}
/**
* Mark a particular area dirty.
@@ -162,6 +162,15 @@ public:
}
/**
+ * Queue a request to change the blitter. This is not executed immediately,
+ * but instead on the next draw-tick.
+ */
+ void ChangeBlitter(const char *new_blitter)
+ {
+ this->change_blitter = new_blitter;
+ }
+
+ /**
* Get the currently active instance of the video driver.
*/
static VideoDriver *GetInstance() {
@@ -303,6 +312,9 @@ protected:
private:
void GameLoop();
void GameThread();
+ void RealChangeBlitter(const char *repl_blitter);
+
+ const char *change_blitter; ///< Request to change the blitter. nullptr if no pending request.
};
#endif /* VIDEO_VIDEO_DRIVER_HPP */