fix(graphics): coalesce terminal kitty placements - #3152
Conversation
A Unicode-placeholder image arrives as one placement per viewport row it covers, and after 624dfd4 the budgeted encoder emitted one placement per frame, so every redraw painted images one row per frame.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review. 📝 WalkthroughWalkthroughThe graphics encoder now accepts a coalescing flag. It coalesces only pure redisplays that fit the transaction budget. Uploads and superseded-image deletes stop further coalescing. Tests cover these transaction boundaries. ChangesGraphics transaction coalescing
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This change coalesces terminal image redisplays so images repaint in one transaction instead of filling in row by row. No actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant GraphicsUpdate
participant IncrementalEncoder
participant ImageCache
GraphicsUpdate->>IncrementalEncoder: encode incremental update with coalescing flag
IncrementalEncoder->>ImageCache: check cached image and source binding
ImageCache-->>IncrementalEncoder: pure redisplay or upload/delete required
IncrementalEncoder->>IncrementalEncoder: coalesce pure redisplays within budget
IncrementalEncoder-->>GraphicsUpdate: emit transactions
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 7f996534-308e-4c22-bf64-01f9a4d3088e
📒 Files selected for processing (1)
src/kitty_graphics.rs
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
Keep pixel uploads and superseded-image deletes in a transaction of their own: a placement joins the coalesced transaction only when its image is uploaded and its source already maps to that image, and nothing joins after an upload or a delete.
Greptile SummaryThe PR updates budgeted terminal-only Kitty graphics rendering to batch cached placement replays while retaining one upload or cleanup operation per transaction.
Confidence Score: 5/5The PR appears safe to merge, with cached placement replay batching remaining bounded and isolated from uploads and cleanup operations. The changed predicate restricts coalescing to already-uploaded, correctly bound images; the incremental loop still visits every placement and preserves replay progress across deferred frames.
|
| Filename | Overview |
|---|---|
| src/kitty_graphics.rs | Adds budget-aware coalescing for pure terminal-image placement replays and comprehensive regression tests without changing upload or cleanup transaction isolation. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Begin budgeted graphics update] --> B{Cleanup already emitted?}
B -->|Yes| C[Return cleanup transaction]
B -->|No| D[Inspect next placement]
D --> E{Cached image and source binding match?}
E -->|No| F[Emit one upload or update transaction]
E -->|Yes| G[Encode placement replay]
G --> H{Combined bytes fit budget?}
H -->|Yes| I[Append replay and inspect next placement]
H -->|No| J[Return transaction as incomplete]
I --> D
F --> J
D -->|All visited| K[Clear replay state and return complete]
Reviews (1): Last reviewed commit: "fix(graphics): coalesce only pure kitty ..." | Re-trigger Greptile
|
thanks for finding this and putting together the first fix. while testing it in yazi, i found the same row splitting also affects image upload and cleanup, which causes black bands during preview changes. #3166 preserves your two commits and extends the fix across the full image lifecycle, so i'm superseding this one with that pr. |
|
makes sense — thanks for extending it. |
Problem
Since 624dfd4, a terminal image rendered through Unicode placeholders
is re-displayed one placement per frame.
kitty_virtual_image_placementsyields one placement per viewport row the image covers, so a 23-row
image takes 23 frames (16 ms apart, 368 ms) to repaint on every redraw,
and each of those frames re-sends the whole cell grid. In Neovim
(snacks.nvim) images visibly fill in row by row. Not in any release: no
tag contains 624dfd4.
Cause
encode_graphics_update_incrementalreturnsincompleteafter thefirst transaction, whether that transaction is a re-display (
a=p,~70 bytes) or a pixel upload.
Fix
Pure re-display transactions (image already uploaded and the source
already bound to it, so
encode_placement_updateemits neither anupload nor a superseded-image delete) now coalesce into the transaction
being assembled, within the caller's transaction budget. Pixel uploads
and deletes keep a transaction of their own, and nothing joins after
them. Only the terminal-only budgeted path coalesces: with pane-layer
graphics active, terminal images keep the one-per-frame cadence, and
stale-placement deletes stay one per frame.
Verification
cargo fmt --checkandcargo clippy --all-targets --locked -- -D warningsare clean.cargo nextest run --lockedwithLIBGHOSTTY_VT_OPTIMIZE=ReleaseFast,excluding four tests that also fail on unmodified master
(
pane_spawn_cwd_fallback_in_server,live_handoff_keeps_unmanaged_agent_name_bound_to_saved_session,live_handoff_keeps_agent_started_pane_after_agent_exits,multi_client_client_crash_sigkill_does_not_affect_server):3,354 passed, 5 skipped.
budgeted_image_rows_redisplay_in_one_transactionandbudgeted_pixel_uploads_do_not_coalescefail on unmodified master;budgeted_redisplay_coalescing_respects_budgetpins the budget cutoff;budgeted_upload_keeps_other_redisplays_outandbudgeted_superseded_image_delete_does_not_coalescepin that uploadsand superseded-image deletes stay in a transaction of their own.