#include "frame_policy.h" #ifdef MT_NATIVE_HAS_LIVE_CLIENT #include "android_perf.h" #include "platform/EterBase/FrameRateMode.h" #include #include #include #include namespace mt_host { // --fps-cap N: the loop starts a frame at most every 1/N s (0 = as fast as vsync allows). int g_fps_cap = 0; // --refresh-rate N: the surface's preferred frame rate (Android ANativeWindow_setFrameRate; MainActivity // also picks the matching display mode). 0 leaves the system default. int g_refresh_rate = 0; // --fps-mode N: the frame-rate setting for this run (a test override: the saved setting stays); // --idle-fps N: the rate after --idle-after S seconds without input (0 = never lower it). int g_fps_mode = -1; int g_idle_fps = 30; double g_idle_after_s = 15.0; void FrameRatePolicy::load() { path_ = settings_path(); int mode = MtFrameRate::MODE_STANDARD; if (std::ifstream in{path_}; in) in >> mode; if (g_fps_mode >= 0) mode = g_fps_mode; MtFrameRate::Set(mode); saved_mode_ = MtFrameRate::Get(); max_hz_ = int(std::lround(android_perf::max_refresh_rate())); if (max_hz_ < 30) max_hz_ = 60; } FrameRatePolicy::Decision FrameRatePolicy::decide(double idle_seconds, bool auto_hunt) { Decision d; d.mode = MtFrameRate::Get(); if (d.mode != saved_mode_) save(saved_mode_ = d.mode); const int active = d.mode == MtFrameRate::MODE_SAVER ? 30 : d.mode == MtFrameRate::MODE_HIGH ? max_hz_ : std::min(60, max_hz_); d.idle = g_idle_fps > 0 && g_idle_fps < active && idle_seconds >= g_idle_after_s && !auto_hunt; d.fps = d.idle ? g_idle_fps : active; d.display_hz = d.mode == MtFrameRate::MODE_HIGH && !d.idle ? max_hz_ : std::min(60, max_hz_); return d; } std::string FrameRatePolicy::settings_path() { std::string dir; if (char* pref = SDL_GetPrefPath("metin2port", "client")) { dir = pref; SDL_free(pref); } return dir + "frame_rate.cfg"; } void FrameRatePolicy::save(int mode) { std::ofstream out{path_, std::ios::trunc}; out << mode << '\n'; } } // namespace mt_host #endif