FontAtlas: a query for whether a frame is owed, for consumers that draw on demand (a4be6f1's eviction) #190

Open
opened 2026-11-01 20:10:09 +00:00 by jorijnvdgraaf · 0 comments

Since a4be6f1 the atlas evicts, and a consumer that draws on demand has to guess when to draw. A glyph that finds no free cell draws blank and joins the atlas's waiting list (waiting_, private); cells come free at Settle, when a frame begins, for glyphs not drawn in the last framesInFlight + 1 frames (Packer::Allocate's depth); so the waiting glyphs get their cells only if another frame is drawn, and nothing in the library asks for one. AGENTS.consumer.md says so for frame-clock-less programs ("steps it itself … or its full atlas never frees a cell and new glyphs stay blank") but gives them no query to step by.

What a consumer ends up writing (imsd-messages, pinned at 3f646ec): after each frame it re-walks every string it drew and calls FontAtlas::Lookup per code point to count the glyphs that are not Resident() — the set the atlas already has — and keeps asking for frames while that count stands, giving up after framesInFlight + 1 gainless frames, a number copied from the library's eviction depth and kept in step by a pin-bump checklist. Any change of what is drawn restarts the wait. It works, and it is the wrong layer: the atlas knows whether glyphs wait, whether Settle placed one, and how deep the eviction window is.

Ask: a query on FontAtlas — FrameOwed() (or WaitingGlyphs() as the count) — true while glyphs wait and the next frame can still place one: a placement happened in the last frame, or fewer than the eviction depth frames have passed since the oldest waiting glyph joined. A consumer then asks for a frame when the atlas says so, and the counting walk, the copied depth and the patience go.

Context: found by imsd-messages' pre-push review (round 36, 2026-11-01); waived there for the app's 1.0 with this issue as the follow-up, as #188 was.

**Since a4be6f1 the atlas evicts, and a consumer that draws on demand has to guess when to draw.** A glyph that finds no free cell draws blank and joins the atlas's waiting list (`waiting_`, private); cells come free at `Settle`, when a frame begins, for glyphs not drawn in the last framesInFlight + 1 frames (`Packer::Allocate`'s depth); so the waiting glyphs get their cells only if another frame is drawn, and nothing in the library asks for one. `AGENTS.consumer.md` says so for frame-clock-less programs ("steps it itself … or its full atlas never frees a cell and new glyphs stay blank") but gives them no query to step by. **What a consumer ends up writing** (imsd-messages, pinned at 3f646ec): after each frame it re-walks every string it drew and calls `FontAtlas::Lookup` per code point to count the glyphs that are not `Resident()` — the set the atlas already has — and keeps asking for frames while that count stands, giving up after framesInFlight + 1 gainless frames, a number copied from the library's eviction depth and kept in step by a pin-bump checklist. Any change of what is drawn restarts the wait. It works, and it is the wrong layer: the atlas knows whether glyphs wait, whether `Settle` placed one, and how deep the eviction window is. **Ask**: a query on `FontAtlas` — `FrameOwed()` (or `WaitingGlyphs()` as the count) — true while glyphs wait and the next frame can still place one: a placement happened in the last frame, or fewer than the eviction depth frames have passed since the oldest waiting glyph joined. A consumer then asks for a frame when the atlas says so, and the counting walk, the copied depth and the patience go. **Context**: found by imsd-messages' pre-push review (round 36, 2026-11-01); waived there for the app's 1.0 with this issue as the follow-up, as #188 was.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Catcrafts/Crafter.Graphics#190
No description provided.