Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,9 @@ jobs:
libgles-dev libdrm-dev libavcodec-dev libavutil-dev libsystemd-dev
OMACVM_VDECD_SYSTEMD=1 src/tests/vdecd-down.sh

- name: Chromium's video decoder tells the Mac an odd-size picture's own size (a stand-in for the kernel's ioctls)
run: src/tests/vdecd-logical.sh

- name: The VA driver shim gives Chromium surfaces of their real size, waits for its pictures, never decodes into an import and says each surface's own size (a stand-in for Mesa's driver)
run: |
sudo apt-get install -yq --no-install-recommends gcc libva-dev
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ GitHub.
| `src/battery/` | The Mac's battery (feature `battery`; UTM, Fusion, OmacVM.app; Parallels has its own): DKMS module `omacvm_battery` (BAT0, ADP0; from try-omarchy, GPL-2.0-only), root agent `omacvm-battery` (OmacVM.app: virtio port `org.omacvm.battery`; UTM/Fusion: the Bridge's `battery` events through `bridge/guest/omacvm-bridge`), UPower never suspends for it. Mac side: `bridge/mac/battery.swift`, OmacVM.app's `NativeBatteryBridge.swift`. Its README |
| `src/wallpaper/` | Guest `omacvm-wallpaper` (path unit) → `POST /wallpaper` on the bridge |
| Video decoding (OmacVM.app) | Guest VA-API (Mesa virgl) → virglrenderer's video protocol → VideoToolbox backend (`app/runtime/patches/virgl-videotoolbox-decode.patch`: `src/vrend/virgl_video_vt.c`; SPS/PPS rebuilt for H.264, VPS/SPS/PPS for HEVC with an explicit short-term RPS rewritten into every slice header (VA-API omits the SPS's sets), AV1 frames cut from the temporal unit by the first tile's offset (with film grain also into the buffer the guest shows, its `film_grain_target`: `virgl-video-av1-film-grain.patch`), VP9 frames as they come; bit-exact against FFmpeg's software decoding; IOSurface → GPU copy into the guest's textures; pictures finish beside QEMU's GPU thread, from a serial queue per decoder, and planes and fences wait for theirs: `virgl-videotoolbox-decode-async.patch`, `OMACVM_VIDEO_DECODE_SYNC=1` = the old wait). VM side in `src/app/guest/install.sh`: `vainfo`, VA driver shim `omacvm_drv_video.c` (`LIBVA_DRIVER_NAME=omacvm`, `/usr/local/lib/dri`: NV12 surfaces only, AV1 only for Chromium-based processes, exportable surfaces of their real size for Chromium's processes when the runtime says `omacvm.vaexport=1`: Chrome checks the dma-buf size of the ARGB frames it converts to, `OMACVM_VA_EXPORT=1|0`; Chromium told a largest size of 1920 (`OMACVM_VA_MAX`, 0: none) only with a runtime that does not say `omacvm.vadecasync=1`; with one, Chromium's decoders wait for each picture after `vaEndPicture` (a fenced empty command on the display's DRM file; `OMACVM_VA_DECODE_WAIT=1|0`); Chromium's converted ARGB frames fill their rounded planes (RGB imports at the rounded size, the video processing regions rewritten, `OMACVM_VA_FILL=1|0`): call tiles not squeezed; with a runtime that says `omacvm.valogical=1` every 4:2:0 surface Mesa makes at a size not a multiple of 16 is declared to the Mac at its own size (a NOP payload, `virgl-resource-logical-size.patch`, ADR 0061; `OMACVM_VA_LOGICAL=1|0`; Mac `OMACVM_VIDEO_LOGICAL=0`): apps that sample the planes (mpv, Chrome on Wayland) draw exactly the picture, no repeated last row; video processing from a declared source gets its region scaled by Mesa's size over the declared one (every process; Chromium's fill leaves it alone) and a converting `vaGetImage` reads an import of the planes at the picture's size; surfaces the decoder asks at the coded size (H.264 not a multiple of 16, HEVC not of 8) keep their padding rows (VA-API has no crop); a decoding or encoding context never begins a picture in a surface made from the app's memory, where Mesa's virgl driver crashes: `VA_STATUS_ERROR_INVALID_SURFACE`, also for that picture's `vaRenderPicture`/`vaEndPicture` (an error instead of a crash); imports and codec contexts are remembered until destroyed, no table limit; `OMACVM_VA_IMPORT_GUARD=0` (tests); tests `src/app/guest/tests/va-shim-surfaces.sh`, `va-shim-decode-wait.sh`, `va-shim-vpp-fill.sh`, `va-shim-import-decode.sh`, `va-shim-logical.sh`), Firefox pref. QEMU env: `OMACVM_VIDEO_DECODE=0`, `OMACVM_VIDEO_DEBUG=1`, `OMACVM_VIDEO_AV1=1` (the app sets it when the VM folder has `video-decode` = `av1`, written by `apply`). Guest profile numbers are Mesa ≥ 26's (`OMACVM_VIRGL_VIDEO_ABI=legacy`). `docs/video-decode.md` |
| Chromium video (OmacVM.app) | Feature `chromium-video` (tag `app-only`: on in OmacVM.app VMs, off elsewhere). Arch Linux ARM's Chromium has no VA-API, only V4L2 (ADR 0025). `src/vdec/guest/`: kernel module `omacvm-vdec` (DKMS, `module/`: V4L2 stateful decoder, no decoding of its own; CAPTURE = single-plane ARGB (`V4L2_PIX_FMT_ABGR32`) dmabufs the daemon hands in; protocol in `module/omacvm-vdec.h` (`OVD_VERSION`: daemon and module of different builds refuse each other, daemon exit 3), control device `/dev/omacvm-vdec`; instance ids cyclic (never reused); max 8 open, 256 unread messages per decoder; daemon gone = errors, not hangs) + `omacvm-vdecd` (FFmpeg VA-API decode, GL pass NV12→ARGB into GBM buffers, EGL fences with a 1 s timeout; one failing video fails alone; H.264 + VP9, HEVC only with `OMACVM_VDEC_HEVC=1` since Chromium 153's stateful V4L2 decoder lacks it; service `omacvm-vdecd` as user `omacvm-vdec`, `WatchdogSec=5`, status in `/run/omacvm-vdec/status`, `OMACVM_VDEC_DEBUG=1`; GPU not usable at start = the daemon waits 0 s -> 118 s (count in `/run/omacvm-vdec/gpu-tries`, `RuntimeDirectoryPreserve=restart`, cleared when ready), then exit 4, `RestartSec=2` (flat: crashes still restart in 2 s); exit 127 (a library gone) is not restarted; pacman hook `95-omacvm-vdecd.hook` (any `usr/lib/*.so*`) → `vdecd.sh hook`: built again when a library in its own NEEDED is gone (new FFmpeg soname), started when down or not ready; `vdecd.sh why` = the check's reason (last run only, `_SYSTEMD_INVOCATION_ID`); `vdecd.sh vafail` = the "video decoding" FAIL line when `vaInitialize` failed; test `src/tests/vdecd-down.sh`). Module update while an app has it open: installed, loaded at the next VM start (`omacvm check` says so). DKMS helpers shared with battery/camera: `src/guest/dkms.sh`. `chromium-flags.py` (as the user) adds `AcceleratedVideoDecoder` and the `no-av1` extension (YouTube sends VP9) to the last `--enable-features`/`--load-extension` of `~/.config/chromium-flags.conf`, marker `~/.local/state/omacvm/chromium-v4l2-flags.json`. WirePlumber rule `50-omacvm-vdec.conf` (`/etc/wireplumber/wireplumber.conf.d/`): WirePlumber 0.5 hangs, and links no sound, on a V4L2 device it cannot open (the decoder without a ready daemon), so it leaves the decoder alone; `install.sh` restarts a running WirePlumber once when the rule is new, before it loads the module, never during a call (`in_call`: a running `Stream/Input/Audio` node; then the module waits for the next VM start). `70-omacvm-vdec.rules`: the misc device `/dev/omacvm-vdec` belongs to the daemon and starts it (`TAG+="systemd"`, `SYSTEMD_WANTS`) whenever the module loads, also late (`src/tests/vdec-wireplumber.sh`). `install.sh USER on|off` from `guest/install.sh` (app VMs). Test: `test/vdec-test.c` (V4L2 like Chromium vs FFmpeg software; `--churn`, `--early-drain`, `--expect-fail`, `--stall`, `--flood`). `docs/video-decode.md` |
| Chromium video (OmacVM.app) | Feature `chromium-video` (tag `app-only`: on in OmacVM.app VMs, off elsewhere). Arch Linux ARM's Chromium has no VA-API, only V4L2 (ADR 0025). `src/vdec/guest/`: kernel module `omacvm-vdec` (DKMS, `module/`: V4L2 stateful decoder, no decoding of its own; CAPTURE = single-plane ARGB (`V4L2_PIX_FMT_ABGR32`) dmabufs the daemon hands in; protocol in `module/omacvm-vdec.h` (`OVD_VERSION`: daemon and module of different builds refuse each other, daemon exit 3), control device `/dev/omacvm-vdec`; instance ids cyclic (never reused); max 8 open, 256 unread messages per decoder; daemon gone = errors, not hangs) + `omacvm-vdecd` (FFmpeg VA-API decode, GL pass NV12→ARGB into GBM buffers, EGL fences with a 1 s timeout; buffers rounded up to even, and for an odd-size picture the Mac is told its size before Chromium gets them (`vdecd-logical.h`: an OMLS NOP on the daemon's render node, only with `omacvm.valogical=1`, `OMACVM_VA_LOGICAL=0`; Chromium imports the picture's part and virgl drops that size; `src/tests/vdecd-logical.sh`); one failing video fails alone; H.264 + VP9, HEVC only with `OMACVM_VDEC_HEVC=1` since Chromium 153's stateful V4L2 decoder lacks it; service `omacvm-vdecd` as user `omacvm-vdec`, `WatchdogSec=5`, status in `/run/omacvm-vdec/status`, `OMACVM_VDEC_DEBUG=1`; GPU not usable at start = the daemon waits 0 s -> 118 s (count in `/run/omacvm-vdec/gpu-tries`, `RuntimeDirectoryPreserve=restart`, cleared when ready), then exit 4, `RestartSec=2` (flat: crashes still restart in 2 s); exit 127 (a library gone) is not restarted; pacman hook `95-omacvm-vdecd.hook` (any `usr/lib/*.so*`) → `vdecd.sh hook`: built again when a library in its own NEEDED is gone (new FFmpeg soname), started when down or not ready; `vdecd.sh why` = the check's reason (last run only, `_SYSTEMD_INVOCATION_ID`); `vdecd.sh vafail` = the "video decoding" FAIL line when `vaInitialize` failed; test `src/tests/vdecd-down.sh`). Module update while an app has it open: installed, loaded at the next VM start (`omacvm check` says so). DKMS helpers shared with battery/camera: `src/guest/dkms.sh`. `chromium-flags.py` (as the user) adds `AcceleratedVideoDecoder` and the `no-av1` extension (YouTube sends VP9) to the last `--enable-features`/`--load-extension` of `~/.config/chromium-flags.conf`, marker `~/.local/state/omacvm/chromium-v4l2-flags.json`. WirePlumber rule `50-omacvm-vdec.conf` (`/etc/wireplumber/wireplumber.conf.d/`): WirePlumber 0.5 hangs, and links no sound, on a V4L2 device it cannot open (the decoder without a ready daemon), so it leaves the decoder alone; `install.sh` restarts a running WirePlumber once when the rule is new, before it loads the module, never during a call (`in_call`: a running `Stream/Input/Audio` node; then the module waits for the next VM start). `70-omacvm-vdec.rules`: the misc device `/dev/omacvm-vdec` belongs to the daemon and starts it (`TAG+="systemd"`, `SYSTEMD_WANTS`) whenever the module loads, also late (`src/tests/vdec-wireplumber.sh`). `install.sh USER on|off` from `guest/install.sh` (app VMs). Test: `test/vdec-test.c` (V4L2 like Chromium vs FFmpeg software; `--churn`, `--early-drain`, `--expect-fail`, `--stall`, `--flood`). `docs/video-decode.md` |
| `src/camera/` | Feature `camera` (from try-omarchy): guest `omacvm-camera` (user service) feeds `/dev/video42` "Mac Camera" (v4l2loopback via DKMS, `exclusive_caps`) and asks the Mac for frames only while v4l2loopback reports a reader: Bridge `GET /camera` (UTM, Fusion; `src/bridge/mac/camera.swift`) or OmacVM.app's virtio port `org.omacvm.camera` (same Swift file, linked into `app/app/Sources/OmacVM`). Each start makes a new capture session with the camera picked then (`pickCamera`: the built-in one unless suspended, the lid closed; else macOS's default; else the first connected); gone (`wasDisconnected`), suspended (`isSuspended`, macOS 14+), interrupted or no frame for 5 s = stopped and started again (2 s, up to 30 s) while a VM reads, at once when a camera is connected; `src/bridge/mac/test-camera.sh`. Parallels passes the camera itself (a USB camera, `uvcvideo`, "MacBook Pro Camera" on /dev/video0; `SharedCamera` in config.pvs): nothing installed there. `omacvm-camera --status` for the check |
| `src/keyboard/` | `mac-layout.sh` (macOS input source → XKB), guest layout + Cmd+V paste |
| `src/ime/` | Feature `mac-ime` (experimental, off, OmacVM.app only; docs/adr/0043-mac-ime.md, #273 by @Vocllum): the Mac's input methods type in Omarchy. `guest/addon/`: an Fcitx5 module (C++, `protocol.cpp` = the port's JSON lines, no Fcitx5 in it) in Omarchy's own Fcitx5: focus, field kind and caret (Hyprland logical pixels: a RelativeRect caret plus `j/activewindow`'s origin, else the window's box with `exact:false`) to the Mac, preedit and commit into the focused field; `guest/install.sh USER on\|off\|--status` builds it in the VM as package `omacvm-fcitx5-ime` (PKGBUILD, again when its sources or Fcitx5's version change), the port's udev rule (`uaccess`), `GTK_IM_MODULE=fcitx` in `~/.config/environment.d/90-omacvm-ime.conf` (unset for Fcitx5 itself: drop-in `~/.config/systemd/user/omarchy-fcitx5.service.d/90-omacvm-ime.conf`, else it shows a tip to unset it) and `--enable-wayland-ime` in existing Chromium/Electron flag files (marker `~/.local/state/omacvm/ime-flags`). Mac side: virtio port `org.omacvm.ime` (nr 8) and `OMACVM_IME_SOCKET` only when the VM's record says on at its start (`OmacVMFeatures/MacIME.swift`, MacLinks), QEMU's window code as `NSTextInputClient` (`omacvm-cocoa-ime.patch`, rules in `omacvm-cocoa-ime-logic.patch`), the app's switch row `MacIMERow.swift` (runs its own `omacvm enable\|disable mac-ime` while the VM runs). Tests: `src/ime/tests/run.sh`, `app/runtime/Tests/keys/test-ime.sh`, `swift run features-tests` |
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@
What's new in each OmacVM release. The release notes on GitHub say the same
in more words.

## 3.2.12 (unreleased)

- **Odd-size videos in Omarchy's Chromium are no longer one column narrower.** In an OmacVM.app
VM, Arch Linux ARM's Chromium (Omarchy's default browser) decodes on the Mac through OmacVM's
V4L2 decoder, whose buffers are the picture rounded up to even. A video of an odd width or
height (a VP9 video of 853x480 or 1001x563) came out squeezed by that extra column and row.
The decoder now tells the Mac the picture's size for such buffers. Measured in a test VM
(Chromium 153, Mac mini M4): 853x480 and 1001x563 line ratios exact (1.0002; 1.00005/1.00007),
as with CPU decoding (3.2.11: one column, and one column and one row, too many in their
place); 854x480, 720p, 1080p and 1000x562 were and stay exact. Needs Update VM (the 3.2.11
app is enough).

## 3.2.11

In an OmacVM.app VM, Google Chrome's GPU process no longer crashes in video calls, most
Expand Down
Loading
Loading