fix(display): end the scroll state at scroller-to-static handovers (#716)

A static plugin screen that follows a scroller no longer starts with the ticker's lagging rows on scan-compensated panels, and the 1 Hz loop's second frame is no longer recorded as a ~1 s mid-scroll freeze / Render stall. The display controller calls DisplayManager.end_scroll_for_static_screen() before a static screen's first display() (clears the scan history; _scan_segments passes its frames through in one swap) and set_scrolling_state(False) after it; the scroller's hold stays until then, so late-frame counts are unchanged. A screen's first frame is tagged 'handover': gaps of 250 ms or more before it go to the additive handover_freezes (frame_soak prints 'Handover gaps'), not freezes. The display thread is named display-<plugin id>. The WiFi notice and the schedule-off blank are not covered yet (docs list them as a follow-up).

ledpi A B B A soak (20 min each, --preview): main 0.118% / 0.113% late with 6 / 3 freezes; with this and #717 0.107% / 0.104% late, 0 freezes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-10-01 20:13:57 -04:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 41db488c73
commit 34be83d595
12 changed files with 1041 additions and 38 deletions
+5 -1
View File
@@ -232,7 +232,11 @@ its prefetch inline. Verify with a Vegas soak on ledpi, A/B.
Plugins declare `frame_policy` (STATIC, PERIODIC(hz), ANIMATED(fps),
SCROLL). `_needs_high_fps` becomes the mapping for legacy plugins
(`needs_high_fps`, the `static-image` special case, `enable_scrolling`),
and its per-screen INFO line drops to DEBUG.
and its per-screen INFO line drops to DEBUG. It is already read twice per
screen: once quietly before the first frame, so `_dispatch_first_frame` can
end the previous scroll for a screen that runs the 1 Hz loop
(`_start_screen_handover`), and once after it to pick the loop. A declared
policy answers both.
## How each stage is verified