8756ce38be
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.
429 lines
22 KiB
Markdown
429 lines
22 KiB
Markdown
# chromium-fourier — first-build status (2026-04-26 00:42 UTC)
|
||
|
||
## Where we are
|
||
|
||
Build environment: **chromium-builder LXD container on boltzmann**
|
||
(8 cores, 28 GB RAM cap, 824 GB NVMe, Beryllium OS rkr3 host kernel).
|
||
Source: chromium-147.0.7727.116 release tarball extracted at
|
||
`/build/chromium/src` (25 GB extracted).
|
||
|
||
`gn gen out/Default` **succeeds** with our 7Ji-style args
|
||
(`use_v4l2_codec=true use_v4lplugin=true use_linux_v4l2_only=true
|
||
use_vaapi=false`, system toolchain via `unbundle:default`, system clang
|
||
at `/usr/bin/clang`, version-symlink `/usr/lib/clang/23` →
|
||
`/usr/lib/clang/22`, compiler-rt-adjust-paths style suffix patch
|
||
manually applied). 28057 targets generated.
|
||
|
||
`ninja -C out/Default chrome` **fails immediately** with two distinct walls:
|
||
|
||
### Wall 1 — clang version mismatch (chromium 147 ↔ Arch clang 22)
|
||
|
||
Chromium 147's compile flags include
|
||
`-fno-lifetime-dse` and
|
||
`-fsanitize-ignore-for-ubsan-feature=array-bounds`. Both are clang 23+
|
||
features. Arch Linux ARM ships **clang 22.1.3** (extra repo). Every
|
||
single C++ compile fails with `clang++: error: unknown argument`.
|
||
|
||
Resolutions, in order of effort:
|
||
|
||
- **(a)** Wait for Arch ARM to bump clang to 23. Tracking package
|
||
upstream — happens whenever LLVM 23 lands in extra. Days to weeks.
|
||
- **(b)** Use chromium's bundled clang via
|
||
`tools/clang/scripts/update.py`. That hits the same CIPD/gs://
|
||
"linux-arm64 isn't a first-class target" issue we saw with
|
||
`gclient sync` earlier — chromium's clang prebuilts are x86_64-only
|
||
for many platforms.
|
||
- **(c)** Fork an older chromium (e.g., 132 or 138) that compiles
|
||
cleanly with clang 22. 7Ji's chromium-mpp PKGBUILD targets 132 and
|
||
builds clean on Arch ARM today. Loses 15 versions of upstream
|
||
chromium evolution but ships fast.
|
||
- **(d)** Patch chromium 147 to drop the offending flags
|
||
(`build/config/compiler/BUILD.gn` has the cflags lists). 50–200 line
|
||
patch, brittle across version bumps but tractable. Fights every
|
||
rebase.
|
||
|
||
### Wall 2 — bundled x86_64 esbuild under qemu
|
||
|
||
After Wall 1 (or independently for Action targets):
|
||
`qemu-x86_64-static: Could not open '/lib64/ld-linux-x86-64.so.2'`
|
||
when chromium runs the bundled x86_64 `esbuild` from
|
||
`third_party/devtools-frontend/.../scripts/build/typescript/ts_library.py`.
|
||
Same shape as the bundled `node-linux-x64` issue we already fixed (we
|
||
symlinked system node into that path). `esbuild` needs the same
|
||
treatment — install system esbuild via `npm install -g esbuild` and
|
||
symlink it into the path chromium expects. Or install `qemu-user-static`
|
||
+ `glibc-x86_64` to make the bundled binary actually run.
|
||
|
||
**Wall 2 is much smaller than Wall 1** — a handful of bundled-x86_64
|
||
binaries to identify and replace, vs. fundamental clang version mismatch.
|
||
|
||
## What worked
|
||
|
||
- LXD container provisioning on boltzmann via his recommendation —
|
||
the host environment is right.
|
||
- Tarball-instead-of-gclient approach — sidesteps CIPD-doesn't-have-
|
||
linux-arm64 problem for source acquisition, leaves only a few
|
||
bundled binary issues at build time.
|
||
- Wall 1 / Wall 2 are both **identifiable and bounded**. We're past
|
||
the "is this even doable" phase; this is now down to grinding the
|
||
patches.
|
||
|
||
## Options — needs your call
|
||
|
||
1. **Grind through Wall 1 with patches** — patch
|
||
`build/config/compiler/BUILD.gn` to drop flags clang 22 doesn't
|
||
know. Iterate per build error. Estimated 5–15 patch-and-retry
|
||
cycles to compile clean. Then 6–10 h actual build.
|
||
2. **Pin to chromium 132** — match 7Ji's known-working version on
|
||
Arch ARM. Drop our STUDY focus on "current upstream Chromium" and
|
||
ship a 1-year-old binary. Build should work much sooner.
|
||
3. **Pin to chromium 138 or 140** — middle ground. Likely uses clang
|
||
22 features and not 23. Some research needed to find the cutover.
|
||
4. **Use chromium's bundled clang** — not viable on linux-arm64
|
||
without extensive sysroot setup; same CIPD issue as gclient sync.
|
||
5. **Wait for Arch ARM clang 23** — passive, days-to-weeks horizon.
|
||
|
||
Recommended (FWIW): **start with (3)** — find the latest chromium
|
||
version that builds clean against clang 22 (probably 138-141 range),
|
||
ship that as `chromium-fourier`, then bump as Arch ARM bumps clang.
|
||
That gives us a working browser in a few hours rather than days, on
|
||
mainline Linux + Wayland + V4L2 unlock — which is the actual goal.
|
||
The "current upstream Chromium" requirement was nice-to-have, not
|
||
essential.
|
||
|
||
## State of the build host (preserved)
|
||
|
||
- Container: `chromium-builder` on boltzmann (running, idle)
|
||
- Source: `/build/chromium/src` (extracted tarball, 25 GB)
|
||
- Build dir: `/build/chromium/src/out/Default` (gn-gen'd, no artifacts)
|
||
- Tools installed: gn, ninja, clang 22, lld, gperf, nodejs (system),
|
||
rust, qt5/6, all the gtk/wayland/va/v4l deps from the long pacman
|
||
shopping list
|
||
- Patches applied to source: `compiler-rt-adjust-paths` style (manual)
|
||
- Symlinks: `/usr/lib/clang/23` → `/usr/lib/clang/22`,
|
||
`third_party/node/linux/node-linux-x64/bin/node` → `/usr/bin/node`
|
||
- Service unit history: `chromium-fetch.service` (one-shot, succeeded
|
||
on tarball + extract); `chromium-build.service` (one-shot, three
|
||
failed attempts above).
|
||
|
||
Discard the container and start over with option 2 if you pick that
|
||
direction; otherwise iterate from current state.
|
||
|
||
## Pivot 2026-04-26 — cross-compile from x86_64
|
||
|
||
After the analysis above, the framing shifted. The real wall isn't
|
||
"Arch ARM clang 22 vs LLVM 23" — Arch x86_64 is also on llvm 22.1.3, no
|
||
LLVM 23 anywhere in extra/staging. The flags chromium 147 emits
|
||
(`-fno-lifetime-dse`, `-fsanitize-ignore-for-ubsan-feature=array-bounds`,
|
||
the `/usr/lib/clang/23/...` path) come from **chromium's clang fork**,
|
||
not upstream LLVM 23. Chromium ships its own LLVM with chromium-specific
|
||
passes; the "23" in the path is chromium-internal versioning.
|
||
|
||
Implication: PKGBUILD'ing clang 23 is the wrong tree. The right tree is
|
||
either pin to an older chromium (option 2 above) or **cross-compile from
|
||
an x86_64 host** so chromium's x86_64 bundled clang prebuilt is
|
||
reachable and `target_cpu="arm64"` produces the aarch64 binary cleanly.
|
||
Cross-compile sidesteps every wall we hit:
|
||
|
||
- CIPD has full `linux-amd64` prebuilts (the gap was `linux-arm64`)
|
||
- Chromium's bundled clang downloads cleanly on x86_64
|
||
- No qemu-x86_64-static dance for tools (host IS x86_64)
|
||
- `tools/clang/scripts/update.py` works as Google intends
|
||
- `gclient sync` works; no DEPS surgery needed
|
||
|
||
his provisioned a cross-build host for this on 2026-04-26:
|
||
|
||
- **CT 220 `chromium-builder-x86` on data**, x86_64 Ryzen 7 1700,
|
||
14 cores, 32 GiB RAM + 8 GiB swap, 200 GiB ZFS rootfs.
|
||
- Reach via `mcp__hub-tools__remote_shell host=hertz` →
|
||
`ssh root@192.168.88.30` (data) → `pct exec 220 -- ...`
|
||
- `builder` user uid 1001, NOPASSWD sudo, `DisableSandbox` in pacman.conf.
|
||
|
||
Source fetch started 2026-04-26 05:45 UTC as transient unit
|
||
`chromium-fetch.service` on CT 220. Estimated 1-2 h for `fetch
|
||
--no-history chromium` over the LAN. Then `tools/clang/scripts/update.py`
|
||
to install chromium's bundled clang (x86_64 host, arm64 sysroot), then
|
||
`gn gen` with `target_cpu="arm64"` + cross-compile flags, then build.
|
||
|
||
The boltzmann `chromium-builder` LXD container is preserved as fallback
|
||
but no longer the active build host. If cross-compile pans out, that
|
||
container can be torn down.
|
||
|
||
## First runtime validation on ohm — 2026-04-26 22:26 UTC
|
||
|
||
Cross-compile produced a working aarch64 binary (chrome 647 MB ELF +
|
||
chrome_crashpad_handler 4.3 MB + .pak + locales). Tarball
|
||
`chromium-fourier-147.tar.gz` (226 MB) transferred CT 220 → hertz → ohm.
|
||
Launched in mfritsche's KWin Wayland session (tty2, panfrost render
|
||
node) playing `bbb_1080p30_h264.mp4` from file:// with
|
||
`LIBVA_DRIVER_NAME=v4l2_request`,
|
||
`LIBVA_V4L2_REQUEST_VIDEO_PATH=/dev/video0`,
|
||
`--use-gl=egl --ozone-platform=wayland
|
||
--enable-features=VaapiVideoDecodeLinuxGL,AcceleratedVideoDecodeLinuxGL
|
||
--disable-features=UseChromeOSDirectVideoDecoder
|
||
--autoplay-policy=no-user-gesture-required`.
|
||
|
||
**Result: V4L2 path NOT engaged.** Chrome 147 routes the H.264 stream
|
||
through `MojoVideoDecoderService` → `media/filters/ffmpeg_video_decoder.cc`
|
||
(software FFmpeg). Renderer pegs at ~92 % CPU, `/dev/video0` is never
|
||
opened (`fuser` returns empty), no `V4L2VideoDecoder` /
|
||
`VaapiVideoDecoder` log lines appear at `--v=1
|
||
--vmodule="*/vaapi/*=2,*/v4l2/*=2,*video_decoder*=2,*media/gpu/*=2"`.
|
||
Compositor also fell back to software (`Switching to software
|
||
compositing.` even though panfrost render node was picked) — secondary
|
||
issue, separate from the codec wall.
|
||
|
||
**Conclusion**: 7Ji-style gn args (`use_v4l2_codec=true
|
||
use_v4lplugin=true use_linux_v4l2_only=true`) alone are insufficient
|
||
on chromium 147. The V4L2VideoDecoder factory is still gated behind
|
||
`BUILDFLAG(IS_CHROMEOS)` — `media/mojo/services/gpu_mojo_media_client_*.cc`
|
||
and `media/gpu/gpu_video_decode_accelerator_factory.cc` only register
|
||
the V4L2 path on ChromeOS targets.
|
||
|
||
## Validation pass 2 — 2026-04-26 22:38 UTC — V4L2VDA proven engaged
|
||
|
||
Two distinct issues were diagnosed and the codec one was fully resolved
|
||
without source surgery beyond a 2-line patch:
|
||
|
||
### Issue 1 — runtime master gate
|
||
`media::kAcceleratedVideoDecodeLinux` (user-visible feature name
|
||
"AcceleratedVideoDecoder") is hard-coded in
|
||
`media/base/media_switches.cc:750` to `FEATURE_ENABLED_BY_DEFAULT` only
|
||
when `BUILDFLAG(USE_VAAPI)` is set. On a USE_V4L2_CODEC-only build it
|
||
defaults DISABLED, the linux gpu_mojo_media_client returns
|
||
`VideoDecoderType::kUnknown`, and chrome silently falls back to
|
||
`media/filters/ffmpeg_video_decoder.cc`.
|
||
|
||
**Fix**: 2-line patch (now `patches/enable-v4l2-decoder-default.patch`):
|
||
```
|
||
-#if BUILDFLAG(USE_VAAPI)
|
||
+#if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
|
||
```
|
||
|
||
The placeholder `chromeos-pipeline-bypass.patch` was deleted; PKGBUILD
|
||
now references the real patch. **Verified to apply cleanly on the CT 220
|
||
tree** (chromium 149 main).
|
||
|
||
### Issue 2 — bundled GL libs missing from tarball
|
||
The first runtime tarball shipped only `chrome` + `.pak` + locales +
|
||
`chrome_crashpad_handler`. It omitted `libEGL.so` / `libGLESv2.so`
|
||
(ANGLE) plus `libvk_swiftshader.so` and `libvulkan.so.1`. Without these,
|
||
the GPU process logs `gl::init::InitializeStaticGLBindingsOneOff failed`
|
||
and chrome falls into "Switching to software compositing." mode — which
|
||
*also* gates the V4L2 path off because the gpu_mojo_media_client never
|
||
gets a chance to dispatch.
|
||
|
||
Additionally, `--use-gl=egl` is rejected ("Requested GL implementation
|
||
gl=egl-gles2,angle=none not found in allowed implementations:
|
||
[(gl=egl-angle,angle=opengl|opengles|vulkan)]"): the build only allows
|
||
ANGLE-mediated paths. Right launcher invocation:
|
||
`--use-gl=angle --use-angle=gles`.
|
||
|
||
**Fix**: package the four libs alongside `chrome` and update the
|
||
launcher flag set. Both will be encoded in the next iteration of the
|
||
PKGBUILD's `package()` and a `chromium-fourier` launcher script.
|
||
|
||
### What we observed once both fixes were in place
|
||
With patch + bundled libs + `--enable-features=AcceleratedVideoDecoder`
|
||
+ `--use-gl=angle --use-angle=gles`, chrome on RK3566 hantro logs:
|
||
|
||
```
|
||
[gpu]: V4L2VideoDecoder()
|
||
[gpu]: Open(): No devices supporting H264 for type: 0 <- type=0 is single-planar; chrome retries multi-planar
|
||
[gpu]: InitializeBackend(): Using a stateless API for profile: h264 main and fourcc: S264
|
||
[gpu]: SetupInputFormat(): Input (OUTPUT queue) Fourcc: S264
|
||
[gpu]: AllocateInputBuffers(): Requesting: 17 OUTPUT buffers of type V4L2_MEMORY_MMAP
|
||
[gpu]: SetExtCtrlsInit(): Setting EXT_CTRLS for H264
|
||
[gpu]: SetupOutputFormat(): Output (CAPTURE queue) candidate: NV12
|
||
[gpu]: ContinueChangeResolution(): Requesting: 6 CAPTURE buffers of type V4L2_MEMORY_MMAP
|
||
[renderer]: OnDecoderSelected<video>: V4L2VideoDecoder
|
||
MediaEvent: "Selected V4L2VideoDecoder for video decoding,
|
||
config: codec: h264, profile: h264 main, [...]
|
||
coded size: [1920,1080], visible rect: [0,0,1920,1080]"
|
||
```
|
||
|
||
`fuser /dev/video1 /dev/media0` shows `chrome` (gpu pid) holding both
|
||
fds. The hantro stateless decoder is engaged. **First end-to-end
|
||
chromium-fourier V4L2 hardware decode validation: PASS** for H.264
|
||
1080p Big Buck Bunny on PineTab2.
|
||
|
||
Caveat: the render-side CPU was still ~85% during playback. Subsequent
|
||
investigation traced this to a different root cause than initially
|
||
guessed (see Pass 3 below).
|
||
|
||
## Validation pass 3 — 2026-04-26 22:50 UTC — zero-copy diagnosis
|
||
|
||
The 85 % CPU is **not** caused by software compositing or dmabuf v5
|
||
negotiation. The dmabuf-v5 warning ("Binding to zwp_linux_dmabuf_v1
|
||
version 4 but version 5 is available") is benign — chrome happily binds
|
||
to its supported max (v4). The `WaylandZwpLinuxDmabuf::OnTrancheFlags`
|
||
NOTIMPLEMENTED is also benign — KWin sends it, chrome ignores it, but
|
||
the substantive feedback (formats + modifiers) lands via
|
||
`OnTrancheFormats` / `OnTrancheTargetDevice` regardless.
|
||
|
||
Real cause: `gpu_feature_info.supports_nv12_gl_native_pixmap` ends up
|
||
**false** on this build. With it false, V4L2-decoded NV12 frames go
|
||
through the NV12-to-AR24 VPP conversion path (see
|
||
`media/mojo/services/gpu_mojo_media_client_linux.cc`
|
||
`GetPreferredRenderableFourccs` — without NV12 native pixmap support,
|
||
only `Fourcc::AR24` is added to the renderable set, forcing the VPP).
|
||
That's where the 85 % is spent.
|
||
|
||
Why is `supports_nv12_gl_native_pixmap` false?
|
||
`GLOzoneEGLWayland::CanImportNativePixmap` (in
|
||
`ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc`) requires the
|
||
chrome GL display to expose `EGL_EXT_image_dma_buf_import`. With
|
||
`--use-gl=angle --use-angle=gles`, chrome's GL display sits behind
|
||
ANGLE's EGL, and ANGLE's GLES backend on Linux does not propagate
|
||
`EGL_EXT_image_dma_buf_import` from the underlying mesa EGL up to its
|
||
clients. Verified directly: `EGL_PLATFORM=surfaceless eglinfo` on ohm
|
||
shows panfrost native EGL exposes both
|
||
`EGL_EXT_image_dma_buf_import` and `EGL_EXT_image_dma_buf_import_modifiers` —
|
||
the capability is there at the panfrost layer, ANGLE just hides it.
|
||
|
||
We tried `--use-gl=egl` (direct EGL/GLES2, bypass ANGLE) but were
|
||
rejected with "Requested GL implementation (gl=egl-gles2,angle=none) not
|
||
found in allowed implementations". `WaylandSurfaceFactory::GetAllowedGLImplementations()`
|
||
in chromium 149 advertises only ANGLE-mediated impls; the
|
||
`kGLImplementationEGLGLES2` slot is missing from the list. The
|
||
`CreateViewGLSurface` dispatcher does still handle that impl — only the
|
||
*advertisement* was tightened.
|
||
|
||
### Patch 2/2 — `wayland-allow-direct-egl-gles2.patch`
|
||
3-line diff in `ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc`:
|
||
```
|
||
+ impls.emplace_back(gl::GLImplementationParts(gl::kGLImplementationEGLGLES2));
|
||
impls.emplace_back(gl::ANGLEImplementation::kOpenGL);
|
||
```
|
||
Re-allows the direct EGL/GLES2 path, ahead of the ANGLE entries so
|
||
chrome picks it by default. Verified to apply cleanly on the CT 220
|
||
tree; staged via `patch -p1` mid-rebuild (ninja's mtime-based rebuild
|
||
will pick up the change automatically).
|
||
|
||
### Outstanding for next pass (revised)
|
||
1. Rebuild lands → repackage with all four GL libs +
|
||
`chrome_crashpad_handler` + chrome → ship to ohm.
|
||
2. Validate via `chrome --use-gl=egl --ozone-platform=wayland`
|
||
`--enable-features=AcceleratedVideoDecoder` (no ANGLE shim) and
|
||
confirm `chrome://gpu` reports `Native GpuMemoryBuffers: true` and
|
||
`supports_nv12_gl_native_pixmap=true`. Target CPU during 1080p30 H.264
|
||
playback: under 30 % combined renderer + gpu.
|
||
3. If (2) passes, declare V1 of chromium-fourier shippable on ohm.
|
||
4. Add a `chromium-fourier` launcher shim under `/usr/bin/` that
|
||
defaults to `--use-gl=egl --ozone-platform=wayland`.
|
||
5. Sort the chromium 147 vs 149 confusion — the fetch went to ToT on
|
||
main rather than the 147 release branch. Either pin the branch or
|
||
accept that we're tracking ToT (probably preferable for V4L2 fixes
|
||
that are still in flight upstream).
|
||
6. Replicate end-to-end on RK3588 (ampere CoolPi or boltzmann Rock 5
|
||
ITX+) once the mainline VDPU381 driver is stable on those — those
|
||
boxes use **panthor** for Mali-G610 (Valhall), not panfrost; the
|
||
patches should be backend-agnostic but the validation is per-box.
|
||
|
||
### State of the build host (post pass 3)
|
||
- CT 220 `/build/chromium/src` patched with both
|
||
`enable-v4l2-decoder-default.patch` and
|
||
`wayland-allow-direct-egl-gles2.patch` (applied directly with
|
||
`patch -p1` mid-rebuild; ninja picks up the mtime change).
|
||
- `chromium-rebuild.service` running as a transient unit, output in
|
||
`/tmp/chromium-rebuild.log`. Most of the 93k ninja steps are cache
|
||
hits; only the patched files + their downstream objects need
|
||
recompiling.
|
||
- Tarball still on CT 220 at `/build/chromium-fourier-147.tar.gz`
|
||
(misleadingly named: it's actually 149.0.7812.0 from the main fetch,
|
||
not the 147 release tarball — separate cleanup for next pass) and on
|
||
hertz at `/tmp/chromium-fourier-147.tar.gz`. **Will be replaced by
|
||
the post-rebuild tarball once it lands.**
|
||
|
||
---
|
||
|
||
## 2026-04-28 — Patch 4 lands, KWin owns the residual stall
|
||
|
||
### Patch 4 — `nv12-external-oes-on-modifier-external-only.patch`
|
||
On panfrost / panthor, every NV12 modifier (LINEAR + AFBC ×2 + AFRC) is
|
||
flagged `external_only` in `eglQueryDmaBufModifiersEXT`. Chromium's
|
||
`OzoneImageGLTexturesHolder::GetBinding` only picked
|
||
`GL_TEXTURE_EXTERNAL_OES` when the SharedImageFormat carried
|
||
`PrefersExternalSampler` — which is set for the generic Linux multi-plane
|
||
case but **not** for V4L2 producers that arrive via the standard ozone
|
||
pixmap path. The frame then took the `GL_TEXTURE_2D` branch, ANGLE's
|
||
`validationES.cpp:4894` rejected the YUV EGLImage on a non-EXTERNAL_OES
|
||
target, the import failed, and the renderer fell back to the
|
||
NV12→AR24 software conversion (~131 % CPU baseline).
|
||
|
||
Patch closes the gap: also pick `EXTERNAL_OES` when the EGL driver
|
||
advertises the pixmap's modifier as `external_only` (cached per
|
||
`(fourcc, modifier)` tuple via a function-local
|
||
`base::flat_map`+`base::Lock`, so the EGL round-trip stays off the
|
||
per-frame hot path). Adds a single static helper
|
||
`NativePixmapEGLBinding::ModifierRequiresExternalOES`. ~+90 lines, zero
|
||
deletions, no shader changes (Skia Ganesh already handles
|
||
`GL_TEXTURE_EXTERNAL_OES` natively via `GrGLTextureInfo.fTarget`).
|
||
|
||
### Validation on ohm (RK3566 PineTab2 / hantro mainline 6.19.10)
|
||
- `bbb_1080p30_h264.mp4` plays clean, no garble, no decoder error
|
||
- Steady-state **34.7 % combined CPU** during 1080p30 H.264 (browser 12 +
|
||
GPU 9 + net 6 + render 6 + audio 1) vs v3 baseline ~131 % — **~3.8×
|
||
reduction**. Risk-1 (ANGLE+EXTERNAL_OES sampling regression on Skia
|
||
Ganesh / panfrost) **cleared**.
|
||
- `V4L2VideoDecoder()` constructor + `Using a stateless API for profile:
|
||
h264 main and fourcc: S264` confirmed in log; 6 CAPTURE buffers
|
||
V4L2_MEMORY_MMAP, NV12 output. 19 live dmabuf fds in GPU process
|
||
during steady playback — healthy V4L2 rotation + compositor depth, not
|
||
a leak.
|
||
|
||
### KWin 6.6.4 GL_ALPHA bug — separate, preexisting, blocks long playback
|
||
Across BOTH v3 (no patch 4) and v4 (with patch 4) chromium-fourier
|
||
builds, mid-playback the renderer + GPU process both park in
|
||
`futex_do_wait`, `<video>` element keeps its ⏸ icon, currentTime
|
||
advances on the audio clock, and audio outputs static (last ALSA buffer
|
||
recycled) then silence. No D-state, no v4l2/vb2/dma_fence wchan, no
|
||
error in `chrome-v[34].log`.
|
||
|
||
`journalctl` for `kwin_wayland`:
|
||
```
|
||
GL_INVALID_VALUE in glTexImage2D(internalFormat=GL_ALPHA)
|
||
GL_INVALID_OPERATION in glTexSubImage2D(invalid texture level 0) × N
|
||
```
|
||
First occurrence on this box: **2026-03-06**. KWin is requesting an
|
||
internal format that doesn't exist in modern GLES (`GL_ALPHA` is GLES1.x
|
||
legacy, not valid for `glTexImage2D` with GLES3 contexts). The
|
||
allocation fails, then every `glTexSubImage2D` to that texture errors at
|
||
level 0; KWin keeps retrying the same broken upload every frame, never
|
||
recovers. The frame-callback ack to wayland clients stalls → chrome's
|
||
renderer parks waiting for the present-feedback that never lands.
|
||
|
||
Patch 4 looks "guilty" only because of timing: with NV12 zero-copy, the
|
||
renderer is fast enough to actually post a v4l2-backed dmabuf within the
|
||
window where KWin's broken path runs; v3 was slow enough (NV12→AR24
|
||
software conversion) that the bug surfaced 5–10× later. **Triangulation:**
|
||
chrome v4 stalls + chrome v3 stalls + VLC `cannot convert decoder/filter
|
||
output` + mpv `could not initialize video chain` — every wayland video
|
||
client hits it; ffmpeg `-hwaccel v4l2request -f null` plays through
|
||
clean (decode path is healthy, the wall is the compositor's GL backend).
|
||
|
||
### Decoder-stack sanity post-reboot (2026-04-28 ~13:30)
|
||
After a reboot the V4L2 device numbering shuffled:
|
||
- `/dev/video0` = `rockchip,rk3568-vpu-dec` (hantro DEC, was video1)
|
||
- `/dev/video1` = `rockchip,rk3568-vepu-enc` (hantro ENC)
|
||
- `/dev/video2` = `rockchip-rga`
|
||
- `/dev/media0` = controller for DEC, `/dev/media1` = controller for ENC
|
||
|
||
Anything that hardcoded `/dev/video1` for decode now talks to the
|
||
encoder. Chrome and ffmpeg both handle this transparently (they enumerate
|
||
via media-ctl); mpv's `--hwdec=v4l2request` returns `Could not create
|
||
device` post-shuffle — separate mpv-side bug, not ours.
|
||
|
||
### Outstanding (revised, supersedes earlier list)
|
||
1. **Patch 4 lands publicly:** bump PKGBUILD `source=` and `prepare()`,
|
||
commit + tag a `chromium-fourier-149-r4` release on
|
||
`git@github.com:marfrit/chromium-fourier`.
|
||
2. **KWin pivot** — see `KWIN_PIVOT.md` (separate doc) for the plan to
|
||
identify and patch the `glTexImage2D(GL_ALPHA)` site, since ohm is the
|
||
only board on hand and every wayland video client is affected.
|
||
3. **Replication on ampere** (RK3588, panthor + rkvdec2 + hantro
|
||
multiplanar) — needs ampere woken; currently DOWN.
|
||
4. **firefox-fourier 150 build** — `firefox-fourier-150.0.1-1-aarch64.pkg.tar.zst`
|
||
is built (95 MB on workstation:/tmp/, sha256 acbf1870…), pending
|
||
fresnel power-on for V4L2 stateless validation on RK3399.
|