mirror of https://github.com/OpenTTD/OpenTTD.git
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.
This commit is contained in:
parent
e56d2c63c3
commit
8946b41d20
|
@ -308,18 +308,11 @@ static bool SwitchNewGRFBlitter()
|
||||||
}
|
}
|
||||||
if (BlitterFactory::GetBlitterFactory(repl_blitter) == nullptr) continue;
|
if (BlitterFactory::GetBlitterFactory(repl_blitter) == nullptr) continue;
|
||||||
|
|
||||||
DEBUG(misc, 1, "Switching blitter from '%s' to '%s'... ", cur_blitter, repl_blitter);
|
/* Inform the video driver we want to switch blitter as soon as possible. */
|
||||||
Blitter *new_blitter = BlitterFactory::SelectBlitter(repl_blitter);
|
VideoDriver::GetInstance()->ChangeBlitter(repl_blitter);
|
||||||
if (new_blitter == nullptr) NOT_REACHED();
|
|
||||||
DEBUG(misc, 1, "Successfully switched to %s.", repl_blitter);
|
|
||||||
break;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,11 @@
|
||||||
#include "../stdafx.h"
|
#include "../stdafx.h"
|
||||||
#include "../core/random_func.hpp"
|
#include "../core/random_func.hpp"
|
||||||
#include "../network/network.h"
|
#include "../network/network.h"
|
||||||
|
#include "../blitter/factory.hpp"
|
||||||
#include "../debug.h"
|
#include "../debug.h"
|
||||||
|
#include "../fontcache.h"
|
||||||
#include "../gfx_func.h"
|
#include "../gfx_func.h"
|
||||||
|
#include "../gfxinit.h"
|
||||||
#include "../progress.h"
|
#include "../progress.h"
|
||||||
#include "../thread.h"
|
#include "../thread.h"
|
||||||
#include "../window_func.h"
|
#include "../window_func.h"
|
||||||
|
@ -74,6 +77,27 @@ void VideoDriver::StopGameThread()
|
||||||
this->game_thread.join();
|
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()
|
void VideoDriver::Tick()
|
||||||
{
|
{
|
||||||
if (!this->is_game_threaded && std::chrono::steady_clock::now() >= this->next_game_tick) {
|
if (!this->is_game_threaded && std::chrono::steady_clock::now() >= this->next_game_tick) {
|
||||||
|
@ -115,6 +139,11 @@ void VideoDriver::Tick()
|
||||||
|
|
||||||
this->LockVideoBuffer();
|
this->LockVideoBuffer();
|
||||||
|
|
||||||
|
if (this->change_blitter != nullptr) {
|
||||||
|
this->RealChangeBlitter(this->change_blitter);
|
||||||
|
this->change_blitter = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
while (this->PollEvent()) {}
|
while (this->PollEvent()) {}
|
||||||
::InputLoop();
|
::InputLoop();
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ class VideoDriver : public Driver {
|
||||||
const uint DEFAULT_WINDOW_HEIGHT = 480u; ///< Default window height.
|
const uint DEFAULT_WINDOW_HEIGHT = 480u; ///< Default window height.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VideoDriver() : is_game_threaded(true) {}
|
VideoDriver() : is_game_threaded(true), change_blitter(nullptr) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark a particular area dirty.
|
* Mark a particular area dirty.
|
||||||
|
@ -161,6 +161,15 @@ public:
|
||||||
return ZOOM_LVL_OUT_4X;
|
return ZOOM_LVL_OUT_4X;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Get the currently active instance of the video driver.
|
||||||
*/
|
*/
|
||||||
|
@ -303,6 +312,9 @@ protected:
|
||||||
private:
|
private:
|
||||||
void GameLoop();
|
void GameLoop();
|
||||||
void GameThread();
|
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 */
|
#endif /* VIDEO_VIDEO_DRIVER_HPP */
|
||||||
|
|
Loading…
Reference in New Issue