Changeset - r24438:b17f2f305eee
[Not reviewed]
master
0 2 0
Patric Stout - 4 years ago 2020-12-06 19:38:34
truebrain@openttd.org
Codechange: unroll the SDL2 main loop

This commit prepares for the next commit, as Emscripten needs to
have a way to trigger a single iteration of the main loop. To
keep the real changes more clear, this commit only unrolls the
loop, and makes no changes to the logic itself.
2 files changed with 94 insertions and 76 deletions:
0 comments (0 inline, 0 general)
src/video/sdl2_v.cpp
Show inline comments
 
@@ -664,19 +664,90 @@ void VideoDriver_SDL::Stop()
 
	}
 
}
 

	
 
void VideoDriver_SDL::MainLoop()
 
void VideoDriver_SDL::LoopOnce()
 
{
 
	uint32 cur_ticks = SDL_GetTicks();
 
	uint32 last_cur_ticks = cur_ticks;
 
	uint32 next_tick = cur_ticks + MILLISECONDS_PER_TICK;
 
	uint32 mod;
 
	int numkeys;
 
	const Uint8 *keys;
 
	uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
 
	InteractiveRandom(); // randomness
 

	
 
	while (PollEvent() == -1) {}
 
	if (_exit_game) return;
 

	
 
	mod = SDL_GetModState();
 
	keys = SDL_GetKeyboardState(&numkeys);
 

	
 
#if defined(_DEBUG)
 
	if (_shift_pressed)
 
#else
 
	/* Speedup when pressing tab, except when using ALT+TAB
 
	 * to switch to another application */
 
	if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0)
 
#endif /* defined(_DEBUG) */
 
	{
 
		if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
 
	} else if (_fast_forward & 2) {
 
		_fast_forward = 0;
 
	}
 

	
 
	cur_ticks = SDL_GetTicks();
 
	if (SDL_TICKS_PASSED(cur_ticks, next_tick) || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) {
 
		_realtime_tick += cur_ticks - last_cur_ticks;
 
		last_cur_ticks = cur_ticks;
 
		next_tick = cur_ticks + MILLISECONDS_PER_TICK;
 

	
 
		bool old_ctrl_pressed = _ctrl_pressed;
 

	
 
		_ctrl_pressed  = !!(mod & KMOD_CTRL);
 
		_shift_pressed = !!(mod & KMOD_SHIFT);
 

	
 
		/* determine which directional keys are down */
 
		_dirkeys =
 
			(keys[SDL_SCANCODE_LEFT]  ? 1 : 0) |
 
			(keys[SDL_SCANCODE_UP]    ? 2 : 0) |
 
			(keys[SDL_SCANCODE_RIGHT] ? 4 : 0) |
 
			(keys[SDL_SCANCODE_DOWN]  ? 8 : 0);
 
		if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
 

	
 
		/* The gameloop is the part that can run asynchronously. The rest
 
		 * except sleeping can't. */
 
		if (_draw_mutex != nullptr) draw_lock.unlock();
 

	
 
		GameLoop();
 

	
 
		if (_draw_mutex != nullptr) draw_lock.lock();
 

	
 
		UpdateWindows();
 
		_local_palette = _cur_palette;
 
	} else {
 
		/* Release the thread while sleeping */
 
		if (_draw_mutex != nullptr) draw_lock.unlock();
 
		CSleep(1);
 
		if (_draw_mutex != nullptr) draw_lock.lock();
 

	
 
		NetworkDrawChatMessage();
 
		DrawMouseCursor();
 
	}
 

	
 
	/* End of the critical part. */
 
	if (_draw_mutex != nullptr && !HasModalProgress()) {
 
		_draw_signal->notify_one();
 
	} else {
 
		/* Oh, we didn't have threads, then just draw unthreaded */
 
		CheckPaletteAnim();
 
		DrawSurfaceToScreen();
 
	}
 
}
 

	
 
void VideoDriver_SDL::MainLoop()
 
{
 
	cur_ticks = SDL_GetTicks();
 
	last_cur_ticks = cur_ticks;
 
	next_tick = cur_ticks + MILLISECONDS_PER_TICK;
 

	
 
	CheckPaletteAnim();
 

	
 
	std::thread draw_thread;
 
	std::unique_lock<std::recursive_mutex> draw_lock;
 
	if (_draw_threaded) {
 
		/* Initialise the mutex first, because that's the thing we *need*
 
		 * directly in the newly created thread. */
 
@@ -707,78 +778,16 @@ void VideoDriver_SDL::MainLoop()
 

	
 
	DEBUG(driver, 1, "SDL2: using %sthreads", _draw_threaded ? "" : "no ");
 

	
 
	for (;;) {
 
		uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
 
		InteractiveRandom(); // randomness
 

	
 
		while (PollEvent() == -1) {}
 
		if (_exit_game) break;
 

	
 
		mod = SDL_GetModState();
 
		keys = SDL_GetKeyboardState(&numkeys);
 

	
 
#if defined(_DEBUG)
 
		if (_shift_pressed)
 
#else
 
		/* Speedup when pressing tab, except when using ALT+TAB
 
		 * to switch to another application */
 
		if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0)
 
#endif /* defined(_DEBUG) */
 
		{
 
			if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
 
		} else if (_fast_forward & 2) {
 
			_fast_forward = 0;
 
		}
 

	
 
		cur_ticks = SDL_GetTicks();
 
		if (SDL_TICKS_PASSED(cur_ticks, next_tick) || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) {
 
			_realtime_tick += cur_ticks - last_cur_ticks;
 
			last_cur_ticks = cur_ticks;
 
			next_tick = cur_ticks + MILLISECONDS_PER_TICK;
 

	
 
			bool old_ctrl_pressed = _ctrl_pressed;
 

	
 
			_ctrl_pressed  = !!(mod & KMOD_CTRL);
 
			_shift_pressed = !!(mod & KMOD_SHIFT);
 

	
 
			/* determine which directional keys are down */
 
			_dirkeys =
 
				(keys[SDL_SCANCODE_LEFT]  ? 1 : 0) |
 
				(keys[SDL_SCANCODE_UP]    ? 2 : 0) |
 
				(keys[SDL_SCANCODE_RIGHT] ? 4 : 0) |
 
				(keys[SDL_SCANCODE_DOWN]  ? 8 : 0);
 
			if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
 

	
 
			/* The gameloop is the part that can run asynchronously. The rest
 
			 * except sleeping can't. */
 
			if (_draw_mutex != nullptr) draw_lock.unlock();
 

	
 
			GameLoop();
 

	
 
			if (_draw_mutex != nullptr) draw_lock.lock();
 

	
 
			UpdateWindows();
 
			_local_palette = _cur_palette;
 
		} else {
 
			/* Release the thread while sleeping */
 
			if (_draw_mutex != nullptr) draw_lock.unlock();
 
			CSleep(1);
 
			if (_draw_mutex != nullptr) draw_lock.lock();
 

	
 
			NetworkDrawChatMessage();
 
			DrawMouseCursor();
 
		}
 

	
 
		/* End of the critical part. */
 
		if (_draw_mutex != nullptr && !HasModalProgress()) {
 
			_draw_signal->notify_one();
 
		} else {
 
			/* Oh, we didn't have threads, then just draw unthreaded */
 
			CheckPaletteAnim();
 
			DrawSurfaceToScreen();
 
		}
 
	while (!_exit_game) {
 
		LoopOnce();
 
	}
 

	
 
	MainLoopCleanup();
 
#endif
 
}
 

	
 
void VideoDriver_SDL::MainLoopCleanup()
 
{
 
	if (_draw_mutex != nullptr) {
 
		_draw_continue = false;
 
		/* Sending signal if there is no thread blocked
src/video/sdl2_v.h
Show inline comments
 
@@ -42,12 +42,21 @@ public:
 
	const char *GetName() const override { return "sdl"; }
 
private:
 
	int PollEvent();
 
	void LoopOnce();
 
	void MainLoopCleanup();
 
	bool CreateMainSurface(uint w, uint h, bool resize);
 

	
 
	/**
 
	 * This is true to indicate that keyboard input is in text input mode, and SDL_TEXTINPUT events are enabled.
 
	 */
 
	bool edit_box_focused;
 

	
 
	uint32 cur_ticks;
 
	uint32 last_cur_ticks;
 
	uint32 next_tick;
 

	
 
	std::thread draw_thread;
 
	std::unique_lock<std::recursive_mutex> draw_lock;
 
};
 

	
 
/** Factory for the SDL video driver. */
0 comments (0 inline, 0 general)