Commit graph

34 commits

Author SHA1 Message Date
Hellings
739e24b38b Initial commit 2026-10-26 00:05:21 -04:00
Hellings
30102c9871 initial commit 2026-10-25 23:44:14 -04:00
Allie H
877455b386 Rm Electron logs 2026-03-11 17:35:57 -04:00
Allie H
68b4916f64 Further optimization passes 2026-03-11 17:35:46 -04:00
Allie H
ff54140d62 Further optimization passes 2026-03-11 09:19:47 -04:00
Stephen Hellings
8b640d9f91 Lazily enable HW accel for Electron windows 2026-03-10 18:01:55 -04:00
Stephen Hellings
ca8c1246ce Env variable passing 2026-03-10 17:38:36 -04:00
Stephen Hellings
0a1c22035b Optimize Electron bridge FPS: rx buffer, flush latency, OSR dirty rects
- Replace Buffer.concat on IPC rx path with a growing ring buffer (rxAppend/rxConsume)
- Replace setTimeout(flushSurfaceBuffers, 10) with setImmediate() to cut 10ms per frame
- Use OSR paint dirty rect for partial DamageBuffer updates instead of full-frame copy

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-10 17:09:55 -04:00
Stephen Hellings
0a72ec60bf Fix rendering efficiency and screencopy Y-flip
Rendering: Skip the full bind/clear/draw/finish/submit cycle when
nothing visual has changed (no new Electron frames, no dirty Wayland
surfaces, no cursor movement). In the DRM path, also skip when no
screencopy or portal streams are active. Frame callbacks are always
sent unconditionally to prevent Wayland client stalls.

Screencopy: Remove the incorrect row-flip after glReadPixels in both
the wlr-screencopy fulfillment and portal stream readback paths.
Smithay already applies a Y-correction when rendering to GBM-backed
FBOs, so glReadPixels returns top-down data. The manual flip was
inverting an already-correct image, producing upside-down output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-10 13:43:34 -04:00
Stephen Hellings
0bede114a6 Remove garbage GPTed readme 2026-03-10 13:11:57 -04:00
Stephen Hellings
104261d74c Further optimization passes 2026-03-10 10:26:14 -04:00
Stephen Hellings
03b73066cb Get rid of that nohup 2026-03-10 09:34:14 -04:00
Stephen Hellings
da9a49ea8d Significant render opts 2026-03-10 09:33:57 -04:00
Stephen Hellings
d1c993e295 Whatever bro 2026-03-09 21:59:18 -04:00
Stephen Hellings
42b111410c Again 2026-03-09 21:32:16 -04:00
Stephen Hellings
4fe557c536 fix: register Wayland display/socket fds with calloop to fix DRM rendering stall
The DRM event loop only woke for registered calloop sources (VBlank,
libinput, session). When the VBlank rendering cycle broke (transient
page-flip failure, timing edge), nothing woke the loop to restart it —
only input events (mouse movement) would un-stall rendering.

Three changes:

1. Register the Wayland display poll_fd as a calloop source so client
   surface commits immediately wake the event loop and trigger
   render_frame via the main callback.

2. Register the listening socket fd so new Wayland client connections
   also wake the loop promptly.

3. Add a periodic timer (fires every frame_time ≈ 16ms) as a safety net
   to restart stalled VBlank cycles even with no input or client
   activity.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-09 19:24:33 -04:00
Stephen Hellings
83cdaffd05 Cry 2026-03-09 18:07:07 -04:00
Stephen Hellings
d28e50fcf9 Attempt 5... 2026-03-09 15:54:44 -04:00
Stephen Hellings
d4c8d1c465 Attempt 5... 2026-03-09 15:54:29 -04:00
Stephen Hellings
e245af128c fix: add frame.finish() to flush GL commands, fix IPC write ordering
Two critical fixes:

1. **Flickering (GL frame not finalized)**: render_frame was missing
   the frame.finish() call that nested.rs has (line 688). Without it,
   GL rendering commands are never flushed to the GBM BO, so the DRM
   page flip scans out a buffer with stale/incomplete pixel data,
   alternating between rendered and unrendered content every frame.

2. **IPC protocol corruption (EPIPE/ECONNRESET)**: Node's socket.write()
   is async and buffers data in userspace. The native sendFd() call
   (sendmsg with SCM_RIGHTS) goes directly to the kernel, racing ahead
   of the buffered header+plane bytes. The compositor then reads the
   1-byte SCM_RIGHTS dummy as the next message magic, hits 'unknown
   magic', and the IPC reader thread exits — closing the socket (EPIPE).
   Fix: use fs.writeSync() on the raw fd for header+plane data so it
   reaches the kernel buffer before sendFd's sendmsg.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-09 14:31:47 -04:00
Stephen Hellings
6c487d6b75 fix: swapchain slot retention to eliminate flickering, add keyboard_key action, align maximize with nested.rs
Three fixes:

1. **Flickering (every-other-frame)**: Swapchain slots were dropped
   immediately after page_flip, setting acquired=false so the next
   acquire() could return the same GBM BO currently being scanned out
   by the CRTC. Added current_slot field to EventLoopData that holds
   the submitted slot until the next frame replaces it, preventing
   buffer reuse during scanout.

2. **Missing keyboard_key action**: The DRM codepath was missing the
   'keyboard_key' custom action handler that nested.rs has. Added it
   with evdev→XKB keycode conversion and keyboard.input() dispatch.

3. **Maximize alignment**: DRM maximize was clamping to size hints and
   centering horizontally, while nested.rs uses full output width.
   Aligned to match nested.rs behavior.

4. **z_order sorting**: Electron window rendering now sorts by z_order
   to match nested.rs's chain+sort approach.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-09 13:30:45 -04:00
Stephen Hellings
5123aac2d4 fix: merge [[root]] entries into config.windows and force initial modeset
Two critical bugs causing a black/off screen:

1. [[root]] window configs were spawned as Electron processes but never
   added to config.windows. The render loop, window_mapped state, and
   respawn logic all iterate config.windows — so root windows were
   invisible. Fix: merge root entries (with fullscreen geometry and low
   z_order) into config.windows before WoState::new(), so all subsystems
   see them uniformly.

2. When the display manager (Ly) leaves the CRTC in a state Smithay
   considers 'already committed' (matching mode/connectors),
   commit_pending() returns false and only page_flip() is used.
   page_flip without a prior modeset can 'succeed' but produce no
   visible output because the CRTC was never properly activated with
   a framebuffer. Fix: force a full modeset commit (ALLOW_MODESET) on
   the very first frame (total_flips==0) regardless of commit_pending.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-09 13:16:00 -04:00
Stephen Hellings
b82a9ca9c3 fix: clear IPC socket timeout after handshake, add vblank recovery and render diagnostics
Three bugs addressed:

1. SO_RCVTIMEO(5s) on the IPC socket was never cleared after the HELLO
   handshake. When the web page becomes static (no paint events for >5s),
   the blocking read_exact in recv_message times out, the IPC reader thread
   exits, and the socket is closed — causing ECONNRESET on the Electron
   side and permanently stalling frame delivery. Fix: clear SO_RCVTIMEO
   to zero (infinite) immediately after successful HELLO exchange.

2. If a VBlank event is lost or delayed (e.g. during DRM master transitions),
   vblank_pending stays true and all subsequent render_frame calls bail out
   permanently. Fix: if vblank_pending has been stuck for >500ms, force-clear
   it with a warning so rendering can resume.

   making it impossible to diagnose the black screen from logs. Fix: add
   INFO-level logging for first render, first page flip, first texture
   import, swapchain exhaustion on first frame, and vblank recovery events.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-09 13:08:59 -04:00
Stephen Hellings
ae528b5132 fix: Electron offscreen rendering and DRM render node propagation
Three root causes prevented Electron frames from reaching the compositor:

1. --disable-gpu killed Chromium's rendering pipeline, preventing the
   'paint' event from firing in offscreen mode. Replaced with
   --use-gl=swiftshader so Chromium can composite internally while the
   native wo_dmabuf module handles GPU buffer allocation separately.

2. DISPLAY=:0 with no X server caused Electron to fail silently on
   pure Wayland sessions (Ly/logind). Replaced with
   --ozone-platform=headless which lets Chromium's OSR pipeline work
   without any display server connection.

3. WO_DRM_RENDER_NODE was never set, so the native wo_dmabuf.node
   module always defaulted to /dev/dri/renderD128 regardless of which
   GPU the compositor actually opened. Now resolved via sysfs
   (card1 -> renderD128, card2 -> renderD129, etc.) and passed through
   to Electron.

Also: retry EACCES/EPERM as transient during DRM device open (logind
session activation can lag behind libseat's is_active() flag on Ly).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-09 12:31:09 -04:00
Stephen Hellings
eee56bc5f4 Attempt 4... 2026-03-09 11:35:01 -04:00
Stephen Hellings
4dcb10d9f1 Attempt 3 to fix launching permission denied 2026-03-09 11:21:08 -04:00
Stephen Hellings
5e154e19f9 Attempt 2 to fix launching permission denied 2026-03-09 09:45:30 -04:00
Stephen Hellings
d9fa1323c3 More robust retries when page flip fails 2026-03-09 03:22:10 -04:00
Stephen Hellings
cbe2dd43bd Do not use npm for pkg 2026-03-08 23:39:36 -04:00
Stephen Hellings
d184ab69e4 Fix types + build issue 2026-03-08 23:38:12 -04:00
Stephen Hellings
e03fe3739f Commit lockfile 2026-03-08 23:27:48 -04:00
Stephen Hellings
ee5b7f764e Upd PKGBUILD 2026-03-08 23:22:34 -04:00
stephen hellings
e442ad43a0
Create LICENSE 2026-03-08 23:12:27 -04:00
Stephen Hellings
33359b814e Initial commit 2026-03-08 23:04:02 -04:00