Commit Graph

880 Commits

Author SHA1 Message Date
Geoffrey McRae
142dc2bcef [client] input: track pointer confinement state 2026-08-06 18:02:07 +10:00
Geoffrey McRae
1baa5a3710 [client] input: gate motion on active capture 2026-08-06 18:02:07 +10:00
Geoffrey McRae
a2a185a95b [client] input: fix rotated cursor scaling 2026-08-06 18:02:07 +10:00
Geoffrey McRae
bbb168aafd [client] input: round warps past viewport edges 2026-08-06 18:02:07 +10:00
Geoffrey McRae
e9a16ef523 [client] input: add cursor transition diagnostics
Add opt-in sequence-numbered tracing across the core and Wayland
mouse paths.
2026-08-06 13:19:27 +10:00
Geoffrey McRae
c7ed04412e [client/idd/obs] scheduler: isolate timing owner delivery 2026-08-05 15:45:30 +10:00
Geoffrey McRae
afb80e0ae4 [client] overlay: render splash fade from monotonic time
Move splash transitions onto the render thread and derive opacity from
elapsed monotonic time. Pace active animation at a display-compatible
minimum of 60 Hz while allowing incoming frames to satisfy that demand.

Reset the splash cleanly across reconnects and latch state changes with
the full-frame restoration decision.
2026-08-05 11:58:32 +10:00
Geoffrey McRae
12f6485e52 [client/obs] scheduler: correct phase feedback
Only report the client queue lead when JIT rendering provides a valid
measurement. Clamp linear phase errors instead of wrapping them into the
opposite direction at half of a refresh period.

Timestamp OBS frames after the shared framebuffer becomes ready.
2026-08-05 11:52:44 +10:00
Geoffrey McRae
2c74f4a0f9 [client] display: use trusted nominal cadence
Always track Wayland surface outputs alongside fractional scaling and use
RandR modes for X11 cadence. Remove render-derived feedback so a
throttled client cannot teach the producer to remain throttled.

Release scheduling after nominal output timing remains unavailable.
2026-08-05 11:50:48 +10:00
Geoffrey McRae
d815ef87d5 [client] overlay: restore every splash fade frame
Mark the active fade as requiring a fully restored render target.
This also covers guest-driven renders between animation ticks so they
cannot blend over stale splash content.
2026-08-05 10:53:52 +10:00
Geoffrey McRae
606a06535e [client] overlay: keep the splash fade on fresh buffers
Fully invalidate the render target when the full-screen splash changes.
This restores the desktop before alpha blending and prevents stale fade
states from cycling between swapchain buffers when guest updates are
sparse.
2026-08-05 10:24:57 +10:00
Geoffrey McRae
5be46121a2 [client/idd] preserve frame timing across reconnects 2026-08-04 13:49:07 +10:00
Geoffrey McRae
5ebc208d43 [client/idd] harden demand-driven frame delivery 2026-08-04 13:49:07 +10:00
Geoffrey McRae
97e7f439c2 [client/idd] align frame delivery to presentation 2026-08-04 13:49:07 +10:00
Geoffrey McRae
b23430b9a8 [client] report presentation cadence over LGMP 2026-08-04 13:49:07 +10:00
Geoffrey McRae
9025653a24 [client] limit overlay swaps to minimum render rate
Treat every completed swap as satisfying the interactive overlay
refresh requirement. Only force a JIT overlay render after the 60 Hz
deadline, and rearm the timer-based deadline after frame-driven swaps.

This prevents interactive overlays from adding redundant swaps when
incoming frames already keep the client at or above the required rate.
2026-08-03 23:53:33 +10:00
Geoffrey McRae
cb5b9ab292 [client] round overlay damage outward
Expand ImGui window damage to include its border and round both logical
window bounds and framebuffer-scaled bounds outward.

This prevents a one-pixel strip of stale desktop content when an
overlay window is resized at fractional positions or display scales.
2026-08-03 23:53:33 +10:00
Geoffrey McRae
fbe08d00ce [client] expose EGL stages in frame latency
Correlate received frames with the texture update actually consumed by
the renderer and retain damage until its token becomes renderable.

Split client latency into dispatch, import, queue, preparation, setup,
effects, desktop, composition, and swap stages in FRAME LATENCY.
Exclude diagnostic overlay work from composition and preserve client
wait time when producer timing is unavailable.

Publish joined samples through a bounded token queue, avoid sleeping
while producer timing is finalized, and correct Wayland photon units.
2026-08-03 23:53:33 +10:00
Geoffrey McRae
24be0a8869 [host] measure ready time at framebuffer publication
Exclude command queue reset and cleanup from the ready stage, and keep
the wall-clock residual only as the legacy timing fallback.
2026-08-03 23:53:33 +10:00
Geoffrey McRae
4f39270736 [client] add ImPlot and rework latency graphs 2026-08-03 23:53:33 +10:00
Geoffrey McRae
7533c855c2 [client/host/idd/lgmp] add additional timing metrics 2026-08-03 23:53:33 +10:00
Geoffrey McRae
47905ec65e [client] spice: update to properly support all cursor types 2026-08-01 15:43:30 +10:00
Geoffrey McRae
08993d3e1e [client] core: use portable alloc_sprintf instead of asprintf
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
build / client-tests (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client-tests (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client-tests (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client-tests (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client-tests (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client-tests (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client-tests (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client-tests (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
2026-07-31 14:01:08 +10:00
Geoffrey McRae
1a2e92beae [client] tests: replace test defines with the unified ENABLE_TEST define 2026-07-31 13:35:50 +10:00
Geoffrey McRae
66547fc090 [client] font: skip stb-incompatible UI font faces 2026-07-31 13:25:00 +10:00
Geoffrey McRae
9417a71264 [client] lgmp: fix timeout due to improper handling of pause/resume 2026-07-31 12:57:09 +10:00
Geoffrey McRae
33c81d2cf5 [client] audio: enable building without audio support
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
build / render-tests (push) Has been cancelled
Fixes #1183
2026-07-30 16:16:04 +10:00
Geoffrey McRae
74ae4f543e [client] tests: add framebuffer rendering validation
Add an optional EGL framebuffer capture path for the test transport.
Capture the fully composed frame before presentation and retain its
surface format and HDR state for validation.

Add GoogleTest integration tests which run the production client
under a headless Weston compositor and compare every output pixel
against an independent reference implementation.

The matrix covers BGRA, RGBA, BGR32, RGB24, PQ RGBA10 and scRGB
RGBA16F with full, moving, overlapping, maximum-count, invalid, null
and zero-area damage rectangles. Validate HDR-to-SDR conversion and
native HDR output metadata when supported by the compositor.

Keep tests opt-in through ENABLE_RENDER_TESTS and document how to run
the software and native HDR tiers.
2026-07-30 15:23:03 +10:00
Geoffrey McRae
a1fc3d20d3 [client] wayland: allow seatless operation for github CI testing 2026-07-30 15:23:03 +10:00
Geoffrey McRae
f5dee45adc [client] renderers: only rebuild the font atlas if marked dirty 2026-07-30 15:14:29 +10:00
Geoffrey McRae
4f02eda913 [client] overlay: add ImGui support for non-latin characters 2026-07-30 12:39:47 +10:00
Geoffrey McRae
a9b8f437d4 [client] overlay: show layout-translated hotkey labels
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Related to #1298
2026-07-30 10:30:47 +10:00
Geoffrey McRae
e754f5841e [client] keybind: use physical keycodes for layout-independent hotkeys
Fixes #1298
2026-07-30 10:21:26 +10:00
Geoffrey McRae
deb447c3ce [client] kb: add support for missing key mappings
Fixes #1321
2026-07-30 10:03:14 +10:00
Geoffrey McRae
8fb355e6b7 [client] overlay: guard ImGui table and tab bar scopes 2026-07-30 09:17:09 +10:00
Geoffrey McRae
510f6e8e14 [client] overlay: stabilize configuration ImGui IDs 2026-07-30 09:12:55 +10:00
Geoffrey McRae
9c24acc6f9 [client] overlay: fix unsafe ImGui string handling 2026-07-30 09:08:25 +10:00
Geoffrey McRae
0738ea402a [client] overlay: fix invalid label usage in igPlotLines call 2026-07-30 08:55:03 +10:00
Quantum
1af909adae [client] main: display spice VM name in process title 2026-07-30 07:52:24 +10:00
Geoffrey McRae
36b33033a1 [client] transport: introduce pluggable frame transports
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Move shared-memory ownership, LGMP session handling, queue access, and
DMA setup behind a transport interface. The LGMP backend preserves the
existing zero-copy frame and DMA paths while owning its lgmp:* options.

Expose the initialized EGL context through a versioned renderer interop
record for future accelerated decode backends. Add an LGMP-independent,
deterministic test transport for graphics-pipeline validation.
2026-07-29 13:36:49 +10:00
Geoffrey McRae
5196c5503a [client] main: prevent accidental access to appState without accessors
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
2026-07-29 12:39:10 +10:00
Geoffrey McRae
56ad487d0a [common] debug: set the crash handler process name 2026-07-29 12:39:10 +10:00
Geoffrey McRae
6dd91a1269 [common] debug: unwind all threads and print on force quit 2026-07-29 12:39:10 +10:00
Geoffrey McRae
61f00ae625 [client] hdr: refactor name to clean up log output 2026-07-29 12:39:10 +10:00
Geoffrey McRae
737614bc69 [client] audio: redesign playback synchronization
Model playback latency from the device period, arrival jitter, source
packet phase, and resampler delay. Treat audio:latencyOffset as an
explicit addition to this minimum and align the first device pull to
the next packet deadline. This starts playback near its steady-state
target without unnecessary prefill or startup underruns. Use a
512-frame default period as a practical low-latency baseline.

Replace the startup clock hold with a one-sided proportional
acquisition controller, then hand off to source/device rate
feed-forward and a slow phase loop. Calibrate the logical device
timeline at handoff, discard correction that opposes the current
error, and slew-limit rate changes. This prevents startup drain,
integral wind-up, overshoot, and long convergence while preserving
clock-drift compensation.

Allow audio backends to expose a real-time resampler and use
PipeWire's adaptive resampler when version 1.4 or newer supports it.
Retain libsamplerate as the fallback and add audio:resampler to select
the implementation. Wait for PipeWire stream setup to complete and
propagate rate-control failures cleanly.

Track PipeWire input-consumption and output-equivalent clocks
separately. The input clock measures ring latency while the output
clock drives feed-forward using the ratio that governed each request.
This removes delayed self-feedback that made adaptive resampling
oscillate between the correction limits.

Reduce audio:debug output to useful latency, clock, jitter, and xrun
values, and scale the playback graph from the startup estimate. Update
the option names and documentation for the new latency model.
2026-07-29 12:39:08 +10:00
Geoffrey McRae
814f1797fe [client] audio: reduce playback startup delay 2026-07-28 23:49:45 +10:00
Geoffrey McRae
739931fca3 [client] audio: include the jitter in the target calculation 2026-07-28 23:45:11 +10:00
Geoffrey McRae
76230726cc [client] audio: harden playback at small period sizes
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Bound playback writes and synchronization slews to the physical ring
storage, preventing overwritten samples from being treated as valid PCM.
Trigger clock resynchronization when output must be dropped.

Wait for enough startup audio to cover backend demand and a complete
source packet. Generate silence if playback begins early instead of
rewinding the reader into stale ring storage.

Honor PipeWire playback frame requests and fully initialize empty chunks.
This keeps playback reliable when using small device period sizes.
2026-07-28 22:59:08 +10:00
Geoffrey McRae
d956dd8fd3 [client] audio: rework synchronization for low latency
Drive playback timing from audio sample positions instead of packet
arrival cadence. Use SPICE multimedia timestamps to anchor streams,
detect discontinuities, and estimate the long-term source rate. Ignore
their coarse phase corrections when steering the playback buffer.

Measure the device clock independently and wait for it to stabilize
before enabling a bounded, slew-limited phase controller. Align startup
buffering from logical producer and consumer positions so backend
startup reserves do not become persistent latency.

Size the buffer from the backend period, measured delivery jitter, and
resampler delay. Update PipeWire and PulseAudio to report their actual
startup requirements and presentation latency. Default to a 10 ms
device period with 4 ms of additional buffering, and make detailed
synchronization diagnostics opt-in through audio:debug.

This reduces startup and steady-state latency while compensating for
physical and virtual device clock drift without reacting to transport
jitter or SPICE timestamp quantization.
2026-07-28 21:07:02 +10:00
Geoffrey McRae
dc20ac05ab [client] main: fix release build uninitalized value warning 2026-07-28 13:42:38 +10:00