chromium-fourier r2 + firefox-fourier 150.0.1 + KWIN_PIVOT.md
build and publish packages / distcc-avahi-aarch64 (push) Successful in 46s
build and publish packages / lmcp-any (push) Successful in 9s
build and publish packages / lmcp-debian (push) Successful in 4s
build and publish packages / claude-his-any (push) Successful in 7s
build and publish packages / ffmpeg-v4l2-request-aarch64 (push) Successful in 12m8s
build and publish packages / claude-his-debian (push) Successful in 5s

chromium-fourier:
- patch 3/3 nv12-external-oes-on-modifier-external-only.patch — adds
  NativePixmapEGLBinding::ModifierRequiresExternalOES helper, extends
  OzoneImageGLTexturesHolder::GetBinding to honor EGL external_only
  flag for NV12 dmabufs on panfrost / panthor. Validated on ohm
  (RK3566 hantro mainline 6.19.10): bbb_1080p30_h264.mp4 plays at
  34.7 % combined CPU vs ~131 % pre-patch baseline (~3.8x).
- PKGBUILD pkgrel 1->2, source array + sha256sums + prepare() hook for
  patch 4, patch numbering 1/2,2/2 -> 1/3,2/3,3/3.
- NEXT.md appended with 2026-04-28 section: patch 4 design, validation
  log, KWin GL_ALPHA bug pinpoint (preexisting since 2026-03-06,
  affects every wayland video client; unrelated to chromium-fourier),
  device-renumbering note (/dev/video1 = encoder post-reboot).
- KWIN_PIVOT.md: 4-phase plan to identify and patch KWin's
  glTexImage2D(internalFormat=GL_ALPHA) site, ohm-only test plan,
  scope discipline.
- patches/ now tracked (compiler-rt-adjust-paths, enable-v4l2,
  wayland-allow-direct-egl-gles2, nv12-external-oes); the dead-end
  chromeos-pipeline-bypass.patch removed.

firefox-fourier:
- 4 patches (gfxinfo v4l2 stateless fourccs, libwrapper hwdevice ctx,
  ffmpegvideo v4l2-request route, prefs v4l2-request default).
- PKGBUILD bumped to firefox 150.0.1, Arch toolchain glue patches
  layered in, mozconfig with --without-wasm-sandboxed-libraries for
  ALARM, package() launcher fix (rm -f symlink before cat > to avoid
  ENOENT through the dangling /usr/local symlink mach install drops).
- 150.0.1-1-aarch64.pkg.tar.zst built on boltzmann (95 MB), pending
  fresnel power-on for V4L2 stateless validation on RK3399.
This commit is contained in:
2026-04-28 12:02:18 +00:00
parent 7bb2fbeca9
commit 8756ce38be
15 changed files with 1711 additions and 60 deletions
+210
View File
@@ -0,0 +1,210 @@
# firefox-fourier — V4L2 Stateless Decoder Patch Plan
Plan to extend Firefox 149's V4L2 hardware decode path to cover Rockchip
mainline kernel boards (RK3399 rkvdec, RK3566/RK3588 hantro, RK3588
rkvdec2) by routing stateless `S264`/`S265`/`VP9F` fourccs through
libavcodec's `v4l2_request` hwaccel, which mainline FFmpeg surfaces via
`AV_HWDEVICE_TYPE_DRM` (no dedicated `_V4L2REQUEST` enum exists upstream
— confirmed against `libavutil/hwcontext.h`).
## 1. Files touched (in order)
| # | Path | Change | Lines |
|---|------|--------|-------|
| 1 | `widget/gtk/GfxInfo.cpp` | `V4L2ProbeDevice` (~L10301110): add `S264`/`S265`/`VP9F` matches alongside existing `H264`/`HEVC`/`VP90`. Set `mIsV4L2Supported = Some(true)` and OR the same `CODEC_HW_DEC_*` bits. Tag a new bool `mV4L2IsStateless` so downstream can branch. | +35 / -2 |
| 2 | `dom/media/platforms/ffmpeg/FFmpegLibWrapper.h` | Add wrappers for `av_hwdevice_ctx_create` (currently only `_alloc`/`_init` per L173174) and `av_hwdevice_find_type_by_name`. Needed because stateless wants the *device-path-aware* `_create` form to bind `/dev/dri/renderD128`. | +4 / 0 |
| 3 | `dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp` | `dlsym` the two new pointers; gate behind `LIBAVUTIL_VERSION_MAJOR >= 56`. | +6 / 0 |
| 4 | `dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h` | Add `AVBufferRef* mDRMDeviceContext = nullptr;` and `bool mUsingV4L2Request = false;` next to existing `mUsingV4L2`. | +3 / 0 |
| 5 | `dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp` | New `CreateV4L2RequestDeviceContext()` modelled on `CreateVAAPIDeviceContext` (current uses `av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI)`). Wire it in alongside the existing V4L2 init branch (the one feeding `ChooseV4L2PixelFormat` at L~258). `FindVideoHardwareAVCodec` call at L708 stays unchanged for stateless — we want the *generic* `h264`/`hevc`/`vp9` decoder + a DRM hw_device_ctx, not a `_v4l2m2m` codec. | +90 / -5 |
| 6 | `modules/libpref/init/StaticPrefList.yaml` | New pref `media.ffmpeg.v4l2-request.enabled` mirroring `media.ffmpeg.vaapi.enabled` (default `@IS_LINUX@`). | +6 / 0 |
| 7 | `dom/media/ipc/RDDProcessHost.cpp` + sandbox policy file | Whitelist `/dev/media*`, `/dev/dri/renderD*`, `/dev/video*` for the RDD process (already partly done for VAAPI — verify `policy/linux/SandboxBrokerPolicyFactory.cpp`). | +6 / 0 |
Total: roughly **+150 / -10** across 7 files.
## 2. Probe extension — `GfxInfo.cpp::V4L2ProbeDevice`
Existing pattern (~L1075):
```cpp
if (outFormats.Contains("H264")) { mIsV4L2Supported = Some(true);
mV4L2SupportedCodecs |= CODEC_HW_DEC_H264; ... }
```
Add three siblings, each setting an additional `mV4L2IsStateless = true`:
```cpp
if (outFormats.Contains("S264")) { /* CODEC_HW_DEC_H264 | stateless */ }
if (outFormats.Contains("S265")) { /* CODEC_HW_DEC_HEVC | stateless */ }
if (outFormats.Contains("VP9F")) { /* CODEC_HW_DEC_VP9 | stateless */ }
```
Decision: do **not** introduce a separate `mIsV4L2StatelessSupported`.
Collapse under `mIsV4L2Supported` so the existing feature-gate plumbing
(`MediaCodecsSupport`, `gfxFeature::HW_DECODE_VIDEO`) flips identically
— only `mV4L2IsStateless` distinguishes the routing in step 3. Stateful
+ stateless on the same SoC (rare, but RK3588 has both rkvdec2 + hantro
VEPU) gracefully degrades to whichever codec wins enumeration order.
The capture-format gate (`YV12`/`NV12`) needs widening: stateless
decoders frequently expose only `NV12` or `NV15` (10-bit, RK3588 HEVC).
Add `NV15` and `NM12` (multiplanar NV12, hantro). Without this the
prober rejects an otherwise-good device.
## 3. Decoder routing — `FFmpegVideoDecoder.cpp`
Codec selection happens at **L651** (`AV_HWDEVICE_TYPE_VAAPI`
`h264_vaapi`) and **L708** (the V4L2 fallback path → `h264_v4l2m2m` via
`FindVideoHardwareAVCodec(mLib, mCodecID)` resolving by suffix). The
stateless route diverges from both: the *codec* must remain the generic
`h264`/`hevc`/`vp9` decoder (libavcodec auto-binds `v4l2_request` from
its `hw_configs` when a DRM hw_device_ctx is attached). Pseudo-patch:
```cpp
if (gfxInfo.mUsingV4L2 && gfxInfo.mV4L2IsStateless) {
AVCodec* codec = mLib->avcodec_find_decoder(mCodecID); // generic
mCodecContext = mLib->avcodec_alloc_context3(codec);
if (!CreateV4L2RequestDeviceContext()) return false;
mCodecContext->get_format = ChooseV4L2PixelFormat; // already returns DRM_PRIME
mUsingV4L2Request = true;
}
```
`CreateV4L2RequestDeviceContext()` body:
```cpp
const char* drm = "/dev/dri/renderD128";
if (mLib->av_hwdevice_ctx_create(&mDRMDeviceContext,
AV_HWDEVICE_TYPE_DRM, drm, nullptr, 0) < 0) return false;
mCodecContext->hw_device_ctx = mLib->av_buffer_ref(mDRMDeviceContext);
```
`av_hwdevice_ctx_create` — not currently wrapped — is the entry point.
The codec's internal hwaccel selector then walks
`avcodec_get_hw_config()` and picks the entry whose `device_type ==
AV_HWDEVICE_TYPE_DRM` and `pix_fmt == AV_PIX_FMT_DRM_PRIME`, which is
the v4l2_request hwaccel registered in `libavcodec/v4l2_request_*.c`.
No `av_hwdevice_find_type_by_name("v4l2_request")` needed — stays an
internal libavcodec name.
## 4. Dmabuf / DRM_PRIME reuse
`ChooseV4L2PixelFormat` at L~258270 already returns
`AV_PIX_FMT_DRM_PRIME` and is the *only* format the v4l2_request
hwaccel produces. The downstream consumer (DMABufSurfaceYUV import in
`FFmpegVideoFramePool.cpp`) is already DRM_PRIME-aware for the
stateful path — same code reads `AVDRMFrameDescriptor` from
`frame->data[0]`. **No new output handling required for NV12/YV12.**
10-bit caveat: RK3588 HEVC outputs `DRM_FORMAT_NV15` / `NV20`
(Mali-tile). Existing `WaylandDMABufSurface::CreateYUVSurface`
modifier list does not include `DRM_FORMAT_MOD_ARM_AFBC` or NV15
fourcc. Either reject 10-bit at probe (capture format gate above) or
extend `gfx/layers/DMABUFSurfaceImage.cpp` — out of scope for v1; gate
to NV12 only.
SAND format pollution Turner mentioned in bug 1969297 c#3 is
**Pi5-specific**; rkvdec/hantro do not produce SAND. Safe to ignore for
the Rockchip target.
## 5. Configuration
New pref:
```yaml
- name: media.ffmpeg.v4l2-request.enabled
type: RelaxedAtomicBool
value: @IS_LINUX@
mirror: always
```
No new env var. No `MOZ_X11_EGL`-style kludge. The existing
`MOZ_LOG=PlatformDecoderModule:5` covers diagnostics. Default-on
matches `media.ffmpeg.vaapi.enabled` shape; users get fallback to
software via existing failure paths if `av_hwdevice_ctx_create` fails
(e.g., missing `/dev/media0`).
## 6. Test plan (fresnel — RK3399, KDE Wayland)
1. `ls /dev/video* /dev/media*` — confirm `/dev/video0` (rkvdec
output) and `/dev/media0` exist.
2. `v4l2-ctl -d /dev/video0 --list-formats-out` — expect
`S264`/`S265`/`VP9F`.
3. Start: `MOZ_LOG="PlatformDecoderModule:5,FFmpegVideo:5"
firefox-fourier 2>&1 | tee fx.log`.
4. Open `https://test-videos.co.uk/bigbuckbunny/mp4-h264` 1080p clip.
5. Success markers in `fx.log`:
- `V4L2ProbeDevice: /dev/video0 supports S264 (stateless)`
- `Choosing FFmpeg pixel format for V4L2 video decoding.`
- `Requesting pixel format DRM PRIME`
- `av_hwdevice_ctx_create(DRM, /dev/dri/renderD128) ok`
- **No** `Using preferred software codec h264`.
6. `cat /sys/kernel/debug/clk/clk_summary | grep vdec` — clock should
be active during playback.
7. `top` — CPU < 40% on a single A72 core for 1080p H.264 (stock =
100% on all 6 cores).
## 7. Build + ship — `firefox-fourier` PKGBUILD
Mirror `chromium-fourier` shape exactly (sibling).
```bash
pkgname=firefox-fourier
pkgver=149.0
arch=('aarch64' 'x86_64')
makedepends=(rust clang lld nodejs python cbindgen nasm yasm wasi-libc-bin
gtk3 mesa libva ffmpeg) # ffmpeg only for headers via system libs
source=(
"https://archive.mozilla.org/pub/firefox/releases/${pkgver}/source/firefox-${pkgver}.source.tar.xz"
patches/0001-gfxinfo-v4l2-stateless-fourccs.patch
patches/0002-libwrapper-hwdevice-ctx-create.patch
patches/0003-ffmpegvideo-v4l2-request-route.patch
patches/0004-prefs-v4l2-request.patch
mozconfig
)
```
`prepare()`: `cd firefox-${pkgver}` → apply patches with `patch -Np1`.
`build()`: `MOZ_NOSPAM=1 ./mach build`. `package()`: `./mach install
DESTDIR=${pkgdir}`. `mozconfig` enables
`--enable-default-toolkit=cairo-gtk3-wayland`, `--with-system-ffmpeg`,
`ac_add_options --disable-tests`. **No** `--enable-media-gpu-process`
— let it default. Tarball is the official Mozilla source release (not
gecko-dev).
Extra makedepends vs. stock firefox PKGBUILD: none — this only
modifies existing C++.
## 8. Risk register (ranked)
1. **libavcodec ABI mismatch.** ALARM ships ffmpeg 7.x; Firefox dlopens
whatever's at `libavcodec.so.61`. If the v4l2_request hwaccel was
compiled out (Arch's ffmpeg has it; ALARM rebuild may not),
`av_hwdevice_ctx_create(DRM, ...)` succeeds but no codec binds —
silent fallback. Mitigation: `ffmpeg -hwaccels` should list `drm`.
2. **Renderer-process sandbox** blocks `/dev/dri/renderD128` open.
VAAPI already brokered this for RDD process; verify
`SandboxBrokerPolicyFactory.cpp` covers `/dev/media*` too — likely
doesn't.
3. **glxtest probe runs in stripped env.** `v4l2test` (the
FireTestProcess child) needs `cap_sys_admin` for
`VIDIOC_S_EXT_CTRLS` request API ioctls? No — request API just
needs `O_RDWR` on `/dev/media*`. Should be fine.
4. **Regression of stateful path.** Adding new fourccs is additive;
the routing branch is gated on `mV4L2IsStateless`. Stateful boards
(Pi4) untouched.
5. **NV15/10-bit on RK3588** — explicitly out-of-scope v1;
gate-rejected.
6. **rkvdec2 driver maturity.** Linux 6.12 mainline rkvdec2 H.264
works; HEVC/VP9 still upstream-pending on some boards. Probe will
skip what kernel doesn't expose.
7. **DMA-BUF modifier negotiation** with panfrost/panthor on Wayland
— already shaken out by chromium-fourier on RK3566; same code
path.
## 9. Upstream path (bug 1969297)
Split into 4 reviewable commits matching files 1, 2+3, 5, 6 from the
table. Add a gtest exercising `V4L2ProbeDevice` against a synthetic
v4l2test stdout containing `S264` (no kernel needed). Reach out to
skyevg (D252119 author) for review continuity. r? jya for the
FFmpegVideoDecoder change. The `av_hwdevice_ctx_create` wrapper
addition is a self-contained 6-liner that should land independently.
The 10-bit/SAND concerns Turner raised remain valid for Pi5 —
explicitly scope this series to **stateless DRM_PRIME NV12 only**,
leaving SAND for a follow-up bug.