High-performance, peer-to-peer macOS host to Windows 10+ display streaming daemon built in Rust.
Renderd is an open-source, ultra-low-latency peer-to-peer display streaming system designed specifically for using a Windows PC (Windows 10 or later) as a secondary high-refresh-rate desktop display for a macOS host workstation. Operating directly over QUIC/UDP with hardware-accelerated video pipelines (ScreenCaptureKit and VideoToolbox on macOS; Direct3D12 and MediaFoundation on Windows), Renderd delivers sub-16ms latency display mirroring without cloud relays or intermediary servers.
Note
Renderd has achieved its first end-to-end macOS remote desktop stream! The complete real-time host-to-viewer pipeline is verified working: zero-copy ScreenCaptureKit screen capture, VideoToolbox hardware HEVC encoding, QUIC datagram transport, mDNS service discovery, session handshake, sliding-window datagram reassembly, VideoToolbox hardware decoding, BGRA pixel buffer extraction, and SoftRenderer presentation with continuous live desktop updates. All 147 workspace unit & integration tests pass.
Software display extensions between macOS and Windows endpoints have historically suffered from fundamental latency, image quality, and architecture compromises:
- Proprietary Relays & Subscription Paywalls: Most commercial cross-platform display applications route video frames through remote cloud servers or require subscription services.
- High Latency & Frame Stutter: Protocols built on top of WebRTC or TCP struggle with jitter control and frame pacing on high-refresh-rate displays (120Hz/144Hz).
- Lack of macOS Host → Windows Viewer Synergy: Existing open-source tools (like Sunshine/Moonlight) are optimized primarily for Windows hosts streaming to client devices. There is no dedicated, lightweight daemon for a macOS host streaming to a Windows 10 or later viewer.
Renderd solves this by pairing Apple's zero-copy ScreenCaptureKit and VideoToolbox hardware encoder directly with Windows' low-overhead Direct3D12 / MediaFoundation decoder over a custom QUIC transport layer.
| Feature / Metric | Apple Sidecar | Luna Display | Sunshine / Moonlight | DeskIn / Duet | Renderd |
|---|---|---|---|---|---|
| Host Support | macOS | macOS / Windows | Windows / Linux | macOS / Windows | macOS 13+ (Apple Silicon) |
| Viewer Support | iPadOS only | iPadOS / Mac / Win | Multi-platform | Multi-platform | Windows 10+ (x86_64 / ARM64) |
| Protocol Transport | Proprietary AWDL | Proprietary Wi-Fi/USB | WebRTC / Custom UDP | Cloud Relay / TCP | QUIC Datagrams / UDP |
| Hardware Video Pipeline | AVFoundation | Custom Dongle | NVENC / AMF / VAAPI | Software / HW hybrid | ScreenCaptureKit → D3D12 |
| Vsync Phase Sync | ❌ No | ❌ No | ❌ No | ❌ No | ✅ Yes (~16.7ms phase alignment) |
| Cloud Dependency | iCloud Auth | None | None | Cloud Account | Zero (100% Peer-to-Peer) |
| Open Source | ❌ No | ❌ No | ✅ Yes | ❌ No | ✅ Yes (MIT License) |
Renderd separates control plane signaling (QUIC Stream 0 with Protobuf framing) from data plane frame delivery (QUIC Datagrams with 16-byte fixed headers).
flowchart LR
subgraph macOS Host ["macOS Host (Renderd Host Daemon)"]
SCK["ScreenCaptureKit\n(Zero-Copy Frame Capture)"] --> VT["VideoToolbox\n(HEVC / H.264 HW Encoder)"]
VT --> FRAG["Frame Fragmenter\n(Sliding-Window Datagrams)"]
FRAG --> QUIC_H["QUIC Engine (quinn)\n(Stream 0 Control + Datagrams)"]
end
subgraph Transport ["Network Layer (Peer-to-Peer UDP)"]
QUIC_H <== "Control Envelopes (Proto3)" ==> QUIC_V["QUIC Engine (quinn)"]
QUIC_H -. "Sub-16ms Video Datagrams" .-> QUIC_V
end
subgraph Windows Viewer ["Windows 10+ Viewer (Renderd Viewer Client)"]
QUIC_V --> REASS["Fragment Reassembler\n(Sliding-Window, W=4 Frames)"]
REASS --> MF["MediaFoundation\n(Hardware Video Decoder)"]
MF --> D3D12["Direct3D12 Renderer\n(Zero-Copy Swapchain Present)"]
end
┌──────────────────────────────────────────────────────────────────┐
│ Stream 0 (Control Plane): [u32 length][Protobuf Envelope] │
├──────────────────────────────────────────────────────────────────┤
│ Datagrams (Data Plane): [16-byte Fragment Header][Payload] │
└──────────────────────────────────────────────────────────────────┘
renderd-proto: Shared Protobuf definitions, envelope validation, and domain newtypes (FrameId,FragmentId,BitrateKbps).renderd-config: Layered configuration loader with TOML template defaults, environment variable overrides (RENDERD_*), and CLI flag parsing.renderd-frame: Low-overhead 16-byte fragment header codec and out-of-order sliding-window reassembly state machine.renderd-clock: Presentation clock estimation, rolling network statistics, and monotonic instant tracking for vsync phase alignment.renderd-abr: Adaptive Bitrate control algorithm with AIMD state transitions, panic state keyframe requests, and bandwidth probing.renderd-crypto: SPAKE2+ P-256 key exchange (RFC 9382), HKDF-SHA256 key derivation, and TLS 1.3 certificate generation.renderd-vt-sys: Safe C/FFI bindings to Apple'sVideoToolboxframework for hardware video encoding.renderd-sc-sys: Safe C/FFI bindings to Apple'sScreenCaptureKitframework for zero-copy GPU frame capture.renderd-net: QUIC transport engine (QuicServer/QuicClient), 4-byte length-prefixed control stream framing, non-yielding datagram burst sender, and smooth path RTT telemetry exporter.renderd-keychain: Platform-agnosticKeychainStoreinterface with macOS Keychain Services (kSecClassGenericPassword), Windows Credential Manager (CredWriteW/CredReadW), and headless mock stores.renderd-discovery: mDNS peer discovery with macOS Bonjour (dns_sd.h), Windows Win32 mDNS (DnsServiceRegister/DnsServiceBrowse), and static IP resolution fallbacks.renderd-host: macOS host daemon orchestrating all subsystems viaHostApp::run():CapturePipeline(zero-copy ScreenCaptureKit frames),EncodePipeline(VideoToolbox HEVC hardware encoder with SPSC ring buffer),ClockController(vsync pacing fromVsyncReport),AbrManager(dual-timescale bitrate decisions),HostSession(IDLE → PAIRING → CONNECTED → STREAMINGstate machine),NetworkManager, andUiManager(macOS menu bar and user notifications). Runs persistently via SIGINT/SIGTERM signal handler.renderd-viewer: Windows viewer display application featuring nativewinitevent loop management, Per-Monitor v2 DPI awareness, D3D12 swap chain and YUV-to-RGB shader renderer,ID3D12VideoDecoderhardware video decoder, datagram receiver and sliding-window reassembly task, DWM vsync phase reporter (VsyncReportvia QUIC Stream 0), dual-timescale ABR feedback exporter (ReactiveStatsat 100 ms /PeriodicStatsat 500 ms), SPAKE2+ prover pairing UI with PIN entry, reconnect watchdog with mDNS re-discovery, semi-transparent "Reconnecting" status overlay, Windows system tray icon viaShell_NotifyIcon, and CI release packaging workflow.
renderd/
├── Cargo.toml # Workspace root manifest (15 members: 13 crates + 2 tools)
├── rust-toolchain.toml # Rust toolchain pinning (MSRV 1.80+)
├── clippy.toml # Workspace Clippy lint rules
├── .rustfmt.toml # Code formatting rules
├── deny.toml # Security audit & license policies (cargo-deny)
├── nextest.toml # Test runner configuration (cargo-nextest)
├── proto/
│ └── renderd.proto # Control plane Protobuf schema
├── templates/
│ ├── renderd-host.default.toml # Canonical macOS host daemon configuration
│ └── renderd-viewer.default.toml # Canonical Windows viewer configuration
├── tools/
│ ├── proto-gen/ # Code generator tool compiling renderd.proto → Rust
│ ├── latency-bench/ # Frame capture & network round-trip benchmark CLI
│ └── bundle-host/ # Assembles and signs the macOS .app bundle
├── crates/
│ ├── renderd-proto/ # Protobuf types, newtypes, and envelope validation
│ ├── renderd-config/ # Layered config loader, schemas, and validators
│ ├── renderd-frame/ # Fragment header codec & reassembly state machine
│ ├── renderd-clock/ # Presentation clock synchronization (vsync phase)
│ ├── renderd-abr/ # Adaptive Bitrate control algorithm
│ ├── renderd-crypto/ # SPAKE2+ (RFC 9382), HKDF key derivation, TLS certs
│ ├── renderd-vt-sys/ # VideoToolbox hardware encoder FFI bindings
│ ├── renderd-sc-sys/ # ScreenCaptureKit capture FFI bindings
│ ├── renderd-net/ # QUIC socket transport, framing & datagram pipeline
│ ├── renderd-keychain/ # macOS Keychain & Windows Credential Manager
│ ├── renderd-discovery/ # mDNS / Bonjour peer discovery
│ ├── renderd-host/ # macOS Host daemon executable binary
│ └── renderd-viewer/ # Windows Viewer display client architecture
└── docs/ # Specifications and architecture docs
Renderd is executing across an engineering roadmap defined in ISSUES-0001-milestones.md (Milestones 1–8) and ISSUES-0002-integration.md (Milestone 9).
- Milestone 1: Repository Bootstrap & Infrastructure (
v0.1.0-bootstrap) - Milestone 2: Foundation Layer (
v0.2.0-foundation) - Milestone 3: Primitive Layer (Frame & Crypto) (
v0.3.0-primitives) - Milestone 4: FFI Layer (VideoToolbox & ScreenCaptureKit) (
v0.4.0-ffi) - Milestone 5: Service Layer (Net, Keychain & Discovery) (
v0.5.0-services) - Milestone 6: Algorithm Layer (ABR & Clock Sync) (
v0.6.0-algorithms) - Milestone 7: Host Application (
renderd-host) (v0.7.0-host) - Milestone 8: Viewer Application (
renderd-viewer) (v0.8.0-viewer) - Milestone 9: End-to-End macOS Integration & Validation (
v0.9.0-integration)
- End-to-end macOS streaming (
ScreenCaptureKit→VideoToolboxHW Encode → QUIC →VideoToolboxHW Decode →SoftRenderer) - Cross-platform support (macOS host ↔ Windows D3D12/MediaFoundation viewer integration)
- Input injection (Low-latency mouse, keyboard, and touch input event forwarding)
- Audio streaming (CoreAudio capture & WASAPI / DirectSound playback)
- Clipboard sync (Bidirectional text and image pasteboard synchronization)
- File transfer (Drag-and-drop peer-to-peer file transport)
- WAN / NAT traversal (STUN/TURN/ICE signaling fallback for remote network connections)
- Performance optimization (Zero-copy GPU texture sharing & sub-10ms latency tuning)
| Component | Operating System | Target Architecture |
|---|---|---|
| Renderd Host Daemon | macOS 13.0+ (Ventura / Sonoma / Sequoia) | aarch64-apple-darwin (Apple Silicon) |
| Renderd Viewer Client | Windows 10 or later (primary); Windows 11 supported | x86_64-pc-windows-msvc, aarch64-pc-windows-msvc |
Our GitHub Actions CI pipeline validates every commit using the following jobs:
| Job | Runner | Checks |
|---|---|---|
build-and-test-host |
macos-15 |
cargo fmt, cargo clippy, cargo nextest (host + shared crates) |
build-and-test-viewer |
windows-2025 |
cargo fmt, cargo clippy, cargo nextest (viewer + shared crates) |
proto-check |
ubuntu-latest |
Regenerates renderd.proto and verifies no diff in generated code |
typos |
ubuntu-latest |
Spell-checks the entire repository |
deny / audit |
ubuntu-latest |
Dependency license and security advisory checks (weekly + on Cargo changes) |
- Rust: Stable toolchain 1.80+ (
rustup toolchain install stable) - macOS (Host Development): Xcode Command Line Tools (
xcode-select --install) - Windows (Viewer Development): Visual Studio 2022 C++ Workload (Windows 10 / 11 SDK)
# Clone repository
git clone https://github.com/Ad1th/renderd.git
cd renderd
# Check workspace compilation across all targets
cargo check --workspace
# Run code generator tool for Protobuf types
cargo run --manifest-path tools/proto-gen/Cargo.toml
# Build release binaries
cargo build --workspace --release# Code formatting check
cargo fmt --check
# Strict workspace Clippy lints
cargo clippy --workspace --all-targets -- -D warnings
# Execute test suite (preferred: cargo-nextest)
cargo nextest run --workspace
# Fallback if cargo-nextest is not installed
cargo test --workspaceOn the macOS host, start the daemon. It grants itself no permissions — macOS will prompt for Screen Recording access on first run, and the daemon must be restarted after you grant it.
cargo run -p renderd-hostOn startup it prints the exact command to run on the viewer machine, for example:
INFO renderd_host::app: QUIC server endpoint listening for incoming viewer connections listen_addr=0.0.0.0:4433
INFO renderd_host::app: Connect the viewer with: renderd-viewer --host 10.219.217.235:4433
On the Windows viewer, either let mDNS find the host:
cargo run -p renderd-viewer…or, if the two machines cannot see each other's multicast traffic — different subnets, a VPN, or a firewall that blocks mDNS — pass the address the host printed:
cargo run -p renderd-viewer -- --host 10.219.217.235:4433--host is the path that always works; discovery is a convenience on top of it.
| Flag | Default | What it does |
|---|---|---|
--host <ADDR> |
— | Connect straight to this address, skipping discovery. A bare IP uses port 4433. |
--codec <auto|h264|hevc> |
auto |
auto offers H.264 first on Windows, HEVC first elsewhere. Pin one if the other misbehaves. |
--decoder <mf|d3d12> |
mf |
mf uses a Media Foundation decoder MFT, on the GPU (DXVA through D3D11) when viewer.hw_accel is on and the MFT supports it. d3d12 is a development path that does not yet supply DXVA picture parameters. |
--renderer <auto|soft> |
auto |
auto presents on the GPU through a D3D11 flip-model swap chain and falls back to the CPU renderer if that fails. soft forces the CPU renderer. |
--fullscreen |
off | Start borderless fullscreen. |
--width, --height |
1920×1080 | Initial window size. |
--log-level <LEVEL> |
info |
trace, debug, info, warn, error. |
| Flag | Default | What it does |
|---|---|---|
--port <PORT> |
4433 | UDP port to listen on. |
--display-id <ID> |
0 | Which display to capture. |
--config <PATH> |
— | TOML config file. |
--log-level <LEVEL> |
info |
Logging verbosity. |
- Check the two agree on a codec. The host logs
Encoder configured codec=…; the viewer logshandshake completed with host … codec=…. A stock Windows install has no HEVC decoder unless the HEVC Video Extensions are installed from the Microsoft Store, which is why the viewer asks for H.264 there by default. - Confirm frames are leaving the host. It logs
DataSender: datagram burst checkpointevery 100 frames. If that is silent, capture never started — check the Screen Recording permission. - Confirm frames are arriving. The viewer logs
DatagramReceiver: first QUIC datagram received from host, thenfirst frame reassembled. If datagrams arrive but no frame reassembles, packets are being lost or reordered beyond the window. - Turn on the VideoToolbox traces on macOS with
RENDERD_VT_TRACE=1, which reports every CoreMedia call in the encode and decode paths. They are off by default because they write to unbuffered stderr on every frame.
Renderd adapts on its own. The bitrate backs off as soon as queuing delay builds, frames are skipped at capture rather than queued, lost packets are resent instead of costing a keyframe, and the encoded resolution steps down (896, 720, 544 lines) while the link carries less than the picture needs and back up when it carries more. You can still help it on a link you know is slow:
- Tell it the ceiling. Set
abr.max_bitrate_kbpsto roughly what the link sustains, e.g.3000for a link that tops out around 3 Mbps. Withhost.max_stream_height = 0(the default) this sets the largest resolution the stream will use: 1080p60 of desktop text needs about 8-10 Mbps. Settinghost.max_bitrate_kbps(the starting bitrate) near the link's speed too makes the very first picture arrive quickly. - Read the lag off the logs. Each second the host logs
HOST METRICSwithsend_queue_kb(video waiting on the host), and every half-secondVIEWER TELEMETRYwithcapture_skippedandencoder_skipped. Asend_queue_kbthat stays high means the link is the bottleneck. Run the host with--log-level debugto see the ABR decisions with the viewer's measuredqueue_delay_ms.Resizing the stream to fit the linkmarks each resolution change; on the viewer,nacked_frags,recovered_totalandlost_totalshow how much loss retransmits absorbed.
- RFC-0002: System Architecture Specification — Comprehensive technical architecture, control/data plane specs, and security design.
- REPO-0001: Engineering & Repository Guidelines — Coding standards, DAG dependencies, crate boundaries, and CI rules.
- ISSUES-0001: Milestones 1–8 Component Roadmap — 100-issue breakdown covering component implementation across Milestones 1–8.
- ISSUES-0002: Milestone 9 Integration & Validation Roadmap — 18-issue breakdown for end-to-end integration and system validation.
- BRAND.md — Renderd visual identity specification, design system, colors, and typography guidelines.
- CHANGELOG.md — Detailed version history adhering to Keep a Changelog standards.
- CONTRIBUTING.md — Quick-start guide for contributors.
Contributions are welcome! Please read CONTRIBUTING.md for the quick-start guide and docs/REPO-0001-repository.md for the complete engineering standards before submitting code.
- Ensure all code passes
cargo fmt,cargo clippy --workspace --all-targets -- -D warnings, andcargo nextest run. - Follow Conventional Commits format (
feat(...),fix(...),ci(...),docs(...)). - Check
CODEOWNERSfor domain-specific review routing. - See §21 of REPO-0001 for the full pull request checklist and what not to contribute.
Distributed under the MIT License. See LICENSE for details.