Every paint handed prompt_toolkit a finished ANSI frame and let it parse
that back into fragments, write all ~1400 cells into a fresh Char grid,
diff the grid, and re-emit ANSI. Measured on the PicoCalc that round trip
is 70-125 ms, and it is paid in full whether the frame changed by one row,
by all of them, or not at all - the 2 s header tick recomposes an
identical frame and still pays it.
Since the frame is already rows of text, FastRenderer compares this
frame's rows against the last frame's and rewrites only the ones that
differ. Opt-in for now (MESHTERM_FASTRENDER=1) and deliberately narrow:
a floating dialog or the busy overlay is placed by pt's float containers,
so those paints fall straight through to the stock renderer.
The erase has to lead the row, never follow it. A row that exactly fills
53 columns leaves the cursor in the last column with wrap pending, and an
erase-to-end there clears the character just written - the last cell of
every row went missing until the clear moved in front.
Alongside it, three costs that were pure waste on this platform:
* The redraw was postponed up to max_render_postpone_time before it
even started - a flat 3 ms on the Lyra, 10 ms on desktop, on every
key. That default guards a UI whose own output floods it with
invalidations; here they are keystrokes and a 2 s tick.
* The splash rendered its body twice per paint - once to measure the
box, once to fill it - and ran the corner glow ungated, walking every
line to hand back the identical list on a console with no truecolor
to blend. compose_dialog had the same ungated glow.
* A tile's decoded layers were re-read from the SD card on every frame
(~96 ms each), so panning one dot re-read every tile that had not
moved. They are held in RAM now, bounded at a viewport plus its ring.
On the device, driven over the real radio: main menu 115 -> 40 ms,
Contacts 155 -> 73 ms, Dashboard 213 -> 117 ms, leaving a screen
375 -> 103 ms. Console readback confirms the frames are byte-identical.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>