Expand description
A live frame-time/FPS overlay: PerfOverlayApp wraps any App with one, on any Backend.
PerfOverlayApp: a live frame-time/FPS overlay for any App, on any Backend.
Wrap an existing App once and it gains a toggleable perf readout on
every backend, with no backend-specific code in the wrapped app itself:
use retroglyph_core::app::run_blocking;
use retroglyph_core::backend::{Backend, Headless};
use retroglyph_core::terminal::Terminal;
use retroglyph_ui::PerfOverlayApp;
let term = Terminal::new(Headless::new(40, 10));
let app = PerfOverlayApp::new(MyGame, "headless");
run_blocking(term, app).expect("run_blocking");§What’s generic and what’s backend-specific
The frame-time bookkeeping (FrameStats), the toggle-key check,
and the decision of when to draw are all backend-agnostic:
PerfOverlayApp::update only ever talks to
Terminal/Surface, which every
Backend implements identically. The one thing every caller still
supplies by hand is the backend label string (there is no portable way to ask a Backend
what to call itself); everything else, including toggling the overlay on and off, works
unmodified on crossterm, a native window, or a browser tab.
§Rendering
DefaultPerfRenderer (used by PerfOverlayApp::new) draws a single-row NNNfps MM.Mms minMM.M maxMM.M <backend> readout, compact enough to fit an 80-column terminal alongside a
long backend label. For a richer overlay (a bordered panel, a frame-time sparkline, extra
app-supplied metrics like resolution or vsync state), pass a closure to
PerfOverlayApp::with_closure: composing this crate’s Panel/
Sparkline widgets, or PerfOverlay directly,
requires no glue code beyond the closure itself. Implement PerfRenderer directly, and
construct with PerfOverlayApp::with_renderer, only for a named, reusable renderer type
instead of a closure.
This whole wrapper exists in large part because
FrameStats::record needs a
Frame, which a plain widget draw call had no way to reach:
PerfOverlayApp::update is what intercepts Frame on the way
through and calls FrameStats::record for the widget that otherwise couldn’t. An app that
doesn’t need this wrapper’s other job (generic toggle-key handling across any wrapped
App, on every backend) no longer needs it just for that:
AnimatedPerfOverlay reaches Frame directly, so an app that
already owns a FrameStats field can record and draw it in a single call, with no decorator at
all.
§Toggling
PerfOverlayApp::update drains every event out of the wrapped
Terminal before handing control to the inner
App, keeps any that match the toggle key (backtick, or F1 as an
alias, by default; see default_is_toggle_key), and re-queues the rest via
Terminal::requeue_events so the inner app sees
exactly the input it would have without the overlay, minus the toggle presses. This works
identically on every backend because it only goes through
Terminal’s own event queue, never a backend-specific input path
(in particular, never
Input::push_event, whose documented default is
a no-op for backends that never receive events from outside their own poll_event).
The toggle key doesn’t just flip visibility: it cycles through PerfOverlayMode:
Off -> Compact ->
Full -> back to Off. Full only exists once
PerfOverlayApp::cycle_with registers a second, richer PerfRenderer (typically
PerfOverlay, a bordered panel with a frame-time
Sparkline); without it, the cycle degrades to the plain two-state
Off/Compact toggle.
Structs§
- Default
Perf Renderer - The built-in
PerfRenderer, used byPerfOverlayApp::new. - Perf
Overlay App - Wraps an
Appwith a toggleable perf overlay. See the module docs.
Enums§
- Perf
Overlay Mode - How much detail
super::PerfOverlayAppcurrently shows, advanced by the toggle key.
Constants§
- DEFAULT_
LAYER PerfOverlayApp’s default overlay layer:Layer::Debug.- FRAME_
HISTORY - How many frames
PerfOverlayApp’s internalFrameStatsremembers.
Traits§
- Perf
Renderer - Draws a
super::PerfOverlayApp’s stats into a rectangular area of aSurface.
Functions§
- default_
is_ toggle_ key - Whether
eventis the overlay’s default toggle key.