Damage tracking
Ghostty records damage as terminal state changes. Frame building uses that damage to identify work for the renderer. A submitted frame gives observers the rows from one completed render turn.
Write / resize / appearance change ↓ native dirty-state update ↓ frame data and changed ranges ↓ renderer submission ↓ onFrame / submittedFrameChanged cells and full repaint
Section titled “Changed cells and full repaint”A first frame needs the whole viewport. Later writes can reuse unchanged rows and buffers. GPU paths build persistent cell and glyph records in Zig and upload changed byte ranges. Canvas and DOM paths use their own row reuse strategies. A resize, font change, palette change or lost GPU resource can require broader repainting.
Scrolling changes which retained rows occupy the viewport. It can also change glyph placement and frame ownership. Damage-aware rendering reduces unnecessary work, but the cost still depends on the renderer and workload. The benchmark report records those differences.
Observer ownership
Section titled “Observer ownership”An observer that needs rendered text should use the coherent submitted frame. Native history reads answer a different question, the terminal state at the time of the read. Reading current state after a write can get ahead of what the browser has submitted.
refresh(startRow, endRow) requests repainting a range. clearTextureAtlas releases cached glyph images so they can be rebuilt. These operations change renderer work; the emulator remains the owner of text.
See TerminalSubmittedFrame and the frame methods on Terminal in the generated API. Read the wasm core for the full pipeline.