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
30 changes: 25 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ deployment glue, unless the maintainer explicitly approves that scope.
This repository may document integration points, but it must not silently make
host-specific changes for a consumer.

## Nixling-style review panel policy
## 8-reviewer panel sign-off policy

Non-trivial plan-driven or multi-phase work requires unanimous 8/8 panel
approval at each phase boundary before moving to the next phase. The required
Expand Down Expand Up @@ -134,7 +134,27 @@ If there is uncertainty about whether a change is trivial, use the panel.

## Branch protection expectation

`main` is intended to be protected once the bootstrap branch lands. Require PRs,
fresh approval after new commits, passing CI jobs, and maintainer bypass only for
emergency repository repair. Non-trivial plan-driven work still requires the 8/8
panel even if GitHub's branch rule only enforces ordinary PR approval.
After initial repository bootstrap, nobody direct-pushes to `main`. All changes
use this flow:

1. Create a topic branch.
2. Run the relevant local validation for the changed scope.
3. Open a pull request.
4. Wait for required CI to pass and required conversations to be resolved.
5. Squash-merge the PR after review requirements are met.

Expected `main` protection settings:

- block direct pushes for everyone;
- require pull requests before merge;
- require PR review before merge;
- dismiss stale approvals when new commits are pushed;
- require required CI jobs to pass;
- require all conversations to be resolved;
- disallow force-pushes;
- disallow branch deletion;
- restrict maintainer bypass to emergency repository repair and document any
bypass in the PR or follow-up issue.

Non-trivial plan-driven work still requires the 8/8 panel even if GitHub's
branch rule only enforces ordinary PR approval.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ first stable release.
- Governance documentation for contributors, agents, security reporting, and
release notes.

### Changed

- Removed Firefox-specific packaging, wrapper, policy, and logging instructions
from the generic repository docs; client-specific guidance belongs in
downstream client repositories.
- Reframed governance as a generic 8-reviewer panel sign-off policy with
branch-to-PR-to-CI-to-squash-merge expectations after bootstrap.

## 0.1.0-alpha.1 - TBD

### Added
Expand Down
13 changes: 11 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ with the command attempted and the failure.

## Pull requests

After initial repository bootstrap, nobody direct-pushes to `main`. Start from a
topic branch, run the relevant local validation, open a pull request, wait for
required CI and conversation resolution, and squash-merge only after review
requirements are satisfied.

Pull requests should include:

- A concise summary.
Expand All @@ -88,8 +93,8 @@ Keep unrelated changes in separate commits. Avoid vague subjects such as

## Review panel expectations

Non-trivial plan-driven or multi-phase work follows the same review-panel style
used by `nixling`.
Non-trivial plan-driven or multi-phase work follows the 8-reviewer panel
sign-off policy.

At each phase boundary, work must receive 8/8 sign-off before the next phase
starts:
Expand Down Expand Up @@ -122,11 +127,15 @@ notes, and integration instructions may not.

The public `main` branch should be protected after the initial bootstrap push:

- block direct pushes for everyone;
- require pull requests before merge;
- require at least one approving review for ordinary changes;
- require the documented 8/8 panel for non-trivial plan-driven work;
- dismiss stale approvals when new commits are pushed;
- require the `make test (Ubuntu packages)` and `optional Nix flake checks`
workflow jobs to pass;
- require all conversations to be resolved before merge;
- disallow force-pushes;
- disallow branch deletion;
- restrict maintainer bypass to emergency repository repair and document any
bypass in the PR or follow-up issue.
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,24 +72,23 @@ Do not overwrite the only copy of the real driver with the shim. The shim must
be able to `dlopen()` the real `virtio_gpu_drv_video.so`, preferably through an
absolute path compiled with `REAL_DRIVER=...`.

## Nix and Firefox
## Nix

Nix/NixOS users can package the shim by setting `REAL_DRIVER` to the real Mesa
virtio-gpu VA driver path in the target graphics closure and exposing the shim
through a higher-priority `LIBVA_DRIVERS_PATH`. The flake exposes:
through a higher-priority `LIBVA_DRIVERS_PATH`. The public generic flake
documents the shim package, checks, compatibility report, and overlay:

```bash
nix build github:vicondoa/virgl-vaapi-compat#virgl-vaapi-compat
nix build github:vicondoa/virgl-vaapi-compat#firefox
nix build github:vicondoa/virgl-vaapi-compat#compatibility-report
```

See [`docs/nix.md`](docs/nix.md).

Firefox users should treat this as one possible workaround for a VA-API DMABUF
format-descriptor mismatch, not as a general Firefox acceleration switch. You
still need a working VA-API virtio-gpu stack and Firefox VA-API enabled. See
[`docs/firefox.md`](docs/firefox.md) and [`docs/debugging.md`](docs/debugging.md).
Client-specific packaging, browser policies, wrapper packages, and application
logging recipes belong in downstream client repositories. This generic repo only
documents the libva shim boundary.

## Safety and scope

Expand Down Expand Up @@ -122,7 +121,6 @@ clients accept the existing virgl I420 descriptor path. See
- [`docs/design.md`](docs/design.md) - design goals, non-goals, and constraints
- [`docs/debugging.md`](docs/debugging.md) - reproducing and diagnosing the
motivating failure mode
- [`docs/firefox.md`](docs/firefox.md) - Firefox-specific VA-API notes
- [`docs/nix.md`](docs/nix.md) - Nix/NixOS integration notes
- [`docs/troubleshooting.md`](docs/troubleshooting.md) - common symptoms and
fixes
Expand Down
57 changes: 12 additions & 45 deletions docs/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@ DMABUF fails because the client rejects the exported DRM PRIME descriptor shape.

## Known motivating investigation

A prior debugging session (`f15bd57d-e724-47f2-9d2e-012652265f5e`) found:
A prior investigation found:

- Firefox cannot use the `virtio_media` `/dev/video0` V4L2 M2M path directly;
Firefox Linux hardware decode uses VA-API.
- The original motivating browser client used VA-API for this hardware decode
path rather than the `virtio_media` `/dev/video0` V4L2 M2M path directly.
- Enabling `graphics.virglVideo = true` made the guest virtio-gpu VA-API driver
expose H.264 profiles.
- Firefox selected H.264 VA-API decode (`hw: "true"`, `VAAPI_VLD`) but failed
with messages such as `CreateImageVAAPI(): failed to get VideoFrameSurface`
and `VAAPI dmabuf allocation error`, then fell back to software decode.
- The client selected H.264 VA-API decode but rejected the exported DMABUF
descriptor, then fell back to software decode.
- The root cause was virgl exporting `DRM_PRIME_2` `VA_FOURCC_I420` descriptors
while Firefox rejected that descriptor before reaching its lower DMABUF YUV
while the client rejected that descriptor before reaching its lower DMABUF YUV
import path.
- A first workaround patched Firefox's I420 allowlist. This project is the
preferred wrapper/shim approach because it leaves Firefox unpatched.
- A first workaround patched the client allowlist. This project is the preferred
wrapper/shim approach because it leaves clients unpatched.

Known stack versions from that investigation:

Expand All @@ -31,9 +30,6 @@ Known stack versions from that investigation:
| virglrenderer | `1.3.0` |
| crosvm | `4c80bf3523cf84114054209d88a7af3eefd8423f` |
| Cloud Hypervisor | `52.0` |
| Firefox | `151.0.2` |
| Firefox Developer Edition | `152.0b1` |

## Establish what path the client uses

First separate three different acceleration paths:
Expand All @@ -42,9 +38,9 @@ First separate three different acceleration paths:
2. **VA-API** through libva and `virtio_gpu_drv_video.so`
3. **Software decode**

For Firefox on Linux, the relevant hardware decode path is VA-API. Seeing a
`virtio_media` node is not enough; Firefox will not directly use that V4L2 M2M
path for this class of decode.
For the motivating browser client, the relevant hardware decode path was VA-API.
Seeing a `virtio_media` node was not enough because that client did not directly
use the V4L2 M2M path for this class of decode.

## Check VA-API visibility

Expand Down Expand Up @@ -85,35 +81,6 @@ If libva cannot initialize the shim, confirm that the build-time libva headers
and runtime libva agree. Rebuild with the target system's `pkg-config` and libva
headers when in doubt.

## Firefox VA-API logging

Firefox logging can show whether VA-API decode is selected and where it fails.
Useful environment variables include:

```bash
MOZ_LOG="PlatformDecoderModule:5,FFmpegVideo:5,DMABUF:5,WidgetDMABuf:5,VAAPI:5"
MOZ_LOG_FILE=firefox-vaapi.log
LIBVA_MESSAGING_LEVEL=2
LIBVA_DRIVER_NAME=virtio_gpu
```

Run Firefox from a terminal with those variables, reproduce playback, then check
for evidence that the VA-API decoder was selected:

- `hw: "true"`
- `VAAPI_VLD`
- H.264 profile selection

Then look for the failure signatures:

- `CreateImageVAAPI(): failed to get VideoFrameSurface`
- `VAAPI dmabuf allocation error`
- fallback from hardware to software decode

The exact log module names can change between Firefox releases. If a module is
silent, keep `PlatformDecoderModule`, `DMABUF`, and `WidgetDMABuf` enabled and
consult the Firefox version's current logging names.

## DMABUF and I420 failure signature

The failure this shim targets has a specific shape:
Expand All @@ -140,7 +107,7 @@ LIBVA_DRIVERS_PATH=/path/to/shim/lib/dri${LIBVA_DRIVERS_PATH:+:$LIBVA_DRIVERS_PA
vainfo
```

For a client such as Firefox, include the same shim variables in the launch
For an affected client, include the same shim variables in the launch
environment. When the hook is installed and a matching export occurs, stderr may
include lines like:

Expand Down
10 changes: 5 additions & 5 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ accepted by affected clients.
- a color management tool
- a DMABUF allocator
- a GPU synchronization layer
- a Mesa, virglrenderer, crosvm, or Firefox fork
- a Mesa, virglrenderer, crosvm, browser, or client fork
- a generic workaround for all virtio-gpu graphics problems

If a client fails before VA-API decode is selected, if H.264 profiles are not
Expand All @@ -36,10 +36,10 @@ use virtio-gpu video at all, this shim is not the primary fix.
## Why a shim

The motivating failure was not that H.264 decode was unavailable. The guest
virtio-gpu VA driver advertised H.264 decode and Firefox selected VA-API, but
surface export failed at a descriptor compatibility boundary: virgl exported a
`DRM_PRIME_2` I420 descriptor, and Firefox rejected that descriptor before
falling through to its lower DMABUF YUV import path.
virtio-gpu VA driver advertised H.264 decode and the affected client selected
VA-API, but surface export failed at a descriptor compatibility boundary: virgl
exported a `DRM_PRIME_2` I420 descriptor, and the client rejected that descriptor
before falling through to its lower DMABUF YUV import path.

A client patch that allowed that I420 descriptor can work, but it ties the
workaround to one client. A VA driver shim keeps clients unpatched and confines
Expand Down
72 changes: 0 additions & 72 deletions docs/firefox.md

This file was deleted.

37 changes: 28 additions & 9 deletions docs/nix.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@ and the shim `dlopen()`s the real driver.

## Flake outputs

The public flake exposes:
The generic shim integration points are:

| Output | Purpose |
| --- | --- |
| `.#virgl-vaapi-compat` / `.#default` | The generic `virtio_gpu_drv_video.so` shim package. |
| `.#firefox` | Optional Firefox package wrapper with scoped `LIBVA_*` environment, locked VA-API policies, and a virgl `glxtest` stub. Its executable is `bin/firefox`, so all Firefox launches through that package use the wrapper. |
| `.#compatibility-report` | JSON report of the evaluated nixpkgs/libva/Mesa/virglrenderer/crosvm/Cloud Hypervisor/Firefox versions and derived libva init symbol. |
| `.#compatibility-report` | JSON report of the evaluated generic graphics stack versions and derived libva init symbol. |
| `.#checks.<system>.default` | Build-time drift gate: compiles the shim, checks the exported libva ABI symbol, and runs the fake-driver behavior harness. |
| `overlays.default` | Adds `virgl-vaapi-compat`, `wrapFirefoxVirglVaapiCompat`, and the compatibility report to `pkgs`, and replaces `pkgs.firefox` with the wrapped Firefox built from the unwrapped upstream `prev.firefox`. |
| `overlays.default` | Adds the generic shim package and compatibility report to `pkgs` for downstream consumers. |
| `lib.libvaAbi` | Helper function for downstream flakes that need to derive the libva driver init ABI from a libva package version. |

Examples:

```bash
nix build github:vicondoa/virgl-vaapi-compat#virgl-vaapi-compat
nix build github:vicondoa/virgl-vaapi-compat#firefox
nix build github:vicondoa/virgl-vaapi-compat#compatibility-report
cat result/compatibility-report.json
```
Expand Down Expand Up @@ -70,6 +69,26 @@ allowed when the active headers compile, the expected init symbol is exported,
and the fake-driver harness passes. Actual API or behavior drift fails the
package/check instead of relying on a fixed allowlist of exact versions.

## `lib.libvaAbi`

`lib.libvaAbi` is a small helper for downstream flakes that need to derive the
libva driver entry point from a package version without importing this package
derivation. Call it with a nixpkgs `lib` and a libva package version:

```nix
let
abi = virgl-vaapi-compat.lib.libvaAbi {
inherit (pkgs) lib;
libvaVersion = pkgs.libva.version;
};
in abi.initSymbol
```

The returned attribute set includes `initMajor`, `initMinor`, `initAbi`,
`initSymbol`, and `expectedPkgConfigVersionPrefix`. It is intentionally limited
to libva ABI derivation; it does not imply that a full graphics stack is known
good without the package checks.

## VM integration

In a NixOS guest, this shim is usually most useful when the guest already has a
Expand All @@ -81,10 +100,10 @@ A conservative integration is to wrap only the affected application with
`LIBVA_DRIVERS_PATH` and `LIBVA_DRIVER_NAME` rather than replacing the global VA
driver search path for the whole system.

If you apply the overlay in a NixOS guest, `pkgs.firefox` becomes the wrapped
Firefox and still installs `bin/firefox`. Do not also install stock Firefox from
the pre-overlay package set, or both packages will try to provide the same
`bin/firefox` path.
Downstream clients should wrap only their affected application with
`LIBVA_DRIVERS_PATH` and `LIBVA_DRIVER_NAME`. Application-specific packages,
browser policies, and launch wrappers belong outside this generic shim
repository.

## Updating and garbage collection

Expand Down
Loading
Loading