- 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>
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>