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. */
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
#include <immintrin.h> //_mm_pause
|
||||||
#include <stdlib.h> // qsort
|
#include <stdlib.h> // qsort
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
@ -254,6 +255,8 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD
|
||||||
m_RenderFrameTimeHigh = 0.0f;
|
m_RenderFrameTimeHigh = 0.0f;
|
||||||
m_RenderFrames = 0;
|
m_RenderFrames = 0;
|
||||||
m_LastRenderTime = time_get();
|
m_LastRenderTime = time_get();
|
||||||
|
m_LastCpuTime = time_get();
|
||||||
|
m_LastAvgCpuFrameTime = 0;
|
||||||
|
|
||||||
m_GameTickSpeed = SERVER_TICK_SPEED;
|
m_GameTickSpeed = SERVER_TICK_SPEED;
|
||||||
|
|
||||||
|
@ -1712,6 +1715,86 @@ void CClient::InitInterfaces()
|
||||||
m_Friends.Init();
|
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()
|
void CClient::Run()
|
||||||
{
|
{
|
||||||
m_LocalStartTime = time_get();
|
m_LocalStartTime = time_get();
|
||||||
|
@ -1902,13 +1985,16 @@ void CClient::Run()
|
||||||
|
|
||||||
Update();
|
Update();
|
||||||
|
|
||||||
if(!g_Config.m_GfxAsyncRender || m_pGraphics->IsIdle())
|
const bool SkipFrame = LimitFps();
|
||||||
|
|
||||||
|
if(!SkipFrame && (!g_Config.m_GfxAsyncRender || m_pGraphics->IsIdle()))
|
||||||
{
|
{
|
||||||
m_RenderFrames++;
|
m_RenderFrames++;
|
||||||
|
|
||||||
// update frametime
|
// update frametime
|
||||||
int64 Now = time_get();
|
int64 Now = time_get();
|
||||||
m_RenderFrameTime = (Now - m_LastRenderTime) / (float)time_freq();
|
m_RenderFrameTime = (Now - m_LastRenderTime) / (float)time_freq();
|
||||||
|
|
||||||
if(m_RenderFrameTime < m_RenderFrameTimeLow)
|
if(m_RenderFrameTime < m_RenderFrameTimeLow)
|
||||||
m_RenderFrameTimeLow = m_RenderFrameTime;
|
m_RenderFrameTimeLow = m_RenderFrameTime;
|
||||||
if(m_RenderFrameTime > m_RenderFrameTimeHigh)
|
if(m_RenderFrameTime > m_RenderFrameTimeHigh)
|
||||||
|
|
|
@ -86,6 +86,8 @@ class CClient : public IClient, public CDemoPlayer::IListner
|
||||||
IGraphics::CTextureHandle m_DebugFont;
|
IGraphics::CTextureHandle m_DebugFont;
|
||||||
|
|
||||||
int64 m_LastRenderTime;
|
int64 m_LastRenderTime;
|
||||||
|
int64 m_LastCpuTime;
|
||||||
|
float m_LastAvgCpuFrameTime;
|
||||||
float m_RenderFrameTimeLow;
|
float m_RenderFrameTimeLow;
|
||||||
float m_RenderFrameTimeHigh;
|
float m_RenderFrameTimeHigh;
|
||||||
int m_RenderFrames;
|
int m_RenderFrames;
|
||||||
|
@ -273,6 +275,7 @@ public:
|
||||||
void RegisterInterfaces();
|
void RegisterInterfaces();
|
||||||
void InitInterfaces();
|
void InitInterfaces();
|
||||||
|
|
||||||
|
bool LimitFps();
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,7 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern IEngineGraphics *CreateEngineGraphics();
|
extern IEngineGraphics *CreateEngineGraphics(); // NOTE: not used
|
||||||
extern IEngineGraphics *CreateEngineGraphicsThreaded();
|
extern IEngineGraphics *CreateEngineGraphicsThreaded();
|
||||||
|
|
||||||
#endif
|
#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(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(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(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")
|
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_GfxTextureQuality = g_Config.m_GfxTextureQuality;
|
||||||
static int s_GfxTextureCompression = g_Config.m_GfxTextureCompression;
|
static int s_GfxTextureCompression = g_Config.m_GfxTextureCompression;
|
||||||
|
|
||||||
CUIRect Label, Button, Screen, Texture, BottomView;
|
CUIRect Label, Button, ScreenLeft, ScreenRight, Texture, BottomView;
|
||||||
|
|
||||||
// cut view
|
// cut view
|
||||||
MainView.HSplitBottom(80.0f, &MainView, &BottomView);
|
MainView.HSplitBottom(80.0f, &MainView, &BottomView);
|
||||||
BottomView.HSplitTop(20.f, 0, &BottomView);
|
BottomView.HSplitTop(20.f, 0, &BottomView);
|
||||||
|
|
||||||
// render screen menu background
|
// render screen menu background
|
||||||
int NumOptions = g_Config.m_GfxFullscreen ? 3 : 4;
|
int NumOptions = 3 + (!g_Config.m_GfxFullscreen);
|
||||||
if(Graphics()->GetNumScreens() > 1)
|
if(Graphics()->GetNumScreens() > 1)
|
||||||
++NumOptions;
|
++NumOptions;
|
||||||
float ButtonHeight = 20.0f;
|
float ButtonHeight = 20.0f;
|
||||||
|
@ -1279,8 +1279,8 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
||||||
float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing;
|
float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing;
|
||||||
|
|
||||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||||
MainView.HSplitTop(BackgroundHeight, &Screen, &MainView);
|
MainView.HSplitTop(BackgroundHeight, &ScreenLeft, &MainView);
|
||||||
RenderTools()->DrawUIRect(&Screen, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
RenderTools()->DrawUIRect(&ScreenLeft, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||||
|
|
||||||
// render textures menu background
|
// render textures menu background
|
||||||
NumOptions = 3;
|
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);
|
RenderTools()->DrawUIRect(&Texture, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||||
|
|
||||||
// render screen menu
|
// render screen menu
|
||||||
Screen.HSplitTop(ButtonHeight, &Label, &Screen);
|
ScreenLeft.HSplitTop(ButtonHeight, &Label, &ScreenLeft);
|
||||||
Label.y += 2.0f;
|
Label.y += 2.0f;
|
||||||
UI()->DoLabel(&Label, Localize("Screen"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
UI()->DoLabel(&Label, Localize("Screen"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||||
|
|
||||||
Screen.HSplitTop(Spacing, 0, &Screen);
|
ScreenLeft.VSplitMid(&ScreenLeft, &ScreenRight);
|
||||||
Screen.HSplitTop(ButtonHeight, &Button, &Screen);
|
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;
|
static int s_ButtonGfxFullscreen = 0;
|
||||||
if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button))
|
if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button))
|
||||||
Client()->ToggleFullscreen();
|
Client()->ToggleFullscreen();
|
||||||
|
|
||||||
if(!g_Config.m_GfxFullscreen)
|
if(!g_Config.m_GfxFullscreen)
|
||||||
{
|
{
|
||||||
Screen.HSplitTop(Spacing, 0, &Screen);
|
ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft);
|
||||||
Screen.HSplitTop(ButtonHeight, &Button, &Screen);
|
ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft);
|
||||||
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
||||||
static int s_ButtonGfxBorderless = 0;
|
static int s_ButtonGfxBorderless = 0;
|
||||||
if(DoButton_CheckBox(&s_ButtonGfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button))
|
if(DoButton_CheckBox(&s_ButtonGfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button))
|
||||||
Client()->ToggleWindowBordered();
|
Client()->ToggleWindowBordered();
|
||||||
}
|
}
|
||||||
|
|
||||||
Screen.HSplitTop(Spacing, 0, &Screen);
|
ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft);
|
||||||
Screen.HSplitTop(ButtonHeight, &Button, &Screen);
|
ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft);
|
||||||
static int s_ButtonGfxVsync = 0;
|
static int s_ButtonGfxVsync = 0;
|
||||||
if(DoButton_CheckBox(&s_ButtonGfxVsync, Localize("V-Sync"), g_Config.m_GfxVsync, &Button))
|
if(DoButton_CheckBox(&s_ButtonGfxVsync, Localize("V-Sync"), g_Config.m_GfxVsync, &Button))
|
||||||
Client()->ToggleWindowVSync();
|
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
|
// FSAA button
|
||||||
{
|
{
|
||||||
Screen.HSplitTop(Spacing, 0, &Screen);
|
ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft);
|
||||||
Screen.HSplitTop(ButtonHeight, &Button, &Screen);
|
ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft);
|
||||||
RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||||
CUIRect Text;
|
CUIRect Text;
|
||||||
Button.VSplitLeft(ButtonHeight+5.0f, 0, &Button);
|
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
|
// render texture menu
|
||||||
Texture.HSplitTop(ButtonHeight, &Label, &Texture);
|
Texture.HSplitTop(ButtonHeight, &Label, &Texture);
|
||||||
Label.y += 2.0f;
|
Label.y += 2.0f;
|
||||||
|
|
Loading…
Reference in a new issue