From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/game/client/vgui_fpspanel.cpp | 1610 +++++++++++++++++----------------- 1 file changed, 805 insertions(+), 805 deletions(-) (limited to 'mp/src/game/client/vgui_fpspanel.cpp') diff --git a/mp/src/game/client/vgui_fpspanel.cpp b/mp/src/game/client/vgui_fpspanel.cpp index a1e7d282..a44dde34 100644 --- a/mp/src/game/client/vgui_fpspanel.cpp +++ b/mp/src/game/client/vgui_fpspanel.cpp @@ -1,805 +1,805 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=====================================================================================// - -#include "cbase.h" -#include "ifpspanel.h" -#include -#include "view.h" -#include -#include "VGuiMatSurface/IMatSystemSurface.h" -#include -#include -#include -#include -#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" - -static ConVar cl_showfps( "cl_showfps", "0", 0, "Draw fps meter at top of screen (1 = fps, 2 = smooth fps)" ); -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; - nFPSThreshold1 = 50; - } - else if ( IsX360() || g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 90 ) - { - nFPSThreshold1 = 30; - nFPSThreshold1 = 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( 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( 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(); - } - - g_pMatSystemSurface->DrawColoredText( m_hFont, x, 2 + i * ( vgui::surface()->GetFontTall( m_hFont ) + 2 ), - 255, 255, 255, 255, - "vel: %.2f", - vel.Length() ); - } - - 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 ); - delete fpsPanel; - 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 ); - delete ioPanel; - 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 +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=====================================================================================// + +#include "cbase.h" +#include "ifpspanel.h" +#include +#include "view.h" +#include +#include "VGuiMatSurface/IMatSystemSurface.h" +#include +#include +#include +#include +#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" + +static ConVar cl_showfps( "cl_showfps", "0", 0, "Draw fps meter at top of screen (1 = fps, 2 = smooth fps)" ); +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; + nFPSThreshold1 = 50; + } + else if ( IsX360() || g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 90 ) + { + nFPSThreshold1 = 30; + nFPSThreshold1 = 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( 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( 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(); + } + + g_pMatSystemSurface->DrawColoredText( m_hFont, x, 2 + i * ( vgui::surface()->GetFontTall( m_hFont ) + 2 ), + 255, 255, 255, 255, + "vel: %.2f", + vel.Length() ); + } + + 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 ); + delete fpsPanel; + 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 ); + delete ioPanel; + 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 -- cgit v1.2.3