Skip to content

Support fixed-resolution KMS/GLES rendering and RGBA8 canvases#843

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

Support fixed-resolution KMS/GLES rendering and RGBA8 canvases#843
brandonpayton wants to merge 6 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

Support fixed-resolution native KMS/GLES applications in the browser presentation path without app-specific scaling or rendering behavior. The core feature is not LOVE-specific: Kandelo now lets a KMS consumer render at its intended connector mode while the browser UI stretches that scanout to the available canvas area, and the WebGL-backed GLES bridge exposes the render-target formats needed by native GLES renderers.

LOVE/BYTEPATH/SNKRX remain in this PR as consumers and regression fixtures. They are the applications that exposed the bug, but the runtime fixes are generic KMS/GLES behavior rather than a LOVE-only renderer path.

The immediate regression was BYTEPATH rendering its 480x270 game through RGBA4 canvases because Kandelo did not advertise RGBA8 render-target support on the GLES query path. BYTEPATH uses neutral 127-gray displacement maps for RGB glitch shaders; RGBA4 quantization moved that neutral value far enough to produce exaggerated red/green/blue copies. Advertising the equivalent GLES capability (GL_OES_rgb8_rgba8) keeps native renderers on RGBA8 targets and restores the intended small channel separation.

Changes

  • Expose GL_OES_rgb8_rgba8 from the WebGL-backed GLES query path so native GLES renderers can use RGBA8 render targets.
  • Make glReadPixels handle packed, 16-bit, and 32-bit formats with correct byte sizing and chunked reads under the GL query cap.
  • Match browser readPixels destination typed arrays to packed GL types, including unaligned output spans.
  • Replace the earlier KMS maxCssScale presentation knob with generic presentation.kms.fit: "contain" | "stretch" metadata.
  • Let KMS demo metadata declare fixed target-resolution scanouts that the browser canvas can stretch, leaving user software at its original target resolution.
  • Add a Chromium browser regression test that boots BYTEPATH gameplay through the native KMS/GLES path, captures the raw KMS canvas, and asserts full-pane fill plus bounded RGB channel separation.
  • Keep the LOVE native package on the upstream renderer and document the browser presentation contract.

Why LOVE Is Still In The PR

This PR is non-LOVE-specific at the platform layer, but it still carries LOVE package and demo metadata because that is the current end-to-end proof. BYTEPATH and SNKRX exercise fixed-resolution KMS presentation, GLES render-target selection, shader-driven post-processing, and browser canvas scaling in a way the simpler framebuffer demos do not.

There is no Kandelo runtime branch that detects BYTEPATH, SNKRX, or LOVE to fake success. The LOVE-specific pieces are package/build inputs and demo metadata for real consumers of the generic KMS/GLES path.

Evidence

Check Result
git diff --check passed
scripts/dev-shell.sh bash scripts/build-gles-stubs.sh passed
scripts/dev-shell.sh bash packages/registry/love/build-love.sh passed; patch applies and love.wasm rebuilds
scripts/dev-shell.sh bash images/vfs/scripts/build-shell-vfs-image.sh passed; shell VFS rebuilt with LOVE runtime
../scripts/dev-shell.sh npx vitest run test/webgl-bridge.test.ts from host/ passed: 25 tests
scripts/dev-shell.sh npx vitest run web-libs/kandelo-session/test/kandelo-session.test.ts passed: 46 tests
../../scripts/dev-shell.sh env KANDELO_PLAYWRIGHT_PORT=5424 CI=1 npx playwright test test/kandelo-kms-gles-rendering.spec.ts --project=chromium from apps/browser-demos/ passed

Final BYTEPATH browser capture from the renamed Playwright run:

Capture Backing store CSS rect Fill RGB shift
10s gameplay 480x270 2048x1045 width=1, height=1 rg=1, rb=2
22s gameplay 480x270 2048x1045 width=1, height=1 rg=1, rb=2

The same browser run syslog showed the normal native renderer path only:

  • love: using KMS/EGL/GLES presenter on /dev/dri/card0
  • love: using upstream LÖVE OpenGL renderer on Kandelo KMS/EGL

Contract Notes

  • Browser-facing KMS presentation behavior changed through image metadata.
  • Host WebGL behavior changed for the browser KMS path. Node-visible POSIX behavior is unchanged.
  • ABI was not changed.
  • Package source/build inputs changed; local LOVE and shell VFS artifacts were rebuilt for validation, but binary release indexes were not published.

Not Run

  • Full browser Playwright suite.
  • POSIX/libc/Sortix conformance suites.
  • Full ./run.sh browser end-to-end manual flow.

@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 4abed8b4
libcurl wasm32 built 1d458751
libcxx wasm32 built d1bd7b31
libcxx wasm64 built 32af8393
libpng wasm32 built 3e1c079a
libxml2 wasm32 built 40a555ff
libxml2 wasm64 built fe951af3
lua wasm32 built 30dd472d
openssl wasm32 built 616986d6
openssl wasm64 built 825b6bb0
sqlite wasm32 built 484ab226
sqlite wasm64 built 76a2e894
zlib wasm32 built 4e4b009a
zlib wasm64 built d74a24d9
bc wasm32 built c56a0f4a
bzip2 wasm32 built 93333409
coreutils wasm32 built 5d7fdd33
curl wasm32 built 09a5488b
dash wasm32 built 3922aedb
diffutils wasm32 built 221e6447
dinit wasm32 built 9bbdabcc
fbdoom wasm32 built c227df15
file wasm32 built a07a9688
findutils wasm32 built 078849a6
gawk wasm32 built 0f34002e
git wasm32 built 7d03e863
grep wasm32 built 26871459
gzip wasm32 built 76e14b50
hello wasm32 built 32acb009
kandelo-sdk wasm32 built 81ef91ef
kernel wasm32 built 6cc63019
less wasm32 built 20f67825
love wasm32 built fb1813ea
lsof wasm32 built ed775e1b
m4 wasm32 built ffea6883
make wasm32 built 2188afba
mariadb wasm32 built 901e4053
mariadb wasm64 built 61d4ca00
modeset wasm32 built 8eb6bcf6
msmtpd wasm32 built 5d951703
nano wasm32 built d7a89326
ncurses wasm32 built daf5b7ce
netcat wasm32 built c3c36f9f
nginx wasm32 built 35da7db3
php wasm32 built f92498f8
posix-utils-lite wasm32 built 82c894c1
sed wasm32 built 4ca55777
spidermonkey wasm32 built 408b1d23
tar wasm32 built 4d433ca8
tcl wasm32 built 39a98ff1
unzip wasm32 built 0a32037f
userspace wasm32 built 496aa079
vim wasm32 built 78cc6068
wget wasm32 built 411ae16e
xz wasm32 built 17f29bbb
zip wasm32 built 40ff04a9
zstd wasm32 built 305c5946
bash wasm32 built 1744b60a
mariadb-test wasm32 built 9ff37770
mariadb-vfs wasm32 built bb356df2
mariadb-vfs wasm64 built 4a0e15b4
nethack wasm32 built 3de70420
node wasm32 built 970219b3
spidermonkey-node wasm32 built bace1832
vim-browser-bundle wasm32 built 398d9ac4
nethack-browser-bundle wasm32 built 0c33c114
rootfs wasm32 built f4a664f0
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.

@brandonpayton brandonpayton changed the title Render LOVE demos through native KMS scanout modes Fix LOVE KMS rendering precision and browser scaling Jul 5, 2026
@brandonpayton brandonpayton changed the title Fix LOVE KMS rendering precision and browser scaling Support fixed-resolution KMS/GLES rendering and RGBA8 canvases Jul 5, 2026
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.
Expose the RGBA8 render-target capability through the GLES extension string so LOVE keeps RGBA8 canvases instead of falling back to RGBA4, which exaggerated BYTEPATH's RGB shader offsets. Add safer packed readback sizing/typing for glReadPixels.

Add stretch-fit KMS presentation metadata for LOVE demos and a Chromium browser regression test that boots BYTEPATH gameplay, captures the raw KMS canvas, and asserts full-pane scaling plus bounded RGB channel separation.
@brandonpayton brandonpayton force-pushed the emdash/love-target-resolution-upscale branch from 5828b1d to 18a7de2 Compare July 5, 2026 14:23
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