Implement maximum frame rate limit

This new configuration can be adjusted from the display configuration
screen and allows to cap maximum fps so that CPU load is greatly
reduced, especially on menu screens.


git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@9484 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: b63c4a7c907bbfb3fc8d44a6a77c7c1948341174
Former-commit-id: c331b396c32d1fd7d57b17ab880f44b808e12088
This commit is contained in:
xavi92 2024-07-15 02:52:31 +00:00
parent ab2286b71e
commit 9914e9d24c
13 changed files with 76 additions and 67 deletions

View file

@ -274,9 +274,4 @@ void GfEventLoop::recompute()
// Call the 'recompute' callback if any.
if (_pPrivate->cbRecompute)
_pPrivate->cbRecompute();
// ... otherwise let the CPU take breath (and fans stay at low and quiet speed,
// which would not be the case if really doing nothing).
else
SDL_Delay(1); // ms.
}

View file

@ -19,6 +19,7 @@
#include <SDL.h>
#include "tgfclient.h"
#include "tgf.h"
#ifdef WEBSERVER
#include "webserver.h"
@ -48,12 +49,14 @@ class GfuiEventLoop::Private
// Variables.
bool bRedisplay; // Flag to say if a redisplay is necessary.
double max_refresh; // Max refresh rate.
};
GfuiEventLoop::Private::Private()
: cbMouseButton(0), cbMouseMotion(0), cbMousePassiveMotion(0), cbMouseWheel(0),
cbJoystickAxis(0), cbJoystickButton(0),
cbDisplay(0), cbReshape(0), bRedisplay(false)
cbDisplay(0), cbReshape(0), bRedisplay(false),
max_refresh(50.0)
{
}
@ -238,11 +241,22 @@ void GfuiEventLoop::operator()()
if (!quitRequested())
{
double now = GfTimeClock();
// Recompute if anything to.
recompute();
// Redisplay if anything to.
redisplay();
double elapsed = GfTimeClock() - now;
if (_pPrivate->max_refresh)
{
double rate = 1.0 / _pPrivate->max_refresh;
if (elapsed < rate)
GfSleep(rate - elapsed);
}
}
}
@ -294,6 +308,11 @@ void GfuiEventLoop::postRedisplay(void)
_pPrivate->bRedisplay = true;
}
void GfuiEventLoop::setMaxRefreshRate(double rate)
{
_pPrivate->max_refresh = rate;
}
void GfuiEventLoop::forceRedisplay()
{
#ifdef WEBSERVER

View file

@ -210,6 +210,7 @@ ScreenSizeVector GfScrGetSupportedSizes(int nDisplayIndex)
tScreenSize last;
last.width = 0;
last.height = 0;
last.refresh_rate = 0;
bounds.w = 0;
bounds.h = 0;
@ -243,6 +244,7 @@ ScreenSizeVector GfScrGetSupportedSizes(int nDisplayIndex)
GfLogDebug(" %d x %d x %d @ %d hz\n",mode.w,mode.h,SDL_BITSPERPIXEL(mode.format),mode.refresh_rate);
last.width = mode.w;
last.height = mode.h;
last.refresh_rate = mode.refresh_rate;
vecSizes.push_back(last);
}
}
@ -262,6 +264,7 @@ ScreenSizeVector GfScrGetSupportedSizes(int nDisplayIndex)
// Desperation stick the Display Bounds into the vector
last.width = bounds.w;
last.height = bounds.h;
last.refresh_rate = mode.refresh_rate;
vecSizes.push_back(last);
}
@ -279,12 +282,14 @@ tScreenSize GfScrGetCurrentDisplaySize(int nDisplayIndex)
size.width = 0;
size.height = 0;
size.refresh_rate = 0;
SDL_DisplayMode mode;
if(SDL_GetCurrentDisplayMode(nDisplayIndex, &mode) == 0)
{
size.width = mode.w;
size.height = mode.h;
size.refresh_rate = mode.refresh_rate;
}
return size;
}
@ -494,6 +499,10 @@ bool GfScrInitSDL2(int nWinWidth, int nWinHeight, int nFullScreen)
GfScrStartDisplayId = 0;
}
double maxRefreshRate = GfParmGetNum(hparmScreen, pszScrPropSec, GFSCR_ATT_MAXREFRESH, NULL, 50);
GfuiApp().eventLoop().setMaxRefreshRate(maxRefreshRate);
bool bFullScreen;
if (nFullScreen < 0)
bFullScreen =
@ -727,6 +736,7 @@ bool GfScrInitSDL2(int nWinWidth, int nWinHeight, int nFullScreen)
GfLogInfo(" Full screen : %s\n", (bfVideoMode & SDL_WINDOW_FULLSCREEN) ? "Yes" : "No");
GfLogInfo(" Size : %dx%d\n", nWinWidth, nWinHeight);
GfLogInfo(" Color depth : %d bits\n", nTotalDepth);
GfLogInfo(" Max. refresh rate : %f\n", maxRefreshRate);
// Report about underlying hardware (needs a running frame buffer).
GfglFeatures::self().dumpHardwareInfo();
@ -813,6 +823,8 @@ void GfScrShutdown(void)
GfParmGetNum(hparmScreen, GFSCR_SECT_INTESTPROPS, GFSCR_ATT_STARTUPDISPLAY, 0, 0));
GfParmSetStr(hparmScreen, GFSCR_SECT_VALIDPROPS, GFSCR_ATT_VDETECT,
GfParmGetStr(hparmScreen, GFSCR_SECT_INTESTPROPS, GFSCR_ATT_VDETECT, GFSCR_VAL_VDETECT_AUTO));
GfParmSetNum(hparmScreen, GFSCR_SECT_VALIDPROPS, GFSCR_ATT_MAXREFRESH, 0,
GfParmGetNum(hparmScreen, GFSCR_SECT_INTESTPROPS, GFSCR_ATT_MAXREFRESH, 0, 50));
const char* pszVInitMode =
GfParmGetStr(hparmScreen, GFSCR_SECT_INTESTPROPS, GFSCR_ATT_VINIT,
GFSCR_VAL_VINIT_COMPATIBLE);
@ -1280,6 +1292,20 @@ bool GfScrInitSDL2()
// Setup the event loop about the new display.
GfuiApp().eventLoop().setReshapeCB(gfScrReshapeViewport);
GfuiApp().eventLoop().postRedisplay();
double maxRefreshRate = 50;
void* hparmScreen =
GfParmReadFileLocal(GFSCR_CONF_FILE, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
if (hparmScreen)
{
maxRefreshRate = GfParmGetNum(hparmScreen,
GFSCR_SECT_VALIDPROPS, GFSCR_ATT_MAXREFRESH, NULL, maxRefreshRate);
GfParmReleaseHandle(hparmScreen);
}
GfuiApp().eventLoop().setMaxRefreshRate(maxRefreshRate);
return true;
}
else

View file

@ -75,6 +75,7 @@ typedef struct ScreenSize
{
int width; // Width in pixels.
int height; // Height in pixels.
double refresh_rate; // Refresh rate in Hz.
} tScreenSize;
typedef std::vector<tScreenSize> ScreenSizeVector;
@ -812,6 +813,9 @@ class TGFCLIENT_API GfuiEventLoop : public GfEventLoop
//! Force a call to the "redisplay/refresh" callback function.
void forceRedisplay();
//! Sets maximum refresh rate to the event loop.
void setMaxRefreshRate(double rate);
protected:
//! Process a keyboard event.

View file

@ -489,9 +489,6 @@ configure_for_joy_axis:
return;
}
}
/* Let CPU take breath (and fans stay at low and quiet speed) */
GfSleep(0.001);
}
/* Push button callback for each command button : activate input devices action collection loop */

View file

@ -33,10 +33,8 @@ static const char* ADisplayModes[DisplayMenu::nDisplayModes] = { "Full-screen",
static const char* MonitorTypes[DisplayMenu::nDisplayTypes] = { "none", "4:3", "16:9", "21:9" };
static const char* SpansplitValues[] = { GR_VAL_NO, GR_VAL_YES };
static const int NbSpansplitValues = sizeof(SpansplitValues) / sizeof(SpansplitValues[0]);
#ifndef NoMaxRefreshRate
static const int AMaxRefreshRates[] = { 0, 30, 40, 50, 60, 75, 85, 100, 120, 150, 200 };
static const int AMaxRefreshRates[] = {30, 40, 50, 60, 75, 85, 100, 120, 150, 200 };
static const int NMaxRefreshRates = sizeof(AMaxRefreshRates) / sizeof(AMaxRefreshRates[0]);
#endif
// Call-backs ================================================================
@ -146,7 +144,6 @@ void DisplayMenu::onChangeMenuDisplay(tComboBoxInfo *pInfo)
pMenu->setMenuDisplay(pInfo->nPos);
}
#ifndef NoMaxRefreshRate
void DisplayMenu::onChangeMaxRefreshRate(tComboBoxInfo *pInfo)
{
// Get the DisplayMenu instance from call-back user data.
@ -154,7 +151,6 @@ void DisplayMenu::onChangeMaxRefreshRate(tComboBoxInfo *pInfo)
pMenu->setMaxRefreshRateIndex(pInfo->nPos);
}
#endif
// Re-init screen to take new graphical settings into account (implies process restart).
void DisplayMenu::onAccept(void *pDisplayMenu)
@ -185,6 +181,7 @@ void DisplayMenu::onAccept(void *pDisplayMenu)
// Restart the game.
GfuiApp().restart();
}
GfuiApp().eventLoop().setMaxRefreshRate(pMenu->_nMaxRefreshRate);
GfuiScreenActivate(pMenu->getPreviousMenuHandle());
}
@ -193,7 +190,8 @@ bool DisplayMenu::restartNeeded()
bool needRestart = ((_eDisplayMode != _eOriginalDisplayMode)
|| (_nScreenWidth !=_nOriginalScreenWidth)
|| (_nScreenHeight != _nOriginalScreenHeight)
|| (_nOriginalMenuDisplay != _nMenuDisplay));
|| (_nOriginalMenuDisplay != _nMenuDisplay))
|| (_nOriginalMaxRefreshRate != _nMaxRefreshRate);
if(GfScrUsingResizableWindow() && (_eDisplayMode == eResizable))
needRestart = false;
@ -252,7 +250,6 @@ void DisplayMenu::updateControls()
sprintf(buf, "%g", _fArcRatio);
GfuiEditboxSetString(getMenuHandle(), _nArcRatioID, buf);
#ifndef NoMaxRefreshRate
nControlId = getDynamicControlId("MaxRefreshRateCombo");
int nMaxRefRateIndex = 0; // Defaults to None.
for (int nMaxRefRateInd = 0; nMaxRefRateInd < NMaxRefreshRates; nMaxRefRateInd++)
@ -262,7 +259,6 @@ void DisplayMenu::updateControls()
break;
}
GfuiComboboxSetSelectedIndex(getMenuHandle(), nControlId, nMaxRefRateIndex);
#endif
}
void DisplayMenu::loadSettings()
@ -294,12 +290,10 @@ void DisplayMenu::loadSettings()
}
#ifndef NoMaxRefreshRate
// Max. refresh rate (Hz).
_nMaxRefreshRate =
(int)GfParmGetNum(hScrConfParams, pszScrPropSec, GFSCR_ATT_MAXREFRESH, NULL, 0);
#endif
_nMaxRefreshRate = _nOriginalMaxRefreshRate =
(int)GfParmGetNum(hScrConfParams, pszScrPropSec, GFSCR_ATT_MAXREFRESH, NULL, 50);
// Release screen config params file.
GfParmReleaseHandle(hScrConfParams);
}
@ -319,9 +313,7 @@ void DisplayMenu::storeSettings() const
GfParmSetNum(hScrConfParams, GFSCR_SECT_INTESTPROPS, GFSCR_ATT_WIN_X, (char*)NULL, _nScreenWidth);
GfParmSetNum(hScrConfParams, GFSCR_SECT_INTESTPROPS, GFSCR_ATT_WIN_Y, (char*)NULL, _nScreenHeight);
GfParmSetNum(hScrConfParams, GFSCR_SECT_INTESTPROPS, GFSCR_ATT_STARTUPDISPLAY, (char*)NULL, _nMenuDisplay);
#ifndef NoMaxRefreshRate
GfParmSetNum(hScrConfParams, GFSCR_SECT_INTESTPROPS, GFSCR_ATT_MAXREFRESH, (char*)NULL, _nMaxRefreshRate);
#endif
const char* pszDisplMode =
(_eDisplayMode == eFullScreen) ? GFSCR_VAL_YES : GFSCR_VAL_NO;
@ -424,6 +416,8 @@ void DisplayMenu::storeWindowSettings() const
// Open screen config params file.
void* hScrConfParams = GfParmReadFileLocal(GFSCR_CONF_FILE, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
GfParmSetNum(hScrConfParams, GFSCR_SECT_VALIDPROPS, GFSCR_ATT_MAXREFRESH, NULL, _nMaxRefreshRate);
if(_eDisplayMode == eResizable)
GfParmSetStr(hScrConfParams, GFSCR_SECT_WINDOWPROPS, GFSCR_ATT_RESIZABLE, GFSCR_VAL_YES);
else
@ -459,6 +453,7 @@ void DisplayMenu::resetScreenSizes()
tScreenSize _currSize = GfScrGetCurrentDisplaySize( _nMenuDisplay);
_nScreenWidth = _currSize.width;
_nScreenHeight = _currSize.height;
_nMaxRefreshRate = _currSize.refresh_rate;
}
else
{
@ -511,6 +506,20 @@ void DisplayMenu::resetScreenSizes()
// Select the found one in the combo-box.
GfuiComboboxSetSelectedIndex(getMenuHandle(), nComboId, nScreenSizeIndex);
{
const int nComboId = getDynamicControlId("MaxRefreshRateCombo");
if (nComboId != -1)
for (size_t i = 0; i < NMaxRefreshRates; i++)
{
if (AMaxRefreshRates[i] == _nMaxRefreshRate)
{
GfuiComboboxSetSelectedIndex(getMenuHandle(), nComboId, i);
break;
}
}
}
}
void DisplayMenu::setScreenSizeIndex(int nIndex)
@ -553,12 +562,10 @@ void DisplayMenu::setMenuDisplay(int nIndex)
}
}
#ifndef NoMaxRefreshRate
void DisplayMenu::setMaxRefreshRateIndex(int nIndex)
{
_nMaxRefreshRate = AMaxRefreshRates[nIndex];
}
#endif
DisplayMenu::DisplayMenu()
: GfuiMenuScreen("displayconfigmenu.xml")
@ -576,9 +583,7 @@ DisplayMenu::DisplayMenu()
_nOriginalScreenHeight = 600;
_nOriginalMenuDisplay = 0;
_eOriginalDisplayMode = eWindowed;
#ifndef NoMaxRefreshRate
_nMaxRefreshRate = 0;
#endif
_nMaxRefreshRate = 50;
}
bool DisplayMenu::initialize(void *pPreviousMenu)
@ -626,10 +631,8 @@ bool DisplayMenu::initialize(void *pPreviousMenu)
_nArcRatioID = createEditControl("arcratioedit", this, NULL, onChangeArcRatio);
#ifndef NoMaxRefreshRate
const int nMaxRefRateComboId =
createComboboxControl("MaxRefreshRateCombo", this, onChangeMaxRefreshRate);
#endif
createButtonControl("ApplyButton", this, onAccept);
createButtonControl("CancelButton", this, onCancel);
@ -659,7 +662,6 @@ bool DisplayMenu::initialize(void *pPreviousMenu)
GfuiComboboxAddText(getMenuHandle(), nSpanSplitsComboId, SpansplitValues[index]);
#ifndef NoMaxRefreshRate
// 6) Max refresh rate combo.
std::ostringstream ossMaxRefRate;
for (int nRefRateInd = 0; nRefRateInd < NMaxRefreshRates; nRefRateInd++)
@ -671,7 +673,6 @@ bool DisplayMenu::initialize(void *pPreviousMenu)
ossMaxRefRate << "None";
GfuiComboboxAddText(getMenuHandle(), nMaxRefRateComboId, ossMaxRefRate.str().c_str());
}
#endif
return true;
}

View file

@ -25,8 +25,6 @@
#include "confscreens.h"
// Comment-out to activate max. refresh rate settings.
#define NoMaxRefreshRate 1
class DisplayMenu : public GfuiMenuScreen
@ -46,9 +44,7 @@ public:
void setMonitorType(EDisplayType eType);
void setArcRatio(float ratio);
void setMenuDisplay(int nIndex);
#ifndef NoMaxRefreshRate
void setMaxRefreshRateIndex(int nIndex);
#endif
void storeSettings() const;
void loadSettings();
@ -76,9 +72,7 @@ protected:
static void onChangeScreenDist(void *pDisplayMenu);
static void onChangeArcRatio(void *pDisplayMenu);
static void onChangeMenuDisplay(tComboBoxInfo *pInfo);
#ifndef NoMaxRefreshRate
static void onChangeMaxRefreshRate(tComboBoxInfo *pInfo);
#endif
static void onAccept(void *pDisplayMenu);
static void onCancel(void *pDisplayMenu);
@ -113,10 +107,9 @@ private:
int _nScreenDistId;
int _nArcRatioID;
#ifndef NoMaxRefreshRate
//! Currently selected max. refresh rate (Hz).
int _nMaxRefreshRate;
#endif
int _nOriginalMaxRefreshRate;
};
extern void* DisplayMenuInit(void* pPreviousMenu);

View file

@ -279,9 +279,6 @@ Idle2(void)
return;
}
}
/* Let CPU take breath (and fans stay at low and quite speed) */
GfSleep(0.001);
}

View file

@ -195,9 +195,6 @@ Idle2(void)
return;
}
}
/* Let CPU take breath (and fans stay at low and quite speed) */
GfSleep(0.001);
}

View file

@ -163,9 +163,6 @@ Idle2(void)
return;
}
}
/* Let CPU take breath (and fans stay at low and quiet speed) */
GfSleep(0.001);
}
static void

View file

@ -95,11 +95,6 @@ static void splashIdle()
// And now it's done, remember it.
splBackgroundWorkDone = true;
}
else
{
// Wait a little, to let the CPU take breath.
GfSleep(0.001);
}
// Close if the splash screen delay is over.
if (splTimedOut)

View file

@ -544,9 +544,6 @@ HostServerIdle(void)
GfuiApp().eventLoop().postRedisplay();
}
/* Let CPU take breath (and fans stay at low and quiet speed) */
GfSleep(0.001);
}
@ -581,9 +578,6 @@ ClientIdle(void)
GfuiApp().eventLoop().postRedisplay();
}
/* Let CPU take breath (and fans stay at low and quiet speed) */
GfSleep(0.001);
}
static void

View file

@ -541,9 +541,6 @@ HostServerIdle(void)
GfuiApp().eventLoop().postRedisplay();
}
/* Let CPU take breath (and fans stay at low and quiet speed) */
GfSleep(0.001);
}
@ -578,9 +575,6 @@ ClientIdle(void)
GfuiApp().eventLoop().postRedisplay();
}
/* Let CPU take breath (and fans stay at low and quiet speed) */
GfSleep(0.001);
}
static void