From fa2dc9bbf34ff7d75a7d370092415936535d7b02 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 19 May 2026 20:59:35 +0200 Subject: [PATCH] fps: overlay debug a dalt-dreta del canvas (verd, F10 toggle, 8bithud, alineat amb notificacions i overscan-aware) --- source/core/input/global_inputs.cpp | 4 +++ source/core/input/input.h | 1 + source/core/rendering/screen.cpp | 54 ++++++++++++++++++++++++++++- source/core/rendering/screen.h | 14 ++++++++ source/core/system/director.cpp | 1 + 5 files changed, 73 insertions(+), 1 deletion(-) diff --git a/source/core/input/global_inputs.cpp b/source/core/input/global_inputs.cpp index 3c2d48d..8f28983 100644 --- a/source/core/input/global_inputs.cpp +++ b/source/core/input/global_inputs.cpp @@ -127,6 +127,10 @@ namespace GlobalInputs { notifyPresentationMode(); return true; } + if (Input::get()->checkInput(Input::Action::TOGGLE_FPS, Input::Repeat::OFF)) { + Screen::get()->toggleFps(); + return true; + } // F5/F6 només actuen quan el post-procesado està actiu. if (Screen::isShaderEnabled()) { if (Input::get()->checkInput(Input::Action::TOGGLE_SHADER_TYPE, Input::Repeat::OFF)) { diff --git a/source/core/input/input.h b/source/core/input/input.h index a441cd1..a6dae65 100644 --- a/source/core/input/input.h +++ b/source/core/input/input.h @@ -54,6 +54,7 @@ class Input { SHOW_VERSION, TOGGLE_VSYNC, NEXT_PRESENTATION_MODE, + TOGGLE_FPS, // Centinela final (usar para sizing) NUMBER_OF_INPUTS diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 387b07c..54ea974 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -169,9 +169,12 @@ void Screen::start() { // Vuelca el contenido del renderizador en pantalla void Screen::blit() { - // Dibuja la notificación activa sobre el gameCanvas antes de presentar + updateFps(); + + // Dibuja la notificación activa i, si toca, l'overlay de FPS sobre el gameCanvas SDL_SetRenderTarget(renderer_, game_canvas_); renderNotification(); + renderFps(); #ifndef NO_SHADERS // Si el backend GPU està viu i accelerat, passem sempre per ell (tant amb @@ -525,6 +528,55 @@ void Screen::renderNotification() { notification_outline_color_); } +// Alterna la visibilitat de l'overlay de FPS. No persisteix a config. +void Screen::toggleFps() { + fps_visible_ = !fps_visible_; + if (fps_visible_) { + fps_window_start_ticks_ = SDL_GetTicks(); + fps_frame_count_ = 0; + fps_value_ = 0; + } +} + +auto Screen::isFpsVisible() const -> bool { + return fps_visible_; +} + +// Acumula frames i recalcula el FPS cada segon real (no afectat per dt del joc). +// Cridat des de blit() una vegada per frame. +void Screen::updateFps() { + if (!fps_visible_) { return; } + ++fps_frame_count_; + const Uint32 NOW = SDL_GetTicks(); + const Uint32 ELAPSED = NOW - fps_window_start_ticks_; + if (ELAPSED >= 1000) { + fps_value_ = static_cast((static_cast(fps_frame_count_) * 1000) / ELAPSED); + fps_frame_count_ = 0; + fps_window_start_ticks_ = NOW; + } +} + +// Dibuixa "NN FPS" a dalt a la dreta del canvas, mateixa Y que les notificacions +// (incloent l'ajust per overscan) i amb la mateixa font 8bithud. +void Screen::renderFps() { + if (!fps_visible_ || notification_text_ == nullptr) { return; } + constexpr int RIGHT_MARGIN = 2; + const Color FPS_COLOR{0x60, 0xD0, 0x70}; // verd (mateix to que SUCCESS de notificacions) + const Color FPS_OUTLINE{0x26, 0x53, 0x2C}; // ~40% darken del verd + const std::string MSG = std::to_string(fps_value_) + " FPS"; + const int TEXT_W = notification_text_->lenght(MSG, 1); + const int X = game_canvas_width_ - TEXT_W - RIGHT_MARGIN; + const int Y = notification_y_ + safeNotificationY(); + notification_text_->writeDX(Text::FLAG_COLOR | Text::FLAG_STROKE, + X, + Y, + MSG, + 1, + FPS_COLOR, + 1, + FPS_OUTLINE); +} + // Y minima del canvas visible. Solo no zero quan estem en overscan i l'aspect // de finestra obliga a escalar mes ample que alt (el canvas vertical desborda // i la franja superior es retalla). En cas contrari (qualsevol altre mode, o diff --git a/source/core/rendering/screen.h b/source/core/rendering/screen.h index c90dfa4..568acce 100644 --- a/source/core/rendering/screen.h +++ b/source/core/rendering/screen.h @@ -73,6 +73,10 @@ class Screen { void notify(const std::string &text, Color text_color, Color outline_color, Uint32 duration_ms); // Muestra una notificación en la línea superior del canvas durante durationMs. Sobrescribe cualquier notificación activa (sin apilación). void clearNotification(); // Limpia la notificación actual + // FPS overlay (debug, no persistent) + void toggleFps(); // Alterna la visibilitat de l'overlay de FPS + [[nodiscard]] auto isFpsVisible() const -> bool; // Estat actual + // GPU / shaders (post-procesado). En builds con NO_SHADERS (Emscripten) son no-op. void initShaders(); // Crea el backend GPU si no existe y lo inicializa void shutdownShaders(); // Libera el backend GPU @@ -115,6 +119,10 @@ class Screen { void renderNotification(); // Dibuja la notificación activa (si la hay) sobre el gameCanvas [[nodiscard]] auto safeNotificationY() const -> int; // Y minima dins del canvas que segueix sent visible en overscan (segons aspect ratio finestra/canvas) + // FPS overlay + void updateFps(); // Acumula temps i recalcula fps cada segon (a cridar des de blit) + void renderFps(); // Dibuixa "NN FPS" a dalt a la dreta del canvas + #ifndef NO_SHADERS // Aplica els paràmetres actuals del shader al backend segons options // (pass-through si `videoShaderEnabled==false`, preset per defecte si true). @@ -142,6 +150,12 @@ class Screen { Uint32 notification_end_time_; // SDL_GetTicks() hasta el cual se muestra int notification_y_; // Fila vertical en el canvas virtual + // FPS overlay (debug, no persistent) + bool fps_visible_{false}; // F10 toggle + int fps_value_{0}; // Ultim valor calculat (frames per segon) + int fps_frame_count_{0}; // Frames acumulats durant la finestra actual + Uint32 fps_window_start_ticks_{0}; // Inici de la finestra d'1s actual (SDL_GetTicks) + #ifndef NO_SHADERS // GPU / shaders std::unique_ptr shader_backend_; // Backend GPU (nullptr si inactivo) diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index f4b0370..66fc844 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -234,6 +234,7 @@ void Director::initInput() { Input::get()->bindKey(Input::Action::NEXT_SHADER_PRESET, SDL_SCANCODE_F6); Input::get()->bindKey(Input::Action::TOGGLE_VSYNC, SDL_SCANCODE_F7); Input::get()->bindKey(Input::Action::NEXT_PRESENTATION_MODE, SDL_SCANCODE_F8); + Input::get()->bindKey(Input::Action::TOGGLE_FPS, SDL_SCANCODE_F10); Input::get()->bindKey(Input::Action::SHOW_VERSION, SDL_SCANCODE_F11); // Mando - Movimiento del jugador