NVIDIA's Wayland EGL implementation sets explicit-sync acquire and
release points while presenting a frame. The requests emitted by
eglSwapBuffers and its final surface commit must be treated as one
logical transaction.
The pointer-warp path can commit the main surface from the input
thread while the render thread is inside eglSwapBuffers. If this
occurs between the explicit-sync requests, the cursor commit applies
incomplete pending state and the compositor disconnects the client
with:
explicit sync is used, but no release point is set
Add a surface lock and hold it across EGL presentation. Use the same
lock for direct commits, frame callback registration, and
pointer-constraint updates, replacing the narrower confinement lock.
This prevents another thread from splitting the EGL transaction and
removes the need for __NV_DISABLE_EXPLICIT_SYNC=1.
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.
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.
Avoid querying playback timing on every graph cycle. Refresh backend
latency only when audio diagnostics request it, and defer callback
errors for reporting from non-realtime contexts.
Move microphone delivery to a bounded SPSC queue drained by a sender
thread. This keeps PureSpice locking and socket writes out of the
PipeWire capture callback while bounding overload behavior.
Validate and recycle capture buffers before enqueueing their contents.
These changes improve deadline margin when using small period sizes.
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.
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.
Validate mastering primaries and luminance independently so one
unsupported component does not discard the other.
Trust content chromaticities when extended target volumes are supported,
and report the exact values and reason when metadata must be omitted.
Convert HDR scRGB input to normalized linear Rec.2020 before CAS, then
convert the filtered result back to scRGB. Use the content metadata to
select an appropriate normalization peak while leaving SDR unchanged.
This follows AMD's documented recommendation for applying CAS to HDR
content and prevents HDR highlights from being clamped and dimmed.
PQ sources excluded every external filter from the post-process chain.
Decode PQ/BT.2020 into FP16 linear scRGB before active effects and pass
the resulting transfer state to the desktop shader.
Keep the raw PQ path when no effect is active. This avoids adding a
conversion pass or per-frame latency to the common case.
Describe PQ pixels with the protocol-defined primary luminance range and
keep mastering luminance in the target volume. Track extended target-volume
support and omit unsupported metadata instead of creating an invalid image
description.
Keep the reference white associated with the active PQ description until
a replacement is ready. If asynchronous description creation fails, the
renderer now retains the complete previous HDR state instead of combining
new white-level values with stale compositor metadata.
Decode PQ/BT.2020 desktop pixels into an FP16 linear scRGB target before
compositing the color cursor, ImGui, damage overlay, and letterboxing.
Encode the damaged result to PQ once at the surface boundary. Keep logical
AND/XOR cursor masks in the encoded domain.
This preserves premultiplied cursor edges, prevents encoded-domain
blending, uses the Wayland output reference white for local overlays, and
keeps guest cursor white and display calibration independent from frame
SDR white. It also corrects HDR-to-SDR absolute luminance scaling, gamut
matrices, black handling, and buffer-age repair for the extra pass.
Suppress overlays when their conversion framebuffer is unavailable rather
than allowing unconverted sRGB draws into an HDR target.
Use named transfer constants for cursor shader state. Convert clipped
surface rectangles explicitly before using the frame-damage merge helper,
which avoids mixing its unsigned type with the EGL surface rectangle type.
Only advertise native PQ when the FP16 composition target is available.
SDR and native scRGB retain their direct single-pass paths.