Files
itgmania212121/src/ScreenStatsOverlay.cpp
T
sukibaby eb35a9b9af Switch from Float to Integer Time Values
- 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
2024-09-22 01:27:45 -07:00

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.
*/