diff --git a/src/client/game.cpp b/src/client/game.cpp index 4a4c89fcf..6714b1bcb 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -650,20 +650,6 @@ public: const static float object_hit_delay = 0.2; -struct FpsControl { - FpsControl() : last_time(0), busy_time(0), sleep_time(0) {} - - void reset(); - - void limit(IrrlichtDevice *device, f32 *dtime); - - u32 getBusyMs() const { return busy_time / 1000; } - - // all values in microseconds (us) - u64 last_time, busy_time, sleep_time; -}; - - /* The reason the following structs are not anonymous structs within the * class is that they are not used by the majority of member functions and * many functions that do require objects of thse types do not modify them @@ -1201,7 +1187,7 @@ void Game::run() // Calculate dtime = // m_rendering_engine->run() from this iteration // + Sleep time until the wanted FPS are reached - draw_times.limit(device, &dtime); + draw_times.limit(device, &dtime, g_menumgr.pausesGame()); const auto current_dynamic_info = ClientDynamicInfo::getCurrent(); if (!current_dynamic_info.equal(client_display_info)) { @@ -4330,48 +4316,6 @@ void Game::drawScene(ProfilerGraph *graph, RunStats *stats) Misc ****************************************************************************/ -void FpsControl::reset() -{ - last_time = porting::getTimeUs(); -} - -/* - * On some computers framerate doesn't seem to be automatically limited - */ -void FpsControl::limit(IrrlichtDevice *device, f32 *dtime) -{ - const float fps_limit = (device->isWindowFocused() && !g_menumgr.pausesGame()) - ? g_settings->getFloat("fps_max") - : g_settings->getFloat("fps_max_unfocused"); - const u64 frametime_min = 1000000.0f / std::max(fps_limit, 1.0f); - - u64 time = porting::getTimeUs(); - - if (time > last_time) // Make sure time hasn't overflowed - busy_time = time - last_time; - else - busy_time = 0; - - if (busy_time < frametime_min) { - sleep_time = frametime_min - busy_time; - if (sleep_time > 0) - sleep_us(sleep_time); - } else { - sleep_time = 0; - } - - // Read the timer again to accurately determine how long we actually slept, - // rather than calculating it by adding sleep_time to time. - time = porting::getTimeUs(); - - if (time > last_time) // Make sure last_time hasn't overflowed - *dtime = (time - last_time) / 1000000.0f; - else - *dtime = 0; - - last_time = time; -} - void Game::showOverlayMessage(const char *msg, float dtime, int percent, bool draw_sky) { m_rendering_engine->draw_load_screen(wstrgettext(msg), guienv, texture_src, diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index c1a51d289..22b55ec6b 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -44,6 +44,46 @@ RenderingEngine *RenderingEngine::s_singleton = nullptr; const video::SColor RenderingEngine::MENU_SKY_COLOR = video::SColor(255, 140, 186, 250); const float RenderingEngine::BASE_BLOOM_STRENGTH = 1.0f; +/* Helper stuff */ + +void FpsControl::reset() +{ + last_time = porting::getTimeUs(); +} + +void FpsControl::limit(IrrlichtDevice *device, f32 *dtime, bool assume_paused) +{ + const float fps_limit = (device->isWindowFocused() && !assume_paused) + ? g_settings->getFloat("fps_max") + : g_settings->getFloat("fps_max_unfocused"); + const u64 frametime_min = 1000000.0f / std::max(fps_limit, 1.0f); + + u64 time = porting::getTimeUs(); + + if (time > last_time) // Make sure time hasn't overflowed + busy_time = time - last_time; + else + busy_time = 0; + + if (busy_time < frametime_min) { + sleep_time = frametime_min - busy_time; + if (sleep_time > 0) + sleep_us(sleep_time); + } else { + sleep_time = 0; + } + + // Read the timer again to accurately determine how long we actually slept, + // rather than calculating it by adding sleep_time to time. + time = porting::getTimeUs(); + + if (time > last_time) // Make sure last_time hasn't overflowed + *dtime = (time - last_time) / 1000000.0f; + else + *dtime = 0; + + last_time = time; +} static gui::GUISkin *createSkin(gui::IGUIEnvironment *environment, gui::EGUI_SKIN_TYPE type, video::IVideoDriver *driver) @@ -66,7 +106,6 @@ static gui::GUISkin *createSkin(gui::IGUIEnvironment *environment, return skin; } - static std::optional chooseVideoDriver() { auto &&configured_name = g_settings->get("video_driver"); @@ -106,6 +145,8 @@ static irr::IrrlichtDevice *createDevice(SIrrlichtCreationParameters params, std throw std::runtime_error("Could not initialize the device with any supported video driver"); } +/* RenderingEngine class */ + RenderingEngine::RenderingEngine(IEventReceiver *receiver) { sanity_check(!s_singleton); diff --git a/src/client/renderingengine.h b/src/client/renderingengine.h index b8293f49a..629843ac9 100644 --- a/src/client/renderingengine.h +++ b/src/client/renderingengine.h @@ -46,6 +46,19 @@ class RenderingCore; // Instead of a mechanism to disable fog we just set it to be really far away #define FOG_RANGE_ALL (100000 * BS) +struct FpsControl { + FpsControl() : last_time(0), busy_time(0), sleep_time(0) {} + + void reset(); + + void limit(IrrlichtDevice *device, f32 *dtime, bool assume_paused = false); + + u32 getBusyMs() const { return busy_time / 1000; } + + // all values in microseconds (us) + u64 last_time, busy_time, sleep_time; +}; + class RenderingEngine { public: @@ -103,11 +116,6 @@ public: return s_singleton->m_device; } - u32 get_timer_time() - { - return m_device->getTimer()->getTime(); - } - gui::IGUIEnvironment *get_gui_env() { return m_device->getGUIEnvironment(); diff --git a/src/gui/guiEngine.cpp b/src/gui/guiEngine.cpp index 3f21e69e6..a0e4055b8 100644 --- a/src/gui/guiEngine.cpp +++ b/src/gui/guiEngine.cpp @@ -315,10 +315,15 @@ void GUIEngine::run() ); const bool initial_window_maximized = g_settings->getBool("window_maximized"); - u64 t_last_frame = porting::getTimeUs(); + FpsControl fps_control; f32 dtime = 0.0f; - while (m_rendering_engine->run() && (!m_startgame) && (!m_kill)) { + fps_control.reset(); + + while (m_rendering_engine->run() && !m_startgame && !m_kill) { + + fps_control.limit(device, &dtime); + if (device->isWindowVisible()) { // check if we need to update the "upper left corner"-text if (text_height != g_fontengine->getTextHeight()) { @@ -328,13 +333,12 @@ void GUIEngine::run() driver->beginScene(true, true, RenderingEngine::MENU_SKY_COLOR); - if (m_clouds_enabled) - { - cloudPreProcess(); + if (m_clouds_enabled) { + drawClouds(dtime); drawOverlay(driver); - } - else + } else { drawBackground(driver); + } drawFooter(driver); @@ -349,22 +353,9 @@ void GUIEngine::run() driver->endScene(); } - u32 frametime_min = 1000 / (device->isWindowFocused() - ? g_settings->getFloat("fps_max") - : g_settings->getFloat("fps_max_unfocused")); - if (m_clouds_enabled) - cloudPostProcess(frametime_min, device); - else - sleep_ms(frametime_min); - - u64 t_now = porting::getTimeUs(); - dtime = static_cast(t_now - t_last_frame) * 1.0e-6f; - t_last_frame = t_now; - m_script->step(); sound_volume_control(m_sound_manager.get(), device->isWindowActive()); - m_sound_manager->step(dtime); #ifdef __ANDROID__ @@ -407,47 +398,16 @@ void GUIEngine::cloudInit() m_cloud.camera = m_smgr->addCameraSceneNode(0, v3f(0,0,0), v3f(0, 60, 100)); m_cloud.camera->setFarValue(10000); - - m_cloud.lasttime = m_rendering_engine->get_timer_time(); } /******************************************************************************/ -void GUIEngine::cloudPreProcess() +void GUIEngine::drawClouds(float dtime) { - u32 time = m_rendering_engine->get_timer_time(); - - if(time > m_cloud.lasttime) - m_cloud.dtime = (time - m_cloud.lasttime) / 1000.0; - else - m_cloud.dtime = 0; - - m_cloud.lasttime = time; - - m_cloud.clouds->step(m_cloud.dtime*3); + m_cloud.clouds->step(dtime*3); m_cloud.clouds->render(); m_smgr->drawAll(); } -/******************************************************************************/ -void GUIEngine::cloudPostProcess(u32 frametime_min, IrrlichtDevice *device) -{ - // Time of frame without fps limit - u32 busytime_u32; - - // not using getRealTime is necessary for wine - u32 time = m_rendering_engine->get_timer_time(); - if(time > m_cloud.lasttime) - busytime_u32 = time - m_cloud.lasttime; - else - busytime_u32 = 0; - - // FPS limit - if (busytime_u32 < frametime_min) { - u32 sleeptime = frametime_min - busytime_u32; - device->sleep(sleeptime); - } -} - /******************************************************************************/ void GUIEngine::setFormspecPrepend(const std::string &fs) { diff --git a/src/gui/guiEngine.h b/src/gui/guiEngine.h index 7d33ce7c5..eb3e01f62 100644 --- a/src/gui/guiEngine.h +++ b/src/gui/guiEngine.h @@ -280,16 +280,10 @@ private: /** initialize cloud subsystem */ void cloudInit(); /** do preprocessing for cloud subsystem */ - void cloudPreProcess(); - /** do postprocessing for cloud subsystem */ - void cloudPostProcess(u32 frametime_min, IrrlichtDevice *device); + void drawClouds(float dtime); /** internam data required for drawing clouds */ struct clouddata { - /** delta time since last cloud processing */ - f32 dtime; - /** absolute time of last cloud processing */ - u32 lasttime; /** pointer to cloud class */ irr_ptr clouds; /** camera required for drawing clouds */