Skip to content

fix(sdl2): content-hash attributes in line fingerprint to fix text ghosting#2219

Merged
theangelperalta merged 2 commits into
lem-project:mainfrom
theangelperalta:fix/sdl2-line-fingerprint-attribute-mutation
Jun 4, 2026
Merged

fix(sdl2): content-hash attributes in line fingerprint to fix text ghosting#2219
theangelperalta merged 2 commits into
lem-project:mainfrom
theangelperalta:fix/sdl2-line-fingerprint-attribute-mutation

Conversation

@theangelperalta

Copy link
Copy Markdown
Collaborator

Summary

The SDL2 frontend composites persistent per-view GPU textures and only re-renders lines the core display layer marks as changed. That decision is made by a per-window line-fingerprint cache in src/display/physical-line.lisp: each frame every screen line is hashed, and if the hash matches the cached one the line is skipped.

The fingerprint folded each item through sxhash. In SBCL, sxhash on a standard-object (the attribute class) and on a structure-object (the color struct) is identity-based, not content-based. Attributes can be mutated in place — e.g. vi-mode and skk-mode recolor the shared cursor attribute via set-attribute. After such a mutation the object identity is unchanged, so sxhash is unchanged, so the fingerprint is unchanged, so the line is skipped on redraw — leaving the previous frame's glyphs on the persistent texture. That is the ghosting.

M-x redraw-display cleared the fingerprint cache and repainted every line, which is why a forced redraw made the ghost disappear.

This makes the fingerprint hash attribute/color content, consistent with how the rest of the pipeline compares attributes (attribute-equal, drawing-object-equal, the SDL2 text-surface-cache).

Changes

src/display/physical-line.lisp

  • Added item-content-hash, a content-based hash used by djb2:
    • attribute → folds foreground, background, reverse, bold, underline.
    • color → folds the red/green/blue components.
    • cons → recurses through the spine (tolerant of dotted tails) so attributes nested inside the (start end attribute) entries of logical-line-attributes are content-hashed, not caught by the identity-based sxhash of the surrounding sublist.
    • everything else → sxhash (unchanged behavior).
  • djb2 now calls item-content-hash instead of sxhash.

The performance optimization is preserved: genuinely unchanged lines still hash identically and are still skipped; only in-place attribute mutation now correctly invalidates the line.

tests/display-cache.lisp

  • Added test-fingerprint-detects-attribute-mutation, asserting the line fingerprint changes after an in-place set-attribute mutation, covering both an attribute referenced through logical-line-attributes and one referenced through end-of-line-cursor-attribute (the literal cursor case).

Notes

  • Scope is limited to the two files above; no API signatures changed.
  • Complies with contract.yml style rules (colon-prefixed loop keywords, kebab-case naming, docstring on the new function).

@code-contractor-app

code-contractor-app Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ Code Contractor Validation: PASSED

🎉 All violations have been dismissed.

ℹ️ 1 violation(s) dismissed

📚 About Code Contractor

Declarative Code Standards That Learn and Improve

Define domain-specific validation rules in YAML.
Your contracts document team knowledge and evolve into more accurate AI enforcement.

Want this for your repo?
Install Code Contractor

@code-contractor-app code-contractor-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Contractor validation failed ❌ — see the sticky comment for full results.

Comment thread tests/display-cache.lisp
@code-contractor-app code-contractor-app Bot dismissed their stale review June 4, 2026 22:25

All violations have been dismissed.

@code-contractor-app code-contractor-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ All violations have been dismissed. This PR is ready to merge.

The SDL2 frontend composites persistent per-view GPU textures and only
re-renders lines the per-window line-fingerprint cache marks as changed.
That fingerprint folded each item through sxhash, but in SBCL sxhash on a
standard-object (attribute) and structure-object (color) is identity-based,
not content-based.

Attributes can be mutated in place -- e.g. vi-mode and skk-mode recolor the
shared cursor attribute via set-attribute. After such a mutation the object
identity is unchanged, so sxhash is unchanged, the fingerprint is unchanged,
and the line is skipped on redraw -- leaving the previous frame's glyphs on
the persistent texture (ghosting). M-x redraw-display cleared the cache and
masked the bug.

Add item-content-hash, used by djb2, which folds attribute content
(foreground/background/reverse/bold/underline) and color components, and
recurses through cons spines so attributes nested in the (start end attribute)
entries of logical-line-attributes are content-hashed. This makes the
fingerprint consistent with attribute-equal and the rest of the pipeline.
Genuinely unchanged lines still hash identically and are still skipped.

Add test-fingerprint-detects-attribute-mutation covering in-place mutation
through both logical-line-attributes and end-of-line-cursor-attribute.
…l access

Address Code Contractor internal_symbol_rule: switch the mutation test to
the exported `make-attribute`/`set-attribute` (via the package's :use of
:lem-core) instead of `lem-core::`, and document why the remaining
`make-logical-line`/`compute-line-fingerprint` internals are accessed
(white-box unit test of the display layer's fingerprint cache).
@theangelperalta theangelperalta force-pushed the fix/sdl2-line-fingerprint-attribute-mutation branch from 602c507 to 145214a Compare June 4, 2026 22:59
@theangelperalta theangelperalta merged commit 4def86e into lem-project:main Jun 4, 2026
10 checks passed
@theangelperalta theangelperalta deleted the fix/sdl2-line-fingerprint-attribute-mutation branch June 4, 2026 23:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant