Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
90bc98d
feat(compositor): fail legibly when D3D11 init fails, instead of fall…
EtienneLescot Jul 27, 2026
4775a7c
docs(compositor): correct the WGC rationale -- capture is not mandatory
EtienneLescot Jul 27, 2026
9ace24e
feat(compositor): add a CPU backend -- WARP render + software decode,…
EtienneLescot Jul 27, 2026
0554ebb
feat(compositor): select the CPU backend automatically, and tell the …
EtienneLescot Jul 27, 2026
0b82025
feat(compositor): let the CPU backend reach the export encoder
EtienneLescot Jul 27, 2026
d0a091a
fix(compositor): CPU backend reach on the GIF-refactored pipeline
Jul 29, 2026
12e60f7
feat(compositor): scaffold macOS Metal+VideoToolbox port
Jul 28, 2026
0b7ef9e
feat(compositor): mac_frames.rs — software decode → NV12 → CVPixelBuf…
Jul 28, 2026
359114b
feat(compositor): add d3d_macos, text_macos, wrapper_macos — backend …
Jul 28, 2026
1578133
feat(compositor): compositor_macos — Compositor skeleton, CVMetalText…
Jul 28, 2026
a679ba5
feat(compositor): shaders.metal — MSL port of all 9 shader entry points
Jul 28, 2026
45c6d83
feat(compositor): pipeline_macos — VideoToolbox hwaccel decode + dual…
Jul 28, 2026
c96bc34
fix(compositor/build.rs): discover macOS SDK via xcrun on macOS
Jul 28, 2026
2fbe27f
fix(ci): indent the build: job so the macOS job parses
Jul 28, 2026
8eeb57c
feat(compositor): compositor_macos engine — render targets, MSL pipel…
Jul 28, 2026
d64542f
feat(compositor): pipeline_macos::Decoder — seek / next / cur_time_se…
Jul 28, 2026
3eb7369
feat(compositor): pipeline_macos::VideoEncoder — h264_videotoolbox + …
Jul 28, 2026
986f5e8
feat(compositor): pipeline_macos::run_composited_multi — multi-clip e…
Jul 28, 2026
f64d097
feat(compositor): text_metal — CoreText/CoreGraphics text rasterizer
Jul 28, 2026
2f542af
fix(compositor): dedup `pub mod live` and `pub mod pipeline` in lib.rs
Jul 29, 2026
d35d9ec
fix(compositor/build.rs): reach the macOS ffmpeg and libclang at all
sepion02 Jul 29, 2026
ce1fc8a
fix(compositor): AVERROR(EAGAIN) is -35 on macOS, not -11
sepion02 Jul 29, 2026
d356609
refactor(compositor): move the timeline walk out of the Windows pipeline
sepion02 Jul 29, 2026
439610e
fix(compositor): port shaders.metal to MSL that actually compiles
sepion02 Jul 29, 2026
49b85fd
feat(compositor): make the Metal engine produce a frame
sepion02 Jul 29, 2026
fbbbc13
fix(compositor): rewrite text_macos.rs on the CoreText C API
sepion02 Jul 29, 2026
5d7838d
fix(app): open the HUD without waiting for the microphone prompt
sepion02 Jul 29, 2026
eecd670
fix(compositor-view): actually find the addon, unpackaged and packaged
sepion02 Jul 29, 2026
3007c82
build(mac): add the macOS compositor addon build script
sepion02 Jul 29, 2026
174fdc7
ci(macos): run the compositor tests, not just a type-check
sepion02 Jul 29, 2026
e0a7516
fix(build,test): unblock tsc, and stop assuming an x64 host
sepion02 Jul 29, 2026
f3f95e5
docs(compositor): repoint the module map at the per-platform files
sepion02 Jul 29, 2026
97bae9a
ci(windows): cargo check the compositor on every PR
sepion02 Jul 29, 2026
834031a
refactor(compositor): move the pure geometry into frame_geometry
sepion02 Jul 29, 2026
953e7da
refactor(compositor): one LayerCB, one LiveParams, for both backends
sepion02 Jul 29, 2026
816b48d
refactor(compositor): compose_frame's geometry becomes plan_frame
sepion02 Jul 29, 2026
2df0092
fix(build/mac): install the addon by rename, not by overwriting it
sepion02 Jul 29, 2026
c0a6524
fix(compositor): three MSL modes that were mis-ported from HLSL
sepion02 Jul 29, 2026
9b17829
feat(compositor): draw the layers on Metal, not just the video
sepion02 Jul 29, 2026
6d109a5
feat(compositor): render the cursor on Metal, trail included
sepion02 Jul 29, 2026
f6ca9c5
feat(compositor): wire the dual-Kawase background blur on Metal
sepion02 Jul 29, 2026
4d94960
fix(compositor): the shadow fix landed in dead code, and two more div…
sepion02 Jul 29, 2026
12c7398
feat(compositor): render the 3D tilt on Metal — and unbreak modes 8, …
sepion02 Jul 29, 2026
631666a
fix(compositor): the three annotation modes were each a different shader
sepion02 Jul 29, 2026
d816381
feat(compositor): draw annotations on Metal, and call the CoreText ra…
sepion02 Jul 29, 2026
b254f8e
feat(compositor): macOS export encodes — first MP4 out of the Metal e…
sepion02 Jul 29, 2026
9695e0d
test(compositor): pin the iso-render claim to a number
sepion02 Jul 29, 2026
6b17975
feat(compositor): mux audio into the macOS export
sepion02 Jul 29, 2026
d67cb72
fix(compositor): the annotation blur sampled mip 0 and so blurred not…
sepion02 Jul 29, 2026
2577967
fix(compositor): text annotations were rendered upside down
sepion02 Jul 29, 2026
db0ea09
perf(compositor): 2.4x on macOS export — VideoToolbox was the slow path
sepion02 Jul 29, 2026
1983f9f
perf(compositor): render NV12 straight into the encoder's CVPixelBuffer
sepion02 Jul 29, 2026
6a51a81
docs(compositor): correct the zero-copy measurement — it is 1.5x, not…
sepion02 Jul 29, 2026
209a496
build(mac): ship the ffmpeg dylibs, and vendor them LGPL by construction
sepion02 Jul 29, 2026
46552bc
fix(compositor): mac was missing clear_srv_cache after the rebase ont…
sepion02 Jul 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,114 @@ jobs:
- uses: ./.github/actions/setup
- run: npx vite build

# PR #189 — port macOS du compositor (Metal + VideoToolbox).
#
# Compile check on a `macos-14` runner (Apple Silicon). Verifies that the
# scaffold + engine-layer code added by #189 actually compiles for
# `aarch64-apple-darwin` — bindgen + cc on macOS produce the ffmpeg FFI
# bindings + the VideoToolbox context that the Rust crate statically
# references, and the `metal`/`objc`/`block`/`core-foundation` crates need
# their macOS system frameworks (Metal/CoreVideo/CoreMedia) linked.
#
# ffmpeg via Homebrew: this job installs `ffmpeg` from homebrew-core on the
# runner to satisfy bindgen + the cargo:rustc-link-lib lines for avformat/
# avcodec/avutil/swscale/swresample. NB: homebrew's `ffmpeg` is GPL-3.0 (it
# bundles x264/x265/svt-av1 etc.) — that is fine for a CI compile-check, but
# the dev/runtime story is different: `scripts/fetch-ffmpeg.mjs` documents
# that BtbN publishes no macOS build, so a pinned LGPL macOS dylib has to
# land separately before we can ship. The vendored `electron/native/bin/
# darwin-*/` directory is the runtime pin and is empty today.
#
# Why this job runs at all today: every commit on #189 that touches
# compositor_macos.rs / pipeline_macos.rs / mac_frames.rs / shaders.metal /
# d3d_macos.rs / text_macos.rs is unverifiable from Windows (cross-compile
# requires the macOS SDK + headers, which we don't have). This job is the
# only signal that the macOS-side Rust still type-checks.
#
# `cargo test`, NOT just `cargo check` — and that difference is the whole point.
# Three of the bugs that kept the first macOS run from rendering anything are
# invisible to a type-check and are each pinned by a test now:
# * `shaders.metal` is compiled AT RUNTIME by `new_library_with_source`, so a
# whole file of invalid MSL (HLSL's global `cbuffer`/`Texture2D` have no MSL
# equivalent) type-checks perfectly — `every_shader_entry_point_compiles`
# catches it. macos-14 runners have a real Metal device, so it runs for real.
# * `AVERROR(EAGAIN)` is -11 on Windows/Linux and -35 on macOS. A hardcoded -11
# compiles anywhere and silently decodes zero frames —
# `averror_constants_match_the_ffmpeg_macros` confronts it with shim.c.
# * pipeline-state creation rejects shader/attachment mismatches only at
# `newRenderPipelineState` time — `the_compositor_builds_on_the_system_device`.
rust-macos-compositor-check:
name: Rust test (macOS compositor)
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --target aarch64-apple-darwin
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Install ffmpeg (homebrew-core) and verify headers/libs
run: |
brew update
brew install ffmpeg
ls /opt/homebrew/opt/ffmpeg/include | head -5
ls /opt/homebrew/opt/ffmpeg/lib | head -5
/opt/homebrew/opt/ffmpeg/bin/ffmpeg -hide_banner -version | head -1
# MAC_FFMPEG_DIR only reaches build.rs because it now takes precedence over
# FFMPEG_DIR on macOS. crates/.cargo/config.toml sets FFMPEG_DIR in a GLOBAL
# [env] block (cargo has no [target.<cfg>.env] — the macOS section in that file
# is inert and cargo warns "unused key"), so before that change this job pointed
# bindgen at the win64 tree and could never have gone green.
- name: cargo test (compositor, aarch64-apple-darwin)
env:
MAC_FFMPEG_DIR: /opt/homebrew/opt/ffmpeg
run: |
cd crates
cargo test -p openscreen-compositor --lib --tests
- name: cargo build (napi addon)
env:
MAC_FFMPEG_DIR: /opt/homebrew/opt/ffmpeg
run: |
cd crates
cargo build -p compositor-view-napi --release

# The Windows half of the compositor had NO type-check on any pull request.
# `ci.yml`'s only Rust job is the macOS one above; `compositor_windows.rs` — the
# 3654-line D3D11 engine that every Windows user actually runs — is compiled
# exclusively by `build.yml`'s `build-windows` step (`npm run build:win`), and
# build.yml triggers only on `push: tags: v*` or `workflow_dispatch`. A typo in
# that file therefore surfaced when someone cut a release, not when they pushed it.
#
# That gap is what makes any cross-platform refactor of the compositor a blind
# edit, so it gets closed before the refactor rather than after.
#
# `cargo check`, not `build`: the point is "does the Windows engine still compile",
# and check is roughly half the wall-time of a full build on a windows runner.
rust-windows-compositor-check:
name: Rust check (Windows compositor)
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
# bindgen needs libclang. `crates/.cargo/config.toml` pins LIBCLANG_PATH to
# C:\Program Files\LLVM\bin, which is where the windows-latest image already
# has LLVM — so the pin resolves with no extra install.
- name: Check LLVM is where the cargo config expects it
shell: bash
run: ls "/c/Program Files/LLVM/bin/libclang.dll"
# Vendors the pinned BtbN LGPL-shared build into
# crates/thirdparty/ffmpeg-n8.1.2-win64-lgpl-shared — the exact directory
# FFMPEG_DIR points at (crates/.cargo/config.toml). build.rs reads the headers
# from there and links the import libs.
- name: Vendor the pinned ffmpeg
run: npm run fetch:ffmpeg
- name: cargo check (compositor + napi addon)
shell: bash
run: |
cd crates
cargo check -p openscreen-compositor -p compositor-view-napi --all-targets

semantic-pr:
name: Validate PR title (semantic)
runs-on: ubuntu-latest
Expand Down
7 changes: 7 additions & 0 deletions crates/.cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,10 @@
[env]
FFMPEG_DIR = { value = "thirdparty/ffmpeg-n8.1.2-win64-lgpl-shared", relative = true }
LIBCLANG_PATH = "C:\\Program Files\\LLVM\\bin"

# macOS : BtbN ne publie pas de build macOS (cf. scripts/fetch-ffmpeg.mjs), donc on
# laisse `crates/compositor/build.rs` chercher MAC_FFMPEG_DIR (env var explicite posée
# par la CI macOS ou par le dev local) ou un répertoire attendu sous `thirdparty/`.
# LIBCLANG_PATH est inutile sur macOS (clang est dans CommandLineTools), on ne le
# pose donc pas.
[target.'cfg(target_os = "macos")'.env]
6 changes: 4 additions & 2 deletions crates/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
# dépendance téléchargée : build ffmpeg LGPL-shared BtbN (~160 Mo, voir README)
/thirdparty

# sorties générées (vidéos C*.mp4, PNG, GIF, dumps)
/out
# sorties générées (vidéos C*.mp4, PNG, PPM, GIF, dumps). Le glob couvre les `--out`
# nommés par backend (out-hw/, out-cpu/) : un PPM de preuve pèse 6 Mo et il en sort un
# par cfg et par backend.
/out*
*.raw
*.nv12

Expand Down
Loading
Loading