From cf51e14cf57a93c364080bc028fbc911ac827b9c Mon Sep 17 00:00:00 2001 From: OM Date: Fri, 19 May 2023 20:52:10 +0200 Subject: [PATCH] Added FPS counter --- code/client/cl_keys.cpp | 137 -------------------- code/client/cl_ui.h | 1 + code/client/cl_uiview3d.cpp | 67 +++++++++- code/client/client.h | 3 - code/client/keys.h | 11 -- code/qcommon/common.cpp | 241 +++++------------------------------- code/qcommon/qcommon.h | 22 +--- code/renderer/tr_cmds.c | 10 ++ 8 files changed, 109 insertions(+), 383 deletions(-) diff --git a/code/client/cl_keys.cpp b/code/client/cl_keys.cpp index 84c529ea..56f7bddc 100644 --- a/code/client/cl_keys.cpp +++ b/code/client/cl_keys.cpp @@ -29,14 +29,10 @@ key up events are sent even if in console mode */ -field_t historyEditLines[COMMAND_HISTORY]; - int nextHistoryLine; // the last line in the history buffer, not masked int historyLine; // the line being displayed from history buffer // will be <= nextHistoryLine -field_t g_consoleField; -field_t chatField; qboolean chat_team; int chat_playerNum; @@ -1198,136 +1194,3 @@ Key_SetCatcher void Key_SetCatcher( int catcher ) { keyCatchers = catcher; } - -// This must not exceed MAX_CMD_LINE -#define MAX_CONSOLE_SAVE_BUFFER 1024 -#define CONSOLE_HISTORY_FILE "omhistory" -static char consoleSaveBuffer[ MAX_CONSOLE_SAVE_BUFFER ]; -static int consoleSaveBufferSize = 0; - -/* -================ -CL_LoadConsoleHistory - -Load the console history from cl_consoleHistory -================ -*/ -void CL_LoadConsoleHistory( void ) -{ - const char *token; - char *text_p; - int i, numChars, numLines = 0; - fileHandle_t f; - - consoleSaveBufferSize = FS_FOpenFileRead( CONSOLE_HISTORY_FILE, &f, qfalse, qtrue ); - if( !f ) - { - Com_Printf( "Couldn't read %s.\n", CONSOLE_HISTORY_FILE ); - return; - } - - if( consoleSaveBufferSize <= MAX_CONSOLE_SAVE_BUFFER && - FS_Read( consoleSaveBuffer, consoleSaveBufferSize, f ) == consoleSaveBufferSize ) - { - text_p = consoleSaveBuffer; - - for( i = COMMAND_HISTORY - 1; i >= 0; i-- ) - { - if( !*( token = COM_Parse( &text_p ) ) ) - break; - - historyEditLines[ i ].cursor = atoi( token ); - - if( !*( token = COM_Parse( &text_p ) ) ) - break; - - historyEditLines[ i ].scroll = atoi( token ); - - if( !*( token = COM_Parse( &text_p ) ) ) - break; - - numChars = atoi( token ); - text_p++; - if( numChars > ( strlen( consoleSaveBuffer ) - ( text_p - consoleSaveBuffer ) ) ) - { - Com_DPrintf( S_COLOR_YELLOW "WARNING: probable corrupt history\n" ); - break; - } - Com_Memcpy( historyEditLines[ i ].buffer, - text_p, numChars ); - historyEditLines[ i ].buffer[ numChars ] = '\0'; - text_p += numChars; - - numLines++; - } - - memmove( &historyEditLines[ 0 ], &historyEditLines[ i + 1 ], - numLines * sizeof( field_t ) ); - for( i = numLines; i < COMMAND_HISTORY; i++ ) - Field_Clear( &historyEditLines[ i ] ); - - historyLine = nextHistoryLine = numLines; - } - else - Com_Printf( "Couldn't read %s.\n", CONSOLE_HISTORY_FILE ); - - FS_FCloseFile( f ); -} - -/* -================ -CL_SaveConsoleHistory - -Save the console history into the cvar cl_consoleHistory -so that it persists across invocations of q3 -================ -*/ -void CL_SaveConsoleHistory( void ) -{ - int i; - int lineLength, saveBufferLength, additionalLength; - fileHandle_t f; - - consoleSaveBuffer[ 0 ] = '\0'; - - i = ( nextHistoryLine - 1 ) % COMMAND_HISTORY; - do - { - if( historyEditLines[ i ].buffer[ 0 ] ) - { - lineLength = strlen( historyEditLines[ i ].buffer ); - saveBufferLength = strlen( consoleSaveBuffer ); - - //ICK - additionalLength = lineLength + strlen( "999 999 999 " ); - - if( saveBufferLength + additionalLength < MAX_CONSOLE_SAVE_BUFFER ) - { - Q_strcat( consoleSaveBuffer, MAX_CONSOLE_SAVE_BUFFER, - va( "%d %d %d %s ", - historyEditLines[ i ].cursor, - historyEditLines[ i ].scroll, - lineLength, - historyEditLines[ i ].buffer ) ); - } - else - break; - } - i = ( i - 1 + COMMAND_HISTORY ) % COMMAND_HISTORY; - } - while( i != ( nextHistoryLine - 1 ) % COMMAND_HISTORY ); - - consoleSaveBufferSize = strlen( consoleSaveBuffer ); - - f = FS_FOpenFileWrite( CONSOLE_HISTORY_FILE ); - if( !f ) - { - Com_Printf( "Couldn't write %s.\n", CONSOLE_HISTORY_FILE ); - return; - } - - if( FS_Write( consoleSaveBuffer, consoleSaveBufferSize, f ) < consoleSaveBufferSize ) - Com_Printf( "Couldn't write %s.\n", CONSOLE_HISTORY_FILE ); - - FS_FCloseFile( f ); -} diff --git a/code/client/cl_ui.h b/code/client/cl_ui.h index da5178ef..733ab3c5 100644 --- a/code/client/cl_ui.h +++ b/code/client/cl_ui.h @@ -42,6 +42,7 @@ void CL_ShutdownUI( void ); // extern inventory_t client_inv; extern bind_t client_bind; +extern cvar_t* cl_greenfps; const char *CvarGetForUI( const char *name, const char *defval ); void UI_ClearState( void ); diff --git a/code/client/cl_uiview3d.cpp b/code/client/cl_uiview3d.cpp index 80e74c41..6fa316d7 100644 --- a/code/client/cl_uiview3d.cpp +++ b/code/client/cl_uiview3d.cpp @@ -126,7 +126,72 @@ void View3D::DrawFPS ) { - // FIXME: stub + char string[128]; + + setFont("verdana-14"); + if (fps->integer == 2) + { + re.SetColor(UBlack); + re.DrawBox( + 0.0, + m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 4.0, + m_frame.pos.x + m_frame.size.width, + m_font->getHeight(qfalse) * 4.0 + ); + } + + sprintf(string, "FPS %4.1f", currentfps); + if (currentfps > 23.94) { + if (cl_greenfps->integer) { + m_font->setColor(UGreen); + } else { + m_font->setColor(UWhite); + } + } else if (currentfps > 18.0) { + m_font->setColor(UYellow); + } else { + // low fps + m_font->setColor(URed); + } + + m_font->Print( + m_font->getHeight(qfalse) * 10.0, + m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 3.0, + string, + -1, + qfalse + ); + + // Draw elements count + if (cl_greenfps->integer) { + m_font->setColor(UGreen); + } + else { + m_font->setColor(UWhite); + } + + sprintf(string, "wt%5d wv%5d cl%d", cls.world_tris, cls.world_verts, cls.character_lights); + + m_font->Print( + m_font->getHeight(qfalse) * 10.0, + m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 2.0, + string, + -1, + qfalse + ); + + sprintf(string, "t%5d v%5d Mtex%5.2f", cls.total_tris, cls.total_verts, (float)cls.total_texels * 0.00000095367432); + + + m_font->Print( + m_font->getHeight(qfalse) * 10.0, + m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse), + string, + -1, + qfalse + ); + + m_font->setColor(UBlack); } void View3D::DrawProf diff --git a/code/client/client.h b/code/client/client.h index 7af87f79..b5aaee29 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -578,9 +578,6 @@ void Con_PageDown( void ); void Con_Top( void ); void Con_Bottom( void ); -void CL_LoadConsoleHistory( void ); -void CL_SaveConsoleHistory( void ); - // // cl_scrn.c // diff --git a/code/client/keys.h b/code/client/keys.h index f45dbf8c..f77c5825 100644 --- a/code/client/keys.h +++ b/code/client/keys.h @@ -34,17 +34,6 @@ typedef struct { extern qboolean key_overstrikeMode; extern qkey_t keys[K_LASTKEY]; -// NOTE TTimo the declaration of field_t and Field_Clear is now in qcommon/qcommon.h -void Field_KeyDownEvent( field_t *edit, int key ); -void Field_CharEvent( field_t *edit, int ch ); -void Field_Draw(fontInfo_t *font, field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape ); -void Field_BigDraw(fontInfo_t *font, field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape ); - -#define COMMAND_HISTORY 32 -extern field_t historyEditLines[COMMAND_HISTORY]; - -extern field_t g_consoleField; -extern field_t chatField; extern int anykeydown; extern qboolean chat_team; extern int chat_playerNum; diff --git a/code/qcommon/common.cpp b/code/qcommon/common.cpp index 781148ee..d013dfae 100644 --- a/code/qcommon/common.cpp +++ b/code/qcommon/common.cpp @@ -31,6 +31,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #endif +// FPS +#include + #include qboolean CL_FinishedIntro(void); @@ -72,7 +75,6 @@ fileHandle_t com_journalDataFile; // config files are written here cvar_t *paused; cvar_t *config; cvar_t *fps; -float currentfps; cvar_t *com_speeds; cvar_t *developer; cvar_t *com_dedicated; @@ -126,6 +128,18 @@ static char *rd_buffer; static int rd_buffersize; static void (*rd_flush)( char *buffer ); +#define MAX_FPS_TIMES 16 + +using fps_clock_t = std::chrono::high_resolution_clock; +using fps_time_t = fps_clock_t::time_point; +using fps_delta_t = fps_clock_t::duration; + +static int fpsindex; +static fps_delta_t fpstimes[MAX_FPS_TIMES]; +static fps_delta_t fpstotal; +static fps_time_t fpslasttime; +float currentfps; + void Com_BeginRedirect (char *buffer, int buffersize, void (*flush)( char *) ) { if (!buffer || !buffersize || !flush) @@ -1752,6 +1766,22 @@ void Com_Frame( void ) { com_frameNumber, all, sv, ev, cl, time_game, time_frontend, time_backend ); } + if (fps->integer) { + fps_time_t fpstime = fps_clock_t::now(); + fps_delta_t delta = fpstime - fpslasttime; + + fpstotal = (fpstime - fpslasttime) + (fpstotal - fpstimes[fpsindex]); + fpstimes[fpsindex] = fpstime - fpslasttime; + fpsindex = (fpsindex + 1) % MAX_FPS_TIMES; + fpslasttime = fpstime; + + if (fpstotal.count()) { + currentfps = 16.0 / std::chrono::duration(fpstotal).count(); + } else { + currentfps = 0.0; + } + } + // // trace optimization tracking // @@ -1893,23 +1923,10 @@ command line completion =========================================== */ -/* -================== -Field_Clear -================== -*/ -void Field_Clear( field_t *edit ) { - memset(edit->buffer, 0, MAX_EDIT_LINE); - edit->cursor = 0; - edit->scroll = 0; -} static const char *completionString; static char shortestMatch[MAX_TOKEN_CHARS]; static int matchCount; -// field we are working on, passed to Field_AutoComplete(&g_consoleCommand for instance) -static field_t *completionField; - /* =============== FindMatches @@ -1968,200 +1985,4 @@ static void PrintCvarMatches( const char *s ) { } } -/* -=============== -Field_FindFirstSeparator -=============== -*/ -static char *Field_FindFirstSeparator( char *s ) -{ - int i; - - for( i = 0; i < strlen( s ); i++ ) - { - if( s[ i ] == ';' ) - return &s[ i ]; - } - - return NULL; -} - -#ifndef DEDICATED -/* -=============== -Field_CompleteKeyname -=============== -*/ -static void Field_CompleteKeyname( void ) -{ - matchCount = 0; - shortestMatch[ 0 ] = 0; - - Key_KeynameCompletion( FindMatches ); - - if( matchCount == 0 ) - return; - - Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) - - strlen( completionString ) ], shortestMatch, - sizeof( completionField->buffer ) ); - completionField->cursor = ( int )strlen( completionField->buffer ); - - if( matchCount == 1 ) - { - Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " ); - completionField->cursor++; - return; - } - - Com_Printf( "]%s\n", completionField->buffer ); - - Key_KeynameCompletion( PrintMatches ); -} -#endif - -/* -=============== -Field_CompleteFilename -=============== -*/ -static void Field_CompleteFilename( const char *dir, - const char *ext, qboolean stripExt ) -{ - size_t pos; - - matchCount = 0; - shortestMatch[ 0 ] = 0; - - FS_FilenameCompletion( dir, ext, stripExt, FindMatches ); - - if( matchCount == 0 ) - return; - - pos = strlen( completionField->buffer ) - strlen( completionString ); - Q_strncpyz( &completionField->buffer[ pos ], shortestMatch, - sizeof( completionField->buffer ) - pos ); - completionField->cursor = ( int )strlen( completionField->buffer ); - - if( matchCount == 1 ) - { - Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " ); - completionField->cursor++; - return; - } - - Com_Printf( "]%s\n", completionField->buffer ); - - FS_FilenameCompletion( dir, ext, stripExt, PrintMatches ); -} - -static void keyConcatArgs(void) { - int i; - char* arg; - - for (i = 1; i < Cmd_Argc(); i++) { - Q_strcat(completionField->buffer, sizeof(completionField->buffer), " "); - arg = Cmd_Argv(i); - while (*arg) { - if (*arg == ' ') { - Q_strcat(completionField->buffer, sizeof(completionField->buffer), "\""); - break; - } - arg++; - } - Q_strcat(completionField->buffer, sizeof(completionField->buffer), Cmd_Argv(i)); - if (*arg == ' ') { - Q_strcat(completionField->buffer, sizeof(completionField->buffer), "\""); - } - } -} - -static void ConcatRemaining(const char* src, const char* start) { - const char* str; - - str = strstr(src, start); - if (!str) { - keyConcatArgs(); - return; - } - - str += strlen(start); - Q_strcat(completionField->buffer, sizeof(completionField->buffer), str); -} - -/* -=============== -Field_CompleteCommand - -perform Tab expansion -NOTE TTimo this was originally client code only - moved to common code when writing tty console for *nix dedicated server -=============== -*/ -void Field_CompleteCommand(field_t* field) { - field_t temp; - - completionField = field; - - // only look at the first token for completion purposes - Cmd_TokenizeString(completionField->buffer); - - completionString = Cmd_Argv(0); - if (completionString[0] == '\\' || completionString[0] == '/') { - completionString++; - } - matchCount = 0; - shortestMatch[0] = 0; - - if (strlen(completionString) == 0) { - return; - } - - Cmd_CommandCompletion(FindMatches); - Cvar_CommandCompletion(FindMatches); - - if (matchCount == 0) { - return; // no matches - } - - Com_Memcpy(&temp, completionField, sizeof(field_t)); - - if (matchCount == 1) { - Com_sprintf(completionField->buffer, sizeof(completionField->buffer), "\\%s", shortestMatch); - if (Cmd_Argc() == 1) { - Q_strcat(completionField->buffer, sizeof(completionField->buffer), " "); - } - else { - ConcatRemaining(temp.buffer, completionString); - } - completionField->cursor = strlen(completionField->buffer); - return; - } - - // multiple matches, complete to shortest - Com_sprintf(completionField->buffer, sizeof(completionField->buffer), "\\%s", shortestMatch); - completionField->cursor = strlen(completionField->buffer); - ConcatRemaining(temp.buffer, completionString); - - Com_Printf("]%s\n", completionField->buffer); - - // run through again, printing matches - Cmd_CommandCompletion(PrintMatches); - Cvar_CommandCompletion(PrintMatches); -} - -/* -=============== -Field_AutoComplete - -Perform Tab expansion -=============== -*/ -void Field_AutoComplete( field_t *field ) -{ - completionField = field; - - Field_CompleteCommand(field); -} - } diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index 20139d70..fd7fbb2c 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -798,26 +798,6 @@ MISC /* ============================================================== -Edit fields and command line history/completion - -============================================================== -*/ - -#define MAX_EDIT_LINE 256 -typedef struct { - int cursor; - int scroll; - int widthInChars; - char buffer[MAX_EDIT_LINE]; -} field_t; - -void Field_Clear( field_t *edit ); -void Field_CompleteCommand( field_t *edit ); -void Field_AutoComplete( field_t *edit ); - -/* -============================================================== - MISC ============================================================== @@ -882,10 +862,10 @@ void Com_StartupVariable( const char *match ); // only a set with the exact name. Only used during startup. +extern float currentfps; extern cvar_t *paused; extern cvar_t *config; extern cvar_t *fps; -extern float currentfps; extern cvar_t *developer; extern cvar_t *com_dedicated; extern cvar_t *com_speeds; diff --git a/code/renderer/tr_cmds.c b/code/renderer/tr_cmds.c index dda29dbe..dcd040f0 100644 --- a/code/renderer/tr_cmds.c +++ b/code/renderer/tr_cmds.c @@ -42,6 +42,16 @@ R_PerformanceCounters ===================== */ void R_PerformanceCounters( void ) { + if (fps->integer) { + ri.SetPerformanceCounters( + backEnd.pc.c_totalIndexes / 3, + backEnd.pc.c_vertexes, + R_SumOfUsedImages(pc_save.c_totalIndexes / 3, pc_save.c_vertexes), + pc_save.c_totalIndexes / 3, + pc_save.c_vertexes, + backEnd.pc.c_characterlights + ); + } if ( !r_speeds->integer ) { // clear the counters even if we aren't printing Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );