eb35a9b9af
- Use fast data types where possible so the compiler can optimize for speed based on platform
- for example, 128 bits might be fastest on ARM
- good future-proofing
- Refactor GetTimeSinceStart() to be a bit faster
- multiplication is much faster than division
- Implement a RageTimer method to get the seconds value as a plain int, for the places which cast the seconds value to an int
- Changing from GetTimeSinceStartFast() to GetTimeSinceStart() where accuracy is important
- Changing from GetTimeSinceStart() to GetUsecsSinceStart() for timestamp diffs
- Adjust RageThreads to accomodate an unsigned timestamp value
- a constant for the maximum value of `uint_fast64_t` replaces `-1` to accommodate the change from signed to unsigned for the `locked_at` variable
- i have separate constants for `std::numeric_limits<std::uint_fast64_t>::max()` and `static_cast<std::uint_fast64_t>(-1)`, so the reader understands -1 represents an error code, though they evaluate to the same value, so i could remove one of the two
- Add two methods to calculate the MMSSMsMs / MMSSMsMsMs time value from usecs directly instead of inferring it from a seconds value, in RageUtil
- Use a similar counter/modulo based method for WheelNotifyIcon, similar to what i did for text_glow in NoteField in 2eeee03
- Make `g_iStartTime` static const for safety
Rename two timer functions:
GetUsecsSinceStart -> GetTimeSinceStartMicroseconds
GetMicrosecondsSinceStart -> GetSystemTimeAsMicroseconds
Remove std prefix from uint_fast64_t
169 lines
5.6 KiB
C++
169 lines
5.6 KiB
C++
#include "global.h"
|
|
#include "ScreenStatsOverlay.h"
|
|
#include "ActorUtil.h"
|
|
#include "PrefsManager.h"
|
|
#include "RageDisplay.h"
|
|
#include "RageLog.h"
|
|
#include "ScreenDimensions.h"
|
|
|
|
REGISTER_SCREEN_CLASS( ScreenStatsOverlay );
|
|
|
|
void ScreenStatsOverlay::Init()
|
|
{
|
|
Screen::Init();
|
|
|
|
m_textStats.LoadFromFont( THEME->GetPathF(m_sName,"stats") );
|
|
m_textStats.SetName( "Stats" );
|
|
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_textStats );
|
|
this->AddChild( &m_textStats );
|
|
|
|
/* "Was that a skip?" This displays a message when an update takes
|
|
* abnormally long, to quantify skips more precisely, verify them
|
|
* when they're subtle, and show the time it happened, so you can pinpoint
|
|
* the time in the log. */
|
|
m_LastSkip = 0;
|
|
|
|
SHOW_SKIPS.Load( m_sName, "ShowSkips" );
|
|
if( SHOW_SKIPS )
|
|
{
|
|
SKIP_X.Load( m_sName, "SkipX" );
|
|
SKIP_Y.Load( m_sName, "SkipY" );
|
|
SKIP_SPACING_Y.Load( m_sName, "SkipSpacingY" );
|
|
SKIP_WIDTH.Load( m_sName, "SkipWidth" );
|
|
|
|
RectF rectSkips = RectF(
|
|
SKIP_X-SKIP_WIDTH/2,
|
|
SKIP_Y-(SKIP_SPACING_Y*NUM_SKIPS_TO_SHOW)/2 - 10,
|
|
SKIP_X+SKIP_WIDTH/2,
|
|
SKIP_Y+(SKIP_SPACING_Y*NUM_SKIPS_TO_SHOW)/2 + 10
|
|
);
|
|
m_quadSkipBackground.StretchTo( rectSkips );
|
|
m_quadSkipBackground.SetDiffuse( RageColor(0,0,0,0.4f) );
|
|
this->AddChild(&m_quadSkipBackground);
|
|
|
|
for( int i=0; i<NUM_SKIPS_TO_SHOW; i++ )
|
|
{
|
|
/* This is somewhat big. Let's put it on the right side, where it'll
|
|
* obscure the 2P side during gameplay; there's nowhere to put it that
|
|
* doesn't obscure something, and it's just a diagnostic. */
|
|
m_textSkips[i].LoadFromFont( THEME->GetPathF("Common","normal") );
|
|
m_textSkips[i].SetX( SKIP_X );
|
|
m_textSkips[i].SetY(
|
|
SCALE( i, 0, NUM_SKIPS_TO_SHOW-1, rectSkips.top + 10, rectSkips.bottom - 10 )
|
|
);
|
|
m_textSkips[i].SetDiffuse( RageColor(1,1,1,0) );
|
|
m_textSkips[i].SetShadowLength( 0 );
|
|
this->AddChild( &m_textSkips[i] );
|
|
}
|
|
}
|
|
|
|
this->SubscribeToMessage( "ShowStatsChanged" );
|
|
}
|
|
|
|
void ScreenStatsOverlay::Update( float fDeltaTime )
|
|
{
|
|
Screen::Update(fDeltaTime);
|
|
|
|
static bool bShowStatsWasOn = false;
|
|
|
|
if( PREFSMAN->m_bShowStats && !bShowStatsWasOn )
|
|
{
|
|
// Reset skip timer when we toggle Stats on so we don't show a large skip
|
|
// from the span when stats were turned off.
|
|
m_timerSkip.Touch();
|
|
}
|
|
bShowStatsWasOn = PREFSMAN->m_bShowStats.Get();
|
|
|
|
this->SetVisible( PREFSMAN->m_bShowStats );
|
|
if( PREFSMAN->m_bShowStats )
|
|
{
|
|
m_textStats.SetText( DISPLAY->GetStats() );
|
|
if ( SHOW_SKIPS )
|
|
UpdateSkips();
|
|
}
|
|
}
|
|
|
|
void ScreenStatsOverlay::AddTimestampLine( const RString &txt, const RageColor &color )
|
|
{
|
|
m_textSkips[m_LastSkip].SetText( txt );
|
|
m_textSkips[m_LastSkip].StopTweening();
|
|
m_textSkips[m_LastSkip].SetDiffuse( RageColor(1,1,1,1) );
|
|
m_textSkips[m_LastSkip].BeginTweening( 0.2f );
|
|
m_textSkips[m_LastSkip].SetDiffuse( color );
|
|
m_textSkips[m_LastSkip].BeginTweening( 3.0f );
|
|
m_textSkips[m_LastSkip].BeginTweening( 0.2f );
|
|
m_textSkips[m_LastSkip].SetDiffuse( RageColor(1,1,1,0) );
|
|
|
|
m_LastSkip++;
|
|
m_LastSkip %= NUM_SKIPS_TO_SHOW;
|
|
}
|
|
|
|
void ScreenStatsOverlay::UpdateSkips()
|
|
{
|
|
/* Use our own timer, so we ignore `/tab. */
|
|
const float UpdateTime = m_timerSkip.GetDeltaTime();
|
|
|
|
/* FPS is 0 for a little while after we load a screen; don't report
|
|
* during this time. Do clear the timer, though, so we don't report
|
|
* a big "skip" after this period passes. */
|
|
if( !DISPLAY->GetFPS() )
|
|
return;
|
|
|
|
/* We want to display skips. We expect to get updates of about 1.0/FPS ms. */
|
|
const float ExpectedUpdate = 1.0f / DISPLAY->GetFPS();
|
|
|
|
/* These are thresholds for severity of skips. The smallest
|
|
* is slightly above expected, to tolerate normal jitter. */
|
|
const float Thresholds[] =
|
|
{
|
|
ExpectedUpdate * 2.0f, ExpectedUpdate * 4.0f, 0.1f, -1
|
|
};
|
|
|
|
int skip = 0;
|
|
while( Thresholds[skip] != -1 && UpdateTime > Thresholds[skip] )
|
|
skip++;
|
|
|
|
if( skip )
|
|
{
|
|
RString sTime( MicrosecondsToMMSSMsMs(RageTimer::GetTimeSinceStartMicroseconds()) );
|
|
|
|
static const RageColor colors[] =
|
|
{
|
|
RageColor(0,0,0,0), /* unused */
|
|
RageColor(1.0f,1.0f,1.0f,1), /* white*/
|
|
RageColor(1.0f,1.0f,0.0f,1), /* yellow */
|
|
RageColor(1.0f,0.4f,0.4f,1) /* light red */
|
|
};
|
|
|
|
AddTimestampLine( ssprintf("%s: %.0fms (%.0f)", sTime.c_str(), 1000*UpdateTime, UpdateTime/ExpectedUpdate), colors[skip] );
|
|
|
|
if( PREFSMAN->m_bLogSkips )
|
|
LOG->Trace( "Frame skip: %.0fms (%.0f)", 1000*UpdateTime, UpdateTime/ExpectedUpdate );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* (c) 2001-2005 Chris Danford, Glenn Maynard
|
|
* All rights reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
* whom the Software is furnished to do so, provided that the above
|
|
* copyright notice(s) and this permission notice appear in all copies of
|
|
* the Software and that both the above copyright notice(s) and this
|
|
* permission notice appear in supporting documentation.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|