Add: [Video] move GameLoop into its own thread

This allows drawing to happen while the GameLoop is doing an
iteration too.

Sadly, not much drawing currently can be done while the GameLoop
is running, as for example PollEvent() or UpdateWindows() can
influence the game-state. As such, they first need to acquire a
lock on the game-state before they can be called.

Currently, the main advantage is the time spend in Paint(), which
for non-OpenGL drivers can be a few milliseconds. For OpenGL this
is more like 0.05 milliseconds; in these instances this change
doesn't add any benefits for now.

This is an alternative to the former "draw-thread", which moved
the drawing in a thread for some OSes. It has similar performance
gain as this does, although this implementation allows for more
finer control over what suffers when the GameLoop takes too
long: drawing or the next GameLoop. For now they both suffer
equally.
This commit is contained in:
Patric Stout
2021-02-24 15:22:23 +01:00
committed by Patric Stout
parent 3a4a15cc93
commit e56d2c63c3
17 changed files with 206 additions and 51 deletions

View File

@@ -541,14 +541,14 @@ const char *VideoDriver_SDL_Base::Initialize()
return nullptr;
}
const char *VideoDriver_SDL_Base::Start(const StringList &parm)
const char *VideoDriver_SDL_Base::Start(const StringList &param)
{
if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return "Only real blitters supported";
const char *error = this->Initialize();
if (error != nullptr) return error;
this->startup_display = FindStartupDisplay(GetDriverParamInt(parm, "display", -1));
this->startup_display = FindStartupDisplay(GetDriverParamInt(param, "display", -1));
if (!CreateMainSurface(_cur_resolution.width, _cur_resolution.height, false)) {
return SDL_GetError();
@@ -562,6 +562,12 @@ const char *VideoDriver_SDL_Base::Start(const StringList &parm)
SDL_StopTextInput();
this->edit_box_focused = false;
#ifdef __EMSCRIPTEN__
this->is_game_threaded = false;
#else
this->is_game_threaded = !GetDriverParamBool(param, "no_threads") && !GetDriverParamBool(param, "no_thread");
#endif
return nullptr;
}
@@ -637,9 +643,13 @@ void VideoDriver_SDL_Base::MainLoop()
/* Run the main loop event-driven, based on RequestAnimationFrame. */
emscripten_set_main_loop_arg(&this->EmscriptenLoop, this, 0, 1);
#else
this->StartGameThread();
while (!_exit_game) {
LoopOnce();
}
this->StopGameThread();
#endif
}