mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 06:15:09 +00:00
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:
@@ -421,6 +421,31 @@ def test_watchdog_names_what_the_stalled_thread_is_waiting_on():
|
||||
assert "render_loop_waiting_on_a_lock" in text
|
||||
|
||||
|
||||
def test_watchdog_labels_a_stall_before_a_new_screens_first_frame(caplog):
|
||||
# The display controller noted a handover and the next screen's first
|
||||
# display() is still drawing: not a scroll that stopped.
|
||||
rec = _FakeRecorder()
|
||||
dog = frame_timing.StallWatchdog(rec, threshold=0.25, log_interval=0.0)
|
||||
rec.last_frame = (10.0, True, 1)
|
||||
rec._ops = {frame_timing.HANDOVER_OP: 0}
|
||||
with caplog.at_level("WARNING", logger="src.common.frame_timing"):
|
||||
dog.check(10.4, 0.0, None, False)
|
||||
message = caplog.records[0].getMessage()
|
||||
assert message.startswith("Render stall: no frame for 400ms in a handover gap")
|
||||
assert "mid-scroll" not in message
|
||||
|
||||
|
||||
def test_watchdog_says_mid_scroll_when_nothing_is_handing_over(caplog):
|
||||
rec = _FakeRecorder()
|
||||
dog = frame_timing.StallWatchdog(rec, threshold=0.25, log_interval=0.0)
|
||||
rec.last_frame = (10.0, True, 1)
|
||||
rec._ops = {"extend": 100} # other work pending is not a handover
|
||||
with caplog.at_level("WARNING", logger="src.common.frame_timing"):
|
||||
dog.check(10.4, 0.0, None, False)
|
||||
assert caplog.records[0].getMessage().startswith(
|
||||
"Render stall: no frame for 400ms mid-scroll")
|
||||
|
||||
|
||||
def test_watchdog_rate_limits_its_dumps(caplog):
|
||||
rec = _FakeRecorder()
|
||||
dog = frame_timing.StallWatchdog(rec, threshold=0.25, log_interval=30.0)
|
||||
|
||||
Reference in New Issue
Block a user