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.
10 KiB
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 (~L1030–1110): 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 L173–174) 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):
if (outFormats.Contains("H264")) { mIsV4L2Supported = Some(true);
mV4L2SupportedCodecs |= CODEC_HW_DEC_H264; ... }
Add three siblings, each setting an additional mV4L2IsStateless = true:
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:
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:
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~258–270 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:
- 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)
ls /dev/video* /dev/media*— confirm/dev/video0(rkvdec output) and/dev/media0exist.v4l2-ctl -d /dev/video0 --list-formats-out— expectS264/S265/VP9F.- Start:
MOZ_LOG="PlatformDecoderModule:5,FFmpegVideo:5" firefox-fourier 2>&1 | tee fx.log. - Open
https://test-videos.co.uk/bigbuckbunny/mp4-h2641080p clip. - Success markers in
fx.log:V4L2ProbeDevice: /dev/video0 supports S264 (stateless)Choosing FFmpeg pixel format for V4L2 video decoding.Requesting pixel format DRM PRIMEav_hwdevice_ctx_create(DRM, /dev/dri/renderD128) ok- No
Using preferred software codec h264.
cat /sys/kernel/debug/clk/clk_summary | grep vdec— clock should be active during playback.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).
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)
- 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 -hwaccelsshould listdrm. - Renderer-process sandbox blocks
/dev/dri/renderD128open. VAAPI already brokered this for RDD process; verifySandboxBrokerPolicyFactory.cppcovers/dev/media*too — likely doesn't. - glxtest probe runs in stripped env.
v4l2test(the FireTestProcess child) needscap_sys_adminforVIDIOC_S_EXT_CTRLSrequest API ioctls? No — request API just needsO_RDWRon/dev/media*. Should be fine. - Regression of stateful path. Adding new fourccs is additive;
the routing branch is gated on
mV4L2IsStateless. Stateful boards (Pi4) untouched. - NV15/10-bit on RK3588 — explicitly out-of-scope v1; gate-rejected.
- 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.
- 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.