atagen

monolith

public
Star0
Watch0

Commit 6c3361e382e4

tarball

atagen <boss@atagen.co>2026-10-16 13:12 UTC

1 file changed+19-0
monolith: log presented frames per second per output at debug level
Modified file: crates/monolith/src/drm.rs+19 additions
@@ -68,6 +68,9 @@ struct Surface {
6868 /// The vblank the frame being drawn or queued is meant for.
6969 target_ns: Option<u64>,
7070 budget: Budget,
71+ /// Frames presented since `stats_since`, for the once-a-second debug line.
72+ presented: u32,
73+ stats_since: u64,
7174 }
7275
7376 impl Surface {
@@ -366,6 +369,8 @@ fn connect(state: &mut State, connector: connector::Info, crtc: crtc::Handle) {
366369 scheduled: None,
367370 target_ns: None,
368371 budget: Budget::new(),
372+ presented: 0,
373+ stats_since: 0,
369374 refresh_ns: 1_000_000_000_000 / u64::from(wl_mode.refresh.max(1) as u32),
370375 },
371376 );
@@ -418,6 +423,20 @@ fn on_vblank(state: &mut State, crtc: crtc::Handle, meta: &mut Option<DrmEventMe
418423 }
419424 }
420425 surface.last_vblank_ns = Some(t);
426+ surface.presented += 1;
427+ let window = t.saturating_sub(surface.stats_since);
428+ if window >= 1_000_000_000 {
429+ let vblanks = window / surface.refresh_ns.max(1);
430+ tracing::debug!(
431+ output = surface.output.name(),
432+ presented = surface.presented,
433+ vblanks,
434+ budget_us = surface.budget.ns() / 1000,
435+ "frame rate"
436+ );
437+ surface.presented = 0;
438+ surface.stats_since = t;
439+ }
421440 }
422441 if surface.redraw {
423442 schedule(state, crtc);