chromium-fourier r2 + firefox-fourier 150.0.1 + KWIN_PIVOT.md

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
@@ -0,0 +1,75 @@
From: Markus Fritsche <mfritsche@reauktion.de>
Subject: [PATCH 1/4] widget/gtk: recognize V4L2 stateless fourccs in
GfxInfo prober (S264 / S265 / VP9F)
Date: 2026-04-27
Background
----------
Firefox's V4L2 prober in `widget/gtk/GfxInfo.cpp::V4L2ProbeDevice`
parses `v4l2test`'s `V4L2_OUTPUT_FMTS` line and matches against the
fourccs of stateful V4L2-M2M decoders (`H264`, `VP80`, `VP90`, `HEVC`).
That's correct for Pi4 / Mediatek / vendor-MPP stateful decoders but
silently skips every mainline-Linux Rockchip board: RK3399 `rkvdec`,
RK3566 `hantro` (multiplanar), RK3588 `hantro` and `rkvdec2` all
expose stateless fourccs only — `S264`, `S265`, `VP9F`. The probe
binary itself enumerates these correctly (verified end-to-end on
fresnel / Pinebook Pro / RK3399 with `v4l2test --device /dev/video1`
showing `V4L2_OUTPUT_FMTS: S265 S264 VP9F` and
`V4L2_SUPPORTED: TRUE`); the gap is purely in this string table.
This patch adds the three sibling blocks for the stateless fourccs,
each identical in shape to the existing stateful blocks except for
setting a new `mV4L2IsStateless` member. The follow-up patches in
this series (2/4, 3/4, 4/4) consume that member to route through the
libavcodec v4l2_request hwaccel (`AV_HWDEVICE_TYPE_DRM`) instead of
the v4l2m2m codec wrapper used for stateful boards.
Bug 1969297.
diff --git a/widget/gtk/GfxInfo.h b/widget/gtk/GfxInfo.h
--- a/widget/gtk/GfxInfo.h
+++ b/widget/gtk/GfxInfo.h
@@ -127,6 +127,10 @@
mozilla::Maybe<bool> mIsVAAPISupported;
int mVAAPISupportedCodecs = 0;
mozilla::Maybe<bool> mIsV4L2Supported;
+ // firefox-fourier: true when probe matched at least one stateless
+ // V4L2 fourcc (S264 / S265 / VP9F). Drives libavcodec v4l2_request
+ // hwaccel routing in FFmpegVideoDecoder.cpp.
+ bool mV4L2IsStateless = false;
int mV4L2SupportedCodecs = 0;
static int sGLXTestPipe;
diff --git a/widget/gtk/GfxInfo.cpp b/widget/gtk/GfxInfo.cpp
--- a/widget/gtk/GfxInfo.cpp
+++ b/widget/gtk/GfxInfo.cpp
@@ -852,6 +852,29 @@ void GfxInfo::V4L2ProbeDevice(nsCString& dev) {
media::MCSInfo::AddSupport(media::MediaCodecsSupport::HEVCHardwareDecode);
mV4L2SupportedCodecs |= CODEC_HW_DEC_HEVC;
}
+ // firefox-fourier: V4L2 stateless (request API) fourccs. Mainline
+ // Rockchip rkvdec / hantro / rkvdec2 expose these instead of the
+ // V4L2-M2M-stateful fourccs above. Decoding routes through
+ // libavcodec's v4l2_request hwaccel (AV_HWDEVICE_TYPE_DRM) rather
+ // than the *_v4l2m2m codec wrappers — see FFmpegVideoDecoder.cpp.
+ if (outFormats.Contains("S264")) {
+ mIsV4L2Supported = Some(true);
+ mV4L2IsStateless = true;
+ media::MCSInfo::AddSupport(media::MediaCodecsSupport::H264HardwareDecode);
+ mV4L2SupportedCodecs |= CODEC_HW_DEC_H264;
+ }
+ if (outFormats.Contains("S265")) {
+ mIsV4L2Supported = Some(true);
+ mV4L2IsStateless = true;
+ media::MCSInfo::AddSupport(media::MediaCodecsSupport::HEVCHardwareDecode);
+ mV4L2SupportedCodecs |= CODEC_HW_DEC_HEVC;
+ }
+ if (outFormats.Contains("VP9F")) {
+ mIsV4L2Supported = Some(true);
+ mV4L2IsStateless = true;
+ media::MCSInfo::AddSupport(media::MediaCodecsSupport::VP9HardwareDecode);
+ mV4L2SupportedCodecs |= CODEC_HW_DEC_VP9;
+ }
}
const nsTArray<RefPtr<GfxDriverInfo>>& GfxInfo::GetGfxDriverInfo() {
@@ -0,0 +1,52 @@
From: Markus Fritsche <mfritsche@reauktion.de>
Subject: [PATCH 2/4] dom/media/platforms/ffmpeg: wrap
av_hwdevice_ctx_create
Date: 2026-04-27
Background
----------
`FFmpegLibWrapper` already wraps `av_hwdevice_ctx_alloc` (no device
path) and `av_hwdevice_ctx_init`, used by the VAAPI codepath which
discovers the DRM device implicitly. The v4l2_request hwaccel needs
the *path-aware* constructor `av_hwdevice_ctx_create`, which lets the
caller pass `"/dev/dri/renderD128"` (or similar) directly when
creating an `AV_HWDEVICE_TYPE_DRM` context. libavcodec then binds the
v4l2_request hwaccel internally based on the codec's `hw_configs`.
This patch adds the function pointer + the `AV_FUNC_OPTION_SILENT`
registration. Same versioning as the other `av_hwdevice_ctx_*`
wrappers (libavutil 5862). No callers yet — patch 3/4
(FFmpegVideoDecoder routing) consumes it.
Bug 1969297.
diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
--- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
+++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
@@ -177,6 +177,11 @@
// libavutil >= 58
AVBufferRef* (*av_hwdevice_ctx_alloc)(int);
int (*av_hwdevice_ctx_init)(AVBufferRef* ref);
+ // firefox-fourier: device-path-aware constructor needed to bind a
+ // DRM hwdevice (AV_HWDEVICE_TYPE_DRM) to /dev/dri/renderD* for the
+ // libavcodec v4l2_request hwaccel.
+ int (*av_hwdevice_ctx_create)(AVBufferRef** device_ctx, int type,
+ const char* device, void* opts, int flags);
AVBufferRef* (*av_hwframe_ctx_alloc)(AVBufferRef* device_ctx);
int (*av_hwframe_ctx_init)(AVBufferRef* ref);
AVBufferRef* (*av_buffer_ref)(AVBufferRef* buf);
diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
--- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
@@ -293,6 +293,11 @@ FFmpegLibWrapper::LinkResult FFmpegLibWrapper::Link() {
AV_FUNC_AVUTIL_58 | AV_FUNC_AVUTIL_59 |
AV_FUNC_AVUTIL_60 | AV_FUNC_AVUTIL_61 |
AV_FUNC_AVUTIL_62)
+ // firefox-fourier: see comment in FFmpegLibWrapper.h
+ AV_FUNC_OPTION_SILENT(av_hwdevice_ctx_create,
+ AV_FUNC_AVUTIL_58 | AV_FUNC_AVUTIL_59 |
+ AV_FUNC_AVUTIL_60 | AV_FUNC_AVUTIL_61 |
+ AV_FUNC_AVUTIL_62)
AV_FUNC_OPTION_SILENT(
av_buffer_ref, AV_FUNC_AVUTIL_58 | AV_FUNC_AVUTIL_59 | AV_FUNC_AVUTIL_60 |
AV_FUNC_AVUTIL_61 | AV_FUNC_AVUTIL_62)
@@ -0,0 +1,208 @@
From: Markus Fritsche <mfritsche@reauktion.de>
Subject: [PATCH 3/4] dom/media/platforms/ffmpeg: route through libavcodec
v4l2_request hwaccel for V4L2 stateless boards
Date: 2026-04-27
Background
----------
Firefox's existing V4L2 init (`InitV4L2Decoder`) finds the codec by
suffix lookup (`FindVideoHardwareAVCodec(mLib, mCodecID)`), which on
Linux resolves to the **stateful** V4L2-M2M wrapper codec
(`h264_v4l2m2m` etc). Mainline-Linux Rockchip boards (RK3399 rkvdec,
RK3566/RK3588 hantro, RK3588 rkvdec2) only expose **stateless**
V4L2 fourccs (`S264`, `S265`, `VP9F`); the stateful wrapper codec
fails to open, Firefox falls all the way through to software.
This patch adds a sibling init path, `InitV4L2RequestDecoder`, that:
* uses the **generic** codec (e.g. plain `h264`, returned by
`avcodec_find_decoder(AV_CODEC_ID_H264)`) rather than the stateful
wrapper;
* sanity-checks the codec's `hw_configs` for an `AV_HWDEVICE_TYPE_DRM`
entry — that's how libavcodec surfaces the v4l2_request hwaccel
upstream (no dedicated `_V4L2REQUEST` device type exists);
* creates an `AV_HWDEVICE_TYPE_DRM` hwdevice context bound to
`/dev/dri/renderD128` via the new `av_hwdevice_ctx_create` wrapper
(patch 2/4) and attaches it to the codec context;
* reuses the existing `ChooseV4L2PixelFormat` get-format callback
(already returns `AV_PIX_FMT_DRM_PRIME`) and the existing
`apply_cropping = 0` constraint.
`InitV4L2RequestDecoder` is invoked **before** `InitV4L2Decoder` in
`InitHWDecoderIfAllowed`. On Rockchip mainline it succeeds. On Pi4 /
Mediatek / vendor-MPP-stateful boards the codec's `hw_configs` lacks
a DRM entry (the V4L2-M2M codecs don't register one), the sanity
check fails, and the existing stateful `InitV4L2Decoder` runs as
before. No regression of stateful boards.
`mDRMDeviceContext` is unconditionally `av_buffer_unref`'d in
`ProcessShutdown` (no-op when null). Gated behind
`media.ffmpeg.v4l2-request.enabled` from patch 4/4.
Bug 1969297.
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h 2026-03-18 19:22:14.000000000 +0000
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h 2026-04-27 20:43:39.347992674 +0000
@@ -225,7 +225,12 @@
bool IsLinuxHDR() const;
MediaResult InitVAAPIDecoder();
MediaResult InitV4L2Decoder();
+ // firefox-fourier: V4L2 stateless (request API) decode path. Uses
+ // libavcodec's v4l2_request hwaccel, which it surfaces via
+ // AV_HWDEVICE_TYPE_DRM rather than a dedicated _V4L2REQUEST type.
+ MediaResult InitV4L2RequestDecoder();
bool CreateVAAPIDeviceContext();
+ bool CreateV4L2RequestDeviceContext();
bool GetVAAPISurfaceDescriptor(VADRMPRIMESurfaceDescriptor* aVaDesc);
void AddAcceleratedFormats(nsTArray<AVCodecID>& aCodecList,
AVCodecID aCodecID, AVVAAPIHWConfig* hwconfig);
@@ -239,7 +244,10 @@
void AdjustHWDecodeLogging();
AVBufferRef* mVAAPIDeviceContext = nullptr;
+ // firefox-fourier: DRM hwdevice ctx for the v4l2_request hwaccel.
+ AVBufferRef* mDRMDeviceContext = nullptr;
bool mUsingV4L2 = false;
+ bool mUsingV4L2Request = false;
// If video overlay is used we want to upload SW decoded frames to
// DMABuf and present it as a external texture to rendering pipeline.
bool mUploadSWDecodeToDMABuf = false;
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2026-03-18 19:22:14.000000000 +0000
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2026-04-27 20:44:33.280766228 +0000
@@ -406,6 +406,105 @@
return NS_OK;
}
+// firefox-fourier: V4L2 stateless (request API) DRM hwdevice context.
+// libavcodec's v4l2_request hwaccel binds via AV_HWDEVICE_TYPE_DRM —
+// no dedicated _V4L2REQUEST type exists upstream.
+bool FFmpegVideoDecoder<LIBAV_VER>::CreateV4L2RequestDeviceContext() {
+ if (!mLib->av_hwdevice_ctx_create) {
+ FFMPEG_LOG(" av_hwdevice_ctx_create not available (libavutil too old)");
+ return false;
+ }
+ const char* drmDevice = "/dev/dri/renderD128";
+ if (mLib->av_hwdevice_ctx_create(&mDRMDeviceContext,
+ AV_HWDEVICE_TYPE_DRM, drmDevice,
+ nullptr, 0) < 0) {
+ FFMPEG_LOG(" av_hwdevice_ctx_create(DRM, %s) failed", drmDevice);
+ return false;
+ }
+ mCodecContext->hw_device_ctx = mLib->av_buffer_ref(mDRMDeviceContext);
+ FFMPEG_LOG(" DRM hwdevice ctx created on %s", drmDevice);
+ return true;
+}
+
+// firefox-fourier: try V4L2 stateless decode via libavcodec's
+// v4l2_request hwaccel. Distinct from InitV4L2Decoder which uses the
+// stateful h264_v4l2m2m wrapper codec. On Rockchip mainline boards
+// (rkvdec / hantro / rkvdec2) only the stateless path exists.
+MediaResult FFmpegVideoDecoder<LIBAV_VER>::InitV4L2RequestDecoder() {
+ FFMPEG_LOG("Initialising V4L2 stateless (request API) FFmpeg decoder");
+
+ StaticMutexAutoLock mon(sMutex);
+
+ // Use the GENERIC codec (not the _v4l2m2m wrapper). libavcodec picks
+ // the v4l2_request hwaccel internally by walking the codec's
+ // hw_configs once an AV_HWDEVICE_TYPE_DRM ctx is attached.
+ AVCodec* codec = mLib->avcodec_find_decoder(mCodecID);
+ if (!codec) {
+ FFMPEG_LOG(" generic codec for ID %d not found", mCodecID);
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ // Sanity-check: refuse when libavcodec was built without the
+ // v4l2_request hwaccel (no DRM hwaccel registered against this
+ // codec). Distro packagers occasionally drop --enable-v4l2-request.
+ bool hasDrmHwaccel = false;
+ for (int i = 0;; i++) {
+ const AVCodecHWConfig* cfg = mLib->avcodec_get_hw_config(codec, i);
+ if (!cfg) break;
+ if (cfg->device_type == AV_HWDEVICE_TYPE_DRM) {
+ hasDrmHwaccel = true;
+ break;
+ }
+ }
+ if (!hasDrmHwaccel) {
+ FFMPEG_LOG(" codec %s has no DRM hwaccel — libavcodec built "
+ "without --enable-v4l2-request?", codec->name);
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ FFMPEG_LOG(" V4L2 stateless: codec %s : %s", codec->name, codec->long_name);
+
+ if (!(mCodecContext = mLib->avcodec_alloc_context3(codec))) {
+ FFMPEG_LOG(" couldn't init HW ffmpeg context");
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mCodecContext->opaque = this;
+
+ // Reuse the existing V4L2 init helpers: pixel-format selector returns
+ // AV_PIX_FMT_DRM_PRIME, cropping disabled (FFmpeg can't crop opaque
+ // DRM buffers). Same constraints as the stateful V4L2 path.
+ InitHWCodecContext(ContextType::V4L2);
+ mCodecContext->apply_cropping = 0;
+
+ auto releaseDecoder = MakeScopeExit(
+ [&]() MOZ_NO_THREAD_SAFETY_ANALYSIS { ReleaseCodecContext(); });
+
+ if (!CreateV4L2RequestDeviceContext()) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ MediaResult ret = AllocateExtraData();
+ if (NS_FAILED(ret)) {
+ return ret;
+ }
+
+ if (mLib->avcodec_open2(mCodecContext, codec, nullptr) < 0) {
+ FFMPEG_LOG(" Couldn't open V4L2 stateless decoder");
+ return NS_ERROR_DOM_MEDIA_FATAL_ERR;
+ }
+
+ if (mAcceleratedFormats.IsEmpty()) {
+ mAcceleratedFormats.AppendElement(mCodecID);
+ }
+
+ AdjustHWDecodeLogging();
+
+ FFMPEG_LOG(" V4L2 stateless FFmpeg init successful");
+ mUsingV4L2 = true;
+ mUsingV4L2Request = true;
+ releaseDecoder.release();
+ return NS_OK;
+}
+
MediaResult FFmpegVideoDecoder<LIBAV_VER>::InitV4L2Decoder() {
FFMPEG_LOG("Initialising V4L2-DRM FFmpeg decoder");
@@ -659,6 +758,16 @@
# endif // MOZ_ENABLE_VAAPI
# ifdef MOZ_ENABLE_V4L2
+ // firefox-fourier: try V4L2 stateless (request API) first. On
+ // mainline-Linux Rockchip boards (RK3399 rkvdec, RK3566/RK3588
+ // hantro, RK3588 rkvdec2) the kernel exposes only stateless
+ // fourccs, so the stateful path below would fail anyway. On
+ // stateful boards (Pi4 / vendor MPP) this gracefully falls
+ // through (no DRM hwaccel registered for the codec).
+ if (StaticPrefs::media_ffmpeg_v4l2_request_enabled() &&
+ NS_SUCCEEDED(InitV4L2RequestDecoder())) {
+ return;
+ }
// VAAPI didn't work or is disabled, so try V4L2 with DRM
if (NS_SUCCEEDED(InitV4L2Decoder())) {
return;
@@ -2046,6 +2155,11 @@
if (IsHardwareAccelerated()) {
mLib->av_buffer_unref(&mVAAPIDeviceContext);
}
+ // firefox-fourier: release the DRM hwdevice ctx for the v4l2_request
+ // hwaccel. Always safe — av_buffer_unref no-ops on a null pointer.
+ if (mDRMDeviceContext) {
+ mLib->av_buffer_unref(&mDRMDeviceContext);
+ }
#endif
#ifdef MOZ_ENABLE_D3D11VA
if (IsHardwareAccelerated()) {
@@ -0,0 +1,34 @@
From: Markus Fritsche <mfritsche@reauktion.de>
Subject: [PATCH 4/4] modules/libpref: add media.ffmpeg.v4l2-request.enabled
Date: 2026-04-27
Background
----------
Toggle for the V4L2 stateless (request API) decode path introduced
in patch 3/4. Defaults on for Linux, mirroring the
`media.ffmpeg.vaapi.enabled`-style shape. Users can flip to false to
force the existing stateful `InitV4L2Decoder` (or VAAPI / software
fallbacks) without rebuilding.
Bug 1969297.
diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -12159,6 +12159,16 @@
type: uint32_t
value: 2
mirror: once
+
+# firefox-fourier: route V4L2 stateless (request API) decode through
+# libavcodec's v4l2_request hwaccel (AV_HWDEVICE_TYPE_DRM). Required
+# for mainline-Linux Rockchip rkvdec / hantro / rkvdec2. On stateful
+# boards (Pi4 / vendor MPP) the codec's hw_configs lacks a DRM entry
+# and the path silently falls back to InitV4L2Decoder.
+- name: media.ffmpeg.v4l2-request.enabled
+ type: RelaxedAtomicBool
+ value: true
+ mirror: always
#endif # MOZ_WIDGET_GTK
# Set to true in marionette tests to disable the sanity test