mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-19 22:48:18 +00:00
commit
9eeb7dffa5
|
@ -2,6 +2,7 @@
|
|||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
#include <new>
|
||||
|
||||
#include <immintrin.h> //_mm_pause
|
||||
#include <stdlib.h> // qsort
|
||||
#include <stdarg.h>
|
||||
|
||||
|
@ -254,6 +255,8 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD
|
|||
m_RenderFrameTimeHigh = 0.0f;
|
||||
m_RenderFrames = 0;
|
||||
m_LastRenderTime = time_get();
|
||||
m_LastCpuTime = time_get();
|
||||
m_LastAvgCpuFrameTime = 0;
|
||||
|
||||
m_GameTickSpeed = SERVER_TICK_SPEED;
|
||||
|
||||
|
@ -1712,6 +1715,86 @@ void CClient::InitInterfaces()
|
|||
m_Friends.Init();
|
||||
}
|
||||
|
||||
bool CClient::LimitFps()
|
||||
{
|
||||
if(g_Config.m_GfxVsync || !g_Config.m_GfxLimitFps) return false;
|
||||
|
||||
/**
|
||||
If desired frame time is not reached:
|
||||
Skip rendering the frame
|
||||
Do another game loop
|
||||
|
||||
If we don't have the time to do another game loop:
|
||||
Wait until desired frametime
|
||||
|
||||
Returns true if frame should be skipped
|
||||
**/
|
||||
|
||||
#ifdef CONF_DEBUG
|
||||
static double DbgTimeWaited = 0.0;
|
||||
static int64 DbgFramesSkippedCount = 0;
|
||||
static int64 DbgLastSkippedDbgMsg = time_get();
|
||||
#endif
|
||||
|
||||
int64 Now = time_get();
|
||||
const double LastCpuFrameTime = (Now - m_LastCpuTime) / (double)time_freq();
|
||||
m_LastAvgCpuFrameTime = (m_LastAvgCpuFrameTime + LastCpuFrameTime * 4.0) / 5.0;
|
||||
m_LastCpuTime = Now;
|
||||
|
||||
bool SkipFrame = true;
|
||||
double RenderDeltaTime = (Now - m_LastRenderTime) / (double)time_freq();
|
||||
const double DesiredTime = 1.0/g_Config.m_GfxMaxFps;
|
||||
|
||||
// we can't skip another frame, so wait instead
|
||||
if(SkipFrame && RenderDeltaTime < DesiredTime &&
|
||||
m_LastAvgCpuFrameTime * 1.20 > (DesiredTime - RenderDeltaTime))
|
||||
{
|
||||
#ifdef CONF_DEBUG
|
||||
DbgTimeWaited += DesiredTime - RenderDeltaTime;
|
||||
#endif
|
||||
const double Freq = (double)time_freq();
|
||||
const int64 LastT = m_LastRenderTime;
|
||||
double d = DesiredTime - RenderDeltaTime;
|
||||
while(d > 0.00001)
|
||||
{
|
||||
Now = time_get();
|
||||
RenderDeltaTime = (Now - LastT) / Freq;
|
||||
d = DesiredTime - RenderDeltaTime;
|
||||
_mm_pause();
|
||||
}
|
||||
|
||||
SkipFrame = false;
|
||||
m_LastCpuTime = Now;
|
||||
}
|
||||
|
||||
// RenderDeltaTime exceeds DesiredTime, render
|
||||
if(SkipFrame && RenderDeltaTime > DesiredTime)
|
||||
{
|
||||
SkipFrame = false;
|
||||
}
|
||||
|
||||
#ifdef CONF_DEBUG
|
||||
DbgFramesSkippedCount += SkipFrame? 1:0;
|
||||
|
||||
Now = time_get();
|
||||
if(g_Config.m_GfxLimitFps &&
|
||||
g_Config.m_Debug &&
|
||||
(Now - DbgLastSkippedDbgMsg) / (double)time_freq() > 5.0)
|
||||
{
|
||||
char aBuf[128];
|
||||
str_format(aBuf, sizeof(aBuf), "LimitFps: FramesSkippedCount=%d TimeWaited=%.3f (per sec)",
|
||||
DbgFramesSkippedCount/5,
|
||||
DbgTimeWaited/5.0);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf);
|
||||
DbgFramesSkippedCount = 0;
|
||||
DbgTimeWaited = 0;
|
||||
DbgLastSkippedDbgMsg = Now;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SkipFrame;
|
||||
}
|
||||
|
||||
void CClient::Run()
|
||||
{
|
||||
m_LocalStartTime = time_get();
|
||||
|
@ -1902,13 +1985,16 @@ void CClient::Run()
|
|||
|
||||
Update();
|
||||
|
||||
if(!g_Config.m_GfxAsyncRender || m_pGraphics->IsIdle())
|
||||
const bool SkipFrame = LimitFps();
|
||||
|
||||
if(!SkipFrame && (!g_Config.m_GfxAsyncRender || m_pGraphics->IsIdle()))
|
||||
{
|
||||
m_RenderFrames++;
|
||||
|
||||
// update frametime
|
||||
int64 Now = time_get();
|
||||
m_RenderFrameTime = (Now - m_LastRenderTime) / (float)time_freq();
|
||||
|
||||
if(m_RenderFrameTime < m_RenderFrameTimeLow)
|
||||
m_RenderFrameTimeLow = m_RenderFrameTime;
|
||||
if(m_RenderFrameTime > m_RenderFrameTimeHigh)
|
||||
|
|
|
@ -86,6 +86,8 @@ class CClient : public IClient, public CDemoPlayer::IListner
|
|||
IGraphics::CTextureHandle m_DebugFont;
|
||||
|
||||
int64 m_LastRenderTime;
|
||||
int64 m_LastCpuTime;
|
||||
float m_LastAvgCpuFrameTime;
|
||||
float m_RenderFrameTimeLow;
|
||||
float m_RenderFrameTimeHigh;
|
||||
int m_RenderFrames;
|
||||
|
@ -273,6 +275,7 @@ public:
|
|||
void RegisterInterfaces();
|
||||
void InitInterfaces();
|
||||
|
||||
bool LimitFps();
|
||||
void Run();
|
||||
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ public:
|
|||
|
||||
};
|
||||
|
||||
extern IEngineGraphics *CreateEngineGraphics();
|
||||
extern IEngineGraphics *CreateEngineGraphics(); // NOTE: not used
|
||||
extern IEngineGraphics *CreateEngineGraphicsThreaded();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,8 @@ MACRO_CONFIG_INT(GfxFsaaSamples, gfx_fsaa_samples, 0, 0, 16, CFGFLAG_SAVE|CFGFLA
|
|||
MACRO_CONFIG_INT(GfxRefreshRate, gfx_refresh_rate, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen refresh rate")
|
||||
MACRO_CONFIG_INT(GfxFinish, gfx_finish, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
|
||||
MACRO_CONFIG_INT(GfxAsyncRender, gfx_asyncrender, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Do rendering async from the the update")
|
||||
MACRO_CONFIG_INT(GfxMaxFps, gfx_maxfps, 144, 30, 2000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Maximum fps (when limit fps is enabled)")
|
||||
MACRO_CONFIG_INT(GfxLimitFps, gfx_limitfps, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Limit fps")
|
||||
|
||||
MACRO_CONFIG_INT(InpMousesens, inp_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity")
|
||||
|
||||
|
|
|
@ -1264,14 +1264,14 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
static int s_GfxTextureQuality = g_Config.m_GfxTextureQuality;
|
||||
static int s_GfxTextureCompression = g_Config.m_GfxTextureCompression;
|
||||
|
||||
CUIRect Label, Button, Screen, Texture, BottomView;
|
||||
CUIRect Label, Button, ScreenLeft, ScreenRight, Texture, BottomView;
|
||||
|
||||
// cut view
|
||||
MainView.HSplitBottom(80.0f, &MainView, &BottomView);
|
||||
BottomView.HSplitTop(20.f, 0, &BottomView);
|
||||
|
||||
// render screen menu background
|
||||
int NumOptions = g_Config.m_GfxFullscreen ? 3 : 4;
|
||||
int NumOptions = 3 + (!g_Config.m_GfxFullscreen);
|
||||
if(Graphics()->GetNumScreens() > 1)
|
||||
++NumOptions;
|
||||
float ButtonHeight = 20.0f;
|
||||
|
@ -1279,8 +1279,8 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing;
|
||||
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
MainView.HSplitTop(BackgroundHeight, &Screen, &MainView);
|
||||
RenderTools()->DrawUIRect(&Screen, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
MainView.HSplitTop(BackgroundHeight, &ScreenLeft, &MainView);
|
||||
RenderTools()->DrawUIRect(&ScreenLeft, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
// render textures menu background
|
||||
NumOptions = 3;
|
||||
|
@ -1291,46 +1291,40 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
RenderTools()->DrawUIRect(&Texture, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
// render screen menu
|
||||
Screen.HSplitTop(ButtonHeight, &Label, &Screen);
|
||||
ScreenLeft.HSplitTop(ButtonHeight, &Label, &ScreenLeft);
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, Localize("Screen"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
|
||||
Screen.HSplitTop(Spacing, 0, &Screen);
|
||||
Screen.HSplitTop(ButtonHeight, &Button, &Screen);
|
||||
ScreenLeft.VSplitMid(&ScreenLeft, &ScreenRight);
|
||||
ScreenLeft.VSplitRight(Spacing * 0.5f, &ScreenLeft, 0);
|
||||
ScreenRight.VSplitLeft(Spacing * 0.5f, 0, &ScreenRight);
|
||||
|
||||
ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft);
|
||||
ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft);
|
||||
static int s_ButtonGfxFullscreen = 0;
|
||||
if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button))
|
||||
Client()->ToggleFullscreen();
|
||||
|
||||
if(!g_Config.m_GfxFullscreen)
|
||||
{
|
||||
Screen.HSplitTop(Spacing, 0, &Screen);
|
||||
Screen.HSplitTop(ButtonHeight, &Button, &Screen);
|
||||
ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft);
|
||||
ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft);
|
||||
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
||||
static int s_ButtonGfxBorderless = 0;
|
||||
if(DoButton_CheckBox(&s_ButtonGfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button))
|
||||
Client()->ToggleWindowBordered();
|
||||
}
|
||||
|
||||
Screen.HSplitTop(Spacing, 0, &Screen);
|
||||
Screen.HSplitTop(ButtonHeight, &Button, &Screen);
|
||||
ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft);
|
||||
ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft);
|
||||
static int s_ButtonGfxVsync = 0;
|
||||
if(DoButton_CheckBox(&s_ButtonGfxVsync, Localize("V-Sync"), g_Config.m_GfxVsync, &Button))
|
||||
Client()->ToggleWindowVSync();
|
||||
|
||||
if(Graphics()->GetNumScreens() > 1)
|
||||
{
|
||||
Screen.HSplitTop(Spacing, 0, &Screen);
|
||||
Screen.HSplitTop(ButtonHeight, &Button, &Screen);
|
||||
int Index = g_Config.m_GfxScreen;
|
||||
DoScrollbarOption(&g_Config.m_GfxScreen, &Index, &Button, Localize("Screen"), 110.0f, 0, Graphics()->GetNumScreens()-1);
|
||||
if(Index != g_Config.m_GfxScreen)
|
||||
Client()->SwitchWindowScreen(Index);
|
||||
}
|
||||
|
||||
// FSAA button
|
||||
{
|
||||
Screen.HSplitTop(Spacing, 0, &Screen);
|
||||
Screen.HSplitTop(ButtonHeight, &Button, &Screen);
|
||||
ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft);
|
||||
ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft);
|
||||
RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
CUIRect Text;
|
||||
Button.VSplitLeft(ButtonHeight+5.0f, 0, &Button);
|
||||
|
@ -1356,6 +1350,37 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
}
|
||||
}
|
||||
|
||||
ScreenRight.HSplitTop(Spacing, 0, &ScreenRight);
|
||||
ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight);
|
||||
|
||||
// TODO: greyed out checkbox (not clickable)
|
||||
if(!g_Config.m_GfxVsync)
|
||||
{
|
||||
static int s_ButtonGfxCapFps = 0;
|
||||
if(DoButton_CheckBox(&s_ButtonGfxCapFps, Localize("Limit Fps"), g_Config.m_GfxLimitFps, &Button))
|
||||
{
|
||||
g_Config.m_GfxLimitFps ^= 1;
|
||||
}
|
||||
|
||||
if(g_Config.m_GfxLimitFps > 0)
|
||||
{
|
||||
ScreenRight.HSplitTop(Spacing, 0, &ScreenRight);
|
||||
ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight);
|
||||
DoScrollbarOption(&g_Config.m_GfxMaxFps, &g_Config.m_GfxMaxFps,
|
||||
&Button, Localize("Max fps"), 144.0f, 30, 300);
|
||||
}
|
||||
}
|
||||
|
||||
if(Graphics()->GetNumScreens() > 1)
|
||||
{
|
||||
ScreenRight.HSplitTop(Spacing, 0, &ScreenRight);
|
||||
ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight);
|
||||
int Index = g_Config.m_GfxScreen;
|
||||
DoScrollbarOption(&g_Config.m_GfxScreen, &Index, &Button, Localize("Screen"), 110.0f, 0, Graphics()->GetNumScreens()-1);
|
||||
if(Index != g_Config.m_GfxScreen)
|
||||
Client()->SwitchWindowScreen(Index);
|
||||
}
|
||||
|
||||
// render texture menu
|
||||
Texture.HSplitTop(ButtonHeight, &Label, &Texture);
|
||||
Label.y += 2.0f;
|
||||
|
|
Loading…
Reference in a new issue