Skip to content

Commit ad2d4a0

Browse files
committed
refactor(core): implement high-precision FPS limiter
Replace scattered frame rate limiting logic with centralized `FPSLimiter` class. **Key improvements:** - High-precision timing using `RDTSC`, `QueryPerformanceFrequency`, and waitable timers - Unified FPS limit handling from server, client scripts, user settings, and VSync - Dynamic CEF browser frame rate synchronization - Consistent frame pacing through `CModManager` pulse integration **Changes:** - Add `FPSLimiter` class with centralized frame limiting logic - Integrate limiter into `CCore`, replacing old methods and variables - Refactor `CCommands` to handle `fps_limit` and `vsync` cvars - Update all APIs, Lua functions, and network packets to use `FPSLimiterInterface`
1 parent eec9e9e commit ad2d4a0

24 files changed

+917
-468
lines changed

Client/cefweb/CWebCore.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,14 @@ void CWebCore::OnPostScreenshot()
479479
}
480480
}
481481

482+
void CWebCore::OnFPSLimitChange(int iFPS)
483+
{
484+
for (auto& pWebView : m_WebViews)
485+
{
486+
pWebView->GetCefBrowser()->GetHost()->SetWindowlessFrameRate(iFPS);
487+
}
488+
}
489+
482490
void CWebCore::ProcessInputMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
483491
{
484492
if (!m_pFocusedWebView ||

Client/cefweb/CWebCore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ class CWebCore : public CWebCoreInterface
9696
void OnPreScreenshot();
9797
void OnPostScreenshot();
9898

99+
void OnFPSLimitChange(int newFPS);
100+
99101
bool SetGlobalAudioVolume(float fVolume);
100102

101103
bool UpdateListsFromMaster();

Client/cefweb/CWebView.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void CWebView::Initialise()
5454
{
5555
// Initialise the web session (which holds the actual settings) in in-memory mode
5656
CefBrowserSettings browserSettings;
57-
browserSettings.windowless_frame_rate = g_pCore->GetFrameRateLimit();
57+
browserSettings.windowless_frame_rate = g_pCore->GetFPSLimiter()->GetFPSTarget();
5858
browserSettings.javascript_access_clipboard = cef_state_t::STATE_DISABLED;
5959
browserSettings.javascript_dom_paste = cef_state_t::STATE_DISABLED;
6060
browserSettings.webgl = cef_state_t::STATE_ENABLED;

Client/core/CClientVariables.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*****************************************************************************/
1111

1212
#include "StdInc.h"
13+
// #include "FPSLimiter.h"
1314

1415
template <>
1516
CClientVariables* CSingleton<CClientVariables>::m_pSingleton = NULL;
@@ -234,7 +235,20 @@ void CClientVariables::ValidateValues()
234235

235236
ClampValue("console_pos", CVector2D(0, 0), CVector2D(uiViewportWidth - 32, uiViewportHeight - 32));
236237
ClampValue("console_size", CVector2D(50, 50), CVector2D(uiViewportWidth - 32, uiViewportHeight - 32));
237-
ClampValue("fps_limit", 0, std::numeric_limits<short>::max());
238+
239+
// fps_limit is either 0 (no limit) or valid clamp range FPS_LIMIT_MIN, FPS_LIMIT_MAX so this won't work:
240+
// ClampValue("fps_limit", 0, std::numeric_limits<short>::max());
241+
// So do it with our specialized FPS validation function
242+
{
243+
// Re-validate fps_limit cvar to ensure it's within valid range
244+
// This is to catch users manually editing the config file with invalid values
245+
// We don't clamp it here as we want to allow 0 (unlimited)
246+
uint uiTemp;
247+
CVARS_GET("fps_limit", uiTemp);
248+
uiTemp = FPSLimiter::ValidateFPS(uiTemp);
249+
CVARS_SET("fps_limit", uiTemp);
250+
}
251+
238252
ClampValue("chat_font", 0, 3);
239253
ClampValue("chat_lines", 3, 62);
240254
ClampValue("chat_color", CColor(0, 0, 0, 0), CColor(255, 255, 255, 255));
@@ -261,9 +275,10 @@ void CClientVariables::ValidateValues()
261275

262276
void CClientVariables::LoadDefaults()
263277
{
264-
#define DEFAULT(__x,__y) if(!Exists(__x)) \
265-
Set(__x,__y)
266-
#define _S(__x) std::string(__x)
278+
#define DEFAULT(__x, __y) \
279+
if (!Exists(__x)) \
280+
Set(__x, __y)
281+
#define _S(__x) std::string(__x)
267282

268283
if (!Exists("nick"))
269284
{
@@ -279,6 +294,7 @@ void CClientVariables::LoadDefaults()
279294
DEFAULT("console_size", CVector2D(200, 200)); // console size
280295
DEFAULT("serverbrowser_size", CVector2D(720.0f, 495.0f)); // serverbrowser size
281296
DEFAULT("fps_limit", 100); // frame limiter
297+
DEFAULT("vsync", true); // vsync
282298
DEFAULT("chat_font", 2); // chatbox font type
283299
DEFAULT("chat_lines", 10); // chatbox lines
284300
DEFAULT("chat_color", CColor(0, 0, 0, 0)); // chatbox background color
@@ -379,4 +395,11 @@ void CClientVariables::LoadDefaults()
379395
#if 0
380396
DEFAULT ( "streaming_memory", 50 ); // Streaming memory
381397
#endif
398+
399+
#undef DEFAULT
400+
#undef _S
401+
402+
ValidateValues(); // Paranoid validation of all cvar values
403+
404+
m_bLoaded = true; // We have loaded at least the defaults
382405
}

Client/core/CClientVariables.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
class CClientVariables : public CCVarsInterface, public CSingleton<CClientVariables>
2929
{
3030
// Sanity macros << Who ever did this is idiot
31-
#define SAN if(!m_pStorage) return
32-
#define SANGET if(!Node(strVariable)) return false
31+
// TODO: (pxd) Remove these macros and ODR violations
32+
#define SAN if(!m_pStorage) { OutputDebugLine("CClientVariables::Get: m_pStorage is NULL"); return; }
33+
#define SANGET if(!Node(strVariable)) { OutputDebugLine(SString("CClientVariables::Get: Node for cvar %s is NULL"), strVariable.c_str()); return false; }
3334

3435
public:
3536
CClientVariables();
@@ -119,15 +120,15 @@ class CClientVariables : public CCVarsInterface, public CSingleton<CClientVariab
119120
bool Exists(const std::string& strVariable);
120121

121122
bool Load();
122-
bool IsLoaded() { return m_bLoaded; }
123+
bool IsLoaded() { return m_bLoaded; } // TODO: (pxd) Remove if unused? Seems unused
123124
int GetRevision() { return m_iRevision; }
124125
void ValidateValues();
125126

126127
private:
127128
CXMLNode* Node(const std::string& strVariable);
128129
void LoadDefaults();
129130

130-
bool m_bLoaded;
131+
bool m_bLoaded; // TODO: (pxd) Remove if unused? Seems unused
131132
CXMLNode* m_pStorage;
132133
int m_iRevision;
133134
};

0 commit comments

Comments
 (0)