2020-04-23 00:56:21 +08:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
# include "cbase.h"
# include "ifpspanel.h"
# include <vgui_controls/Panel.h>
# include "view.h"
# include <vgui/IVGui.h>
# include "VGuiMatSurface/IMatSystemSurface.h"
# include <vgui_controls/Controls.h>
# include <vgui/ISurface.h>
# include <vgui/IScheme.h>
# include <vgui/IPanel.h>
# include "materialsystem/imaterialsystemhardwareconfig.h"
# include "filesystem.h"
# include "../common/xbox/xboxstubs.h"
# include "steam/steam_api.h"
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
2022-03-02 04:00:42 +08:00
static ConVar cl_showfps ( " cl_showfps " , " 0 " , 0 , " Draw fps meter at top of screen (1 = fps, 2 = smooth fps) " ) ;
2020-04-23 00:56:21 +08:00
static ConVar cl_showpos ( " cl_showpos " , " 0 " , 0 , " Draw current position at top of screen " ) ;
static ConVar cl_showbattery ( " cl_showbattery " , " 0 " , 0 , " Draw current battery level at top of screen when on battery power " ) ;
extern bool g_bDisplayParticlePerformance ;
int GetParticlePerformance ( ) ;
//-----------------------------------------------------------------------------
// Purpose: Framerate indicator panel
//-----------------------------------------------------------------------------
class CFPSPanel : public vgui : : Panel
{
DECLARE_CLASS_SIMPLE ( CFPSPanel , vgui : : Panel ) ;
public :
CFPSPanel ( vgui : : VPANEL parent ) ;
virtual ~ CFPSPanel ( void ) ;
virtual void ApplySchemeSettings ( vgui : : IScheme * pScheme ) ;
virtual void Paint ( ) ;
virtual void OnTick ( void ) ;
virtual bool ShouldDraw ( void ) ;
protected :
MESSAGE_FUNC_INT_INT ( OnScreenSizeChanged , " OnScreenSizeChanged " , oldwide , oldtall ) ;
private :
void ComputeSize ( void ) ;
void InitAverages ( )
{
m_AverageFPS = - 1 ;
m_lastRealTime = - 1 ;
m_high = - 1 ;
m_low = - 1 ;
}
vgui : : HFont m_hFont ;
float m_AverageFPS ;
float m_lastRealTime ;
int m_high ;
int m_low ;
bool m_bLastDraw ;
int m_BatteryPercent ;
float m_lastBatteryPercent ;
} ;
# define FPS_PANEL_WIDTH 300
//-----------------------------------------------------------------------------
// Purpose:
// Input : *parent -
//-----------------------------------------------------------------------------
CFPSPanel : : CFPSPanel ( vgui : : VPANEL parent ) : BaseClass ( NULL , " CFPSPanel " )
{
SetParent ( parent ) ;
SetVisible ( false ) ;
SetCursor ( null ) ;
SetFgColor ( Color ( 0 , 0 , 0 , 255 ) ) ;
SetPaintBackgroundEnabled ( false ) ;
m_hFont = 0 ;
m_BatteryPercent = - 1 ;
m_lastBatteryPercent = - 1.0f ;
ComputeSize ( ) ;
vgui : : ivgui ( ) - > AddTickSignal ( GetVPanel ( ) , 250 ) ;
m_bLastDraw = false ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CFPSPanel : : ~ CFPSPanel ( void )
{
}
//-----------------------------------------------------------------------------
// Purpose: Updates panel to handle the new screen size
//-----------------------------------------------------------------------------
void CFPSPanel : : OnScreenSizeChanged ( int iOldWide , int iOldTall )
{
BaseClass : : OnScreenSizeChanged ( iOldWide , iOldTall ) ;
ComputeSize ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Computes panel's desired size and position
//-----------------------------------------------------------------------------
void CFPSPanel : : ComputeSize ( void )
{
int wide , tall ;
vgui : : ipanel ( ) - > GetSize ( GetVParent ( ) , wide , tall ) ;
int x = wide - FPS_PANEL_WIDTH ;
int y = 0 ;
if ( IsX360 ( ) )
{
x - = XBOX_MINBORDERSAFE * wide ;
y + = XBOX_MINBORDERSAFE * tall ;
}
SetPos ( x , y ) ;
SetSize ( FPS_PANEL_WIDTH , 4 * vgui : : surface ( ) - > GetFontTall ( m_hFont ) + 8 ) ;
}
void CFPSPanel : : ApplySchemeSettings ( vgui : : IScheme * pScheme )
{
BaseClass : : ApplySchemeSettings ( pScheme ) ;
m_hFont = pScheme - > GetFont ( " DefaultFixedOutline " ) ;
Assert ( m_hFont ) ;
ComputeSize ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFPSPanel : : OnTick ( void )
{
bool bVisible = ShouldDraw ( ) ;
if ( IsVisible ( ) ! = bVisible )
{
SetVisible ( bVisible ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CFPSPanel : : ShouldDraw ( void )
{
if ( g_bDisplayParticlePerformance )
return true ;
if ( ( ! cl_showfps . GetInt ( ) | | ( gpGlobals - > absoluteframetime < = 0 ) ) & &
( ! cl_showpos . GetInt ( ) ) )
{
m_bLastDraw = false ;
return false ;
}
if ( ! m_bLastDraw )
{
m_bLastDraw = true ;
InitAverages ( ) ;
}
return true ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void GetFPSColor ( int nFps , unsigned char ucColor [ 3 ] )
{
ucColor [ 0 ] = 255 ; ucColor [ 1 ] = 0 ; ucColor [ 2 ] = 0 ;
int nFPSThreshold1 = 20 ;
int nFPSThreshold2 = 15 ;
if ( IsPC ( ) & & g_pMaterialSystemHardwareConfig - > GetDXSupportLevel ( ) > = 95 )
{
nFPSThreshold1 = 60 ;
nFPSThreshold2 = 50 ;
}
else if ( IsX360 ( ) | | g_pMaterialSystemHardwareConfig - > GetDXSupportLevel ( ) > = 90 )
{
nFPSThreshold1 = 30 ;
nFPSThreshold2 = 25 ;
}
if ( nFps > = nFPSThreshold1 )
{
ucColor [ 0 ] = 0 ;
ucColor [ 1 ] = 255 ;
}
else if ( nFps > = nFPSThreshold2 )
{
ucColor [ 1 ] = 255 ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
//-----------------------------------------------------------------------------
void CFPSPanel : : Paint ( )
{
int i = 0 ;
int x = 2 ;
if ( g_bDisplayParticlePerformance )
{
int nPerf = GetParticlePerformance ( ) ;
if ( nPerf )
{
unsigned char ucColor [ 3 ] = { 0 , 255 , 0 } ;
g_pMatSystemSurface - > DrawColoredText (
m_hFont , x , 42 ,
ucColor [ 0 ] , ucColor [ 1 ] , ucColor [ 2 ] ,
255 , " Particle Performance Metric : %d " , ( nPerf + 50 ) / 100 ) ;
}
}
float realFrameTime = gpGlobals - > realtime - m_lastRealTime ;
if ( cl_showfps . GetInt ( ) & & realFrameTime > 0.0 )
{
if ( m_lastRealTime ! = - 1.0f )
{
i + + ;
int nFps = - 1 ;
unsigned char ucColor [ 3 ] ;
if ( cl_showfps . GetInt ( ) = = 2 )
{
const float NewWeight = 0.1f ;
float NewFrame = 1.0f / realFrameTime ;
if ( m_AverageFPS < 0.0f )
{
m_AverageFPS = NewFrame ;
m_high = ( int ) m_AverageFPS ;
m_low = ( int ) m_AverageFPS ;
}
else
{
m_AverageFPS * = ( 1.0f - NewWeight ) ;
m_AverageFPS + = ( ( NewFrame ) * NewWeight ) ;
}
int NewFrameInt = ( int ) NewFrame ;
if ( NewFrameInt < m_low ) m_low = NewFrameInt ;
if ( NewFrameInt > m_high ) m_high = NewFrameInt ;
nFps = static_cast < int > ( m_AverageFPS ) ;
float frameMS = realFrameTime * 1000.0f ;
GetFPSColor ( nFps , ucColor ) ;
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x , 2 , ucColor [ 0 ] , ucColor [ 1 ] , ucColor [ 2 ] , 255 , " %3i fps (%3i, %3i) %.1f ms on %s " , nFps , m_low , m_high , frameMS , engine - > GetLevelName ( ) ) ;
}
else
{
m_AverageFPS = - 1 ;
nFps = static_cast < int > ( 1.0f / realFrameTime ) ;
GetFPSColor ( nFps , ucColor ) ;
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x , 2 , ucColor [ 0 ] , ucColor [ 1 ] , ucColor [ 2 ] , 255 , " %3i fps on %s " , nFps , engine - > GetLevelName ( ) ) ;
}
}
}
m_lastRealTime = gpGlobals - > realtime ;
int nShowPosMode = cl_showpos . GetInt ( ) ;
if ( nShowPosMode > 0 )
{
Vector vecOrigin = MainViewOrigin ( ) ;
QAngle angles = MainViewAngles ( ) ;
if ( nShowPosMode = = 2 )
{
C_BasePlayer * pPlayer = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( pPlayer )
{
vecOrigin = pPlayer - > GetAbsOrigin ( ) ;
angles = pPlayer - > GetAbsAngles ( ) ;
}
}
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x , 2 + i * ( vgui : : surface ( ) - > GetFontTall ( m_hFont ) + 2 ) ,
255 , 255 , 255 , 255 ,
" pos: %.02f %.02f %.02f " ,
vecOrigin . x , vecOrigin . y , vecOrigin . z ) ;
i + + ;
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x , 2 + i * ( vgui : : surface ( ) - > GetFontTall ( m_hFont ) + 2 ) ,
255 , 255 , 255 , 255 ,
" ang: %.02f %.02f %.02f " ,
angles . x , angles . y , angles . z ) ;
i + + ;
Vector vel ( 0 , 0 , 0 ) ;
C_BasePlayer * player = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( player )
{
vel = player - > GetLocalVelocity ( ) ;
}
2022-08-20 04:19:53 +08:00
if ( nShowPosMode > 1 )
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x , 2 + i * ( vgui : : surface ( ) - > GetFontTall ( m_hFont ) + 2 ) ,
255 , 255 , 255 , 255 ,
" vel: %.2f %.2f %.2f " ,
vel . x , vel . y , vel . z ) ;
else
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x , 2 + i * ( vgui : : surface ( ) - > GetFontTall ( m_hFont ) + 2 ) ,
2020-04-23 00:56:21 +08:00
255 , 255 , 255 , 255 ,
" vel: %.2f " ,
vel . Length ( ) ) ;
}
2022-08-20 04:19:53 +08:00
2020-04-23 00:56:21 +08:00
if ( cl_showbattery . GetInt ( ) > 0 )
{
if ( steamapicontext & & steamapicontext - > SteamUtils ( ) & &
( m_lastBatteryPercent = = - 1.0f | | ( gpGlobals - > realtime - m_lastBatteryPercent ) > 10.0f ) )
{
m_BatteryPercent = steamapicontext - > SteamUtils ( ) - > GetCurrentBatteryPower ( ) ;
m_lastBatteryPercent = gpGlobals - > realtime ;
}
if ( m_BatteryPercent > 0 )
{
if ( m_BatteryPercent = = 255 )
{
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x , 2 + i * ( vgui : : surface ( ) - > GetFontTall ( m_hFont ) + 2 ) ,
255 , 255 , 255 , 255 , " battery: On AC " ) ;
}
else
{
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x , 2 + i * ( vgui : : surface ( ) - > GetFontTall ( m_hFont ) + 2 ) ,
255 , 255 , 255 , 255 , " battery: %d%% " , m_BatteryPercent ) ;
}
}
}
}
class CFPS : public IFPSPanel
{
private :
CFPSPanel * fpsPanel ;
public :
CFPS ( void )
{
fpsPanel = NULL ;
}
void Create ( vgui : : VPANEL parent )
{
fpsPanel = new CFPSPanel ( parent ) ;
}
void Destroy ( void )
{
if ( fpsPanel )
{
fpsPanel - > SetParent ( ( vgui : : Panel * ) NULL ) ;
2022-03-02 04:00:42 +08:00
delete fpsPanel ;
2020-04-23 00:56:21 +08:00
fpsPanel = NULL ;
}
}
} ;
static CFPS g_FPSPanel ;
IFPSPanel * fps = ( IFPSPanel * ) & g_FPSPanel ;
# if defined( TRACK_BLOCKING_IO ) && !defined( _RETAIL )
static ConVar cl_blocking_threshold ( " cl_blocking_threshold " , " 0.000 " , 0 , " If file ops take more than this amount of time, add to 'spewblocking' history list " ) ;
void ShowBlockingChanged ( ConVar * var , char const * pOldString )
{
filesystem - > EnableBlockingFileAccessTracking ( var - > GetBool ( ) ) ;
}
static ConVar cl_showblocking ( " cl_showblocking " , " 0 " , 0 , " Show blocking i/o on top of fps panel " , ShowBlockingChanged ) ;
static ConVar cl_blocking_recentsize ( " cl_blocking_recentsize " , " 40 " , 0 , " Number of items to store in recent spew history. " ) ;
//-----------------------------------------------------------------------------
// Purpose: blocking i/o indicator
//-----------------------------------------------------------------------------
class CBlockingFileIOPanel : public vgui : : Panel
{
typedef vgui : : Panel BaseClass ;
public :
CBlockingFileIOPanel ( vgui : : VPANEL parent ) ;
virtual ~ CBlockingFileIOPanel ( void ) ;
virtual void ApplySchemeSettings ( vgui : : IScheme * pScheme ) ;
virtual void Paint ( ) ;
virtual void OnTick ( void ) ;
virtual bool ShouldDraw ( void ) ;
void SpewRecent ( ) ;
private :
void DrawIOTime ( int x , int y , int w , int h , int slot , char const * label , const Color & clr ) ;
vgui : : HFont m_hFont ;
struct Graph_t
{
float m_flCurrent ;
float m_flHistory ;
float m_flHistorySpike ;
float m_flLatchTime ;
CUtlSymbol m_LastFile ;
} ;
Graph_t m_History [ FILESYSTEM_BLOCKING_NUMBINS ] ;
struct RecentPeaks_t
{
float time ;
CUtlSymbol fileName ;
float elapsed ;
byte reason ;
byte ioType ;
} ;
CUtlLinkedList < RecentPeaks_t , unsigned short > m_Recent ;
void SpewItem ( const RecentPeaks_t & item ) ;
} ;
# define IO_PANEL_WIDTH 400
# define IO_DECAY_FRAC 0.95f
//-----------------------------------------------------------------------------
// Purpose:
// Input : *parent -
//-----------------------------------------------------------------------------
CBlockingFileIOPanel : : CBlockingFileIOPanel ( vgui : : VPANEL parent ) : BaseClass ( NULL , " CBlockingFileIOPanel " )
{
SetParent ( parent ) ;
int wide , tall ;
vgui : : ipanel ( ) - > GetSize ( parent , wide , tall ) ;
int x = 2 ;
int y = 100 ;
if ( IsX360 ( ) )
{
x + = XBOX_MAXBORDERSAFE * wide ;
y + = XBOX_MAXBORDERSAFE * tall ;
}
SetPos ( x , y ) ;
SetSize ( IO_PANEL_WIDTH , 140 ) ;
SetVisible ( false ) ;
SetCursor ( null ) ;
SetFgColor ( Color ( 0 , 0 , 0 , 255 ) ) ;
SetPaintBackgroundEnabled ( false ) ;
m_hFont = 0 ;
vgui : : ivgui ( ) - > AddTickSignal ( GetVPanel ( ) , 250 ) ;
SetZPos ( 1000 ) ;
Q_memset ( m_History , 0 , sizeof ( m_History ) ) ;
SetPaintBackgroundEnabled ( false ) ;
SetPaintBorderEnabled ( false ) ;
MakePopup ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CBlockingFileIOPanel : : ~ CBlockingFileIOPanel ( void )
{
}
void CBlockingFileIOPanel : : ApplySchemeSettings ( vgui : : IScheme * pScheme )
{
BaseClass : : ApplySchemeSettings ( pScheme ) ;
m_hFont = pScheme - > GetFont ( " Default " ) ;
Assert ( m_hFont ) ;
SetKeyBoardInputEnabled ( false ) ;
SetMouseInputEnabled ( false ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlockingFileIOPanel : : OnTick ( void )
{
bool bVisible = ShouldDraw ( ) ;
if ( IsVisible ( ) ! = bVisible )
{
SetVisible ( bVisible ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CBlockingFileIOPanel : : ShouldDraw ( void )
{
if ( ! cl_showblocking . GetInt ( ) )
{
return false ;
}
return true ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
//-----------------------------------------------------------------------------
void CBlockingFileIOPanel : : Paint ( )
{
int x = 2 ;
int maxRecent = clamp ( 0 , cl_blocking_recentsize . GetInt ( ) , 1000 ) ;
int bval = cl_showblocking . GetInt ( ) ;
if ( bval > 0 )
{
IBlockingFileItemList * list = filesystem - > RetrieveBlockingFileAccessInfo ( ) ;
if ( list )
{
int i ;
int c = ARRAYSIZE ( m_History ) ;
for ( i = 0 ; i < c ; + + i )
{
m_History [ i ] . m_flCurrent = 0.0f ;
}
// Grab mutex (prevents async thread from filling in even more data...)
list - > LockMutex ( ) ;
{
for ( int j = list - > First ( ) ; j ! = list - > InvalidIndex ( ) ; j = list - > Next ( j ) )
{
const FileBlockingItem & item = list - > Get ( j ) ;
m_History [ item . m_ItemType ] . m_flCurrent + = item . m_flElapsed ;
RecentPeaks_t recent ;
recent . time = gpGlobals - > realtime ;
recent . elapsed = item . m_flElapsed ;
recent . fileName = item . GetFileName ( ) ;
recent . reason = item . m_ItemType ;
recent . ioType = item . m_nAccessType ;
while ( m_Recent . Count ( ) > maxRecent )
{
m_Recent . Remove ( m_Recent . Head ( ) ) ;
}
m_Recent . AddToTail ( recent ) ;
m_History [ item . m_ItemType ] . m_LastFile = item . GetFileName ( ) ;
// Only care about time consuming synch or async blocking calls
if ( item . m_ItemType = = FILESYSTEM_BLOCKING_SYNCHRONOUS | |
item . m_ItemType = = FILESYSTEM_BLOCKING_ASYNCHRONOUS_BLOCK )
{
if ( item . m_flElapsed > cl_blocking_threshold . GetFloat ( ) )
{
SpewItem ( recent ) ;
}
}
}
list - > Reset ( ) ;
}
// Finished
list - > UnlockMutex ( ) ;
// Now draw some bars...
int itemHeight = ( vgui : : surface ( ) - > GetFontTall ( m_hFont ) + 2 ) ;
int y = 2 ;
int w = GetWide ( ) ;
DrawIOTime ( x , y , w , itemHeight , FILESYSTEM_BLOCKING_SYNCHRONOUS , " Synchronous " , Color ( 255 , 0 , 0 , 255 ) ) ;
y + = 2 * ( itemHeight + 2 ) ;
DrawIOTime ( x , y , w , itemHeight , FILESYSTEM_BLOCKING_ASYNCHRONOUS_BLOCK , " Async Block " , Color ( 255 , 100 , 0 , 255 ) ) ;
y + = 2 * ( itemHeight + 2 ) ;
DrawIOTime ( x , y , w , itemHeight , FILESYSTEM_BLOCKING_CALLBACKTIMING , " Callback " , Color ( 255 , 255 , 0 , 255 ) ) ;
y + = 2 * ( itemHeight + 2 ) ;
DrawIOTime ( x , y , w , itemHeight , FILESYSTEM_BLOCKING_ASYNCHRONOUS , " Asynchronous " , Color ( 0 , 255 , 0 , 255 ) ) ;
for ( i = 0 ; i < c ; + + i )
{
if ( m_History [ i ] . m_flCurrent > m_History [ i ] . m_flHistory )
{
m_History [ i ] . m_flHistory = m_History [ i ] . m_flCurrent ;
m_History [ i ] . m_flHistorySpike = m_History [ i ] . m_flCurrent ;
m_History [ i ] . m_flLatchTime = gpGlobals - > realtime ;
}
else
{
// After this long, start to decay the previous history value
if ( gpGlobals - > realtime > m_History [ i ] . m_flLatchTime + 1.0f )
{
m_History [ i ] . m_flHistory = m_History [ i ] . m_flHistory * IO_DECAY_FRAC + ( 1.0f - IO_DECAY_FRAC ) * m_History [ i ] . m_flCurrent ;
}
}
}
}
}
}
static ConVar cl_blocking_msec ( " cl_blocking_msec " , " 100 " , 0 , " Vertical scale of blocking graph in milliseconds " ) ;
static const char * GetBlockReason ( int reason )
{
switch ( reason )
{
case FILESYSTEM_BLOCKING_SYNCHRONOUS :
return " Synchronous " ;
case FILESYSTEM_BLOCKING_ASYNCHRONOUS :
return " Asynchronous " ;
case FILESYSTEM_BLOCKING_CALLBACKTIMING :
return " Async Callback " ;
case FILESYSTEM_BLOCKING_ASYNCHRONOUS_BLOCK :
return " Async Blocked " ;
}
return " ??? " ;
}
static const char * GetIOType ( int iotype )
{
if ( FileBlockingItem : : FB_ACCESS_APPEND = = iotype )
{
return " Append " ;
}
else if ( FileBlockingItem : : FB_ACCESS_CLOSE = = iotype )
{
return " Close " ;
}
else if ( FileBlockingItem : : FB_ACCESS_OPEN = = iotype )
{
return " Open " ;
}
else if ( FileBlockingItem : : FB_ACCESS_READ = = iotype )
{
return " Read " ;
}
else if ( FileBlockingItem : : FB_ACCESS_SIZE = = iotype )
{
return " Size " ;
}
else if ( FileBlockingItem : : FB_ACCESS_WRITE = = iotype )
{
return " Write " ;
}
return " ??? " ;
}
void CBlockingFileIOPanel : : SpewItem ( const RecentPeaks_t & item )
{
switch ( item . reason )
{
default :
Assert ( 0 ) ;
// break; -- intentionally fall through
case FILESYSTEM_BLOCKING_ASYNCHRONOUS :
case FILESYSTEM_BLOCKING_CALLBACKTIMING :
Msg ( " %8.3f %16.16s i/o [%6.6s] took %8.3f msec: %33.33s \n " ,
item . time ,
GetBlockReason ( item . reason ) ,
GetIOType ( item . ioType ) ,
item . elapsed * 1000.0f ,
item . fileName . String ( )
) ;
break ;
case FILESYSTEM_BLOCKING_SYNCHRONOUS :
case FILESYSTEM_BLOCKING_ASYNCHRONOUS_BLOCK :
Warning ( " %8.3f %16.16s i/o [%6.6s] took %8.3f msec: %33.33s \n " ,
item . time ,
GetBlockReason ( item . reason ) ,
GetIOType ( item . ioType ) ,
item . elapsed * 1000.0f ,
item . fileName . String ( )
) ;
break ;
}
}
void CBlockingFileIOPanel : : SpewRecent ( )
{
FOR_EACH_LL ( m_Recent , i )
{
const RecentPeaks_t & item = m_Recent [ i ] ;
SpewItem ( item ) ;
}
}
void CBlockingFileIOPanel : : DrawIOTime ( int x , int y , int w , int h , int slot , char const * label , const Color & clr )
{
float t = m_History [ slot ] . m_flCurrent ;
float history = m_History [ slot ] . m_flHistory ;
float latchedtime = m_History [ slot ] . m_flLatchTime ;
float historyspike = m_History [ slot ] . m_flHistorySpike ;
// 250 msec is considered a huge spike
float maxTime = cl_blocking_msec . GetFloat ( ) * 0.001f ;
if ( maxTime < 0.000001f )
return ;
float frac = clamp ( t / maxTime , 0.0f , 1.0f ) ;
float hfrac = clamp ( history / maxTime , 0.0f , 1.0f ) ;
float spikefrac = clamp ( historyspike / maxTime , 0.0f , 1.0f ) ;
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x + 2 , y + 1 ,
clr [ 0 ] , clr [ 1 ] , clr [ 2 ] , clr [ 3 ] ,
" %s " ,
label ) ;
int textWidth = 95 ;
x + = textWidth ;
w - = ( textWidth + 5 ) ;
int prevFileWidth = 140 ;
w - = prevFileWidth ;
bool bDrawHistorySpike = false ;
if ( m_History [ slot ] . m_LastFile . IsValid ( ) & &
( gpGlobals - > realtime < latchedtime + 10.0f ) )
{
bDrawHistorySpike = true ;
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x + w + 5 , y + 1 ,
255 , 255 , 255 , 200 , " [%8.3f ms] " , m_History [ slot ] . m_flHistorySpike * 1000.0f ) ;
g_pMatSystemSurface - > DrawColoredText ( m_hFont , x , y + h + 1 ,
255 , 255 , 255 , 200 , " %s " , m_History [ slot ] . m_LastFile . String ( ) ) ;
}
y + = 2 ;
h - = 4 ;
int barWide = ( int ) ( w * frac + 0.5f ) ;
int historyWide = ( int ) ( w * hfrac + 0.5f ) ;
int spikeWide = ( int ) ( w * spikefrac + 0.5f ) ;
int useWide = MAX ( barWide , historyWide ) ;
vgui : : surface ( ) - > DrawSetColor ( Color ( 0 , 0 , 0 , 31 ) ) ;
vgui : : surface ( ) - > DrawFilledRect ( x , y , x + w , y + h ) ;
vgui : : surface ( ) - > DrawSetColor ( Color ( 255 , 255 , 255 , 128 ) ) ;
vgui : : surface ( ) - > DrawOutlinedRect ( x , y , x + w , y + h ) ;
vgui : : surface ( ) - > DrawSetColor ( clr ) ;
vgui : : surface ( ) - > DrawFilledRect ( x + 1 , y + 1 , x + useWide , y + h - 1 ) ;
if ( bDrawHistorySpike )
{
vgui : : surface ( ) - > DrawSetColor ( Color ( 255 , 255 , 255 , 192 ) ) ;
vgui : : surface ( ) - > DrawFilledRect ( x + spikeWide , y + 1 , x + spikeWide + 1 , y + h - 1 ) ;
}
}
class CBlockingFileIO : public IShowBlockingPanel
{
private :
CBlockingFileIOPanel * ioPanel ;
public :
CBlockingFileIO ( void )
{
ioPanel = NULL ;
}
void Create ( vgui : : VPANEL parent )
{
ioPanel = new CBlockingFileIOPanel ( parent ) ;
}
void Destroy ( void )
{
if ( ioPanel )
{
ioPanel - > SetParent ( ( vgui : : Panel * ) NULL ) ;
2022-03-02 04:00:42 +08:00
delete ioPanel ;
2020-04-23 00:56:21 +08:00
ioPanel = NULL ;
}
}
void Spew ( )
{
if ( ioPanel )
{
ioPanel - > SpewRecent ( ) ;
}
}
} ;
static CBlockingFileIO g_IOPanel ;
IShowBlockingPanel * iopanel = ( IShowBlockingPanel * ) & g_IOPanel ;
CON_COMMAND ( spewblocking , " Spew current blocking file list. " )
{
g_IOPanel . Spew ( ) ;
}
# endif // TRACK_BLOCKING_IO