Hypothesis under test: KWin's Transaction::watchDmaBuf calls
DMA_BUF_IOCTL_EXPORT_SYNC_FILE on every plane of every imported
dmabuf and parks the transaction on a QSocketNotifier(POLLIN)
waiting for that sync_file. On V4L2 hantro CAPTURE buffers (RK3566
mainline 6.19, panfrost mesa 26.0.5) the resulting fence either
never signals or signals so late that chrome's 6-buffer V4L2
capture pool exhausts at ~6s, hard-stalling the decoder. mpv with
gpu-next slideshows at 76% drop. weston A/B with same chrome v4
binary plays through clean — KWin's watchDmaBuf is the suspect.
This experiment patches watchDmaBuf to no-op. Wayland clients are
required by spec to ensure buffer contents are complete before
wl_surface.attach+commit, so the fence-wait is a defensive
optimization for misbehaving clients, not a correctness primitive.
If chrome plays through end-to-end at the recorded 34.7% combined
CPU number with this patched KWin, the bug is confirmed and the
upstream fix can be refined (timeout, V4L2-source skip, or use the
dmabuf fd directly in the QSocketNotifier instead of an extra
exported sync_file).
KWIN_PIVOT.md (in chromium-fourier/) carries the discovery thread.
Today's deltas:
- qt6-base-fourier built, installed, validated on ohm. Static-idle
journal shows zero GL_INVALID_VALUE post-relogin; the Qt 6
GL_ALPHA bug is genuinely fixed.
- chrome v4 under KWin still stalls — at ~6s vs ~3s pre-Qt-fix, so
the GL_ALPHA churn was contributing some load but wasn't the
primary cause.
- Clean A/B with weston: same chrome v4 binary, same panfrost,
same V4L2, same hardware → swapping KWin → weston turns the
stall off entirely. Chrome plays through with elevated CPU
(~96 % vs KWin's ~50 % when it isn't stalled) because weston
falls back to LINEAR composite vs KWin's fast-tile path.
- mpv triangulation:
--vo=null --hwdec=v4l2request: clean (decode only)
--vo=drm --hwdec=v4l2request: 0.7 % drops in 19 s (KMS scanout)
--vo=gpu-next --hwdec=v4l2request under KWin: 76 % drops, slideshow
Decode + display hardware path is fully capable. The wall is
specifically KWin's compositor scheduling/presentation pipeline on
this stack — panfrost ES 3.2 + V4L2 stateless NV12 dmabuf clients.
KWIN_PIVOT.md rewritten:
- Phase 4 (qt6 patch, ship, upstream) marked done.
- New Phase 5 (find the KWin culprit): WAYLAND_DEBUG on chrome +
KWin to capture the missing wl_buffer.release / wp_presentation
exchange around the 6 s stall, plus strace-on-kwin and
effects-disable bisection.
- New Phase 6 (fix and ship): kwin-fourier package pattern, ohm
validation, bugs.kde.org filing.
Three small runtime checks in qtbase 6.11.0:
1. src/opengl/qopengltextureglyphcache.cpp createTextureData() and
load_glyph_image_to_texture() — the `#else` branch (active when
qtbase is built with QT_CONFIG(opengles2), every aarch64 distro)
hard-codes GL_ALPHA without checking the runtime context's ES
version. Replace with `useR8 = ctx->format().majorVersion() >= 3`
so ES 3+ contexts get GL_R8 + GL_RED.
2. src/gui/rhi/qrhigles2.cpp toGlTextureFormat() RED_OR_ALPHA8 case
— gated only on caps.coreProfile. Extend with
`caps.gles && caps.ctxMajor >= 3`.
3. src/opengl/qopengltextureuploader.cpp Format_Alpha8 and
Format_Grayscale8 cases — short-circuit on `context->isOpenGLES()`
before reaching the swizzle fallback. Restrict to ES 2 only so
ES 3+ falls through to the existing TextureSwizzle path.
Discovered while validating chromium-fourier patch 3/3 (NV12
EXTERNAL_OES) on ohm. The chrome stall, VLC vout init failure and
mpv "could not initialize video chain" all share this Qt 6 root
cause: every Qt application running on Mali / panfrost / panthor
under a KWin Wayland session emits glTexImage2D(GL_ALPHA) on every
text-glyph cache upload, mesa returns GL_INVALID_VALUE, the
compositor's frame-callback path stalls, and every wayland video
client deadlocks behind it.
PKGBUILD inherits from extra/qt6-base 6.11.0-2 with arch+=aarch64,
epoch=1 to dominate Arch's pkgrel until upstream lands the fix.
qt6-base-cflags.patch and qt6-base-nostrip.patch carried verbatim
from upstream packaging.
KWIN_PIVOT.md (in chromium-fourier/) carries the full diagnosis
thread.
Source-grep collapsed Phase 1+2 onto a single pass. KWin's own GL paths
use GL_R8 correctly (gltexture.cpp:61, shadowitem.cpp:494). The
glTexImage2D(GL_ALPHA) calls observed in the journal originate from
Qt 6:
- qtbase/src/opengl/qopengltextureglyphcache.cpp:111-117 — text glyph
cache upload path. The #else branch (active when qtbase is built
with QT_CONFIG(opengles2)) unconditionally uses GL_ALPHA, with no
runtime check for ES context major version. Correct on ES 2.x;
broken on ES 3.x where GL_ALPHA is no longer a valid glTexImage2D
internalFormat.
- qtbase/src/gui/rhi/qrhigles2.cpp:1373-1378 — Qt-Quick-RHI sibling.
Same logic, gated only on caps.coreProfile, missing the ES≥3 case.
- qtbase/src/opengl/qopengltextureuploader.cpp:253-257 — QImage→GL
upload path; same shape.
KWin runs an ES 3.2 context on Mali-G52 panfrost (RK3566), Qt picks
GL_ALPHA, mesa returns GL_INVALID_VALUE, every dependent draw errors
at level 0, the compositor's frame-callback path stalls. KWin is the
visible victim because it's the compositor, but the bug is in Qt.
KWIN_PIVOT.md rewritten: the patch series and packaging now target
qt6-base-fourier instead of kwin-fourier. Three small hunks (~3 lines
each), runtime-safe via existing caps.gles + caps.ctxMajor / surface
format majorVersion checks. Upstream landing path: bugreports.qt.io
+ Gerrit change against qtbase dev branch.
Earlier framing was wrong — the wall isn't 'Arch ARM clang 22 vs Arch
x86_64 clang 23'. Arch x86_64 is also on 22.1.3; LLVM 23 isn't anywhere
in extra/staging. The flags chromium 147 emits come from chromium's
clang fork (Google maintains an LLVM fork with chromium-specific
passes), not upstream LLVM 23. PKGBUILD'ing clang 23 is the wrong tree.
Right tree: cross-compile from x86_64 so chromium's bundled clang
prebuilt is reachable. CIPD has full linux-amd64 prebuilts, gclient
sync works cleanly, no qemu-x86_64-static dance needed.
his provisioned CT 220 chromium-builder-x86 on data (Ryzen 7 1700,
14 cores, 32 GiB RAM, 200 GiB ZFS). data is normally asleep — woke
via /opt/herding/bin/wake-data. Reach pattern: hertz -> ssh data ->
pct exec 220.
Source fetch running as chromium-fetch.service transient unit on
CT 220. Once src is in, plan: tools/clang/scripts/update.py for
chromium's bundled clang + arm64 sysroot, gn gen with target_cpu=arm64,
build, transfer aarch64 binary to ohm/fresnel/ampere.
boltzmann chromium-builder LXD container preserved as fallback; can
be torn down if cross-compile pans out.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First-build summary on chromium-builder@boltzmann. gn gen succeeds
with our V4L2VDA-unlock args. ninja fails immediately on:
1. chromium 147 emits clang flags (-fno-lifetime-dse,
-fsanitize-ignore-for-ubsan-feature=array-bounds) that clang 22
doesn't know. Arch Linux ARM is on clang 22; clang 23 hasn't
landed in extra yet.
2. Bundled x86_64 esbuild is invoked via qemu-x86_64-static but
/lib64/ld-linux-x86-64.so.2 isn't installed — same shape as the
bundled node-linux-x64 issue we already fixed by symlinking to
system node. Smaller wall.
Documents 5 paths forward (grind patches / pin chromium 132 (7Ji's
known-good) / pin 138-141 middle ground / use chromium's bundled
clang / wait for Arch ARM clang 23) with estimated effort and trade-
offs. Recommends pinning to a chromium version that compiles clean
against clang 22 as the fastest path to a working browser, then
bumping as Arch ARM bumps clang.
Build host state preserved — container running, source extracted,
gn-gen'd, no compile artifacts. Easy to resume from any of the five
paths.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Initial chromium-fourier shape on the chromium-builder@boltzmann LXD
container we provisioned today. Approach is the 7Ji-style "tarball +
system tools" pattern (no gclient/CIPD, the linux-arm64 dependency
binaries don't exist anyway) but stripped of the MPP/X11/panfork
specifics — chromium-fourier targets mainline kernel + Wayland +
panfrost/panthor + V4L2 stateless on /dev/video0, not the vendor
stack 7Ji's chromium-mpp targets.
PKGBUILD highlights:
- pkgver=147.0.7727.116 (current Chrome stable as of 2026-04-25)
- gn args: use_v4l2_codec=true, use_v4lplugin=true, use_linux_v4l2_only=true,
use_vaapi=true. The first three are the magic that unlocks V4L2VDA on
Linux non-ChromeOS without source patches; if they're sufficient on
their own, the chromeos-pipeline-bypass patch stays a no-op.
- ffmpeg_branding="Chrome" + proprietary_codecs=true for H.264.
- enable_widevine=false, enable_nacl=false to keep the tree small.
- Currently development-shaped: prepare()/build() operate on a
pre-extracted /build/chromium/src rather than makepkg-fetched
source. Will switch to canonical source=(...tarball.xz) shape once
the patches stabilise.
patches/chromeos-pipeline-bypass.patch is a placeholder; the actual
patch (if any) gets developed once we see what 7Ji's gn args do or
don't unlock for us.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stage the next side-project: patch upstream Chromium to do HW video
decode through VaapiVideoDecoder + our marfrit/libva-v4l2-request-fourier
backend on a mainline Linux Wayland system, instead of going through
the chromeos pipeline that fails on Brave today.
STUDY.md captures:
- The exact failure stack we're fixing (PickDecoderOutputFormat ->
ImageProcessor init failure in media/gpu/chromeos/video_decoder_pipeline.cc)
- Three candidate patches (chromeos pipeline bypass, V4L2VideoDecoder
factory un-gate, libva backend default)
- Reference forks (JeffyCN, igel-oss, 7Ji-PKGBUILDs/chromium-mpp,
amazingfate/chromium-debian-build) — all use the older V4L2VDA path
with vendor MPP, not VAAPI; useful for PKGBUILD shape and
factory-un-gating patterns but not directly applicable
- Build plan on fermi (depot_tools, ~30 GB fetch, 6-10 h initial build,
distcc-avahi acceleration through CT108 + tesla)
- Phase order — workspace done now, build env next session,
patches after that, package after that, brave-fourier rebase last
No PKGBUILD added yet; one will land when there's something to actually
package. Build artifacts intentionally not in repo (chromium tree is
~100 GB).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First carrier package for the Fourier umbrella. Tracks Kwiboo's
v4l2-request-n8.1 branch (ffmpeg 8.1 base) pinned at commit b57fbbe —
bump _commit to rebase onto newer tip. CI job chained after
claude-his-any so it serializes on the shared aarch64 repo-db;
continue-on-error: true so long ffmpeg builds don't block the debian
downstream.
Deliberately diverges from the AUR package:
- AUR pins 6.1.1 with epoch=2 → would downgrade stock Arch ffmpeg 2:8.1-3.
We track 8.1 so install is a sideways swap, not a regression.
- AUR pulls X11/AMF/CUDA/FireWire/AviSynth/OpenMPT/Bluray/OpenMAX/JPEG-XL/
Theora/XVid/rsvg/soxr/ssh/vidstab/modplug/SDL2/Vulkan/JACK/GSM/Speex —
dropped here; none are needed on a Wayland ARM video-decode fleet.
- AUR uses #branch=…, sha256sums=(SKIP) → every build is tip-of-branch,
not reproducible. We pin via #commit=<sha>.
Kept: encoders (libx264/libx265/libvpx/libdav1d), VAAPI, libdrm, libv4l2,
neon, OpenGL, PulseAudio, subtitle/font stack, gnutls TLS. SDL2 dropped
means no ffplay binary (mpv covers interactive playback).
provides=(ffmpeg) conflicts=(ffmpeg) so it replaces stock ffmpeg on the
target host deliberately. Primary consumers: ohm (Fourier step 5),
fresnel, ampere.
pkgrel 16 builds ship an upstream distcc 3.4 bug: src/compile.c sizes
the rewritten-compiler-name buffer with strlen(argv[0] + 1) — pointer
arithmetic applied before strlen — under-allocating by 2 bytes. glibc
FORTIFY_SOURCE=2 catches the resulting overflow in strcat and aborts,
so every "distcc gcc ..." invocation dies on a modern Arch.
Patch moves the +1 outside the strlen, as intended.
Closesmarfrit/marfrit-packages#3.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tag v0.1.3 added the scripts + quickref, v0.1.4 fixed doc paths.
Package both /usr/bin/repo-inventory.sh and /usr/bin/repo-inventory-nosudo.sh.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Claude Code Edit semantics — literal string replace with uniqueness
check. replace_all flag for bulk edits. Fixes missing edit tool on
lmcp-backed boltzmann / tesla / broglie.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- arch/claude-his-agent/PKGBUILD: fetches v0.1.0 tarball from
git.reauktion.de/marfrit/claude-his-agent, installs agent+skill+helper
to /usr/share/claude-agents/, /usr/share/claude-skills/his/, /usr/bin/
- debian/claude-his-agent/: control+changelog+copyright + build-deb.sh
mirroring the lmcp-debian pattern (dpkg-deb, reproducible mtimes)
- .gitea/workflows/build.yml: two new serialized jobs (claude-his-any +
claude-his-debian) after lmcp-debian; same publish flow as lmcp.
lmcp is arch=any (pure Lua). One build on the aarch64 runner serves
all pacman targets — the pure-Lua package drops into both repo dbs.
Depends on lua + lua-socket from the target distro's base repos.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes install conflict with filesystem pkg on merged-usr systems where
/usr/sbin is a symlink to /usr/bin.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- distcc-3.4 tarball hash + local support files hashed (no more SKIP)
- .gitea/workflows/build.yml now builds, signs, repo-adds and rsyncs
to nc via the marfrit-repo-deploy key. Triggers on push to arch/**
or manual workflow_dispatch.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>