Skip to content

Render LOVE demos through native KMS scanout modes#843

Draft
brandonpayton wants to merge 4 commits into
emdash/love-port-current-base-for-target-upscalefrom
emdash/love-target-resolution-upscale
Draft

Render LOVE demos through native KMS scanout modes#843
brandonpayton wants to merge 4 commits into
emdash/love-port-current-base-for-target-upscalefrom
emdash/love-target-resolution-upscale

Conversation

@brandonpayton

@brandonpayton brandonpayton commented Jul 5, 2026

Copy link
Copy Markdown
Member

Purpose

Keep native LOVE games on the real Kandelo KMS/EGL/GLES path while letting fixed-resolution games render at their intended logical display size and letting the Kandelo UI upscale the final scanout.

The target-resolution work fixed the first issue by allocating LOVE scanout buffers at the game-requested size. The connector-mode follow-up fixed native fullscreen/window queries. The image metadata then made each LOVE profile advertise the connector mode it expects. The final BYTEPATH follow-up caps only the browser presentation zoom so BYTEPATH's deliberately low-resolution shader offsets are not magnified across an oversized browser pane.

This keeps the fix in Kandelo's normal presentation path: /etc/kandelo/demo.json -> kandelo-session presentation parsing -> generic KMS pane -> attachKmsDisplay({ connectorMode }) and generic CSS fitting. It does not add BYTEPATH/SNKRX renderer hacks.

This is a stacked draft PR against emdash/love-port-current-base-for-target-upscale, which captures the current LOVE native-port worktree state. The feature diff is four commits: target-resolution KMS scanout/upscale, connector-mode preservation for native fullscreen/window queries, image-declared virtual KMS connector modes, and an optional KMS CSS presentation scale cap.

Changes

  • Move LOVE presenter setup until after love.conf, then allocate KMS GBM BOs/DRM FBs and the GL viewport from the game window size.
  • Fit the browser KMS canvas from the kernel-reported active scanout size and upscale that canvas with CSS in the Kandelo UI.
  • Track the advertised KMS connector mode separately from the current scanout framebuffer in the host runtime and host protocols.
  • Resize the attached OffscreenCanvas to the framebuffer committed through MODE_SETCRTC, without changing the mode reported by MODE_GETCONNECTOR.
  • Make the Kandelo native LOVE window backend report the advertised connector dimensions for fullscreen/window queries.
  • Add presentation.kms.connectorMode metadata parsing and validation to kandelo-session.
  • Add presentation.kms.maxCssScale metadata parsing and validation to cap browser presentation zoom without changing the KMS framebuffer or dimensions visible to user software.
  • Seed the KMS pane and attachKmsDisplay from image-declared connector modes, defaulting to 1920x1080 for generic KMS demos.
  • Declare virtual KMS connector modes for the LOVE shell profiles: LOVE gallery 960x540, BYTEPATH 480x270, SNKRX 960x540.
  • Cap BYTEPATH's browser presentation scale at 2x, so its 480x270 native scanout is displayed as 960x540 centered in larger panes.
  • Remove the BYTEPATH demo-default patch that changed upstream glitch = 10 to 3.
  • Document the KMS connector-mode vs scanout-size contract, the presentation scale cap, and the LOVE native runtime behavior.

Validation

  • scripts/dev-shell.sh bash packages/registry/love/build-love.sh
  • unzip -p packages/registry/love/love-examples.zip bytepath/globals.lua | rg -n "glitch|distortion|sx, sy" showed upstream glitch = 10.
  • scripts/dev-shell.sh bash images/vfs/scripts/build-shell-vfs-image.sh
  • scripts/dev-shell.sh bash -c 'cd apps/browser-demos && npm run build'
  • scripts/dev-shell.sh bash -c 'cd host && npm test -- dri-kms-stats-sab.test.ts dri-registry.test.ts webgl-bridge.test.ts webgl-shadow.test.ts webgl-main-forward.test.ts webgl-registry.test.ts webgl-muxer.test.ts' passed: 7 files, 94 tests.
  • scripts/dev-shell.sh bash -c 'cd host && npx vitest run ../web-libs/kandelo-session/test/kandelo-session.test.ts' passed: 1 file, 44 tests.
  • git diff --check -- . ':!libc/musl' ':!tests/sortix/os-test'
  • Browser smoke on http://127.0.0.1:5404/ after the virtual connector-mode fix:
    • BYTEPATH: KMS canvas attrs 480x270, CSS rect about 1857x1045; screenshot /tmp/bytepath-kms-virtual-mode.png.
    • BYTEPATH guide-closed smoke: status 480×270 · 11723 flips · captured · pid 100; screenshot /tmp/bytepath-kms-virtual-mode-guide-closed.png.
    • SNKRX: KMS canvas attrs 960x540, CSS rect about 1857x1045; screenshot /tmp/snkrx-kms-virtual-mode.png.
  • Follow-up BYTEPATH shader proof on the same native renderer path:
    • With packaged settings (distortion = 5, glitch = 10), startup/game text still shows RGB separation.
    • Through BYTEPATH's own effects command, lowering glitch to 0 and distortion near 0 removed the split on the same renderer, confirming that the remaining RGB offset was game-authored post-processing rather than a Kandelo CSS-upscale artifact.
  • Browser smoke after rebuilding the shell VFS with presentation.kms.maxCssScale: 2 for BYTEPATH:
    • URL: http://127.0.0.1:5404/?demo=bytepath&scalecap=2x-smoke
    • KMS canvas attrs 480x270, CSS rect 960x540, centered in the pane.
    • Status: 480×270 · 3691 flips · captured · pid 100.
    • Screenshot: /tmp/bytepath-kms-scale-cap.png.

Known unrelated browser diagnostic: the existing remote Kandelo software gallery manifest 404 warning.

Not Run

  • Full POSIX/conformance suites.
  • Full browser Playwright suite.
  • Full ./run.sh browser; it was stopped because binary materialization for unrelated packages fell back to source builds outside the dev-shell toolchain context. The already-built VFS was served through Vite for browser smoke.

Keep the browser KMS connector mode separate from the active scanout framebuffer so DRM_GETCONNECTOR continues to report the display mode after the canvas backing store is resized. Resize the OffscreenCanvas to the committed FB on SETCRTC, pass the advertised mode through the host protocols, and have the native LOVE window backend return that mode for fullscreen/window queries.

This restores BYTEPATH's native fullscreen sizing: the game can request the advertised 1920x1080 desktop mode while the browser still fits the active KMS surface with CSS. Add a host regression test and update the KMS/LOVE docs for the separate connector-mode and scanout-size contract.
@brandonpayton brandonpayton changed the title Render LOVE demos at native target resolution Render LOVE demos through native KMS scanout modes Jul 5, 2026
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

Phase B-1 matrix build status — pr-843-staging

ABI v16. 67 built, 4 failed, 71 total.

Package Arch Status Sha
freetype wasm32 built 309c9846
libcurl wasm32 built 8209531d
libcxx wasm32 built f2f4c9d3
libcxx wasm64 built 0976cfa2
libpng wasm32 built 05e136da
libxml2 wasm32 built 0135b627
libxml2 wasm64 built eb6af6a7
lua wasm32 built 8605336d
openssl wasm32 built 44077384
openssl wasm64 built 2d873da0
sqlite wasm32 built b0036f25
sqlite wasm64 built 56bebe00
zlib wasm32 built a95074ce
zlib wasm64 built 7ae80692
bc wasm32 built 4839df3e
bzip2 wasm32 built 60600970
coreutils wasm32 built f14e966a
curl wasm32 built f34134af
dash wasm32 built dbbd40a6
diffutils wasm32 built 16f0e3c9
dinit wasm32 built ae7dc838
fbdoom wasm32 built 3431d37e
file wasm32 built 6476c513
findutils wasm32 built 98a5306f
gawk wasm32 built f4f69389
git wasm32 built 05018df4
grep wasm32 built cca6e616
gzip wasm32 built 717a6380
hello wasm32 built 452aeb42
kandelo-sdk wasm32 built 33898e9f
kernel wasm32 built 2dea894c
less wasm32 built 5edb6486
love wasm32 built 0f5d004c
lsof wasm32 built e36e8981
m4 wasm32 built 0f528a5a
make wasm32 built ff0e311c
mariadb wasm32 built db55a931
mariadb wasm64 built 65a4c7a1
modeset wasm32 built 0bffa33a
msmtpd wasm32 built 7264ab88
nano wasm32 built 3cb5a232
ncurses wasm32 built 241c562f
netcat wasm32 built 9319fb0c
nginx wasm32 built 0ec9ca8e
php wasm32 built 022b8309
posix-utils-lite wasm32 built 1c80585a
sed wasm32 built 0c503c3f
spidermonkey wasm32 built bd43ea6c
tar wasm32 built fbe26e27
tcl wasm32 built b91d60ee
unzip wasm32 built f65de865
userspace wasm32 built e1a79e77
vim wasm32 built 3e7ee130
wget wasm32 built 7a641c0b
xz wasm32 built a563eeb4
zip wasm32 built 8bb08b58
zstd wasm32 built 8ebdffe5
bash wasm32 built 8eb30d9a
mariadb-test wasm32 built 2ad65ed5
mariadb-vfs wasm32 built 600093f2
mariadb-vfs wasm64 built 109b5075
nethack wasm32 built 7469f8c4
node wasm32 built 1f78e7e9
spidermonkey-node wasm32 built 2e3a7c1e
vim-browser-bundle wasm32 built 688ecc1d
nethack-browser-bundle wasm32 built 447c0f87
rootfs wasm32 built b69f06e8
shell wasm32 failed
lamp wasm32 failed
node-vfs wasm32 failed
wordpress wasm32 failed

Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.

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