Changeset - r25015:8deed239577a
[Not reviewed]
master
0 3 0
Patric Stout - 3 years ago 2021-03-08 13:50:06
truebrain@openttd.org
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.
3 files changed with 44 insertions and 10 deletions:
0 comments (0 inline, 0 general)
src/gfxinit.cpp
Show inline comments
 
@@ -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;
 
}
 

	
src/video/video_driver.cpp
Show inline comments
 
@@ -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();
 

	
src/video/video_driver.hpp
Show inline comments
 
@@ -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 */
0 comments (0 inline, 0 general)