Changeset - r24851:a41e925d9dc7
[Not reviewed]
master
0 11 0
Patric Stout - 3 years ago 2021-02-20 10:08:20
truebrain@openttd.org
Codechange: be consistent in naming the paint function Paint()

Also move this function to be a class member. This to allow
further deduplicating of code in a later commit.
11 files changed with 58 insertions and 23 deletions:
0 comments (0 inline, 0 general)
src/video/allegro_v.cpp
Show inline comments
 
@@ -47,25 +47,25 @@ static int _num_dirty_rects;
 

	
 
void VideoDriver_Allegro::MakeDirty(int left, int top, int width, int height)
 
{
 
	if (_num_dirty_rects < MAX_DIRTY_RECTS) {
 
		_dirty_rects[_num_dirty_rects].x = left;
 
		_dirty_rects[_num_dirty_rects].y = top;
 
		_dirty_rects[_num_dirty_rects].width = width;
 
		_dirty_rects[_num_dirty_rects].height = height;
 
	}
 
	_num_dirty_rects++;
 
}
 

	
 
static void DrawSurfaceToScreen()
 
void VideoDriver_Allegro::Paint()
 
{
 
	PerformanceMeasurer framerate(PFE_VIDEO);
 

	
 
	int n = _num_dirty_rects;
 
	if (n == 0) return;
 

	
 
	_num_dirty_rects = 0;
 
	if (n > MAX_DIRTY_RECTS) {
 
		blit(_allegro_screen, screen, 0, 0, 0, 0, _allegro_screen->w, _allegro_screen->h);
 
		return;
 
	}
 

	
 
@@ -515,25 +515,25 @@ void VideoDriver_Allegro::MainLoop()
 

	
 
		/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
 
		if (cur_ticks >= next_draw_tick && (_switch_mode == SM_NONE || HasModalProgress())) {
 
			next_draw_tick += this->GetDrawInterval();
 
			/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
 
			if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
 

	
 
			this->InputLoop();
 
			::InputLoop();
 
			UpdateWindows();
 
			CheckPaletteAnim();
 

	
 
			DrawSurfaceToScreen();
 
			this->Paint();
 
		}
 

	
 
		/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
 
		if (!_fast_forward || _pause_mode) {
 
			/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
 
			auto next_tick = std::min(next_draw_tick, next_game_tick);
 
			auto now = std::chrono::steady_clock::now();
 

	
 
			if (next_tick > now) {
 
				std::this_thread::sleep_for(next_tick - now);
 
			}
 
		}
src/video/allegro_v.h
Show inline comments
 
@@ -26,22 +26,23 @@ public:
 
	bool ChangeResolution(int w, int h) override;
 

	
 
	bool ToggleFullscreen(bool fullscreen) override;
 

	
 
	bool AfterBlitterChange() override;
 

	
 
	bool ClaimMousePointer() override;
 

	
 
	const char *GetName() const override { return "allegro"; }
 

	
 
protected:
 
	void InputLoop() override;
 
	void Paint() override;
 
};
 

	
 
/** Factory for the allegro video driver. */
 
class FVideoDriver_Allegro : public DriverFactoryBase {
 
public:
 
	FVideoDriver_Allegro() : DriverFactoryBase(Driver::DT_VIDEO, 4, "allegro", "Allegro Video Driver") {}
 
	Driver *CreateInstance() const override { return new VideoDriver_Allegro(); }
 
};
 

	
 
#endif /* VIDEO_ALLEGRO_H */
src/video/cocoa/cocoa_v.h
Show inline comments
 
@@ -66,37 +66,37 @@ public:
 
	const char *GetName() const override { return "cocoa"; }
 

	
 
	/* --- The following methods should be private, but can't be due to Obj-C limitations. --- */
 

	
 
	void GameLoop();
 

	
 
	void AllocateBackingStore();
 

	
 
protected:
 
	Dimension GetScreenSize() const override;
 
	float GetDPIScale() override;
 
	void InputLoop() override;
 
	void Paint() override;
 

	
 
private:
 
	bool PollEvent();
 

	
 
	bool IsFullscreen();
 
	void GameSizeChanged();
 

	
 
	void UpdateVideoModes();
 

	
 
	bool MakeWindow(int width, int height);
 

	
 
	void UpdatePalette(uint first_color, uint num_colors);
 
	void CheckPaletteAnim();
 

	
 
	void Draw(bool force_update = false);
 
	void BlitIndexedToView32(int left, int top, int right, int bottom);
 
};
 

	
 
class FVideoDriver_Cocoa : public DriverFactoryBase {
 
public:
 
	FVideoDriver_Cocoa() : DriverFactoryBase(Driver::DT_VIDEO, 10, "cocoa", "Cocoa Video Driver") {}
 
	Driver *CreateInstance() const override { return new VideoDriver_Cocoa(); }
 
};
 

	
 
#endif /* VIDEO_COCOA_H */
src/video/cocoa/cocoa_v.mm
Show inline comments
 
@@ -456,28 +456,28 @@ void VideoDriver_Cocoa::BlitIndexedToVie
 
	uint32       *dst   = (uint32*)this->window_buffer;
 
	uint          width = this->window_width;
 
	uint          pitch = this->window_pitch;
 

	
 
	for (int y = top; y < bottom; y++) {
 
		for (int x = left; x < right; x++) {
 
			dst[y * pitch + x] = pal[src[y * width + x]];
 
		}
 
	}
 
}
 

	
 
/**
 
 * Draw window.
 
 * Paint window.
 
 * @param force_update Whether to redraw unconditionally
 
 */
 
void VideoDriver_Cocoa::Draw(bool force_update)
 
void VideoDriver_Cocoa::Paint()
 
{
 
	PerformanceMeasurer framerate(PFE_VIDEO);
 

	
 
	/* Check if we need to do anything */
 
	if (this->num_dirty_rects == 0 || [ this->window isMiniaturized ]) return;
 

	
 
	if (this->num_dirty_rects >= lengthof(this->dirty_rects)) {
 
		this->num_dirty_rects = 1;
 
		this->dirty_rects[0].left = 0;
 
		this->dirty_rects[0].top = 0;
 
		this->dirty_rects[0].right = this->window_width;
 
		this->dirty_rects[0].bottom = this->window_height;
 
@@ -493,27 +493,26 @@ void VideoDriver_Cocoa::Draw(bool force_
 
				this->dirty_rects[i].right,
 
				this->dirty_rects[i].bottom
 
			);
 
		}
 

	
 
		NSRect dirtyrect;
 
		dirtyrect.origin.x = this->dirty_rects[i].left;
 
		dirtyrect.origin.y = this->window_height - this->dirty_rects[i].bottom;
 
		dirtyrect.size.width = this->dirty_rects[i].right - this->dirty_rects[i].left;
 
		dirtyrect.size.height = this->dirty_rects[i].bottom - this->dirty_rects[i].top;
 

	
 
		/* Normally drawRect will be automatically called by Mac OS X during next update cycle,
 
		 * and then blitting will occur. If force_update is true, it will be done right now. */
 
		 * and then blitting will occur. */
 
		[ this->cocoaview setNeedsDisplayInRect:[ this->cocoaview getVirtualRect:dirtyrect ] ];
 
		if (force_update) [ this->cocoaview displayIfNeeded ];
 
	}
 

	
 
	this->num_dirty_rects = 0;
 
}
 

	
 
/** Update the palette. */
 
void VideoDriver_Cocoa::UpdatePalette(uint first_color, uint num_colors)
 
{
 
	if (this->buffer_depth != 8) return;
 

	
 
	for (uint i = first_color; i < first_color + num_colors; i++) {
 
		uint32 clr = 0xff000000;
 
@@ -699,25 +698,25 @@ void VideoDriver_Cocoa::GameLoop()
 

	
 
			/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
 
			if (cur_ticks >= next_draw_tick && (_switch_mode == SM_NONE || HasModalProgress())) {
 
				next_draw_tick += this->GetDrawInterval();
 
				/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
 
				if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
 

	
 
				this->InputLoop();
 
				::InputLoop();
 
				UpdateWindows();
 
				this->CheckPaletteAnim();
 

	
 
				this->Draw();
 
				this->Paint();
 
			}
 

	
 
			/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
 
			if (!_fast_forward || _pause_mode) {
 
				/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
 
				auto next_tick = std::min(next_draw_tick, next_game_tick);
 
				auto now = std::chrono::steady_clock::now();
 

	
 
				if (next_tick > now) {
 
					std::this_thread::sleep_for(next_tick - now);
 
				}
 
			}
src/video/sdl2_v.cpp
Show inline comments
 
@@ -115,25 +115,25 @@ static void MakePalette()
 
		SDL_SetSurfacePalette(_sdl_real_surface, _sdl_palette);
 
	}
 
}
 

	
 
void VideoDriver_SDL::CheckPaletteAnim()
 
{
 
	if (_cur_palette.count_dirty == 0) return;
 

	
 
	_local_palette = _cur_palette;
 
	this->MakeDirty(0, 0, _screen.width, _screen.height);
 
}
 

	
 
static void Paint()
 
void VideoDriver_SDL::Paint()
 
{
 
	PerformanceMeasurer framerate(PFE_VIDEO);
 

	
 
	if (IsEmptyRect(_dirty_rect) && _cur_palette.count_dirty == 0) return;
 

	
 
	if (_cur_palette.count_dirty != 0) {
 
		Blitter *blitter = BlitterFactory::GetCurrentBlitter();
 

	
 
		switch (blitter->UsePaletteAnimation()) {
 
			case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
 
				UpdatePalette();
 
				break;
 
@@ -152,40 +152,45 @@ static void Paint()
 
	}
 

	
 
	SDL_Rect r = { _dirty_rect.left, _dirty_rect.top, _dirty_rect.right - _dirty_rect.left, _dirty_rect.bottom - _dirty_rect.top };
 

	
 
	if (_sdl_surface != _sdl_real_surface) {
 
		SDL_BlitSurface(_sdl_surface, &r, _sdl_real_surface, &r);
 
	}
 
	SDL_UpdateWindowSurfaceRects(_sdl_window, &r, 1);
 

	
 
	MemSetT(&_dirty_rect, 0);
 
}
 

	
 
static void PaintThread()
 
void VideoDriver_SDL::PaintThread()
 
{
 
	/* First tell the main thread we're started */
 
	std::unique_lock<std::recursive_mutex> lock(*_draw_mutex);
 
	_draw_signal->notify_one();
 

	
 
	/* Now wait for the first thing to draw! */
 
	_draw_signal->wait(*_draw_mutex);
 

	
 
	while (_draw_continue) {
 
		/* Then just draw and wait till we stop */
 
		Paint();
 
		this->Paint();
 
		_draw_signal->wait(lock);
 
	}
 
}
 

	
 
/* static */ void VideoDriver_SDL::PaintThreadThunk(VideoDriver_SDL *drv)
 
{
 
	drv->PaintThread();
 
}
 

	
 
static const Dimension default_resolutions[] = {
 
	{  640,  480 },
 
	{  800,  600 },
 
	{ 1024,  768 },
 
	{ 1152,  864 },
 
	{ 1280,  800 },
 
	{ 1280,  960 },
 
	{ 1280, 1024 },
 
	{ 1400, 1050 },
 
	{ 1600, 1200 },
 
	{ 1680, 1050 },
 
	{ 1920, 1200 }
 
@@ -811,25 +816,25 @@ void VideoDriver_SDL::LoopOnce()
 
		next_draw_tick += this->GetDrawInterval();
 
		/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
 
		if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
 

	
 
		this->InputLoop();
 
		::InputLoop();
 
		UpdateWindows();
 
		this->CheckPaletteAnim();
 

	
 
		if (_draw_mutex != nullptr && !HasModalProgress()) {
 
			_draw_signal->notify_one();
 
		} else {
 
			Paint();
 
			this->Paint();
 
		}
 
	}
 

	
 
/* Emscripten is running an event-based mainloop; there is already some
 
 * downtime between each iteration, so no need to sleep. */
 
#ifndef __EMSCRIPTEN__
 
	/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
 
	if (!_fast_forward || _pause_mode) {
 
		/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
 
		auto next_tick = std::min(next_draw_tick, next_game_tick);
 
		auto now = std::chrono::steady_clock::now();
 

	
 
@@ -852,25 +857,25 @@ void VideoDriver_SDL::MainLoop()
 

	
 
	if (_draw_threaded) {
 
		/* Initialise the mutex first, because that's the thing we *need*
 
		 * directly in the newly created thread. */
 
		_draw_mutex = new std::recursive_mutex();
 
		if (_draw_mutex == nullptr) {
 
			_draw_threaded = false;
 
		} else {
 
			draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
 
			_draw_signal = new std::condition_variable_any();
 
			_draw_continue = true;
 

	
 
			_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &PaintThread);
 
			_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &VideoDriver_SDL::PaintThreadThunk, this);
 

	
 
			/* Free the mutex if we won't be able to use it. */
 
			if (!_draw_threaded) {
 
				draw_lock.unlock();
 
				draw_lock.release();
 
				delete _draw_mutex;
 
				delete _draw_signal;
 
				_draw_mutex = nullptr;
 
				_draw_signal = nullptr;
 
			} else {
 
				/* Wait till the draw mutex has started itself. */
 
				_draw_signal->wait(*_draw_mutex);
src/video/sdl2_v.h
Show inline comments
 
@@ -37,24 +37,26 @@ public:
 

	
 
	void EditBoxGainedFocus() override;
 

	
 
	void EditBoxLostFocus() override;
 

	
 
	const char *GetName() const override { return "sdl"; }
 

	
 
protected:
 
	Dimension GetScreenSize() const override;
 
	void InputLoop() override;
 
	bool LockVideoBuffer() override;
 
	void UnlockVideoBuffer() override;
 
	void Paint() override;
 
	void PaintThread() override;
 

	
 
private:
 
	int PollEvent();
 
	void LoopOnce();
 
	void MainLoopCleanup();
 
	bool CreateMainSurface(uint w, uint h, bool resize);
 
	bool CreateMainWindow(uint w, uint h);
 
	void CheckPaletteAnim();
 

	
 
#ifdef __EMSCRIPTEN__
 
	/* Convert a constant pointer back to a non-constant pointer to a member function. */
 
	static void EmscriptenLoop(void *self) { ((VideoDriver_SDL *)self)->LoopOnce(); }
 
@@ -64,22 +66,24 @@ private:
 
	 * This is true to indicate that keyboard input is in text input mode, and SDL_TEXTINPUT events are enabled.
 
	 */
 
	bool edit_box_focused;
 

	
 
	std::chrono::steady_clock::time_point cur_ticks;
 
	std::chrono::steady_clock::time_point last_realtime_tick;
 
	std::chrono::steady_clock::time_point next_game_tick;
 
	std::chrono::steady_clock::time_point next_draw_tick;
 

	
 
	int startup_display;
 
	std::thread draw_thread;
 
	std::unique_lock<std::recursive_mutex> draw_lock;
 

	
 
	static void PaintThreadThunk(VideoDriver_SDL *drv);
 
};
 

	
 
/** Factory for the SDL video driver. */
 
class FVideoDriver_SDL : public DriverFactoryBase {
 
public:
 
	FVideoDriver_SDL() : DriverFactoryBase(Driver::DT_VIDEO, 5, "sdl", "SDL Video Driver") {}
 
	Driver *CreateInstance() const override { return new VideoDriver_SDL(); }
 
};
 

	
 
#endif /* VIDEO_SDL_H */
src/video/sdl_v.cpp
Show inline comments
 
@@ -138,25 +138,25 @@ static void CheckPaletteAnim()
 
				break;
 

	
 
			case Blitter::PALETTE_ANIMATION_NONE:
 
				break;
 

	
 
			default:
 
				NOT_REACHED();
 
		}
 
		_cur_palette.count_dirty = 0;
 
	}
 
}
 

	
 
static void DrawSurfaceToScreen()
 
void VideoDriver_SDL::Paint()
 
{
 
	PerformanceMeasurer framerate(PFE_VIDEO);
 

	
 
	int n = _num_dirty_rects;
 
	if (n == 0) return;
 

	
 
	_num_dirty_rects = 0;
 

	
 
	if (n > MAX_DIRTY_RECTS) {
 
		if (_sdl_surface != _sdl_realscreen) {
 
			SDL_BlitSurface(_sdl_surface, nullptr, _sdl_realscreen, nullptr);
 
		}
 
@@ -164,41 +164,46 @@ static void DrawSurfaceToScreen()
 
		SDL_UpdateRect(_sdl_realscreen, 0, 0, 0, 0);
 
	} else {
 
		if (_sdl_surface != _sdl_realscreen) {
 
			for (int i = 0; i < n; i++) {
 
				SDL_BlitSurface(_sdl_surface, &_dirty_rects[i], _sdl_realscreen, &_dirty_rects[i]);
 
			}
 
		}
 

	
 
		SDL_UpdateRects(_sdl_realscreen, n, _dirty_rects);
 
	}
 
}
 

	
 
static void DrawSurfaceToScreenThread()
 
void VideoDriver_SDL::PaintThread()
 
{
 
	/* First tell the main thread we're started */
 
	std::unique_lock<std::recursive_mutex> lock(*_draw_mutex);
 
	_draw_signal->notify_one();
 

	
 
	/* Now wait for the first thing to draw! */
 
	_draw_signal->wait(*_draw_mutex);
 

	
 
	while (_draw_continue) {
 
		CheckPaletteAnim();
 
		/* Then just draw and wait till we stop */
 
		DrawSurfaceToScreen();
 
		this->Paint();
 
		_draw_signal->wait(lock);
 
	}
 
}
 

	
 
/* static */ void VideoDriver_SDL::PaintThreadThunk(VideoDriver_SDL *drv)
 
{
 
	drv->PaintThread();
 
}
 

	
 
static const Dimension _default_resolutions[] = {
 
	{ 640,  480},
 
	{ 800,  600},
 
	{1024,  768},
 
	{1152,  864},
 
	{1280,  800},
 
	{1280,  960},
 
	{1280, 1024},
 
	{1400, 1050},
 
	{1600, 1200},
 
	{1680, 1050},
 
	{1920, 1200}
 
@@ -708,25 +713,25 @@ void VideoDriver_SDL::MainLoop()
 
	std::thread draw_thread;
 
	if (_draw_threaded) {
 
		/* Initialise the mutex first, because that's the thing we *need*
 
		 * directly in the newly created thread. */
 
		_draw_mutex = new std::recursive_mutex();
 
		if (_draw_mutex == nullptr) {
 
			_draw_threaded = false;
 
		} else {
 
			this->draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
 
			_draw_signal = new std::condition_variable_any();
 
			_draw_continue = true;
 

	
 
			_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &DrawSurfaceToScreenThread);
 
			_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &VideoDriver_SDL::PaintThreadThunk, this);
 

	
 
			/* Free the mutex if we won't be able to use it. */
 
			if (!_draw_threaded) {
 
				this->draw_lock.unlock();
 
				this->draw_lock.release();
 
				delete _draw_mutex;
 
				delete _draw_signal;
 
				_draw_mutex = nullptr;
 
				_draw_signal = nullptr;
 
			} else {
 
				/* Wait till the draw mutex has started itself. */
 
				_draw_signal->wait(*_draw_mutex);
 
@@ -773,25 +778,25 @@ void VideoDriver_SDL::MainLoop()
 
			/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
 
			if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
 

	
 
			this->InputLoop();
 
			::InputLoop();
 
			UpdateWindows();
 
			_local_palette = _cur_palette;
 

	
 
			if (_draw_mutex != nullptr && !HasModalProgress()) {
 
				_draw_signal->notify_one();
 
			} else {
 
				CheckPaletteAnim();
 
				DrawSurfaceToScreen();
 
				this->Paint();
 
			}
 
		}
 

	
 
		/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
 
		if (!_fast_forward || _pause_mode) {
 
			/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
 
			auto next_tick = std::min(next_draw_tick, next_game_tick);
 
			auto now = std::chrono::steady_clock::now();
 

	
 
			if (next_tick > now) {
 
				this->UnlockVideoBuffer();
 
				std::this_thread::sleep_for(next_tick - now);
src/video/sdl_v.h
Show inline comments
 
@@ -32,29 +32,33 @@ public:
 
	void AcquireBlitterLock() override;
 

	
 
	void ReleaseBlitterLock() override;
 

	
 
	bool ClaimMousePointer() override;
 

	
 
	const char *GetName() const override { return "sdl"; }
 

	
 
protected:
 
	void InputLoop() override;
 
	bool LockVideoBuffer() override;
 
	void UnlockVideoBuffer() override;
 
	void Paint() override;
 
	void PaintThread() override;
 

	
 
private:
 
	std::unique_lock<std::recursive_mutex> draw_lock;
 

	
 
	int PollEvent();
 
	bool CreateMainSurface(uint w, uint h);
 
	void SetupKeyboard();
 

	
 
	static void PaintThreadThunk(VideoDriver_SDL *drv);
 
};
 

	
 
/** Factory for the SDL video driver. */
 
class FVideoDriver_SDL : public DriverFactoryBase {
 
public:
 
	FVideoDriver_SDL() : DriverFactoryBase(Driver::DT_VIDEO, 5, "sdl", "SDL Video Driver") {}
 
	Driver *CreateInstance() const override { return new VideoDriver_SDL(); }
 
};
 

	
 
#endif /* VIDEO_SDL_H */
src/video/video_driver.hpp
Show inline comments
 
@@ -165,24 +165,34 @@ protected:
 
	 * 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() {}
 

	
 
	/**
 
	 * Paint the window.
 
	 */
 
	virtual void Paint() {}
 

	
 
	/**
 
	 * Thread function for threaded drawing.
 
	 */
 
	virtual void PaintThread() {}
 

	
 
	std::chrono::steady_clock::duration GetGameInterval()
 
	{
 
		return std::chrono::milliseconds(MILLISECONDS_PER_TICK);
 
	}
 

	
 
	std::chrono::steady_clock::duration GetDrawInterval()
 
	{
 
		return std::chrono::microseconds(1000000 / _settings_client.gui.refresh_rate);
 
	}
 
};
 

	
 
#endif /* VIDEO_VIDEO_DRIVER_HPP */
src/video/win32_v.cpp
Show inline comments
 
@@ -323,25 +323,25 @@ bool VideoDriver_Win32::MakeWindow(bool 
 
			if (_wnd.main_wnd == nullptr) usererror("CreateWindow failed");
 
			ShowWindow(_wnd.main_wnd, showstyle);
 
		}
 
	}
 

	
 
	BlitterFactory::GetCurrentBlitter()->PostResize();
 

	
 
	GameSizeChanged(); // invalidate all windows, force redraw
 
	return true; // the request succeeded
 
}
 

	
 
/** Do palette animation and blit to the window. */
 
static void PaintWindow()
 
void VideoDriver_Win32::Paint()
 
{
 
	PerformanceMeasurer framerate(PFE_VIDEO);
 

	
 
	if (IsEmptyRect(_dirty_rect)) return;
 

	
 
	/* Convert update region from logical to device coordinates. */
 
	POINT pt = {0, 0};
 
	ClientToScreen(_wnd.main_wnd, &pt);
 

	
 
	RECT r = { _dirty_rect.left, _dirty_rect.top, _dirty_rect.right, _dirty_rect.bottom };
 
	OffsetRect(&r, pt.x, pt.y);
 

	
 
@@ -376,43 +376,48 @@ static void PaintWindow()
 
	}
 

	
 
	BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
 
	SelectPalette(dc, old_palette, TRUE);
 
	SelectObject(dc2, old_bmp);
 
	DeleteDC(dc2);
 

	
 
	ReleaseDC(_wnd.main_wnd, dc);
 

	
 
	MemSetT(&_dirty_rect, 0);
 
}
 

	
 
static void PaintWindowThread()
 
void VideoDriver_Win32::PaintThread()
 
{
 
	/* First tell the main thread we're started */
 
	std::unique_lock<std::recursive_mutex> lock(*_draw_mutex);
 
	_draw_signal->notify_one();
 

	
 
	/* Now wait for the first thing to draw! */
 
	_draw_signal->wait(*_draw_mutex);
 

	
 
	while (_draw_continue) {
 
		PaintWindow();
 
		this->Paint();
 

	
 
		/* Flush GDI buffer to ensure drawing here doesn't conflict with any GDI usage in the main WndProc. */
 
		GdiFlush();
 

	
 
		_draw_signal->wait(*_draw_mutex);
 
	}
 
}
 

	
 
/* static */ void VideoDriver_Win32::PaintThreadThunk(VideoDriver_Win32 *drv)
 
{
 
	drv->PaintThread();
 
}
 

	
 
/** Forward key presses to the window system. */
 
static LRESULT HandleCharMsg(uint keycode, WChar charcode)
 
{
 
#if !defined(UNICODE)
 
	static char prev_char = 0;
 

	
 
	char input[2] = {(char)charcode, 0};
 
	int input_len = 1;
 

	
 
	if (prev_char != 0) {
 
		/* We stored a lead byte previously, combine it with this byte. */
 
		input[0] = prev_char;
 
@@ -1167,25 +1172,25 @@ void VideoDriver_Win32::MainLoop()
 
		 * directly in the newly created thread. */
 
		try {
 
			_draw_signal = new std::condition_variable_any();
 
			_draw_mutex = new std::recursive_mutex();
 
		} catch (...) {
 
			_draw_threaded = false;
 
		}
 

	
 
		if (_draw_threaded) {
 
			this->draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
 

	
 
			_draw_continue = true;
 
			_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &PaintWindowThread);
 
			_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &VideoDriver_Win32::PaintThreadThunk, this);
 

	
 
			/* Free the mutex if we won't be able to use it. */
 
			if (!_draw_threaded) {
 
				this->draw_lock.unlock();
 
				this->draw_lock.release();
 
				delete _draw_mutex;
 
				delete _draw_signal;
 
				_draw_mutex = nullptr;
 
				_draw_signal = nullptr;
 
			} else {
 
				DEBUG(driver, 1, "Threaded drawing enabled");
 
				/* Wait till the draw thread has started itself. */
 
@@ -1245,25 +1250,25 @@ void VideoDriver_Win32::MainLoop()
 

	
 
			/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
 
			GdiFlush();
 

	
 
			this->InputLoop();
 
			::InputLoop();
 
			UpdateWindows();
 
			CheckPaletteAnim();
 

	
 
			if (_draw_mutex != nullptr && !HasModalProgress()) {
 
				_draw_signal->notify_one();
 
			} else {
 
				PaintWindow();
 
				this->Paint();
 
			}
 
		}
 

	
 
		/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
 
		if (!_fast_forward || _pause_mode) {
 
			/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
 
			auto next_tick = std::min(next_draw_tick, next_game_tick);
 
			auto now = std::chrono::steady_clock::now();
 

	
 
			if (next_tick > now) {
 
				/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
 
				GdiFlush();
src/video/win32_v.h
Show inline comments
 
@@ -38,24 +38,26 @@ public:
 
	void EditBoxLostFocus() override;
 

	
 
	const char *GetName() const override { return "win32"; }
 

	
 
	bool MakeWindow(bool full_screen);
 

	
 
protected:
 
	Dimension GetScreenSize() const override;
 
	float GetDPIScale() override;
 
	void InputLoop() override;
 
	bool LockVideoBuffer() override;
 
	void UnlockVideoBuffer() override;
 
	void Paint() override;
 
	void PaintThread() override;
 

	
 
private:
 
	std::unique_lock<std::recursive_mutex> draw_lock;
 

	
 
	void CheckPaletteAnim();
 

	
 
	static void PaintThreadThunk(VideoDriver_Win32 *drv);
 
};
 

	
 
/** The factory for Windows' video driver. */
 
class FVideoDriver_Win32 : public DriverFactoryBase {
 
public:
0 comments (0 inline, 0 general)