79 Commits

Author SHA1 Message Date
marfrit a36cf85e06 mesa-panvk-bifrost: iter10 polish — drop sandbox bypass, pin sha256, tighten loader select
iter10 of the panvk-bifrost campaign. Eliminates the cosmetic
'--disable-gpu-sandbox' warning at brave-vulkan launch + pins the
Mesa tarball hash + makes the Vulkan ICD selection deterministic
across filesystems.

PKGBUILD changes (pkgrel: 1 -> 2):
  - install ICD JSON at /usr/share/vulkan/icd.d/00-panvk-bifrost.json
    (was: /usr/lib/panvk-bifrost/icd.json — required VK_ICD_FILENAMES,
    which the GPU sandbox would strip, forcing --disable-gpu-sandbox)
  - libvulkan_panfrost.so install path unchanged at /usr/lib/panvk-bifrost/
  - sha256sums[0] pinned to 1d3c3b8a8363b8cc354175bb4a684ad8b035211cc1d6fa17aeb9b9623c513f89
    (mesa-26.0.6.tar.xz from archive.mesa3d.org); patches + brave-vulkan +
    icd.json remain SKIP since they're in-tree (git-tracked)

brave-vulkan changes:
  - dropped --no-sandbox + --disable-gpu-sandbox: env vars MESA_VK_VERSION_OVERRIDE
    and PAN_I_WANT_A_BROKEN_VULKAN_DRIVER survive the GPU sandbox boundary
    (Mesa loader reads them pre-seccomp-lockdown)
  - dropped VK_ICD_FILENAMES (loader auto-picks via icd.d/ directory scan)
  - added VK_LOADER_DRIVERS_SELECT='00-panvk-bifrost*' for deterministic
    ICD selection — Vulkan loader's readdir order is implementation-defined
    per Khronos LoaderDriverInterface, so the '00-' filename prefix is
    not spec-backed (ext4 happens to give insertion-order, other filesystems
    may not). VK_LOADER_DRIVERS_SELECT short-circuits readdir ambiguity.
    (Phase 5 review hardening.)

Test result on ohm (pre-push validation):
  - brave-vulkan launches Brave without sandbox bypass
  - seccomp-bpf sandboxes activate normally for utility/renderer processes
  - 'panvk is not a conformant Vulkan implementation' fires ONCE (loader-select
    excluded stock ICD from enumeration — only patched driver loads)
  - GPU process boots, no 'Exiting GPU process' error
  - Brave runs through full test timeout cleanly

README updated to reflect the new install layout + simplified wrapper.

Campaign artifacts: ~/src/panvk-bifrost/{phase0_findings_iter10.md,
phase8_iteration9_close.md (which iter10 polishes)}.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:28:29 +02:00
marfrit 489d6e3862 mesa-panvk-bifrost: new package — Vulkan-compositor Brave for Bifrost SBCs
iter9 of the panvk-bifrost campaign — operator-confirmed Vulkan output
on PineTab2 (Mali-G52 r1 MC1) 2026-05-20.

Patches Mesa 26.0.6's PanVk Vulkan driver:
  - VK_KHR/EXT_robustness2 + nullDescriptor exposed for PAN_ARCH 6/7
  - has_vk1_1 / has_vk1_2 = true on Bifrost
Patches applied via sed in PKGBUILD prepare() (cleaner than maintaining
a Mesa fork for two two-line tweaks; upstream context drifts between
Mesa releases would make a literal .patch brittle).

Co-installs at /usr/lib/panvk-bifrost/ — stock mesa untouched. Stock
libvulkan_panfrost.so and its ICD JSON keep working for everyone not
opting into the patched driver.

Ships /usr/bin/brave-vulkan that wires up:
  VK_ICD_FILENAMES=/usr/lib/panvk-bifrost/icd.json
  PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1
  MESA_VK_VERSION_OVERRIDE=1.2     # ANGLE needs apiVersion>=1.1; the
                                   # has_vk1_x flags don't move it, so
                                   # the env-var override carries that
  brave --use-gl=disabled --enable-features=Vulkan --use-vulkan=native
        --ozone-platform=x11 --no-sandbox --disable-gpu-sandbox
        --ignore-gpu-blocklist "$@"

Side-steps the stock "GLES3 is unsupported / GPU process exits" failure
documented in panvk-bifrost/README's "Consumer-side benefit" section.

Known limitation: WebGL/WebGL2 in-page won't work — ANGLE needs GLES3
which needs VK_EXT_transform_feedback, which PanVk-Bifrost doesn't
currently support. Browser chrome + standard page rendering work fine.

Gitea Actions job mesa-panvk-bifrost-aarch64 added to build.yml,
patterned on libva-v4l2-request-fourier-aarch64. Mesa build is slow
(~30-60min on actrunner-aarch64). Standalone (no needs:),
continue-on-error so it doesn't block other jobs.

Campaign artifacts: ~/src/panvk-bifrost/{README.md, phase8_iteration9_close.md,
phase0_evidence/iter9_brave_vulkan_breakthrough.txt}.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:03:59 +02:00
marfrit 265bf669c8 Merge pull request 'daedalus-v4l2{,-dkms}: Linux 6.18 compat + systemd unit + auto-enable' (#39) from claude-noether/marfrit-packages:noether/daedalus-v4l2-kernel-6.18-compat into main
Reviewed-on: marfrit/marfrit-packages#39
2026-05-20 08:54:28 +00:00
marfrit df09c1c55d daedalus-v4l2{,-dkms}: f0cd29a -> 481279c — systemd unit + auto-enable
481279c adds packaging/systemd/{daedalus-v4l2.service,modules-load} to
the upstream tree.  This commit wires those into both the Arch
(PKGBUILD + .install) and Debian (build-deb.sh + postinst/prerm/postrm)
package layouts so that a fresh install of daedalus-v4l2 + daedalus-
v4l2-dkms on a Pi 5 leaves the kernel module loaded at next boot AND
the userspace broker daemon enabled — no manual modprobe / systemctl
enable dance needed.

  arch/daedalus-v4l2:
    * pkgver 0.1.0.r18.481279c, pkgrel reset to 1 (new upstream pin).
    * Dropped 'systemd-libs' from depends — daemon doesn't link
      libsystemd (no sd_notify); the .service unit is consumed by
      systemd-the-init, no link-time dep required.
    * package() now installs the .service to
      /usr/lib/systemd/system/daedalus-v4l2.service and the modules-
      load drop-in to /usr/lib/modules-load.d/daedalus-v4l2.conf.
    * New .install file: post_install/post_upgrade run daemon-reload +
      enable + systemd-modules-load + try-restart on upgrade; pre/post
      remove tear down cleanly.  No auto-start — operator decides.

  arch/daedalus-v4l2-dkms:
    * pkgver bump to 481279c, pkgrel reset to 1.  Kernel module itself
      is bit-identical to f0cd29a (commit only touches packaging/) but
      bumping in lockstep keeps DKMS source-tree pkgver matched to the
      userspace pkgver so /etc/modules-load.d points at a module that
      actually exists.

  debian/daedalus-v4l2:
    * Same bump 481279c, PKGREL=1.
    * build-deb.sh stages /lib/systemd/system/ + /usr/lib/modules-load.d/
      and installs both files.
    * Generates DEBIAN/postinst that runs daemon-reload, enables the
      service, triggers systemd-modules-load, and conditionally starts
      the service iff /dev/daedalus-v4l2 is already present (uses the
      same ConditionPathExists= guard as the unit file so apt install
      doesn't fail loudly on a host where dkms hasn't built yet).
    * Generates DEBIAN/prerm (stop + disable on remove) and
      DEBIAN/postrm (daemon-reload).

  debian/daedalus-v4l2-dkms:
    * Lockstep version bump, PKGREL=1.  Postinst (loud-warn-on-missing-
      headers) unchanged.

Verified the SHA via local rev-parse against ~/src/daedalus-v4l2 —
481279c is the "packaging/systemd: ship daedalus-v4l2.service +
modules-load drop-in" commit on main.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 10:34:55 +02:00
marfrit e8a5490d44 Merge pull request 'daedalus-v4l2{,-dkms}: f55b2cd -> f0cd29a — Linux 6.18 compat' (#38) from claude-noether/marfrit-packages:noether/daedalus-v4l2-kernel-6.18-compat into main
Reviewed-on: marfrit/marfrit-packages#38
2026-05-20 08:24:19 +00:00
marfrit ff9db4e273 daedalus-v4l2{,-dkms}: f55b2cd -> f0cd29a — Linux 6.18 compat
DKMS build for daedalus_v4l2 fails against kernel 6.18+ with:

  daedalus_v4l2_main.c:1049: error: too few arguments to function
                            'v4l2_fh_add'
  v4l2-fh.h:97: void v4l2_fh_add(struct v4l2_fh *fh, struct file *filp);

(same for v4l2_fh_del).  Signature changed exactly at v6.18 — verified
v6.13–v6.17 still use the one-arg form via raw.githubusercontent.com
tag walk.

Upstream commit f0cd29a wraps the calls with LINUX_VERSION_CODE so the
module keeps building against:
  * 6.12 LTS / RPi 6.12.75 (one-arg)        — hertz
  * 6.12.88+deb13-arm64 (one-arg)
  * 6.18.29+rpt-rpi-2712 (file* arg)        — higgs running kernel

Higgs (Pi CM5) was hitting this: daedalus-v4l2-dkms 0.1.0+r16+gf55b2cd
showed 'installed' in dpkg but DKMS autoinstall failed for the running
6.18.29 kernel.  Re-running 'dkms autoinstall' after this bump succeeds
+ /dev/daedalus-v4l2 appears.

Also widens debian/daedalus-v4l2-dkms Recommends from
  linux-headers-generic | linux-headers
to
  linux-headers-rpi-2712 | linux-headers-rpi | linux-headers-generic | linux-headers
so apt pulls the right metapackage on Raspberry Pi OS / RPi-2712
kernels by default.

Userspace pkgver bumps in lockstep (no userspace change in f0cd29a, but
keeps daedalus-v4l2 + daedalus-v4l2-dkms versions matching for
LIBVA_DRIVER_NAME selection sanity).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:21:13 +02:00
marfrit 108a3dabe6 firefox-fourier: ship .desktop launcher (pkgrel=7)
Stock firefox.desktop disappears when our 'provides=firefox' replaces stock
firefox-arch, so installing firefox-fourier left the user without a Plasma/GNOME
start-menu entry. Add firefox-fourier.desktop with Categories=Network;WebBrowser;
(routes under Internet on KDE Plasma 6), MIME types for the usual web schemes,
new-window / private-window actions, and the 128px icon from the package's
internal browser/chrome/icons tree.

Reported on ohm (PineTab2 / Plasma 6) — manual /usr/share/applications shim
proved the file works; this commits it to the recipe so future installs Just Work.
2026-05-20 00:09:31 +02:00
claude-noether 31da35a549 linux-pinetab2-danctnix-besser: pkgrel=6 (per-series reconstruction, kernel-agent#29 done proper)
Bumps pkgrel from 5 to 6. Cumulative regenerated from the redone
per-series reconstruction in kernel-agent (replacing the broken
PR #33 attempt with a proper rebase onto v7.0-danctnix1 baseline).

  cumulative.patch: 162 716 -> 279 554 bytes
  b2sum:            50397711a6a3... -> eb179c03f35a...
  manifest.lock:    32 resolved patches (was 4 — c5x interim collapsed
                    the bes2600 driver scope into one cumulative blob;
                    per-series properly tracks each fix)
  bes2600 series-dirs in kernel-agent: now 25 individual series-dirs
                    (one per cleanups commit + Patch H), each with the
                    proper in-tree drivers/staging/bes2600/* paths

Built + installed on ohm 2026-05-19 23:39. Functional verification:
  uname:       7.0.0-danctnix1-6-pinetab2-danctnix-besser
  srcversion:  1A919EED0E6DC2478559B17 (differs from pkgrel=5's
               BEB625FA7443171EA8D55F7 — not byte-equivalent;
               functional equivalence verified: wlan0 associates,
               bes2600_btuart loads, Pattern A 0, no WARN/BUG)

Per-fix revertability now real: removing an include from
fleet/ohm.yaml drops that fix from the cumulative. Bisecting on
kernel-agent side becomes practical.
2026-05-19 23:44:47 +02:00
marfrit b4d1a47d6b Merge pull request 'daedalus-v4l2{,-dkms}: fix hallucinated upstream commit SHA' (#37) from noether/daedalus-sha-fix into main
Reviewed-on: marfrit/marfrit-packages#37
2026-05-19 10:06:13 +00:00
test0r 3548a761a5 daedalus-v4l2{,-dkms}: fix hallucinated upstream commit SHA
The recipes pinned `f55b2cdab8a8c0bc04e8c1bb1d0b6ca85e7d96d2` as the
"Phase 8.13: byte-exact end-to-end via libva" commit, but that SHA
does not exist in git.reauktion.de/reauktion/daedalus-v4l2.

The actual `main` tip (per gitea's for-each-ref) is
`f55b2cd002afdfd08f3c093627317f92e4929074` — same 7-char prefix
(`f55b2cd`), different full hash.  Likely a manually-constructed SHA
based on a short prefix from a working copy that was never pushed.

git archive --format=tar.gz on the bad SHA fails with
  fatal: not a tree object: f55b2cdab8a8...
which surfaces as 500 from Gitea's archive endpoint, which curl in
the CI build-deb.sh sees as `curl: (22) ... error: 500`.

Diagnosed by tailing gitea.log during a fresh archive request from
the CI runner; the underlying `git archive` command in the gitea
container is logged with the full failing SHA + error.

Fixed in all four recipes (arch + debian, daedalus-v4l2 + dkms).
pkgrel bumped to signal new build (PKGVER short-prefix `gf55b2cd`
stays the same — both bad and good SHA share that prefix).
2026-05-19 12:03:39 +02:00
marfrit 6f65462ec4 Merge pull request 'fourier-debian: Path A — ffmpeg into /opt/fourier prefix (no more KDE cascade)' (#36) from noether/fourier-private-prefix into main
Reviewed-on: marfrit/marfrit-packages#36
2026-05-19 08:15:25 +00:00
test0r a0e0d123b2 fourier-debian: Path A — ffmpeg into /opt/fourier prefix
Stock Debian trixie ships FFmpeg 7.1 (libavcodec.so.61), our fork
ships FFmpeg 8.1 (libavcodec.so.62) — different SONAMEs, NOT a
drop-in for trixie's libavcodec61-consuming desktop.  Previous
Conflicts: libavcodec61, libavformat61, ... triggered apt to remove
~50 packages (kde-plasma-desktop, vlc, dolphin, ...) when a user
just wanted ffmpeg-v4l2-request-fourier installed alongside.

This commit:

1. ffmpeg-v4l2-request-fourier (pkgrel=2):
   - --prefix=/opt/fourier (instead of /usr)
   - --extra-ldexeflags / --extra-ldsoflags: -Wl,-rpath,/opt/fourier/lib
     so /opt/fourier/bin/ffmpeg finds its own libs without external help
   - Ship /etc/ld.so.conf.d/fourier.conf with /opt/fourier/lib + ldconfig
     in postinst/postrm.  dlopen-by-SONAME consumers (firefox, daedalus)
     find libavcodec.so.62 via ld.so cache without LD_LIBRARY_PATH.
   - Drop ALL Conflicts/Replaces/Provides for libav* / libpostproc /
     libsw* — no SONAME clash with stock libavcodec61, no reason to
     evict anything.
   - /usr/bin/ffmpeg-fourier + ffprobe-fourier convenience symlinks.

2. daedalus-v4l2 (pkgrel=2):
   - Depends: ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier)
     instead of stock 'ffmpeg (>= 7.1)'.  The daedalus binary was
     linked against libavcodec.so.62 at build time (CI runner had
     marfrit/ffmpeg-v4l2-request-fourier installed); at runtime it
     needs the .so.62 that only the fourier pkg provides.

Not touched:
  - libva-v4l2-request-fourier: ships only v4l2_request_drv_video.so
    at /usr/lib/<triplet>/dri/ which libva dlopens by file pattern.
    Path A would break the lookup unless every consumer launcher sets
    LIBVA_DRIVERS_PATH.  Driver name is unique; no conflict.  STAY.
  - mpv-fourier: Depends already correctly bound to fourier ffmpeg.
    Will receive libavcodec.so.62 via the ld.so.cache mechanism
    above without recipe changes.
2026-05-19 10:12:36 +02:00
marfrit f22f8f03ac fourier-debian: fix mpv Conflicts + daedalus ffmpeg conflict (#35) 2026-05-19 06:42:30 +00:00
test0r e236ec1f42 fourier-debian: fix mpv Conflicts: + daedalus ffmpeg conflict
Two deterministic CI failures from run 115 (PR #34 wiring):

mpv-fourier-debian (task 566): dpkg-deb refuses `Conflicts: pkg1 |
pkg2` — Debian policy doesn't allow alternatives in Conflicts.
Split into separate entries.

daedalus-v4l2-debian (task 563): pacman -Syu pulled stock arch
ffmpeg which conflicts with the already-installed
ffmpeg-v4l2-request-fourier left behind by the earlier
mpv-fourier-aarch64 job (it configures [marfrit] + pre-installs
the fourier ffmpeg).  Drop 'ffmpeg' from the pacman line; mirror
the [marfrit]+pre-install step from mpv-fourier-debian.  Daedalus
only needs libavcodec/libavformat headers which the fourier
package supplies.
2026-05-19 08:42:01 +02:00
marfrit 57e6bac3d4 Merge pull request 'firefox-fourier: explicit CC/CXX=distcc in mozconfig' (#33) from noether/firefox-fourier-moz-distcc into main
Reviewed-on: marfrit/marfrit-packages#33
2026-05-19 04:32:23 +00:00
marfrit c818445611 ci: wire debian builds for 5 fourier recipes (#34) 2026-05-18 22:07:01 +00:00
test0r 45604801fa ci: wire debian builds for 5 fourier recipes
The debian/{ffmpeg-v4l2-request-fourier,libva-v4l2-request-fourier,mpv-fourier,daedalus-v4l2,daedalus-v4l2-dkms}
recipes have been sitting in the tree with no CI trigger since 2026-05-18.
build-deb.sh exists and is runnable, but nothing fires it — so no .debs
were ever pushed to packages.reauktion.de/debian/pool/.

Mirror the lmcp-debian / claude-his-debian pattern: build natively on
the arch-aarch64 runner (dpkg-deb is in extra), rsync the .deb to
hertz's incoming dir, trigger publish-deb for bookworm + trixie.

mpv-fourier-debian also pre-installs ffmpeg-v4l2-request-fourier from
[marfrit] for libavcodec ABI symmetry, matching the arch sibling job.
2026-05-19 00:05:40 +02:00
claude-noether 0a922a9f36 firefox-fourier: explicit CC/CXX=distcc in mozconfig
fermi's makepkg.conf already has BUILDENV=(distcc ...) which prepends
/usr/lib/distcc/bin to PATH at build time. But Mozilla's mach
configure picks CC/CXX from the environment directly — it doesn't
treat the distcc shim in PATH as the default C compiler unless the
env vars are set explicitly. Without this guard the distcc workers
sat idle while mach drove a local-only build.

Mirrors the explicit-distcc pattern already used in
ffmpeg-v4l2-request-fourier/PKGBUILD.

Caveat documented in the comment: only the C/C++ portion
distributes. rustc and host-only build steps stay local. Empirical
~30-40% wall-clock improvement on a 4-worker pool (tesla, dcc1, dcc2,
ampere via Avahi zeroconf).

pkgrel bumped so a rebuild publishes a new package even though the
binary output for users is unchanged (build process speedup only).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:08:49 +00:00
marfrit 9b170e942c Merge pull request 'qt6-base-fourier: fix epoch-mismatch in xcb-private-headers dep' (#32) from noether/qt6-xcb-private-headers-fourier-epoch-fix into main
Reviewed-on: marfrit/marfrit-packages#32
2026-05-18 20:56:54 +00:00
claude-noether cf169fd13e qt6-base-fourier: fix epoch-mismatch in xcb-private-headers dep
`package_qt6-xcb-private-headers-fourier()` depended on
`qt6-base-fourier=$pkgver` (= literal "6.11.1"), but the package itself
ships with `epoch=1` so the installed version is `1:6.11.1-1`.

Pacman's strict-equality version compare treats "6.11.1" as epoch=0 and
"1:6.11.1" as epoch=1 — mismatch — and refuses every upgrade involving
qt6-xcb-private-headers-fourier with "unable to satisfy dependency".

Fix: include the epoch prefix in the dep string —
`qt6-base-fourier=$epoch:$pkgver`. pkgrel bumped to 2 so the rebuild
publishes a new package even though only the dep string changed.

Observed on ohm 2026-05-18 after the broader fleet pacman -Syu —
worked around there with --assume-installed; this fixes it properly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 20:45:31 +00:00
marfrit 81895f991b Merge pull request 'arch/linux-pinetab2-danctnix-besser: pkgrel=4 — first kernel-agent-managed release' (#28) from noether/add-linux-pinetab2-danctnix-besser into main
Reviewed-on: marfrit/marfrit-packages#28
2026-05-18 20:02:34 +00:00
claude-noether 011667c8e4 linux-pinetab2-danctnix-besser: drop accidentally-committed kernel src tree
The PR branch contained the unpacked Linux 7.0 source tree
(~81k files, ~38M additions) under src/. These are makepkg build-dir
artifacts that should never be committed; PKGBUILD downloads + extracts
them at build time.

Their presence inflated the PR file-count display to 81030 changed
files. Removed src/ from tracking and added a stronger .gitignore
in the package dir to prevent regressions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 19:33:43 +00:00
marfrit 0e6f97f041 Merge pull request 'noether/daedalus-v4l2-packages' (#31) from claude-noether/marfrit-packages:noether/daedalus-v4l2-packages into main
Reviewed-on: marfrit/marfrit-packages#31
2026-05-18 19:31:00 +00:00
marfrit fae7a7b80c Merge branch 'main' into noether/add-linux-pinetab2-danctnix-besser 2026-05-18 19:22:03 +00:00
test0r b851861931 debian/mpv-fourier: new package
Mirror of arch/mpv-fourier into the Debian tree.  Same source
pin (mpv 0.41.0), same 3 patches:
  - 0001-meson-add-detection-logic-for-v4l2request-support.patch
  - 0002-vo-hwdec-drmprime-add-separate-hwdecs-for-v4l2reques.patch
    (Kwiboo + Langdale wiring for AV_HWDEVICE_TYPE_V4L2REQUEST
     through drmprime VO hwdec — '--hwdec=v4l2request' actually
     engages on dmabuf-wayland)
  - 0001-vo_dmabuf_wayland-explicit-cache-sync-on-import-fd.patch
    (iter1 of dmabuf-modifier-triage — explicit DMA_BUF_IOCTL_SYNC
     on import fds; KWin-on-RK3566 dark-green chroma readback
     regression fix on ohm.  Root cause is the vb2_dma_resv RFC
     upstream still pending.)

Depends on ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier) —
AV_HWDEVICE_TYPE_V4L2REQUEST only exists in Kwiboo's FFmpeg
fork; stock Debian ffmpeg doesn't have it.

Conflicts/Replaces stock mpv + libmpv2/libmpv1 — drop-in
replacement.  Takes epoch 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 19:01:29 +00:00
test0r 45f4b5e56f debian/ffmpeg-v4l2-request-fourier: new package
Mirror of arch/ffmpeg-v4l2-request-fourier into the Debian tree.
Same source pin (Kwiboo v4l2-request-n8.1 @ b57fbbe), same 2
patches (libudev-bypass-fallback + nv15-to-p010-unpack), same
configure flag policy (drop X11/AMF/CUDA/Bluray/Vulkan/SDL2/etc.
per Fourier fleet focus).

Output: single .deb at /usr/bin/ffmpeg + /usr/bin/ffprobe +
/usr/lib/aarch64-linux-gnu/libav*.so.61.  Conflicts/Replaces
the stock Debian ffmpeg + per-lib packages; takes epoch 2
(matches Debian's existing ffmpeg epoch).

Provides 'ffmpeg -hwaccel v4l2request' + '-hwaccel drm' routes
that drive rkvdec / hantro / cedrus / rpi-hevc-dec /
daedalus_v4l2 stateless decoders through libavcodec's hwdevice
DRM path, bypassing libva.  Required by mpv-fourier and
firefox-fourier as their backing FFmpeg; also the kdirect
bit-exact reference for libva-v4l2-request-fourier validation.

NOT strictly required for the VAAPI-only path on
daedalus-v4l2 hosts (stock Debian ffmpeg + libva-v4l2-request-
fourier covers that).  Install only when going firefox-fourier
or kdirect.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 19:01:18 +00:00
marfrit 3ddc45d625 Merge pull request 'noether/daedalus-v4l2-packages' (#30) from claude-noether/marfrit-packages:noether/daedalus-v4l2-packages into main
Reviewed-on: marfrit/marfrit-packages#30
2026-05-18 18:42:30 +00:00
test0r 1bd11eaf27 daedalus-v4l2{,-dkms}: f04d700 -> f55b2cd (UAF lifetime fix)
Bumps all 4 daedalus packages (arch + debian × userspace + dkms)
to pick up daedalus-v4l2 f55b2cd: "kernel: media_request_get/put
around inf->req (UAF safety)".

Closes the SHIP-WITH-EYES-OPEN concern Sonnet flagged in the
pre-deployment review — without explicit media_request_get on
capture + media_request_put on completion, a concurrent
MEDIA_IOC_REQUEST_REINIT or process-kill triggering
buf_request_complete from the cancel path could drop vb2's
reference before our completion handler ran, leaving inf->req
dangling through v4l2_ctrl_request_complete + buf_done.

Matches the cedrus / rkvdec refcount pattern.  No protocol
change, no API change, no consumer-side adjustment required.
Same byte-exact output verified on hertz post-fix (libva path:
match; standalone test_m2m_stream: 30/30 frames).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:39:40 +00:00
test0r 4776dc01d2 daedalus-v4l2-dkms: loud warning when DKMS build doesn't land
Sonnet pre-deployment review caught a BLOCKER: on a fresh higgs
(Debian 13 / Pi CM5) install without the RPi kernel headers
pre-installed, the postinst's `dkms autoinstall || true` silently
swallowed the build failure. Package appeared installed but the
.ko was absent; `modprobe daedalus_v4l2` then failed and the
entire stack was dead with no clear pointer to the cause.

Fix in both ecosystems:

debian/daedalus-v4l2-dkms/build-deb.sh:
- After `dkms autoinstall`, verify the post-condition with
  `dkms status -m daedalus_v4l2 -v VER -k $(uname -r)`.
- If the module isn't 'installed' / 'loaded' for the running
  kernel, emit a yellow-bolded ANSI warning naming the most
  likely cause (kernel headers package missing) and the exact
  recovery steps (linux-headers-rpi-2712 for RPi or
  linux-headers-$KERNELVER for Debian generic, then
  `dkms autoinstall` + `modprobe`).
- Colour only on TTY; the warning is unconditional regardless.

arch/daedalus-v4l2-dkms/:
- New daedalus-v4l2-dkms.install with post_install +
  post_upgrade hooks that run the same `dkms status` check.
- post_upgrade catches the case where a kernel-headers package
  was uninstalled / pruned between upgrades, silently
  regressing the build.
- Wired into the PKGBUILD via install="${pkgname}.install".

Both versions point at the actual repair commands rather than
just saying "build failed", so the user is one apt/pacman away
from a working stack instead of debugging dkms internals.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:38:52 +00:00
marfrit de358b9461 Merge pull request 'noether/daedalus-v4l2-packages' (#29) from claude-noether/marfrit-packages:noether/daedalus-v4l2-packages into main
Reviewed-on: marfrit/marfrit-packages#29
2026-05-18 18:27:26 +00:00
test0r f3dd1c1886 debian/daedalus-v4l2-dkms: new package — kernel module via DKMS
Mirror of arch/daedalus-v4l2-dkms into the Debian tree.
Architecture: all (source package — DKMS rebuilds per-kernel
at install time).  Same pin (f04d700, Phase 8.13 close).

Installs kernel/ source to /usr/src/daedalus_v4l2-<ver>/ with
generated dkms.conf.  postinst runs `dkms add` + `dkms
autoinstall` so the module builds against the running kernel's
headers automatically.  prerm runs `dkms remove --all`.

Same Makefile-include-path flattening as the Arch sibling:
copies daedalus_v4l2_proto.h into kernel/include/ and patches
the Makefile's -I path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:46 +00:00
test0r add049f0bd debian/daedalus-v4l2: new package — userspace daemon + tools
Mirror of arch/daedalus-v4l2 into the Debian tree.  Same pin
(f04d700, Phase 8.13 close), same install layout.  Output as
arm64 .deb.

Build path: CMake for daemon (build via ninja); in-tree Makefile
for tools.  No debhelper; standalone dpkg-deb so it builds on
the non-Debian runner.

Depends on ffmpeg (libavformat/libavcodec/libavutil 7.1+) at
runtime, libdrm2.  Recommends daedalus-v4l2-dkms (the kernel
module).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:39 +00:00
test0r 249e8461bb debian/libva-v4l2-request-fourier: new package
Mirror of arch/libva-v4l2-request-fourier into the Debian tree.
Same pin (de27e95), same build (meson + ninja), output as
arm64 .deb installing the VA-API ICD as
/usr/lib/aarch64-linux-gnu/dri/v4l2_request_drv_video.so.

Auto-detected by VAAPI consumers (ffmpeg -hwaccel vaapi, mpv
--hwdec=vaapi, Firefox VAAPI accel) when
LIBVA_DRIVER_NAME=v4l2_request is set.

build-deb.sh follows the lmcp pattern: reproducible build with
SOURCE_DATE_EPOCH pin; standalone dpkg-deb so it runs on a
non-Debian builder without dh/debhelper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:33 +00:00
test0r 3293cd6542 arch/daedalus-v4l2-dkms: new package — kernel module via DKMS
PKGBUILD pinning the same daedalus-v4l2 @ f04d700 as the
userspace sibling.  Installs kernel/ source to
/usr/src/daedalus_v4l2-<ver>/ with a generated dkms.conf;
AUTOINSTALL=yes builds the module against the running kernel.

The kernel/ Makefile uses -I$(src)/../include for the shared
protocol header.  In the userspace tree that's daedalus-v4l2/include/;
for DKMS we flatten by copying the header into kernel/include/
and patching the Makefile in package() to point there.

Sibling Debian package: debian/daedalus-v4l2-dkms/

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:21 +00:00
test0r 6de7268b49 arch/daedalus-v4l2: new package — userspace daemon + tools
PKGBUILD pinning daedalus-v4l2 @ f04d700 (Phase 8.13 close).

Installs:
- /usr/bin/daedalus_v4l2_daemon — the FFmpeg-backed decode daemon
- /usr/libexec/daedalus-v4l2/{test_chardev_pingpong,test_m2m_decode,
  test_m2m_stream} — verification harnesses
- /usr/include/daedalus_v4l2_proto.h — shared kernel↔daemon wire
  protocol (for third-party chardev clients)
- /usr/share/doc/daedalus-v4l2/ — README + Phase 8.x closure docs

Runtime deps: ffmpeg (libavformat/libavcodec/libavutil dlopen'd
at runtime per Option γ — daemon binary is link-clean from
FFmpeg), libdrm.

optdepends:
- daedalus-v4l2-dkms: companion kernel module
- libva-v4l2-request-fourier: VAAPI consumer routing through us

Sibling Debian package: debian/daedalus-v4l2/

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:14 +00:00
test0r dbae9832b6 libva-v4l2-request-fourier: 1.0.0.r348.7ac934e -> 1.0.0.r376.de27e95
Bump pin to de27e95 — "v4l2: log error_idx + failing ctrl id on
S_EXT_CTRLS failure" (Phase 8.13 diagnostic).

Includes:
- b5b3acf: daedalus_v4l2 entry in known_decoder_drivers[]
- 2146341: meson option gate (default true) for the daedalus
  probe slot
- de27e95: diagnostic logging on S_EXT_CTRLS failure (logs
  error_idx + failing control id, ioctl-level vs per-control)

Backward-compatible on rkvdec / hantro / cedrus / rpi-hevc-dec
hosts — daedalus probe is off-path unless daedalus_v4l2.ko
is loaded and /dev/video0 advertises driver "daedalus_v4l2".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:25:06 +00:00
claude-noether e49797ab21 linux-pinetab2-danctnix-besser: bump cumulative b2sum to 50397711a6a3...
kernel-agent corrected the @@ hunk counts in the SCS xor-neon patch
(the previous -9,7 +9,12 'fix' was an overcorrection; actual is
-9,6 +9,11). pkgrel=4 build #4 silently tolerated the wrong counts
because the trailer was stripped, but pkgrel=5 with besser#18
behind SCS exposed the inconsistency.

b2sum: ceec602afa8574c74354... -> 50397711a6a3ba522283...
Size unchanged 162 716.
2026-05-18 19:17:14 +02:00
claude-noether 47dfb33e98 linux-pinetab2-danctnix-besser: bump cumulative b2sum to ceec602afa85...
Kernel-agent restored the trailer on the SCS patch (SCS is no longer
last in the includes ordering — besser#18 is). Cumulative grows
+12 bytes for the restored '-- \n2.54.0\n' sentinel.

b2sum: 0eb091ddaba4... -> ceec602afa85...
Size: 162 704 -> 162 716.
2026-05-18 18:15:47 +02:00
claude-noether 5e16fbd603 linux-pinetab2-danctnix-besser: bump to pkgrel=5 (bundle besser#18 fix)
pkgrel=5 = pkgrel=4 + the besser#18 lockdep fix added to the
manifest's includes (in-tree mirror of bes2600-dkms d95453c).

Cumulative b2sum: 334c37b5d37067982bd9... -> 0eb091ddaba4a8f1c3c2a78...
Size: 157 446 -> 162 704 (+5 258 = besser#18 patch with trailer
stripped per the convention now established for the LAST patch in
ka-promote concatenation).

This single pkgrel satisfies all three deliverables of the ohm
migration goal: kernel-agent flow + new marfrit-packages pkg + the
besser#18 fix it contains.
2026-05-18 18:01:44 +02:00
claude-noether ab553ef008 linux-pinetab2-danctnix-besser: bump cumulative b2sum to 334c37b5...
After kernel-agent dropped the wrong git-format-patch trailer from
the SCS xor-neon patch (the trailer was a misdiagnosed fix; the
real problem was the @@ hunk counts).

Cumulative b2sum: ad9e2cb533957f218058... -> 334c37b5d37067982bd9...
Size: 157 458 -> 157 446 (12 byte trailer gone).
2026-05-18 17:00:13 +02:00
claude-noether 7a5587c0c6 linux-pinetab2-danctnix-besser: bump cumulative b2sum to ad9e2cb5...
Re-promoted after kernel-agent fixed malformed @@ hunk counts in the
SCS xor-neon patch (kernel-agent commit ahead of this on
noether/migrate-pinetab2-pkg-and-patches).

b2sum: bd42cd39106298879eeb... -> ad9e2cb533957f218058...
size unchanged at 157 458.
2026-05-18 16:58:23 +02:00
claude-noether 05bf33a1ec linux-pinetab2-danctnix-besser: bump cumulative to b2sum bd42cd3910...
Re-promoted after appending the missing git-format-patch trailer to
the kernel-agent SCS source patch (kernel-agent commit on
noether/migrate-pinetab2-pkg-and-patches). Cumulative size 157446 ->
157458, b2sum a807297b25be... -> bd42cd39106298879eeb...

Also adds .gitignore for makepkg build artifacts (src/, pkg/,
*.log*, logpipe.*).
2026-05-18 16:52:48 +02:00
claude-noether 3f1a26cc1b arch/linux-pinetab2-danctnix-besser: pkgrel=4 — first kernel-agent-managed release
Migrates the danctnix-besser kernel PKGBUILD from the boltzmann-side
hand-managed flow (marfrit/besser/danctnix-besser-pkgbuild/) into this
package tree.

Contents:
  PKGBUILD     - pkgver=7.0.danctnix1 pkgrel=4, single cumulative patch
                 source (replaces the 3-patch arrangement of pkgrel=3 +
                 fixes the duplicated 0003-arm64-... source-array entry
                 bug that was present in pkgrel=3)
  config       - same SCS=n config as pkgrel=3
                 (CONFIG_SHADOW_CALL_STACK disabled per
                 reference_arm64_scs_arm_neon_gcc15 — GCC 15.2.1 build
                 trap)
  0001-bes2600-besser-kernel-agent-cumulative.patch
               - 157446 bytes, b2sum a807297b25be...
               - Generated by ka-promote ohm against
                 kernel-agent:fleet/ohm.yaml
               - Contents: hand-curated c5x cumulative + Patch I (close
                 besser#1) + xor-neon SCS-fix (no-op while SCS=n)
  manifest.lock
               - Provenance: ka-promote-recorded sha256 per included
                 patch, cumulative b2sum, manifest sha256
  README.md    - flow docs, pkgrel history, caveats

Provides:  linux-pinetab2=7.0.danctnix1-4
Conflicts: linux-pinetab2
Verified:  source contents byte-identical to working pkgrel=3 stack
           (148149 + 7735 + 1562 = 157446 = ka-promote output size).
2026-05-18 16:51:26 +02:00
marfrit b248aa2ac8 Merge pull request 'linux-ampere-fourier: bump to kafr2 (v7.0-rc3 + kernel-agent manifest, VP9 + AV1)' (#27) from claude-noether/marfrit-packages:noether/linux-ampere-fourier-kafr2 into main
Reviewed-on: marfrit/marfrit-packages#27
2026-05-18 14:34:57 +00:00
test0r 06023bcf9d linux-ampere-fourier: bump to kafr2 (v7.0-rc3 + fleet/ampere.yaml manifest)
Drops the f8f3ad9 baseline ("18 commits ahead, BLACK-SCREENS ampere"
per fleet/ampere.yaml bisect note) in favor of the kernel-agent-
managed 10-patch set produced by ka-promote from fleet/ampere.yaml.

Baseline: mainline v7.0-rc3 (3daa4f5dc6cc), plus the 10 scope-tagged
patches under marfrit/kernel-agent/patches/{soc,module,board,driver}/:
  - 1 soc/rk3588 pwm15 pinctrl
  - 6 board/coolpi-cm5-genbook DTS patches
  - 3 driver/media Sarma VP9-on-VDPU381 patches (PR #24 closure)

New _commit 48a8c78 reflects this tree state in ~/src/linux-rockchip
(branch vp9-build on ampere, exactly v7.0-rc3 + 10 manifest patches).

End-to-end verified before this iteration was cut (hand-build of the
same tip on 2026-05-18 booted ampere via arch_vp9_test extlinux
label):
  - VP9 decode bit-exact HW==SW==libva (sha c8624d7c42db66525f53a02a515bc38d0a17ef39f692660cc7bebb1e2d2e1b48)
  - AV1 decode bit-exact HW==SW via kdirect (sha 30d2091158d92f3c5e0a807217c3e7307f873267673d92632e7fb147383e7dd1, av1-vpu-dec is mainline 7.0)

prebuild.sh canonical sha256 cleared — gzip-version-dependent, the
script warns-not-fails on mismatch. First successful kafr2 build can
pin a canonical sha here if a reproducibility audit ever needs it.

Cross-references:
  - marfrit/kernel-agent#12 (VP9 enablement closure)
  - marfrit/kernel-agent PR #24 (Sarma patch import + ampere.yaml bump)
2026-05-18 14:03:56 +00:00
marfrit 7542989f2b Merge PR #26: ffmpeg-v4l2-request-fourier NV15 to P010 unpack for Hi10P / Main10 2026-05-18 08:52:50 +00:00
test0r 9e9447502e ffmpeg-v4l2-request-fourier: patch NV15→P010 unpack for Hi10P / Main10
The n8.1 pin's hwcontext_v4l2request.c deliberately blanks the
transfer-formats list for AV_PIX_FMT_YUV420P10 sw_format (the mapping
target for V4L2_PIX_FMT_NV15), so `ffmpeg -hwaccel v4l2request
-vf hwdownload,format=p010le` on a Hi10P / Main10 input failed at
filter-init with -22 EINVAL — even though kernel-side decode succeeded.

0002-nv15-to-p010-unpack.patch adds an inline NV15→P010 unpack
(5 bytes per 4 samples, little-endian → high-10-of-16) inside
v4l2request_transfer_data_from, exposes AV_PIX_FMT_P010 in
transfer_get_formats for that sw_format, and rejects non-P010
destinations explicitly with ENOSYS instead of silently corrupting
output via av_frame_copy on NV15-packed bytes.

Verified on fresnel (RK3399, linux-fresnel-fourier 7.0-14):
- 5-frame smoke test from issue #21 → exit 0, 13.8MB output
- 20-frame mid-fixture decode → bit-exact HW==SW
  sha256 7d9b66d48d8f17b2281da1881c663ecc31722bb218aba1ae23bf28d07aa66b08
- 8-bit baseline (bbb_60s_720p.h264.mp4) still bit-exact HW==SW (no
  regression in the existing NV12 path)
- Cross-device repro of original EINVAL on unpatched ampere (RK3588)
  pkgrel=4, confirming the bug is upstream-FFmpeg-side, not RK3399-specific

Patch is upstream-able to Kwiboo's v4l2-request-n8.1 branch.

Closes #21.
2026-05-18 08:35:19 +00:00
marfrit eb1782e86f Merge pull request 'lmcp: 1.1.1 -> 1.2.1 (tools.d plugin scan + LMCP_HOST/LMCP_CONF env)' (#25) from claude-noether/marfrit-packages:noether/lmcp-1.2.1 into main
Reviewed-on: marfrit/marfrit-packages#25
2026-05-17 23:37:19 +00:00
test0r a168342fa8 lmcp: 1.1.1 -> 1.2.1 (tools.d plugin scan + LMCP_HOST/LMCP_CONF env)
Tracks upstream lmcp v1.2.1 (commits e05438f + c5375b8). Combined
release that lets hosts like hertz/ampere stop maintaining forked
/opt/lmcp/server.lua overrides — packaged server.lua becomes the
canonical entrypoint, host-local tools live in /opt/lmcp/tools.d/
as plugin files, single-interface binding + conf-file auth come via
LMCP_HOST + LMCP_CONF systemd env. Closes lmcp#22 structurally.

New tarball sha256:
  bf9cce1a84c66b1b74c5aec923c5960d60ae33c221afc8d47ce0d74b8f7ee609

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 23:34:07 +00:00
marfrit 4820e53b18 Merge pull request 'lmcp: 1.1.0 -> 1.1.1 (bug fix: empty inputSchema.properties)' (#24) from claude-noether/marfrit-packages:noether/lmcp-1.1.1 into main
Reviewed-on: marfrit/marfrit-packages#24
2026-05-17 22:47:59 +00:00
test0r 248bef5503 lmcp: 1.1.0 -> 1.1.1 (bug fix: empty inputSchema.properties)
Tracks upstream lmcp v1.1.1 (commit 9707f7a). Single-bug-fix
release: lmcp:tool() now normalises empty inputSchema.properties
by dropping the key, so Zod-strict MCP clients don't reject
tools/list with "expected: record, received: array".

Discovered live on a hertz-tools deployment where two custom
no-arg tools tripped the check and caused Claude Code to mark
the endpoint as disconnected.

New tarball sha256:
  80c2e815aa61a2d3baab051c51cd247bdefa9dd03d72c4867b99c49b6eae9cb9

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 22:47:21 +00:00
marfrit 8a49ac6061 Merge pull request 'lmcp: 1.0.0~rc1 -> 1.1.0 (concurrent dispatch + cancellation + windows sync)' (#23) from claude-noether/marfrit-packages:noether/lmcp-1.1.0 into main
Reviewed-on: marfrit/marfrit-packages#23
2026-05-17 20:22:30 +00:00
test0r 4764f5f37f lmcp: 1.0.0~rc1 -> 1.1.0
Tracks upstream lmcp v1.1.0 (commit 7e62f71). Closes 3 upstream
issues: #11 (progress + cancellation), #18 (windows MSI sync), #20
(concurrent handler dispatch).

Arch:
  pkgver=1.1.0 (no pre-release suffix this time).
  _tag back-translation kept so future rc bumps just need pkgver=X.Y.Z_rcN.

Debian:
  PKGVER=1.1.0 (no ~ suffix).
  Changelog entry summarises the three closed issues + the zero-
  handler-source-changes invariant.

New tarball sha256:
  d758a9504389528cb8940ea81bc8cf47afad8c01166aef3484ac4f5752445532

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 19:44:26 +00:00
marfrit dcb1da2f59 Merge pull request 'lmcp: 0.5.4 -> 1.0.0-rc1 (full MCP 2025-06-18 surface)' (#22) from claude-noether/marfrit-packages:noether/lmcp-1.0.0-rc1 into main 2026-05-17 17:42:16 +00:00
test0r 238c5cee7e lmcp: 0.5.4 -> 1.0.0-rc1 (full MCP 2025-06-18 surface)
Bumps both arch and debian packaging to track upstream v1.0.0-rc1
(commit deb73d1).

Arch (arch/lmcp/PKGBUILD):
  pkgver=1.0.0_rc1 (Arch convention: '_' substitutes for '-' in pre-
  release tags). _tag back-translates for the source URL.

Debian (debian/lmcp/build-deb.sh + changelog):
  PKGVER=1.0.0~rc1 (Debian convention: '~' sorts before the release).
  UPSTREAM_TAG=v1.0.0-rc1 drives the archive URL.

New tarball sha256: 81f9222264371735c196664382460261ef60a259348766bbd6fd2f49ea9d1e7e

What's in 1.0.0-rc1 (full release notes in upstream commit):
  - 14 issues closed
  - new MCP primitives: Resources, Prompts, Completion, Logging,
    Sampling, Roots, fetch, web_search
  - protocol: cursor pagination, structuredContent, _meta, tool
    annotations, protocolVersion bump to 2025-06-18
  - transports: stdio (LMCP_TRANSPORT=stdio), full Streamable HTTP
    rewrite with sessions, persistent SSE, server-initiated requests
  - json.lua: UTF-16 surrogate pairs + empty_object sentinel
  - backwards-compatible with every existing sessionless-POST client

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 17:18:18 +00:00
marfrit 70c943e948 Merge pull request 'ffmpeg-v4l2-request-git → ffmpeg-v4l2-request-fourier (dir rename)' (#20) from claude-noether/marfrit-packages:noether/rename-ffmpeg-dir into main
Reviewed-on: marfrit/marfrit-packages#20
2026-05-16 23:08:10 +00:00
claude-noether d6c4260eb8 ffmpeg-v4l2-request-git → ffmpeg-v4l2-request-fourier: rename directory
PKGBUILD already renamed itself (pkgname=ffmpeg-v4l2-request-fourier,
replaces=(ffmpeg ffmpeg-v4l2-request-git)) but the containing
directory was never moved. This commit completes the rename to align
the path with the package identity and the rest of the -fourier
umbrella (libva, mpv, kwin, qt6-base, chromium, linux-*).

CI workflow path-trigger is wildcard (arch/**), unaffected. Step
names + cp source path updated to the new directory.
2026-05-17 01:04:37 +02:00
marfrit 1fed626900 Merge pull request 'libva-v4l2-request-ohm-gl-fix: mark deprecated' (#19) from claude-noether/marfrit-packages:noether/deprecate-ohm-gl-fix into main
Reviewed-on: marfrit/marfrit-packages#19
2026-05-16 23:01:00 +00:00
claude-noether 0b2393cecc libva-v4l2-request-ohm-gl-fix: mark deprecated, point at -fourier
Predecessor experimental package (tarball + 18 stacked patches) is
superseded by libva-v4l2-request-fourier (git-tracked fork tip,
iter38 multi-device probe). The successor already declares
replaces=('libva-v4l2-request-ohm-gl-fix') so installs migrate
automatically; this commit just makes the deprecation visible in
README + pkgdesc.

Kept in-tree as historical reference for the ohm_gl_fix Phase 6
audit trail.
2026-05-17 01:00:25 +02:00
marfrit 697413103d Merge pull request 'libva-v4l2-request-fourier: -Db_lto=false (closes #17)' (#18) from claude-noether/marfrit-packages:noether/libva-disable-lto into main 2026-05-16 16:39:57 +00:00
claude-noether b648276122 libva-v4l2-request-fourier: -Db_lto=false (closes #17)
CI binary segfaulted on HEVC vaEndPicture even though
/etc/makepkg.conf has OPTIONS=(... !lto ...). Root cause: arch-meson's
wrapper hard-codes `-D b_lto=true` regardless of makepkg.conf, so
the binary still gets cross-function ICF (Identical Code Folding)
under -O2 + LTO.

HEVC is the only codec in the campaign that submits a per-frame chain
of 4 control structs (SPS + PPS + DECODE_PARAMS + SLICE_PARAMS); ICF
finds a near-duplicate per-codec helper across the codec dispatch and
merges them, then the wrong instance's local stack layout is invoked
on the HEVC path → SEGV. The other 4 codecs (H.264, VP8, VP9, MPEG-2)
submit fewer/simpler control structs and tolerate the folding by
accident.

Empirical confirmation from the issue body's binary bisection:

  meson build (default debugoptimized)     485 KB   HEVC ✓
  arch-meson + --buildtype=release          145 KB   HEVC ✓
  arch-meson + release + -flto              76 KB   HEVC SEGV
  CI build (this package, 7ac934e-1)        133 KB   HEVC SEGV

Fix: append `-Db_lto=false` to the arch-meson invocation.
pkgrel 1 -> 2.
2026-05-15 19:03:46 +00:00
marfrit 2e2c9b6361 linux-ampere-fourier: chmod +x prebuild.sh (#16) 2026-05-15 17:20:10 +00:00
claude-noether 0d311d61b4 linux-ampere-fourier: chmod +x prebuild.sh
The exec bit was missing on prebuild.sh as committed in PR #15
(it landed mode 0644). Running './prebuild.sh' fails with
'Permission denied'; bash ./prebuild.sh works as a workaround but
the shebang is intended to do its job.

Caught while running the first linux-ampere-fourier build on
boltzmann today. README.md examples show './prebuild.sh' so users
will hit the same error.

Single-bit fix via git update-index --chmod=+x. No content change.
2026-05-15 16:54:29 +00:00
marfrit efc1bfd66a linux-ampere-fourier: bootstrap PKGBUILD (CoolPi GenBook RK3588) (#15) 2026-05-15 16:49:45 +00:00
claude-noether 154fa2f14a linux-ampere-fourier: bootstrap PKGBUILD (CoolPi GenBook RK3588)
Sibling to kernel-agent PR #8 which lands the scope-tagged board
patches + fleet/ampere.yaml manifest. This PR carries the
makepkg-side recipe.

## Baseline

marfrit/linux-rk3588-marfrit @ f8f3ad9 (mainline v7.0-rc3 + 18 commits):
  10 by Markus Fritsche  (board DTS + Kconfig + suspend/wakeup + bt)
   4 by Shawn Lin        (phy: rockchip-snps-pcie3 stability)
   2 by Cristian Ciocaltea (clk + dw-dp bridge — Collabora)
   1 by Sebastian Reichel (Rock 5 ITX hdmirx — unused by ampere)
   1 by Pedro Alves      (CLK_SET_RATE_PARENT VOP2 fix)

The 6 board-relevant patches (pwm15 pinctrl + RK806 power-off +
genbook pwm-fan/speaker/USB-C/lid) are scope-tagged in
kernel-agent. The 12 others are 'cherry-picks-in-baseline'
currently — splitting them into scope-tagged patches is a
follow-up.

## Source distribution

The kernel tree isn't pushable to Gitea (boltzmann's working clone
is shallow). Tarball (260MB) doesn't belong in marfrit-packages
either. Pragmatic shortcut: ship prebuild.sh that produces the
tarball locally from $LINUX_RK3588_MARFRIT_TREE (default
~/src/linux-rockchip) just before makepkg runs. PKGBUILD source
array references the tarball by name; makepkg picks it up from
the PKGBUILD dir.

Build flow:
  cd arch/linux-ampere-fourier
  ./prebuild.sh           # produces 260MB tarball; idempotent w/ sha check
  makepkg -s --noconfirm

Future iteration: host the tarball on Gitea release assets or
packages.reauktion.de/sources/ and switch source to URL.

## What the PR ships

  PKGBUILD                          — the recipe (linux-rk3588-marfrit @ f8f3ad9)
  config                            — snapshot of ampere's /proc/config.gz
  linux-ampere-fourier.preset       — mkinitcpio preset, /boot/firmware/ paths
  extlinux-add.hook                 — alpm hook, fires on /boot/firmware/Image* changes
  extlinux-add.sh                   — idempotent managed-label injector for
                                     /boot/firmware/extlinux/extlinux.conf
                                     (vfat on mmcblk0p1, ampere-specific path)
  prebuild.sh                       — source-staging helper (see above)
  README.md                         — build + install runbook

## ampere-specific boot path differences vs fresnel

ampere boots from /boot/firmware/ (vfat partition), not /boot/ (root
partition) like fresnel. The PKGBUILD installs Image + initramfs + DTB
under /boot/firmware/ directly. The extlinux-add hook fires on
/boot/firmware/<X> path changes and edits
/boot/firmware/extlinux/extlinux.conf. The mkinitcpio preset writes
initramfs to /boot/firmware/.

Only one PRESET ('default') — no fallback image — because
/boot/firmware is ~1G total and two ~20MB initramfs files plus the
DTB and a couple of kernel-image backups would squeeze it tight.

## Out of scope this PR

- Ask 2 (VP9 enablement) and Ask 3 (AV1 dec) from kernel-agent issue #6
- Build + publish + install (sequenced after this PR + kernel-agent PR #8 merge)
- Splitting the 12 non-board commits into scope-tagged kernel-agent patches
2026-05-15 16:19:24 +00:00
marfrit 2af63ce988 Merge pull request 'linux-fresnel-fourier: 7.0-1 -> 7.0-14 (carry vb2_dma_resv RFC v2 series)' (#14) from claude-noether/marfrit-packages:noether/linux-fresnel-fourier-pkgrel14 into main
Reviewed-on: marfrit/marfrit-packages#14
2026-05-15 15:37:23 +00:00
claude-noether e9bc6ebd27 linux-fresnel-fourier: 7.0-1 -> 7.0-14 (carry vb2_dma_resv RFC v2 series)
Sibling to kernel-agent PR #7 (which lands the vb2_dma_resv RFC v2
series under patches/subsystem/media/videobuf2/ and updates
fleet/fresnel.yaml to include them). This PR carries the same three
patches in the build-tree-ready form for the linux-fresnel-fourier
PKGBUILD.

Background: Markus iterated v2 locally on boltzmann reaching pkgrel=14
since the 2026-05-09 bootstrap published 7.0-1. v2 attaches the V4L2
producer fence at device_run in slept-OK context per Dufresne's v1
review on linux-media. Drivers opted in here: hantro + rockchip-rga.

Changes:
- pkgrel 1 -> 14
- pkgdesc adds '+ vb2_dma_resv RFC v2'
- source array gains 3 new local patch files (scope-tagged comments
  point to where they live in marfrit/kernel-agent)
- sha256sums extended to 11 SKIP entries

No prepare() edit needed — the existing for-loop applies every *.patch
in $srcdir, so the 4/5/6 patches get picked up automatically. config
unchanged (verified diff vs boltzmann's local pkgrel=14 tree).

Pre-built artifacts: linux-fresnel-fourier-7.0-14-aarch64.pkg.tar.zst
and linux-fresnel-fourier-headers-7.0-14-aarch64.pkg.tar.zst already
exist on boltzmann at /home/mfritsche/src/kernel-agent-bootstrap/
build/marfrit-packages/arch/linux-fresnel-fourier/ — will be signed
and published via marfrit-publish-arch after this PR merges (no fresh
compile needed; the artifacts were built locally during the iteration
loop that reached pkgrel=14).
2026-05-15 15:33:55 +00:00
marfrit 201e671d61 Merge pull request 'firefox-fourier: vendor-prefs install path correction (browser/defaults -> defaults)' (#13) from claude-noether/marfrit-packages:noether/firefox-fourier-vendor-prefs-correct-path into main
Reviewed-on: marfrit/marfrit-packages#13
2026-05-15 14:23:32 +00:00
claude-noether d63d1cef72 firefox-fourier: move vendor-prefs to defaults/preferences/ (the path Firefox actually scans)
Empirical follow-up to #9. After packaging 150.0.1-4 and installing on
fresnel, MOZ_LOG showed the failure pattern was still present:

  D/FFmpegVideo FFMPEG: Using preferred software codec h264

No VAAPI_VLD engagement, no dmabuf surface locking — Gecko bailed
before reaching the patched VAAPI path. Same symptom as issue #8
pre-fix, despite the prefs file being on disk at the expected path.

Root cause: /usr/lib/firefox-fourier/browser/defaults/preferences/ is
NOT a vendor-prefs scan location in Firefox 150. Mozilla's canonical
scan dir is /usr/lib/<app>/defaults/preferences/ — without the
'browser/' prefix.

Verified by hand-copying the same file to /usr/lib/firefox-fourier/
defaults/preferences/ and re-running the H.264 playback test:

  D/FFmpegVideo FFMPEG: Requesting pixel format VAAPI_VLD
  D/Dmabuf VideoFrameSurface: VAAPI locking dmabuf surface UID 26267
    FFMPEG ID 0x4000000 mAVHWFrameContext ...
  D/Dmabuf VideoFrameSurface: VAAPI locking dmabuf surface UID 26268
    FFMPEG ID 0x4000001 ...
  (15+ surface locks)

End-to-end zero-copy DMABUF path engaged, hantro/rkvdec dekodes the
H.264 stream via libva-v4l2-request-fourier iter38b.

pkgrel 4 -> 5. No other PKGBUILD changes.
2026-05-15 14:18:09 +00:00
marfrit 108c725c58 Merge pull request 'kwin-fourier 6.6.4->6.6.5 + qt6-base-fourier 6.11.0->6.11.1 (track upstream extra)' (#12) from claude-noether/marfrit-packages:noether/kwin-qt6-baseline-bump into main
Reviewed-on: marfrit/marfrit-packages#12
2026-05-15 11:45:27 +00:00
claude-noether 75dadb2925 qt6-base-fourier: rebase 6.11.0 -> 6.11.1 to track upstream extra
Triggered by 'pacman -Syu' on fresnel showing local 1:6.11.0-2 newer
than (then-)extra 6.11.0-4. By the time of this commit Arch has moved
on to 6.11.1-1; rebase straight to that.

Diff against Arch's qt6-base 6.11.1 PKGBUILD reduced:
- _pkgver 6.11.0 -> 6.11.1
- pkgrel 3 -> 1 (reset on pkgver bump)
- sha256 of git tag updated to 2eafe504... (matches Arch's 6.11.1 PKGBUILD)
- Drop cherry-pick of 8b54513cdcf6 (qdbus crash fix landed upstream
  in 6.11.1; Arch dropped it from theirs as well)
- depends: gcc-libs replaced by libgcc + libstdc++ (Arch split these
  into separate packages between 6.11.0 and 6.11.1)
- Build flag: -DFEATURE_sql_ibase=OFF removed, -DFEATURE_mimetype_database=OFF
  added (Arch toggled in 6.11.1)

Kept (the reason this fork exists):
- 0001/0002/0003 GL_R8-on-ES3 patches (Mali GLES3 KWin compositor stall fix)
- qt6-base-cflags.patch + qt6-base-nostrip.patch (system CFLAGS + skip strip)
- qt6-xcb-private-headers-fourier sub-package (depended on by other fork pkgs)
- epoch=1 (precedence guarantee until upstream lands GL_R8/ES3 fix)

Patches NOT dry-run-verified against 6.11.1 source (qt clone is multi-GB
and impractical to fetch for a quick check). They touch glyph cache and
RHI gles2 paths that have been stable since Qt 6.10; expected to apply
cleanly. Will revert pkgrel and re-pin if first build hits hunk failures.
2026-05-15 10:57:02 +00:00
claude-noether fedcc4a357 kwin-fourier: 6.6.4 -> 6.6.5 (track upstream extra)
Triggered by 'pacman -Syu' on fresnel showing local 1:6.6.4-1 newer
than extra 6.6.5-1 (epoch wins, but our base lags upstream).

- pkgver 6.6.4 -> 6.6.5
- pkgrel 3 -> 1 (reset on pkgver bump)
- sha256sum updated for new tarball
- 0001-transaction-bypass-watchDmaBuf-fence-wait.patch dry-run verified
  clean against 6.6.5/src/wayland/transaction.cpp

Epoch=1 retained until upstream lands a proper V4L2 implicit-sync
fence-wait bypass (the patch-header hypothesis is still being tested
through ohm/fresnel HW-decode validation; not upstreamable yet).
2026-05-15 10:53:59 +00:00
marfrit 860ebf2df5 firefox-fourier: flatten patches to top-level (makepkg has no subdir support) (#11) 2026-05-15 08:04:12 +00:00
claude-noether 109858eae5 firefox-fourier: flatten patches to top-level (makepkg has no subdir support)
Follow-up to #10. The subdir layout I assumed worked turned out to not
work — per 'man PKGBUILD':

  The filename in the array must NOT include any path components like ./

makepkg's source-staging only honors basenames; the patches/ subdir
references staged the files but the basename-lookup at apply time
failed with the same 'not found in build directory' error that #9 hit.

I copied the chromium-fourier convention thinking it was proven, but
chromium-fourier has no CI either and likely has the same latent
breakage (separate issue, not in this PR's scope).

The actually-working pattern is the mpv-fourier one: patches at the
top level next to the PKGBUILD. mpv-fourier iter2 just built green
on CI (#92) with that layout.

This commit:
- Moves all 8 patches (5 fourier + 3 arch upstream) from patches/
  to arch/firefox-fourier/ via git mv (preserves blame).
- Removes the now-empty patches/ subdir.
- Strips 'patches/' prefix from source array entries.
- Strips '/patches' from prepare() patch -i paths.

No semantic change to the patch content or apply order.

pkgrel 3 -> 4.
2026-05-15 08:00:27 +00:00
marfrit 9041c1bf51 firefox-fourier: fix patches layout + ship missing arch upstream patches (#10) 2026-05-15 07:56:58 +00:00
claude-noether f41e9a117b firefox-fourier: fix patches layout — ship arch-*.patch + reference patches/
The PKGBUILD has been structurally broken since at least the 150.0.1
import: source array referenced patches at top level ('0001-...patch')
but the actual files live in patches/ — makepkg searched for them in
the package root and failed before doing any work. The arch-0002/3/4
upstream toolchain patches (clang 22, glibc 2.43, Rust 1.95) weren't
shipped in the repo at all.

Caught when boltzmann tried to build 150.0.1-2 (PR #9 follow-up); fails
at the source-staging phase with:

  ==> ERROR: arch-0002-Bug-2033279-Make-enable-rust-simd-work-with-Rust-1.9.patch
              was not found in the build directory and is not a URL.

Why nobody noticed: firefox-fourier has no Gitea Actions job (too heavy
for the runner pool). The shipped 150.0.1-1 .pkg.tar.zst was produced
by hand-staging files; the PKGBUILD itself never reproduced from a
clean checkout.

This commit:
- Moves all source-array patch references under patches/ to match the
  on-disk layout (same convention as chromium-fourier).
- Updates prepare() paths accordingly.
- Adds arch-0002/3/4 patches fetched verbatim from
  https://gitlab.archlinux.org/archlinux/packaging/packages/firefox
  (raw/main/{0002,0003,0004}-...patch). Renamed with arch- prefix in
  the repo to avoid namespace collision with the local 0001..0005.
- Adds the previously-omitted 0005-rdd-sandbox-v4l2-media-ctl.patch
  to the source array + prepare(); this is the patch that broadens
  the RDD sandbox so /dev/media* and /dev/video* ioctls reach the
  decoder child (README §1 enumerates it as load-bearing for the HW
  path). It was present in patches/ but not wired up.

Dry-run verified all 8 patches apply cleanly against firefox-150.0.1
source (some hunks offset by ≤3 lines, no conflicts).

pkgrel 2 -> 3.
2026-05-15 07:24:30 +00:00
marfrit 2f78136479 Merge pull request 'fresnel-fourier stack: bump libva to iter38b + fix firefox HW-decode defaults (#8)' (#9) from claude-noether/marfrit-packages:noether/libva-iter38b-and-firefox-prefs into main
Reviewed-on: marfrit/marfrit-packages#9
2026-05-15 06:13:19 +00:00
claude-noether 62a594ab59 firefox-fourier: ship RK3399 HW-decode default prefs (closes #8)
Three prefs that gate the patched VAAPI / V4L2-request code path are
'false' upstream and need to be 'true' for the libva-v4l2-request
backend to actually engage on RK3399 / panfrost EGL:

  widget.dmabuf.force-enabled
  media.hardware-video-decoding.force-enabled
  media.ffvpx-hw.enabled

Without them, Gecko's DMA-BUF probe silently fails (panfrost EGL
doesn't trip the right detection), the (Intel-tuned) HW-vs-SW cost
heuristic picks SW, and the FFvpx PDM never selects its HW-capable
variant for VP8/VP9. Net result: fresh profiles SW-decode despite the
0001..0004 unlock patches being applied.

Shipped as a vendor-default file at:
  /usr/lib/firefox-fourier/browser/defaults/preferences/rockchip-fourier-defaults.js

Lower precedence than user.js / about:config — power users debugging
HW decode can still flip them off without touching the package.

pkgrel 1 -> 2.

Closes: #8
2026-05-15 06:10:01 +00:00
claude-noether 81cc050bf3 libva-v4l2-request-fourier: bump pin iter8 -> iter38b (7ac934e)
Carries the fork from libva-multiplanar iter8 close (2026-05-06) to
fresnel-fourier iter38b (2026-05-14): multi-device probe so a single
libva session serves rkvdec (H.264 + HEVC + VP9) + hantro (MPEG-2 +
VP8) without LIBVA_V4L2_REQUEST_VIDEO_PATH overrides, plus the
MAX_PROFILES bounds-check fix from iter38b.

Required by the fresnel-fourier README's HW-decode stack (vainfo
exposes all 10 profiles in one session, byte-exact bench verified
across 5 codecs).

68 commits between the old pin (65969da3) and the new (7ac934e0).
pkgver() recomputes the rev count at build time; the static placeholder
is bumped from r280 to r348 to reflect the new pin.
2026-05-15 06:08:21 +00:00
77 changed files with 37790 additions and 44 deletions
+430 -4
View File
@@ -375,7 +375,7 @@ jobs:
run: rm -f /root/repo_pass /root/.ssh/id_ed25519 run: rm -f /root/repo_pass /root/.ssh/id_ed25519
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# ffmpeg-v4l2-request-git (aarch64 only) — FFmpeg with V4L2 Request API # ffmpeg-v4l2-request-fourier (aarch64 only) — FFmpeg with V4L2 Request API
# hwaccel for Rockchip / Allwinner stateless decoders. Used by the Fourier # hwaccel for Rockchip / Allwinner stateless decoders. Used by the Fourier
# umbrella (ohm, fresnel, ampere). Long-running build, so failures don't # umbrella (ohm, fresnel, ampere). Long-running build, so failures don't
# block downstream debian jobs. # block downstream debian jobs.
@@ -416,11 +416,11 @@ jobs:
chmod 600 /root/.ssh/id_ed25519 chmod 600 /root/.ssh/id_ed25519
ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null
- name: makepkg ffmpeg-v4l2-request-git - name: makepkg ffmpeg-v4l2-request-fourier
run: | run: |
set -e set -e
rm -rf /tmp/build-ffmpeg-v4l2 rm -rf /tmp/build-ffmpeg-v4l2
cp -r arch/ffmpeg-v4l2-request-git /tmp/build-ffmpeg-v4l2 cp -r arch/ffmpeg-v4l2-request-fourier /tmp/build-ffmpeg-v4l2
chown -R builder:builder /tmp/build-ffmpeg-v4l2 chown -R builder:builder /tmp/build-ffmpeg-v4l2
cd /tmp/build-ffmpeg-v4l2 cd /tmp/build-ffmpeg-v4l2
# Parallelise wide; distcc-avahi distributes compiles across the # Parallelise wide; distcc-avahi distributes compiles across the
@@ -429,7 +429,7 @@ jobs:
makepkg --nocheck --noconfirm --syncdeps --cleanbuild makepkg --nocheck --noconfirm --syncdeps --cleanbuild
ls -la *.pkg.tar.* | grep -v "\.sig$" ls -la *.pkg.tar.* | grep -v "\.sig$"
- name: sign ffmpeg-v4l2-request-git - name: sign ffmpeg-v4l2-request-fourier
run: | run: |
set -e set -e
cd /tmp/build-ffmpeg-v4l2 cd /tmp/build-ffmpeg-v4l2
@@ -784,3 +784,429 @@ jobs:
- name: wipe secrets - name: wipe secrets
if: always() if: always()
run: rm -f /root/.ssh/id_ed25519_hertz run: rm -f /root/.ssh/id_ed25519_hertz
# -------------------------------------------------------------------------
# ffmpeg-v4l2-request-fourier Debian (aarch64) — debian/<pkg>/build-deb.sh
# builds the Kwiboo FFmpeg fork natively on the arch-aarch64 runner using
# the arch toolchain + system libs, then dpkg-deb's the result. Resulting
# .deb is rsynced to hertz; reprepro publishes into bookworm + trixie.
# -------------------------------------------------------------------------
ffmpeg-v4l2-request-debian:
needs: ffmpeg-v4l2-request-aarch64
runs-on: arch-aarch64
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: install build-deps (Arch pkg names; build-deb.sh links natively)
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
retry pacman -Syu --noconfirm --needed \
dpkg openssh rsync curl base-devel git nasm yasm \
linux-api-headers mesa alsa-lib bzip2 fontconfig fribidi gmp \
gnutls lame libass dav1d libdrm freetype2 libpulse libva \
libvorbis libvpx libwebp x264 x265 libxml2 opus v4l-utils xz zlib
- name: install hertz deploy ssh key
env:
KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }}
run: |
mkdir -m700 -p /root/.ssh
printf '%s\n' "$KEY" > /root/.ssh/id_ed25519_hertz
chmod 600 /root/.ssh/id_ed25519_hertz
ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null
- name: build ffmpeg-v4l2-request-fourier .deb
run: |
set -e
cd debian/ffmpeg-v4l2-request-fourier
./build-deb.sh
ls -la *.deb
- name: upload + publish to suites
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
cd debian/ffmpeg-v4l2-request-fourier
DEB=$(ls ffmpeg-v4l2-request-fourier_*.deb | head -1)
retry rsync -av -e 'ssh -i /root/.ssh/id_ed25519_hertz' "$DEB" \
marfritrepo@hertz.fritz.box:
for suite in bookworm trixie; do
retry ssh -i /root/.ssh/id_ed25519_hertz marfritrepo@hertz.fritz.box \
"publish-deb $suite $DEB"
done
- name: wipe secrets
if: always()
run: rm -f /root/.ssh/id_ed25519_hertz
# -------------------------------------------------------------------------
# libva-v4l2-request-fourier Debian (aarch64) — meson build + dpkg-deb wrap.
# -------------------------------------------------------------------------
libva-v4l2-request-fourier-debian:
needs: libva-v4l2-request-fourier-aarch64
runs-on: arch-aarch64
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: install build-deps
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
retry pacman -Syu --noconfirm --needed \
dpkg openssh rsync curl base-devel git meson ninja pkgconf \
libva libdrm systemd-libs
- name: install hertz deploy ssh key
env:
KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }}
run: |
mkdir -m700 -p /root/.ssh
printf '%s\n' "$KEY" > /root/.ssh/id_ed25519_hertz
chmod 600 /root/.ssh/id_ed25519_hertz
ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null
- name: build libva-v4l2-request-fourier .deb
run: |
set -e
cd debian/libva-v4l2-request-fourier
./build-deb.sh
ls -la *.deb
- name: upload + publish to suites
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
cd debian/libva-v4l2-request-fourier
DEB=$(ls libva-v4l2-request-fourier_*.deb | head -1)
retry rsync -av -e 'ssh -i /root/.ssh/id_ed25519_hertz' "$DEB" \
marfritrepo@hertz.fritz.box:
for suite in bookworm trixie; do
retry ssh -i /root/.ssh/id_ed25519_hertz marfritrepo@hertz.fritz.box \
"publish-deb $suite $DEB"
done
- name: wipe secrets
if: always()
run: rm -f /root/.ssh/id_ed25519_hertz
# -------------------------------------------------------------------------
# mpv-fourier Debian (aarch64) — meson build links against
# ffmpeg-v4l2-request-fourier's libavcodec to keep ABI symmetry between
# the .deb's runtime dep declaration and the binary's actual linkage.
# We pre-install the Arch sibling package from [marfrit] for that.
# -------------------------------------------------------------------------
mpv-fourier-debian:
needs: mpv-fourier-aarch64
runs-on: arch-aarch64
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: install build-deps
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
retry pacman -Syu --noconfirm --needed \
dpkg openssh rsync curl base-devel git meson ninja python-docutils \
ladspa wayland-protocols vulkan-headers \
alsa-lib desktop-file-utils glibc hicolor-icon-theme jack lcms2 \
libarchive libass libbluray libcdio libcdio-paranoia libdisplay-info \
libdrm libdvdnav libdvdread libegl libgl libglvnd libjpeg-turbo \
libplacebo libpulse libsixel libva libvdpau libx11 libxext \
libxkbcommon libxpresent libxrandr libxss libxv luajit mesa mujs \
libpipewire rubberband sdl2 openal uchardet vapoursynth \
vulkan-icd-loader wayland zlib
- name: configure [marfrit] repo + pre-install ffmpeg-v4l2-request-fourier
run: |
set -e
curl -sLo /tmp/marfrit.gpg https://packages.reauktion.de/marfrit.gpg
pacman-key --add /tmp/marfrit.gpg
pacman-key --lsign-key 92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C
rm -f /tmp/marfrit.gpg
if ! grep -q '^\[marfrit\]' /etc/pacman.conf; then
printf '\n[marfrit]\nServer = https://packages.reauktion.de/arch/$arch\nSigLevel = Required\n' >> /etc/pacman.conf
fi
pacman -Sy --noconfirm
rm -f /var/cache/pacman/pkg/ffmpeg-v4l2-request-fourier-*-aarch64.pkg.tar.*
printf 'y\ny\ny\n' | pacman -S marfrit/ffmpeg-v4l2-request-fourier
- name: install hertz deploy ssh key
env:
KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }}
run: |
mkdir -m700 -p /root/.ssh
printf '%s\n' "$KEY" > /root/.ssh/id_ed25519_hertz
chmod 600 /root/.ssh/id_ed25519_hertz
ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null
- name: build mpv-fourier .deb
run: |
set -e
cd debian/mpv-fourier
./build-deb.sh
ls -la *.deb
- name: upload + publish to suites
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
cd debian/mpv-fourier
DEB=$(ls mpv-fourier_*.deb | head -1)
retry rsync -av -e 'ssh -i /root/.ssh/id_ed25519_hertz' "$DEB" \
marfritrepo@hertz.fritz.box:
for suite in bookworm trixie; do
retry ssh -i /root/.ssh/id_ed25519_hertz marfritrepo@hertz.fritz.box \
"publish-deb $suite $DEB"
done
- name: wipe secrets
if: always()
run: rm -f /root/.ssh/id_ed25519_hertz
# -------------------------------------------------------------------------
# daedalus-v4l2 Debian (aarch64) — CMake + Make build, dpkg-deb wrap.
# Userspace daemon + test tools for the daedalus_v4l2 V4L2-stateless shim.
# -------------------------------------------------------------------------
daedalus-v4l2-debian:
needs: claude-his-debian
runs-on: arch-aarch64
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: install build-deps (sans ffmpeg — see [marfrit] step)
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
# Do NOT pull stock 'ffmpeg' here: the arch-aarch64 runner has
# ffmpeg-v4l2-request-fourier pre-installed from the mpv-aarch64
# job (configured via [marfrit]), and pacman -S ffmpeg would
# conflict on the libav* drop-in. Daedalus build only needs
# libavcodec/libavformat headers, which the fourier package
# already supplies. Keep cmake/ninja/pkgconf/libdrm here; the
# ffmpeg-dev equivalent comes via the next step.
retry pacman -Syu --noconfirm --needed \
dpkg openssh rsync curl base-devel git cmake ninja pkgconf \
libdrm
- name: ensure ffmpeg-v4l2-request-fourier installed (link-time ABI source)
run: |
set -e
# Idempotent: pre-install the marfrit fourier ffmpeg so cmake
# finds libavcodec / libavformat / libavutil headers + .so's.
# Mirrors mpv-fourier-debian's [marfrit] step.
curl -sLo /tmp/marfrit.gpg https://packages.reauktion.de/marfrit.gpg
pacman-key --add /tmp/marfrit.gpg
pacman-key --lsign-key 92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C
rm -f /tmp/marfrit.gpg
if ! grep -q '^\[marfrit\]' /etc/pacman.conf; then
printf '\n[marfrit]\nServer = https://packages.reauktion.de/arch/$arch\nSigLevel = Required\n' >> /etc/pacman.conf
fi
pacman -Sy --noconfirm
rm -f /var/cache/pacman/pkg/ffmpeg-v4l2-request-fourier-*-aarch64.pkg.tar.*
printf 'y\ny\ny\n' | pacman -S --needed marfrit/ffmpeg-v4l2-request-fourier
- name: install hertz deploy ssh key
env:
KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }}
run: |
mkdir -m700 -p /root/.ssh
printf '%s\n' "$KEY" > /root/.ssh/id_ed25519_hertz
chmod 600 /root/.ssh/id_ed25519_hertz
ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null
- name: build daedalus-v4l2 .deb
run: |
set -e
cd debian/daedalus-v4l2
./build-deb.sh
ls -la *.deb
- name: upload + publish to suites
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
cd debian/daedalus-v4l2
DEB=$(ls daedalus-v4l2_*.deb | head -1)
retry rsync -av -e 'ssh -i /root/.ssh/id_ed25519_hertz' "$DEB" \
marfritrepo@hertz.fritz.box:
for suite in bookworm trixie; do
retry ssh -i /root/.ssh/id_ed25519_hertz marfritrepo@hertz.fritz.box \
"publish-deb $suite $DEB"
done
- name: wipe secrets
if: always()
run: rm -f /root/.ssh/id_ed25519_hertz
# -------------------------------------------------------------------------
# daedalus-v4l2-dkms Debian (Architecture: all) — packages the kernel
# source tree + dkms.conf. No compilation; just file copy + dpkg-deb.
# -------------------------------------------------------------------------
daedalus-v4l2-dkms-debian:
needs: daedalus-v4l2-debian
runs-on: arch-aarch64
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: install tooling
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
retry pacman -Syu --noconfirm --needed dpkg openssh rsync curl tar gzip
- name: install hertz deploy ssh key
env:
KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }}
run: |
mkdir -m700 -p /root/.ssh
printf '%s\n' "$KEY" > /root/.ssh/id_ed25519_hertz
chmod 600 /root/.ssh/id_ed25519_hertz
ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null
- name: build daedalus-v4l2-dkms .deb
run: |
set -e
cd debian/daedalus-v4l2-dkms
./build-deb.sh
ls -la *.deb
- name: upload + publish to suites
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
cd debian/daedalus-v4l2-dkms
DEB=$(ls daedalus-v4l2-dkms_*.deb | head -1)
retry rsync -av -e 'ssh -i /root/.ssh/id_ed25519_hertz' "$DEB" \
marfritrepo@hertz.fritz.box:
for suite in bookworm trixie; do
retry ssh -i /root/.ssh/id_ed25519_hertz marfritrepo@hertz.fritz.box \
"publish-deb $suite $DEB"
done
- name: wipe secrets
if: always()
run: rm -f /root/.ssh/id_ed25519_hertz
# -------------------------------------------------------------------------
# mesa-panvk-bifrost (aarch64 only) — patched Mesa libvulkan_panfrost.so
# for Bifrost-gen Mali (panvk-bifrost campaign iter9). Co-installs at
# /usr/lib/panvk-bifrost/ so stock mesa stays intact; opt-in via the
# brave-vulkan launcher this package also ships.
#
# Build is slow (~30-60min on actrunner-aarch64): full Mesa-from-source.
# Standalone job — no `needs:` since it doesn't depend on the fourier
# codec stack. continue-on-error so a build hiccup doesn't block other
# jobs in the same workflow run.
# -------------------------------------------------------------------------
mesa-panvk-bifrost-aarch64:
runs-on: arch-aarch64
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: bootstrap runner (idempotent)
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo
- name: import signing key
env:
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
run: |
set -e
gpgconf --homedir /root/.gnupg --kill all 2>/dev/null || true
rm -rf /root/.gnupg /root/repo_pass
mkdir -m700 -p /root/.gnupg
printf '%s' "$PASS" > /root/repo_pass
chmod 600 /root/repo_pass
printf '%s\n' "$PRIV" | gpg --batch --import
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
- name: install deploy ssh key
env:
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
run: |
mkdir -m700 -p /root/.ssh
printf '%s\n' "$KEY" > /root/.ssh/id_ed25519
chmod 600 /root/.ssh/id_ed25519
ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null
- name: makepkg mesa-panvk-bifrost
run: |
set -e
rm -rf /tmp/build-mesa-panvk-bifrost
cp -r arch/mesa-panvk-bifrost /tmp/build-mesa-panvk-bifrost
chown -R builder:builder /tmp/build-mesa-panvk-bifrost
cd /tmp/build-mesa-panvk-bifrost
# MAKEFLAGS for parallel build; runner is multi-core.
# --skipinteg because sha256sums=SKIP in PKGBUILD (matches the
# fourier-fork PKGBUILD convention).
sudo -u builder -H env MAKEFLAGS="-j60" \
makepkg --nocheck --noconfirm --syncdeps --cleanbuild --skipinteg
ls -la *.pkg.tar.* | grep -v "\.sig$"
- name: sign mesa-panvk-bifrost
run: |
set -e
cd /tmp/build-mesa-panvk-bifrost
for f in *.pkg.tar.xz *.pkg.tar.zst *.pkg.tar.gz; do
[ -f "$f" ] || continue
gpg --batch --pinentry-mode loopback --passphrase-file /root/repo_pass \
--detach-sign --yes -u 92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C "$f"
done
- name: update aarch64 repo db
run: |
set -e
mkdir -p /tmp/arch-stage-mesa-panvk
cd /tmp/arch-stage-mesa-panvk
rm -f *
for f in marfrit.db.tar.gz marfrit.db.tar.gz.sig marfrit.files.tar.gz marfrit.files.tar.gz.sig; do
curl -sSLf "https://packages.reauktion.de/arch/aarch64/$f" -o "$f" || rm -f "$f"
done
for ext in xz zst gz; do
ls /tmp/build-mesa-panvk-bifrost/*.pkg.tar.$ext 2>/dev/null && \
mv /tmp/build-mesa-panvk-bifrost/*.pkg.tar.$ext /tmp/build-mesa-panvk-bifrost/*.pkg.tar.$ext.sig .
done || true
export GNUPGHOME=/root/.gnupg
printf 'pinentry-mode loopback\npassphrase-file /root/repo_pass\n' > /root/.gnupg/gpg.conf
printf 'allow-loopback-pinentry\n' > /root/.gnupg/gpg-agent.conf
gpg-connect-agent reloadagent /bye
pkgs=()
for ext in xz zst gz; do
for f in *.pkg.tar.$ext; do [ -f "$f" ] && pkgs+=("$f"); done
done
if [ -f marfrit.db.tar.gz ]; then
for f in "${pkgs[@]}"; do
name=$(echo "$f" | sed -E 's/-[0-9].*//')
repo-remove --sign --key 92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C \
marfrit.db.tar.gz "$name" 2>/dev/null || true
done
fi
repo-add --new --sign --key 92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C \
--verify marfrit.db.tar.gz "${pkgs[@]}"
ln -sf marfrit.db.tar.gz marfrit.db
ln -sf marfrit.files.tar.gz marfrit.files
ln -sf marfrit.db.tar.gz.sig marfrit.db.sig
rm -f marfrit.files.sig
- name: publish to aarch64
run: |
set -e
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
cd /tmp/arch-stage-mesa-panvk
retry rsync -avL --copy-unsafe-links \
-e 'ssh -i /root/.ssh/id_ed25519' \
./ mfritsche@nc.reauktion.de:arch/aarch64/
- name: wipe secrets
if: always()
run: rm -f /root/repo_pass /root/.ssh/id_ed25519
+71
View File
@@ -0,0 +1,71 @@
# Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
#
# daedalus-v4l2-dkms — DKMS package for the daedalus_v4l2 out-of-tree
# kernel module (V4L2 stateless decoder shim for Pi 5 / CM5).
#
# Pair to daedalus-v4l2 (userspace daemon). When loaded, the module
# registers /dev/videoNN (V4L2 m2m) + /dev/mediaNN (media controller) +
# /dev/daedalus-v4l2 (chardev to the userspace daemon). Userspace
# clients drive the V4L2 m2m + request API path; the daemon does the
# actual FFmpeg-backed decode on /dev/daedalus-v4l2.
#
# Project: https://git.reauktion.de/reauktion/daedalus-v4l2
# Sibling userspace package: daedalus-v4l2
# Sibling consumer: libva-v4l2-request-fourier
pkgname=daedalus-v4l2-dkms
_module=daedalus_v4l2
# Same pin as arch/daedalus-v4l2 — keep kernel module + daemon
# bit-versioned together so the chardev wire protocol stays in sync.
_commit=481279c9bffd19e32c8f3299897e9b63fc5a24aa
pkgver=0.1.0.r18.481279c
pkgrel=1 # reset for new upstream pin (481279c — Phase 8.13 close)
pkgdesc="V4L2 stateless decoder shim kernel module (DKMS) — Pi 5 / CM5"
arch=('any')
url="https://git.reauktion.de/reauktion/daedalus-v4l2"
license=('GPL-2.0-or-later')
depends=('dkms')
makedepends=('git')
install="${pkgname}.install"
source=("git+https://git.reauktion.de/reauktion/daedalus-v4l2.git#commit=${_commit}"
"dkms.conf"
"${pkgname}.install")
sha256sums=('SKIP'
'SKIP'
'SKIP')
pkgver() {
cd "${srcdir}/daedalus-v4l2"
printf '0.1.0.r%s.%s' \
"$(git rev-list --count HEAD)" \
"$(git rev-parse --short=7 HEAD)"
}
package() {
local _src="${pkgdir}/usr/src/${_module}-${pkgver}"
install -dm755 "${_src}"
# Install the kernel/ subdir and embed the shared proto header in
# the same tree. The in-tree Makefile uses
# `ccflags-y += -I$(src)/../include` (assuming the parent
# daedalus-v4l2 layout); for DKMS we flatten by copying the header
# into kernel/include/ and patching the Makefile to point there.
cp -r "${srcdir}/daedalus-v4l2/kernel/." "${_src}/"
install -Dm644 "${srcdir}/daedalus-v4l2/include/daedalus_v4l2_proto.h" \
"${_src}/include/daedalus_v4l2_proto.h"
sed -i 's|-I\$(src)/\.\./include|-I$(src)/include|' "${_src}/Makefile"
# dkms.conf at the root of the source tree (DKMS convention).
# Substitute #MODULE_VERSION# placeholder with the actual pkgver
# so dkms install/uninstall match what's on disk.
install -Dm644 "${srcdir}/dkms.conf" "${_src}/dkms.conf"
sed -i "s/#MODULE_VERSION#/${pkgver}/" "${_src}/dkms.conf"
# License
install -Dm644 "${srcdir}/daedalus-v4l2/kernel/daedalus_v4l2_main.c" \
"${pkgdir}/usr/share/licenses/${pkgname}/SPDX-HEADER"
}
@@ -0,0 +1,61 @@
# post-install / post-upgrade hook for daedalus-v4l2-dkms.
#
# pacman + the dkms-helpers alpm hook will already attempt
# `dkms install` on its own. This script's job is to emit a
# loud, actionable warning when the module didn't actually
# build for the running kernel — most commonly because the
# kernel headers package isn't installed yet.
#
# Without this you get a silent failure: the package looks
# installed but `modprobe daedalus_v4l2` returns ENOENT.
_check_dkms_built() {
local name=daedalus_v4l2
local ver=$1
local kernelver=$(uname -r)
if ! command -v dkms >/dev/null 2>&1; then
return 1 # the hard-dep should have caught this
fi
local status
status=$(dkms status -m "$name" -v "$ver" -k "$kernelver" 2>/dev/null || true)
if printf '%s\n' "$status" | grep -q -E 'installed|loaded'; then
return 0 # all good
fi
cat >&2 <<EOF
==> daedalus-v4l2-dkms: DKMS build did NOT land for kernel $kernelver.
==> dkms status -m $name -v $ver -k $kernelver:
==> $(printf '%s' "$status" | head -1)
==>
==> Most likely cause: kernel headers package is missing.
==> Arch / ALARM: pacman -S linux-rpi-headers (or linux-rpi5-headers)
==> Raspberry Pi OS: apt install linux-headers-rpi-2712
==>
==> After installing headers, finish the install with:
==> sudo dkms autoinstall $name/$ver
==> sudo modprobe daedalus_v4l2
==>
==> Until then daedalus_v4l2 will NOT be loadable and the
==> userspace daedalus-v4l2 daemon will have nothing to talk to.
EOF
return 1
}
post_install() {
_check_dkms_built "$1" || true
}
post_upgrade() {
# New version pinned by the bump may have built fine, but if
# a kernel-headers package was uninstalled / pruned since the
# last upgrade we'd silently regress. Re-check.
_check_dkms_built "$1" || true
}
pre_remove() {
# The dkms alpm hook handles dkms remove on its own; nothing
# we need to add here.
:
}
+19
View File
@@ -0,0 +1,19 @@
# DKMS configuration for daedalus_v4l2 — V4L2 stateless decoder shim.
#
# Built against /lib/modules/$kernelver/build with the in-tree Makefile.
# The Makefile uses `obj-m := daedalus_v4l2.o` and links
# daedalus_v4l2_main.o + daedalus_v4l2_chardev.o into the final .ko.
PACKAGE_NAME="daedalus_v4l2"
PACKAGE_VERSION="#MODULE_VERSION#"
# Single module produced by the Makefile.
BUILT_MODULE_NAME[0]="daedalus_v4l2"
DEST_MODULE_LOCATION[0]="/updates"
# Use the package's own Makefile — it already does
# `$(MAKE) -C $(KERNELDIR) M=$(PWD) modules`.
MAKE[0]="make KERNELDIR=/lib/modules/${kernelver}/build all"
CLEAN="make KERNELDIR=/lib/modules/${kernelver}/build clean"
AUTOINSTALL="yes"
+116
View File
@@ -0,0 +1,116 @@
# Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
#
# daedalus-v4l2 — userspace daemon + V4L2 m2m test tools.
#
# Pair to daedalus-v4l2-dkms (kernel module). Together they expose
# /dev/videoNN + /dev/mediaNN as a V4L2 stateless decoder shim on Pi 5 /
# CM5, decoding VP9 / AV1 / H.264 via dlopen'd FFmpeg in a single-
# threaded daemon and shipping decoded NV12 / P010 back through dmabuf.
# Consumed end-to-end by libva-v4l2-request-fourier (>= 1.0.0.r376) so
# `ffmpeg -hwaccel vaapi` against vp9_small.ivf produces byte-exact NV12.
#
# Project: https://git.reauktion.de/reauktion/daedalus-v4l2
# Sibling kernel package: daedalus-v4l2-dkms
# Sibling consumer: libva-v4l2-request-fourier
pkgname=daedalus-v4l2
_upstreampkg=daedalus-v4l2
# Pin the daedalus-v4l2 tip. 481279c = "Phase 8.13: byte-exact end-to-
# end via libva (consumer target hit)" — first commit where the full
# ffmpeg -hwaccel vaapi → libva → /dev/video0 → daemon path lands a
# pixel-correct decoded frame back in ffmpeg. Promote to a later pin
# only after a future phase closes cleanly.
_commit=481279c9bffd19e32c8f3299897e9b63fc5a24aa
# 0.1.0 (pre-1.0) + commit count + short sha. Bump the .Y on each
# Phase 8.x close. pkgver() recomputes at build time.
pkgver=0.1.0.r18.481279c
pkgrel=1 # reset for new upstream pin (481279c — Phase 8.13 close)
pkgdesc="Userspace daemon for the daedalus-v4l2 V4L2 stateless decoder shim (VP9/AV1/H.264 on Pi 5 / CM5)"
arch=('aarch64')
url="https://git.reauktion.de/reauktion/daedalus-v4l2"
license=('BSD-2-Clause' 'GPL-2.0-or-later')
# Daemon dlopens libavformat.so.61 / libavcodec.so.61 / libavutil.so.59
# at runtime (Option γ — see daemon/src/ffmpeg_loader.h). ffmpeg
# provides those; we don't link them.
depends=('ffmpeg' 'libdrm')
# Headers from libav*-dev needed at compile time for type-safe function
# pointer signatures; pkg-config locates them.
makedepends=('cmake' 'ninja' 'pkgconf' 'git' 'ffmpeg')
optdepends=('daedalus-v4l2-dkms: kernel module providing /dev/video0 + /dev/daedalus-v4l2'
'libva-v4l2-request-fourier: VA-API consumer routing through this daemon')
install="${pkgname}.install"
source=("git+https://git.reauktion.de/reauktion/daedalus-v4l2.git#commit=${_commit}"
"${pkgname}.install")
sha256sums=('SKIP'
'SKIP')
pkgver() {
cd "${srcdir}/${_upstreampkg}"
printf '0.1.0.r%s.%s' \
"$(git rev-list --count HEAD)" \
"$(git rev-parse --short=7 HEAD)"
}
build() {
cd "${srcdir}/${_upstreampkg}/daemon"
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr
cmake --build build
cd "${srcdir}/${_upstreampkg}/tools"
make
}
package() {
cd "${srcdir}/${_upstreampkg}"
# Daemon binary
install -Dm755 daemon/build/daedalus_v4l2_daemon \
"${pkgdir}/usr/bin/daedalus_v4l2_daemon"
# Test tools (under /usr/libexec to keep them out of the default PATH
# — they're for verification, not daily use).
install -Dm755 tools/test_chardev_pingpong \
"${pkgdir}/usr/libexec/daedalus-v4l2/test_chardev_pingpong"
install -Dm755 tools/test_m2m_decode \
"${pkgdir}/usr/libexec/daedalus-v4l2/test_m2m_decode"
install -Dm755 tools/test_m2m_stream \
"${pkgdir}/usr/libexec/daedalus-v4l2/test_m2m_stream"
# Shared wire-protocol header (kernel ↔ daemon); useful for
# third-party clients of the chardev.
install -Dm644 include/daedalus_v4l2_proto.h \
"${pkgdir}/usr/include/daedalus_v4l2_proto.h"
# systemd unit + module autoload — without these the daemon never
# starts and the libva/VAAPI consumer's REQ_DECODE has nobody on
# the other end of /dev/daedalus-v4l2.
install -Dm644 packaging/systemd/daedalus-v4l2.service \
"${pkgdir}/usr/lib/systemd/system/daedalus-v4l2.service"
install -Dm644 packaging/systemd/daedalus-v4l2.modules-load \
"${pkgdir}/usr/lib/modules-load.d/daedalus-v4l2.conf"
# Documentation
install -Dm644 README.md \
"${pkgdir}/usr/share/doc/${pkgname}/README.md"
for d in docs/*.md; do
install -Dm644 "$d" "${pkgdir}/usr/share/doc/${pkgname}/$(basename "$d")"
done
# Licenses: BSD-2-Clause for daemon/tools, GPL for the kernel proto
# header; the SPDX headers in src/ are the canonical declaration but
# ship a short note here for package-manager-driven license queries.
install -dm755 "${pkgdir}/usr/share/licenses/${pkgname}"
cat > "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" <<'EOF'
daedalus-v4l2 userspace components are BSD-2-Clause licensed.
The shared kernel↔daemon wire protocol header
(/usr/include/daedalus_v4l2_proto.h) is GPL-2.0-or-later WITH
Linux-syscall-note for kernel-side compatibility. See SPDX
headers on individual source files for the canonical
per-file declaration.
EOF
}
+42
View File
@@ -0,0 +1,42 @@
# post_install / post_upgrade for daedalus-v4l2.
#
# Enables (but doesn't start — leave that to the operator) the
# daemon service so it comes up on next boot. Reloads systemd
# so the new unit file is visible. Triggers modules-load so the
# kernel module loads without a reboot if daedalus-v4l2-dkms is
# also installed.
_activate() {
systemctl daemon-reload >/dev/null 2>&1 || true
systemctl enable daedalus-v4l2.service >/dev/null 2>&1 || true
# Trigger /usr/lib/modules-load.d/daedalus-v4l2.conf without a
# reboot. Safe if the module is already loaded.
systemd-modules-load >/dev/null 2>&1 || true
cat >&2 <<EOF
==> daedalus-v4l2: service enabled, will start on next boot.
==> To start now (requires the kernel module to be loaded):
==> sudo systemctl start daedalus-v4l2.service
==> Verify decode path:
==> journalctl -u daedalus-v4l2.service -f
EOF
}
post_install() {
_activate
}
post_upgrade() {
_activate
systemctl try-restart daedalus-v4l2.service >/dev/null 2>&1 || true
}
pre_remove() {
systemctl stop daedalus-v4l2.service >/dev/null 2>&1 || true
systemctl disable daedalus-v4l2.service >/dev/null 2>&1 || true
}
post_remove() {
systemctl daemon-reload >/dev/null 2>&1 || true
}
@@ -0,0 +1,178 @@
From 0cd6e669735e453ec8772f111065bbb2f70a5bc6 Mon Sep 17 00:00:00 2001
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Mon, 18 May 2026 07:27:10 +0000
Subject: [PATCH] avutil/hwcontext_v4l2request: unpack NV15 to P010 in
transfer_data_from
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
V4L2_PIX_FMT_NV15 (RK3399/RK3588 rkvdec 10-bit 4:2:0 capture) is mapped to
sw_format = AV_PIX_FMT_YUV420P10 in v4l2request_capture_pixelformats[]. The
existing transfer_get_formats explicitly blanked the format list for that
sw_format, so 'ffmpeg -hwaccel v4l2request -vf hwdownload,format=p010le' on
a Hi10P / Main10 input failed at filter init with EINVAL before reaching
the actual decode (which itself succeeds — 2 frames decoded cleanly).
Expose AV_PIX_FMT_P010 as the transfer target for NV15-backed surfaces and
unpack the packed 10-bit samples into the standard high-bits-of-16 layout
inside transfer_data_from. Luma and chroma share the same packing format
(5 bytes per 4 samples, little endian); chroma plane is W × H/2 samples
for 4:2:0.
The other 'needs custom unpack' sw_formats (YUV420P / Allwinner NV12_32L32
tiled and YUV422P10 / rkvdec NV20) keep the original ENOSYS path because
they need different unpack code that isn't covered by this patch.
Closes marfrit/marfrit-packages#21.
---
libavutil/hwcontext_v4l2request.c | 111 +++++++++++++++++++++++++++++-
1 file changed, 110 insertions(+), 1 deletion(-)
diff --git a/libavutil/hwcontext_v4l2request.c b/libavutil/hwcontext_v4l2request.c
index b6633d9081..3842160dfb 100644
--- a/libavutil/hwcontext_v4l2request.c
+++ b/libavutil/hwcontext_v4l2request.c
@@ -1073,6 +1073,56 @@ fail:
return ret;
}
+/*
+ * Unpack one NV15-packed 10-bit plane (5 bytes per 4 samples, little endian)
+ * into a P010-style plane (10 bits in the high bits of a 16-bit container).
+ * `dst_stride` is in bytes; `src_stride` is bytes per row of NV15 data.
+ */
+static void v4l2request_nv15_unpack_plane_to_p010(const uint8_t *src,
+ uint16_t *dst,
+ unsigned width,
+ unsigned height,
+ unsigned src_stride,
+ unsigned dst_stride)
+{
+ for (unsigned y = 0; y < height; y++) {
+ const uint8_t *s = src + y * src_stride;
+ uint16_t *d = (uint16_t *)((uint8_t *)dst + y * dst_stride);
+ unsigned x;
+
+ for (x = 0; x + 4 <= width; x += 4) {
+ uint16_t a = (uint16_t)s[0] | ((uint16_t)(s[1] & 0x03) << 8);
+ uint16_t b = ((uint16_t)s[1] >> 2) | ((uint16_t)(s[2] & 0x0F) << 6);
+ uint16_t c = ((uint16_t)s[2] >> 4) | ((uint16_t)(s[3] & 0x3F) << 4);
+ uint16_t e = ((uint16_t)s[3] >> 6) | ((uint16_t)s[4] << 2);
+
+ d[0] = (uint16_t)(a << 6);
+ d[1] = (uint16_t)(b << 6);
+ d[2] = (uint16_t)(c << 6);
+ d[3] = (uint16_t)(e << 6);
+
+ d += 4;
+ s += 5;
+ }
+
+ if (x < width) {
+ unsigned rem = width - x;
+ uint16_t pix[4] = { 0, 0, 0, 0 };
+
+ pix[0] = (uint16_t)s[0] | ((uint16_t)(s[1] & 0x03) << 8);
+ if (rem >= 2)
+ pix[1] = ((uint16_t)s[1] >> 2) | ((uint16_t)(s[2] & 0x0F) << 6);
+ if (rem >= 3)
+ pix[2] = ((uint16_t)s[2] >> 4) | ((uint16_t)(s[3] & 0x3F) << 4);
+ if (rem >= 4)
+ pix[3] = ((uint16_t)s[3] >> 6) | ((uint16_t)s[4] << 2);
+
+ for (unsigned j = 0; j < rem; j++)
+ d[j] = (uint16_t)(pix[j] << 6);
+ }
+ }
+}
+
static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
enum AVHWFrameTransferDirection dir,
enum AVPixelFormat **formats)
@@ -1082,6 +1132,22 @@ static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
if (dir == AV_HWFRAME_TRANSFER_DIRECTION_TO)
return AVERROR(ENOSYS);
+ /*
+ * NV15-backed surfaces (sw_format = YUV420P10) are exposed as P010 to
+ * downstream filters: the unpack below converts the packed 10-bit
+ * samples into the standard high-bits-of-16 layout. Hi10P / Main10
+ * VAAPI/v4l2-request decode reaches userspace through this path.
+ */
+ if (hwfc->sw_format == AV_PIX_FMT_YUV420P10) {
+ fmts = av_malloc_array(2, sizeof(*fmts));
+ if (!fmts)
+ return AVERROR(ENOMEM);
+ fmts[0] = AV_PIX_FMT_P010;
+ fmts[1] = AV_PIX_FMT_NONE;
+ *formats = fmts;
+ return 0;
+ }
+
fmts = av_malloc_array(2, sizeof(*fmts));
if (!fmts)
return AVERROR(ENOMEM);
@@ -1089,8 +1155,13 @@ static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
fmts[0] = hwfc->sw_format;
fmts[1] = AV_PIX_FMT_NONE;
+ /*
+ * Tiled-NV12-32L32 (Allwinner) and NV20 (rkvdec 4:2:2 10-bit) still need
+ * dedicated unpacks before hwdownload can consume them; leave them as
+ * "no transfer formats" so the filter graph reports the limitation
+ * rather than silently producing garbage.
+ */
if (hwfc->sw_format == AV_PIX_FMT_YUV420P ||
- hwfc->sw_format == AV_PIX_FMT_YUV420P10 ||
hwfc->sw_format == AV_PIX_FMT_YUV422P10)
fmts[0] = AV_PIX_FMT_NONE;
@@ -1110,6 +1181,44 @@ static int v4l2request_transfer_data_from(AVHWFramesContext *hwfc,
map = av_frame_alloc();
if (!map)
return AVERROR(ENOMEM);
+
+ /*
+ * For NV15→P010, map the raw NV15 bytes (sw_format) and unpack into
+ * dst's P010 storage. Otherwise fall through to the original byte-copy
+ * path used for 1:1 sw_format matches (NV12, NV16, AFBC handled by DRM).
+ */
+ if (hwfc->sw_format == AV_PIX_FMT_YUV420P10) {
+ /*
+ * Only P010 is advertised by transfer_get_formats for this sw_format;
+ * a caller that bypasses get_formats and asks for anything else would
+ * silently corrupt output via av_frame_copy on NV15-packed bytes.
+ * Reject explicitly.
+ */
+ if (dst->format != AV_PIX_FMT_P010) {
+ ret = AVERROR(ENOSYS);
+ goto fail;
+ }
+
+ map->format = hwfc->sw_format;
+ ret = v4l2request_map_frame(hwfc, map, src);
+ if (ret)
+ goto fail;
+
+ v4l2request_nv15_unpack_plane_to_p010(map->data[0],
+ (uint16_t *)dst->data[0],
+ dst->width, dst->height,
+ map->linesize[0],
+ dst->linesize[0]);
+ /* NV15 chroma plane is W × H/2 samples (4:2:0, UV interleaved). */
+ v4l2request_nv15_unpack_plane_to_p010(map->data[1],
+ (uint16_t *)dst->data[1],
+ dst->width, dst->height / 2,
+ map->linesize[1],
+ dst->linesize[1]);
+ ret = 0;
+ goto fail;
+ }
+
map->format = dst->format;
ret = v4l2request_map_frame(hwfc, map, src);
--
2.47.3
@@ -24,7 +24,7 @@ _srcname=FFmpeg
_version='8.1' _version='8.1'
_commit='b57fbbe50c9b2656fad86a1a7eeabfd2b2a50935' # v4l2-request-n8.1 tip 2026-04-24 _commit='b57fbbe50c9b2656fad86a1a7eeabfd2b2a50935' # v4l2-request-n8.1 tip 2026-04-24
pkgver=8.1.r123329.b57fbbe pkgver=8.1.r123329.b57fbbe
pkgrel=4 pkgrel=5
epoch=2 epoch=2
pkgdesc='FFmpeg with V4L2 Request API hwaccel (Rockchip / Allwinner stateless decode)' pkgdesc='FFmpeg with V4L2 Request API hwaccel (Rockchip / Allwinner stateless decode)'
arch=('aarch64') arch=('aarch64')
@@ -78,8 +78,9 @@ provides=(
conflicts=(ffmpeg) conflicts=(ffmpeg)
replaces=(ffmpeg ffmpeg-v4l2-request-git) replaces=(ffmpeg ffmpeg-v4l2-request-git)
source=("git+https://github.com/Kwiboo/FFmpeg.git#commit=${_commit}" source=("git+https://github.com/Kwiboo/FFmpeg.git#commit=${_commit}"
'0001-libudev-bypass-fallback.patch') '0001-libudev-bypass-fallback.patch'
sha256sums=('SKIP' 'SKIP') '0002-nv15-to-p010-unpack.patch')
sha256sums=('SKIP' 'SKIP' 'SKIP')
pkgver() { pkgver() {
cd "${_srcname}" cd "${_srcname}"
@@ -91,6 +92,7 @@ pkgver() {
prepare() { prepare() {
cd "${_srcname}" cd "${_srcname}"
patch -Np1 -i "${srcdir}/0001-libudev-bypass-fallback.patch" patch -Np1 -i "${srcdir}/0001-libudev-bypass-fallback.patch"
patch -Np1 -i "${srcdir}/0002-nv15-to-p010-unpack.patch"
} }
build() { build() {
+32 -2
View File
@@ -13,7 +13,7 @@
pkgname=firefox-fourier pkgname=firefox-fourier
pkgver=150.0.1 pkgver=150.0.1
pkgrel=1 pkgrel=7
pkgdesc='Firefox with V4L2 stateless HW video decode unlocked for mainline Linux Rockchip' pkgdesc='Firefox with V4L2 stateless HW video decode unlocked for mainline Linux Rockchip'
arch=('aarch64' 'x86_64') arch=('aarch64' 'x86_64')
url='https://www.mozilla.org/firefox' url='https://www.mozilla.org/firefox'
@@ -87,8 +87,15 @@ source=(
'0002-libwrapper-hwdevice-ctx-create.patch' '0002-libwrapper-hwdevice-ctx-create.patch'
'0003-ffmpegvideo-v4l2-request-route.patch' '0003-ffmpegvideo-v4l2-request-route.patch'
'0004-prefs-v4l2-request.patch' '0004-prefs-v4l2-request.patch'
'0005-rdd-sandbox-v4l2-media-ctl.patch'
# Vendor-default prefs that gate the patched VAAPI path on RK3399 —
# widget.dmabuf.force-enabled etc. See marfrit-packages#8 for evidence.
'rockchip-fourier-defaults.js'
# Plasma/GNOME start-menu entry — categorises under Internet, picks the
# 128px firefox icon shipped under /usr/lib/firefox-fourier/browser/.
'firefox-fourier.desktop'
) )
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP') sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
prepare() { prepare() {
cd "${srcdir}/firefox-${pkgver}" cd "${srcdir}/firefox-${pkgver}"
@@ -103,6 +110,7 @@ prepare() {
patch -Np1 -i "${srcdir}/0002-libwrapper-hwdevice-ctx-create.patch" patch -Np1 -i "${srcdir}/0002-libwrapper-hwdevice-ctx-create.patch"
patch -Np1 -i "${srcdir}/0003-ffmpegvideo-v4l2-request-route.patch" patch -Np1 -i "${srcdir}/0003-ffmpegvideo-v4l2-request-route.patch"
patch -Np1 -i "${srcdir}/0004-prefs-v4l2-request.patch" patch -Np1 -i "${srcdir}/0004-prefs-v4l2-request.patch"
patch -Np1 -i "${srcdir}/0005-rdd-sandbox-v4l2-media-ctl.patch"
cp "${srcdir}/mozconfig" .mozconfig cp "${srcdir}/mozconfig" .mozconfig
} }
@@ -160,4 +168,26 @@ export MOZ_X11_EGL="${MOZ_X11_EGL:-1}"
exec /usr/lib/firefox-fourier/firefox-fourier "$@" exec /usr/lib/firefox-fourier/firefox-fourier "$@"
LAUNCHER LAUNCHER
chmod 0755 "${pkgdir}/usr/bin/firefox-fourier" chmod 0755 "${pkgdir}/usr/bin/firefox-fourier"
# Vendor-default prefs (RK3399 HW-decode unlock) — closes #8.
# Lower precedence than user prefs / about:config; loaded by Firefox
# at startup from the package install dir. The 0004 patch covers
# media.ffmpeg.v4l2-request.enabled; this file covers the three
# additional prefs that gate the path to the patched code.
# Vendor-prefs install path: /usr/lib/firefox-fourier/defaults/preferences/
# (Mozilla's canonical scan dir for third-party default-pref drops.) The
# browser/defaults/preferences/ alternative looked promising but is NOT a
# vendor-prefs scan location in Firefox 150 — empirically confirmed on
# fresnel: file shipped there, VAAPI never engaged. Same file under
# defaults/preferences/ → MOZ_LOG showed `Requesting pixel format
# VAAPI_VLD` + dmabuf surfaces locking end-to-end.
install -Dm644 "${srcdir}/rockchip-fourier-defaults.js" \
"${pkgdir}/usr/lib/firefox-fourier/defaults/preferences/rockchip-fourier-defaults.js"
# Desktop entry — fileless install would leave the package without a
# start-menu entry (stock firefox.desktop disappears when our `provides`
# replaces stock firefox). Plasma & GNOME pick this up via the
# `Categories=Network;WebBrowser;` line → "Internet" submenu.
install -Dm644 "${srcdir}/firefox-fourier.desktop" \
"${pkgdir}/usr/share/applications/firefox-fourier.desktop"
} }
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Hochheiden <ahochheiden@mozilla.com>
Date: Wed, 1 Apr 2026 18:11:37 +0000
Subject: [PATCH] Bug 2023597 - Use `wasm32-wasip1` target for clang >= 22.1
r=firefox-build-system-reviewers,sergesanspaille
https://github.com/llvm/llvm-project/pull/165345
https://releases.llvm.org/22.1.0/tools/clang/docs/ReleaseNotes.html
Differential Revision: https://phabricator.services.mozilla.com/D291023
---
build/moz.configure/toolchain.configure | 3 +++
1 file changed, 3 insertions(+)
diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
index a37ed610cc43..c7d0c8bdf75c 100644
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -695,6 +695,9 @@ def check_compiler(configure_cache, compiler, language, target, android_version)
# This makes clang define __ANDROID_API__ and use versioned library
# directories from the NDK.
toolchain = "%s%d" % (target.toolchain, android_version)
+ elif target.kernel == "WASI" and info.type == "clang" and info.version >= Version("22.1"):
+ # The wasm32-wasi target was renamed to wasm32-wasip1 in LLVM 22.1.
+ toolchain = "wasm32-wasip1"
else:
toolchain = target.toolchain
@@ -0,0 +1,22 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=Firefox (Fourier — V4L2 HW decode)
GenericName=Web Browser
Comment=Browse the Web with V4L2 stateless HW video decode (RK3588/RK3566)
Exec=/usr/bin/firefox-fourier %u
Icon=/usr/lib/firefox-fourier/browser/chrome/icons/default/default128.png
Terminal=false
StartupNotify=true
StartupWMClass=firefox-fourier
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;image/svg+xml;image/webp;image/avif;application/json;application/pdf;audio/flac;audio/ogg;audio/webm;video/ogg;video/webm;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/chrome;x-scheme-handler/mailto;
Actions=new-window;new-private-window;
[Desktop Action new-window]
Name=Open a New Window
Exec=/usr/bin/firefox-fourier --new-window %u
[Desktop Action new-private-window]
Name=Open a New Private Window
Exec=/usr/bin/firefox-fourier --private-window %u
+17
View File
@@ -34,3 +34,20 @@ ac_add_options --with-distribution-id=de.reauktion.fourier
# Reduce build memory pressure on aarch64 — parallel link is heavy. # Reduce build memory pressure on aarch64 — parallel link is heavy.
mk_add_options MOZ_PARALLEL_BUILD=8 mk_add_options MOZ_PARALLEL_BUILD=8
# Explicit distcc routing. fermi's makepkg.conf has
# BUILDENV=(distcc ...) which auto-prepends /usr/lib/distcc/bin to
# $PATH, but mach's configure picks up CC/CXX from the env directly
# and the distcc wrappers won't fire unless we set them. Mirrors the
# ffmpeg-v4l2-request-fourier pattern.
#
# Note: only the C/C++ portion of the build distributes; rustc and
# the host-only build steps stay local. Empirically that's still a
# 30-40% wall-clock win on a 4-worker pool. DISTCC_HOSTS comes from
# makepkg.conf ('+zeroconf' by default — Avahi-discovers tesla,
# dcc1, dcc2, ampere).
if [[ ":${PATH}:" == *":/usr/lib/distcc/bin:"* ]]; then
export CC="distcc gcc"
export CXX="distcc g++"
fi
@@ -0,0 +1,19 @@
// firefox-fourier — RK3399 V4L2-stateless HW-decode default prefs.
//
// The patch series (0001..0004) builds the VAAPI / V4L2-request routing
// path through libavcodec, but the resulting code path is gated by three
// other prefs that are 'false' upstream because the relevant probes don't
// fire on panfrost EGL or trip the Intel-tuned cost heuristic. Without
// these, firefox-fourier silently SW-decodes on a fresh profile despite
// having all the unlock patches applied.
//
// Filed via marfrit/marfrit-packages#8 — see that issue for MOZ_LOG
// evidence on fresnel (Pinebook Pro / RK3399).
//
// These are *vendor* defaults: lower precedence than user.js and
// about:config user prefs. Power users who want to disable HW decode for
// debugging can flip them in user prefs without touching this file.
pref("widget.dmabuf.force-enabled", true);
pref("media.hardware-video-decoding.force-enabled", true);
pref("media.ffvpx-hw.enabled", true);
+4 -4
View File
@@ -2,7 +2,7 @@
# Upstream maintainers: Felix Yan, Antonio Rojas # Upstream maintainers: Felix Yan, Antonio Rojas
# Contributor: Andrea Scarpino <andrea@archlinux.org> # Contributor: Andrea Scarpino <andrea@archlinux.org>
# #
# kwin-fourier — KWin 6.6.4 with the V4L2-stateless implicit-sync # kwin-fourier — KWin 6.6.5 with the V4L2-stateless implicit-sync
# transaction wait bypass. Hypothesis: KWin's # transaction wait bypass. Hypothesis: KWin's
# `Transaction::watchDmaBuf` calls DMA_BUF_IOCTL_EXPORT_SYNC_FILE on # `Transaction::watchDmaBuf` calls DMA_BUF_IOCTL_EXPORT_SYNC_FILE on
# every plane of every imported dmabuf and parks the transaction on a # every plane of every imported dmabuf and parks the transaction on a
@@ -21,9 +21,9 @@
# ../chromium-fourier/KWIN_PIVOT.md for the full diagnosis thread. # ../chromium-fourier/KWIN_PIVOT.md for the full diagnosis thread.
pkgname=kwin-fourier pkgname=kwin-fourier
pkgver=6.6.4 pkgver=6.6.5
_dirver=$(echo $pkgver | cut -d. -f1-3) _dirver=$(echo $pkgver | cut -d. -f1-3)
pkgrel=3 pkgrel=1
_upname=kwin _upname=kwin
epoch=1 epoch=1
arch=(aarch64 x86_64) arch=(aarch64 x86_64)
@@ -103,7 +103,7 @@ conflicts=(kwin)
replaces=(kwin) replaces=(kwin)
source=(https://download.kde.org/stable/plasma/$_dirver/$_upname-$pkgver.tar.xz{,.sig} source=(https://download.kde.org/stable/plasma/$_dirver/$_upname-$pkgver.tar.xz{,.sig}
0001-transaction-bypass-watchDmaBuf-fence-wait.patch) 0001-transaction-bypass-watchDmaBuf-fence-wait.patch)
sha256sums=('3f9439760580a977d018daf4b35b62e5a1700def7b21c8dfbfc789d21378d7ad' sha256sums=('6c187ce7a5506090b438ef900103836fa0537674dde8b31e5b497ef321643cb4'
'SKIP' 'SKIP'
'SKIP') 'SKIP')
validpgpkeys=('E0A3EB202F8E57528E13E72FD7574483BB57B18D' # Jonathan Esk-Riddell <jr@jriddell.org> validpgpkeys=('E0A3EB202F8E57528E13E72FD7574483BB57B18D' # Jonathan Esk-Riddell <jr@jriddell.org>
+31 -11
View File
@@ -6,8 +6,11 @@
# tracks the campaign fork's git history directly, so iteration sweeps # tracks the campaign fork's git history directly, so iteration sweeps
# (DEBUG removal, follow-up bugfixes) land in a clean linear log. # (DEBUG removal, follow-up bugfixes) land in a clean linear log.
# #
# Campaign: ~/src/libva-multiplanar/ (eight closed iterations as of # Campaign: ~/src/libva-multiplanar/ (iter8 close 2026-05-06) plus
# 2026-05-06; iter8 close is the production tip pinned below). # ~/src/fresnel-fourier/ which carried the fork to iter38b — multi-device
# probe so a single libva session serves all 5 codecs (rkvdec H.264 +
# HEVC + VP9, hantro MPEG-2 + VP8) plus a bounds-check fix for
# MAX_PROFILES. Pinned below.
# Fork repo: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier # Fork repo: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
# Bootlin upstream: https://github.com/bootlin/libva-v4l2-request # Bootlin upstream: https://github.com/bootlin/libva-v4l2-request
# #
@@ -20,16 +23,25 @@
pkgname=libva-v4l2-request-fourier pkgname=libva-v4l2-request-fourier
_upstreampkg=libva-v4l2-request _upstreampkg=libva-v4l2-request
# Pin the fork tip. 65969da = "iter8 Phase 4: tests/run_perf_binding_cell.sh" # Pin the fork tip. de27e95 = "v4l2: log error_idx + failing ctrl id
# — last commit on master before fresnel-fourier work started layering # on S_EXT_CTRLS failure" — Phase 8.13 diagnostic that surfaced the
# MPEG-2 rewrites on top of it (2026-05-08). The libva-multiplanar campaign # real root cause of the libva→daedalus_v4l2 request-completion
# closed iter8 at this commit; promote to a later pin only after a future # timeout (turned out the EINVAL libva was logging was a harmless
# iteration closes cleanly. # H264/HEVC probe; actual VP9 stateless control SET worked all along).
_commit=65969da3ee901442a8ca4e1f7f9697d5461d368a #
# Prior pin (7ac934e) was iter38b — fresnel-fourier multi-device probe
# + MAX_PROFILES bounds-check fix. de27e95 adds the daedalus_v4l2
# probe slot (b5b3acf), the meson option gate (2146341), and the
# S_EXT_CTRLS diagnostic (de27e95 itself). Backward-compatible on
# rkvdec / hantro / cedrus / rpi-hevc-dec hosts — daedalus probe is
# off by default unless the kernel module is present.
_commit=de27e95571b67ef34619c23a12db4698f9b3454e
# Project version from meson.build (1.0.0) + commit count + short sha, # Project version from meson.build (1.0.0) + commit count + short sha,
# matching the ffmpeg-v4l2-request-fourier convention. # matching the ffmpeg-v4l2-request-fourier convention. Recomputed at
pkgver=1.0.0.r280.65969da # build time by pkgver() below; the static value here is a placeholder
# so AUR-style consumers see something coherent before src/ exists.
pkgver=1.0.0.r376.de27e95
pkgrel=1 pkgrel=1
pkgdesc="VA-API backend for V4L2 stateless decoders (multiplanar fork — fourier umbrella)" pkgdesc="VA-API backend for V4L2 stateless decoders (multiplanar fork — fourier umbrella)"
arch=('aarch64') arch=('aarch64')
@@ -55,7 +67,15 @@ build() {
cd "${srcdir}/${_upstreampkg}-fourier" cd "${srcdir}/${_upstreampkg}-fourier"
# meson_options.txt only exposes 'kernel_headers' — leave it empty to # meson_options.txt only exposes 'kernel_headers' — leave it empty to
# use system /usr/include kernel UAPI headers. No per-codec toggles. # use system /usr/include kernel UAPI headers. No per-codec toggles.
arch-meson build --buildtype=release #
# b_lto=false: override arch-meson's wrapper default of `-D b_lto=true`,
# which the makepkg.conf OPTIONS=(..., !lto, ...) line does NOT actually
# override (arch-meson hard-codes b_lto=true). The hand-built reproducer
# from issue #17 shows: LTO/ICF kernel-folds per-codec helpers and HEVC's
# multi-control-struct chain (SPS+PPS+DECODE_PARAMS+SLICE_PARAMS) gets a
# wrong helper-instance pulled in at vaEndPicture → segfault. The 4 other
# codecs (single-control-struct) tolerate the folding by accident.
arch-meson build --buildtype=release -Db_lto=false
meson compile -C build meson compile -C build
} }
+8 -1
View File
@@ -1,6 +1,13 @@
# Maintainer: Markus Fritsche <fritsche.markus@gmail.com> # Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
# Campaign: ohm_gl_fix Phase 6 Step 1 # Campaign: ohm_gl_fix Phase 6 Step 1
# #
# DEPRECATED (2026-05-16): superseded by ../libva-v4l2-request-fourier/
# which tracks the campaign fork's git history directly and adds the
# iter38 multi-device probe (single libva session for rkvdec H.264/HEVC/VP9
# + hantro MPEG-2/VP8). The successor declares
# replaces=('libva-v4l2-request-ohm-gl-fix'), so installing it removes
# this package automatically. See README.md for the full deprecation note.
#
# Forks libva-v4l2-request to add hantro-vpu multiplanar + modern # Forks libva-v4l2-request to add hantro-vpu multiplanar + modern
# stateless UAPI support. Conflicts/replaces stock libva-v4l2-request. # stateless UAPI support. Conflicts/replaces stock libva-v4l2-request.
# #
@@ -11,7 +18,7 @@ pkgname=libva-v4l2-request-ohm-gl-fix
_upstreampkg=libva-v4l2-request _upstreampkg=libva-v4l2-request
pkgver=1.0.0.r0.ga3c2476 pkgver=1.0.0.r0.ga3c2476
pkgrel=2 pkgrel=2
pkgdesc="VA-API backend for V4L2 stateless decoders, hantro-vpu multiplanar fork" pkgdesc="DEPRECATED — use libva-v4l2-request-fourier. VA-API backend for V4L2 stateless decoders, hantro-vpu multiplanar fork"
arch=('aarch64') arch=('aarch64')
url="https://github.com/bootlin/libva-v4l2-request" url="https://github.com/bootlin/libva-v4l2-request"
license=('LGPL2.1' 'MIT') license=('LGPL2.1' 'MIT')
@@ -1,5 +1,24 @@
# libva-v4l2-request-ohm-gl-fix # libva-v4l2-request-ohm-gl-fix
> ## ⚠ DEPRECATED — use [`libva-v4l2-request-fourier`](../libva-v4l2-request-fourier/) instead
>
> This package is the **predecessor experimental** build (tarball pin
> + 18 stacked patches) and is no longer maintained as of 2026-05-16.
> Its successor `libva-v4l2-request-fourier` tracks the campaign fork's
> git history directly
> ([git.reauktion.de/marfrit/libva-v4l2-request-fourier](https://git.reauktion.de/marfrit/libva-v4l2-request-fourier))
> so iteration sweeps (DEBUG removal, follow-up bugfixes) land in a clean
> linear log, and adds the iter38 multi-device probe that lets a single
> libva session serve rkvdec H.264/HEVC/VP9 + hantro MPEG-2/VP8 without
> needing `LIBVA_V4L2_REQUEST_VIDEO_PATH` overrides.
>
> `libva-v4l2-request-fourier` declares
> `replaces=('libva-v4l2-request-ohm-gl-fix')`, so installing it will
> remove this package automatically. Kept in-tree as historical reference
> for the ohm_gl_fix Phase 6 audit trail.
---
Bootlin's libva-v4l2-request VA-API backend, with hantro-vpu Bootlin's libva-v4l2-request VA-API backend, with hantro-vpu
multi-planar + chromium-149-era stateless H.264 patches developed multi-planar + chromium-149-era stateless H.264 patches developed
in the [ohm_gl_fix campaign](../../../ohm_gl_fix/) Phase 6 Step 1 in the [ohm_gl_fix campaign](../../../ohm_gl_fix/) Phase 6 Step 1
+168
View File
@@ -0,0 +1,168 @@
# Maintainer: Markus Fritsche <mfritsche@reauktion.de>
#
# linux-ampere-fourier — CoolPi GenBook (RK3588) kernel built from the
# kernel-agent fleet/ampere.yaml manifest applied to mainline v7.0-rc3.
#
# kafr2 baseline (2026-05-18): mainline v7.0-rc3 + the 10 scope-tagged
# kernel-agent patches under patches/{soc,module,board,driver}/:
# - 1 soc/rk3588 pwm15 pinctrl
# - 6 board/coolpi-cm5-genbook DTS patches (pwm-fan, RK806 power-off,
# speaker, USB-C PD, lid switch + USB3 PHY, microphone)
# - 3 driver/media VP9-on-VDPU381 patches (Sarma's v8 series, imported
# via marfrit/kernel-agent#12 closure and PR #24)
#
# Drops the prior f8f3ad9 baseline ("18 commits ahead") because that tip
# black-screens ampere — kernel-agent's ka-promote produces this 10-patch
# minimal set from fleet/ampere.yaml. End-to-end VP9 + AV1 (av1-vpu-dec
# is mainline-7.0) decode verified bit-exact via kdirect on the
# hand-built tip 48a8c78 before this package iteration was cut.
#
# Coexists with the user's other extlinux labels in
# /boot/firmware/extlinux/extlinux.conf; never edits them. Adds a
# managed `linux-ampere-fourier` label (the user sets `default` manually
# after verifying boot).
#
# Bootloader path: /boot/firmware/ (vfat on mmcblk0p1). Kernel +
# initramfs + DTB land there directly. Reverting = boot a different
# extlinux label (e.g. arch_mainline, ubuntu_mainline).
pkgbase=linux-ampere-fourier
pkgname=("$pkgbase" "$pkgbase-headers")
pkgver=7.0rc3.kafr2
pkgrel=1
pkgdesc='CoolPi GenBook kernel (v7.0-rc3 + kernel-agent fleet/ampere.yaml — 6 board patches + 3 VP9-VDPU381 + 1 pwm15)'
arch=(aarch64)
url='https://git.reauktion.de/marfrit/kernel-agent'
license=(GPL-2.0-only)
makedepends=(
bc cpio gettext kmod libelf pahole perl python tar xz
ccache
uboot-tools dtc
)
options=('!strip')
# Pinned tip of the kernel-agent-managed source tree for ampere.
# 10 commits ahead of v7.0-rc3, exactly mirroring fleet/ampere.yaml's
# manifest under apply order:
# - c57d069 soc/rk3588: pwm15 pinctrl entries
# - 05a915c board/genbook: pwm-fan with thermal cooling
# - d007b90 module/coolpi-cm5: RK806 system-power-controller
# - 3722eab board/genbook: speaker via audio-graph-card
# - 3e42ab6 board/genbook: USB-C PD via FUSB302
# - 7c241f2 board/genbook: lid switch + USB3 PHY lane
# - dd545fa board/genbook: wire internal microphone
# - 9ddcae5 driver/media: rkvdec-vp9 helper rename (Sarma)
# - c5063d9 driver/media: rkvdec move vp9 to common (Sarma)
# - 48a8c78 driver/media: rkvdec VP9 for VDPU381 (Sarma)
#
# This is the same tree state ka-promote ampere produces as cumulative.patch
# (see marfrit/kernel-agent build/ampere/v7.0-rc3/manifest.lock for the
# b2sum + per-patch sha256s).
_commit=48a8c785de7f5320513052a64e544c6310d7b273
source=(
# Local tarball produced by ./prebuild.sh from a local clone of the
# linux-rk3588-marfrit branch. Not fetched from a URL because the
# boltzmann working clone is shallow (gitea push rejects) and the
# 260MB tarball isn't committed to marfrit-packages. Run prebuild.sh
# before makepkg; see README in this dir.
"linux-rk3588-marfrit-${_commit:0:7}.tar.gz"
'config' # snapshot of running ampere kernel's /proc/config.gz (7.0.0-rc3-ARCH+)
'linux-ampere-fourier.preset'
'extlinux-add.hook'
'extlinux-add.sh'
)
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
# kernelrelease becomes <Makefile-VERSION>.<PATCH>.<SUBLEVEL><EXTRAVERSION><LOCALVERSION>
# i.e. 7.0.0-rc3-ampere-fourier. Module dir + EXTRAVERSION suffix keep
# this disjoint from the hand-managed /boot/firmware/Image-7.0.0-rc3-ARCH+
# that's currently on the host.
_kernver=7.0.0-rc3-ampere-fourier
_srcdir=linux-rk3588-marfrit
prepare() {
cd "${_srcdir}"
echo ":: writing config"
cp "${srcdir}/config" .config
# LOCALVERSION suffix to differentiate from upstream-stock builds.
scripts/config --set-str LOCALVERSION "-ampere-fourier"
scripts/config -d LOCALVERSION_AUTO
echo ":: olddefconfig (accept new symbols sensibly)"
make olddefconfig
make -s kernelrelease > version
echo ":: kernel release: $(<version)"
}
build() {
cd "${_srcdir}"
unset LDFLAGS
# Native build only — no distcc per kernel-agent policy
# (feedback_kernel_agent_no_distcc.md). ccache stays.
export CC="ccache gcc"
export HOSTCC="ccache gcc"
make ${MAKEFLAGS:--j$(nproc)} Image modules dtbs
}
_package() {
pkgdesc='CoolPi GenBook overclocked kernel (ampere-fourier baseline)'
depends=(coreutils kmod mkinitcpio uboot-tools)
optdepends=('linux-firmware: firmware images needed for some devices')
backup=("etc/mkinitcpio.d/${pkgbase}.preset")
cd "${_srcdir}"
local _kver
_kver=$(<version)
# Kernel image into the vfat firmware partition (where extlinux looks).
install -Dm644 arch/arm64/boot/Image \
"${pkgdir}/boot/firmware/Image-ampere-fourier"
# Single DTB for the GenBook target — install directly under
# /boot/firmware/ (no subdir, matches existing host convention).
install -Dm644 arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dtb \
"${pkgdir}/boot/firmware/rk3588-coolpi-cm5-genbook.dtb-ampere-fourier"
ZSTD_CLEVEL=19 make INSTALL_MOD_PATH="${pkgdir}/usr" \
INSTALL_MOD_STRIP=1 modules_install
rm -f "${pkgdir}/usr/lib/modules/${_kver}/"{source,build}
install -Dm644 "${srcdir}/${pkgbase}.preset" \
"${pkgdir}/etc/mkinitcpio.d/${pkgbase}.preset"
install -Dm755 "${srcdir}/extlinux-add.hook" \
"${pkgdir}/usr/share/libalpm/hooks/95-${pkgbase}-extlinux.hook"
install -Dm755 "${srcdir}/extlinux-add.sh" \
"${pkgdir}/usr/share/libalpm/scripts/${pkgbase}-extlinux"
}
_package-headers() {
pkgdesc='Headers and scripts for the linux-ampere-fourier kernel'
depends=(pahole)
cd "${_srcdir}"
local _kver _builddir
_kver=$(<version)
_builddir="${pkgdir}/usr/lib/modules/${_kver}/build"
install -Dt "${_builddir}" -m644 .config Makefile Module.symvers System.map vmlinux version
install -Dt "${_builddir}/kernel" -m644 kernel/Makefile
cp -a scripts "${_builddir}"
install -Dt "${_builddir}/arch/arm64" -m644 arch/arm64/Makefile
cp -a arch/arm64/include "${_builddir}/arch/arm64/"
cp -a include "${_builddir}/"
find . -name 'Kbuild' -exec install -Dm644 {} "${_builddir}/{}" \;
find . -name 'Kconfig*' -exec install -Dm644 {} "${_builddir}/{}" \;
install -d "${pkgdir}/usr/src"
ln -sr "${_builddir}" "${pkgdir}/usr/src/${pkgbase}"
}
eval "package_${pkgbase}() { _package; }"
eval "package_${pkgbase}-headers() { _package-headers; }"
+70
View File
@@ -0,0 +1,70 @@
# linux-ampere-fourier
Kernel package for ampere (CoolPi GenBook RK3588). Baselined on
`marfrit/linux-rk3588-marfrit @ f8f3ad9` (mainline v7.0-rc3 + 18
RK3588-fleet-relevant commits — 10 Markus, 8 upstream cherry-picks).
See `marfrit/kernel-agent/fleet/ampere.yaml` for the manifest +
`marfrit/kernel-agent/patches/{soc,module,board}/...` for the
scope-tagged board patches in the baseline.
## Build
The kernel source isn't on Gitea — boltzmann's working clone is
shallow (Gitea refuses shallow pushes) and a 260MB tarball doesn't
belong in `marfrit-packages`. Stage the source locally from a
clone of the `linux-rk3588-marfrit` branch:
```sh
cd arch/linux-ampere-fourier
./prebuild.sh # produces linux-rk3588-marfrit-f8f3ad9.tar.gz
makepkg -s --noconfirm # native aarch64 build; no distcc
```
`prebuild.sh` looks at `$LINUX_RK3588_MARFRIT_TREE` (default
`~/src/linux-rockchip`) for the kernel working tree. The tip commit
must be reachable in that clone — fetch the `linux-rk3588-marfrit`
branch first if you cloned from elsewhere.
## Build hosts
Native aarch64 only (per kernel-agent `feedback_kernel_agent_no_distcc.md`).
Either ampere itself (8C/2.4GHz, 32GB, native arch) or boltzmann
(Rock 5 ITX+, same uarch). fermi as fallback.
## Install
Adds a managed label to `/boot/firmware/extlinux/extlinux.conf`:
```
label linux-ampere-fourier
menu label linux-ampere-fourier (managed)
kernel /Image-ampere-fourier
initrd /initramfs-ampere-fourier.img
fdt /rk3588-coolpi-cm5-genbook.dtb-ampere-fourier
append <inherited from arch_mainline>
```
Default label is NOT changed. After verifying boot of the managed
label at the u-boot menu, you flip `default` manually. Reverting =
boot a different label (e.g. `arch_mainline`, `ubuntu_mainline`).
## Boot path
ampere uses `/boot/firmware/` (vfat on mmcblk0p1, ~1G), distinct
from fresnel's `/boot/` on root partition. The PKGBUILD installs
Image, initramfs, and DTB directly under `/boot/firmware/`. No
DTB subdir — single board target.
## Open follow-ups (per kernel-agent issue #6)
- **Ask 2** (VP9 enablement on RK3588 rkvdec) — not addressed in this
iteration. Separate session.
- **Ask 3** (AV1 decoder integration) — backend libva work, not kernel.
- Hosting the source tarball publicly so `prebuild.sh` isn't needed —
candidate: Gitea release asset, or `packages.reauktion.de/sources/`.
- Splitting the 12 non-board cherry-pick commits in the baseline
(4 Shawn Lin phy, 2 Cristian Ciocaltea, etc.) into scope-tagged
patches in kernel-agent — currently they ride along inside the
pinned baseline rather than being explicit `includes:` in the
manifest.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,13 @@
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Path
Target = boot/firmware/Image-ampere-fourier
Target = boot/firmware/rk3588-coolpi-cm5-genbook.dtb-ampere-fourier
Target = boot/firmware/initramfs-ampere-fourier.img
[Action]
Description = Updating extlinux entry for linux-ampere-fourier
When = PostTransaction
Exec = /usr/share/libalpm/scripts/linux-ampere-fourier-extlinux
+62
View File
@@ -0,0 +1,62 @@
#!/bin/sh
# Add / update / remove the linux-ampere-fourier entry in
# /boot/firmware/extlinux/extlinux.conf. Idempotent. Coexists with
# the hand-managed labels in that file; never edits them. Default
# label is NOT touched — user picks at u-boot menu.
#
# ampere boots from a vfat partition (mmcblk0p1) mounted at
# /boot/firmware/, distinct from fresnel's /boot/ on root.
set -eu
CONF="/boot/firmware/extlinux/extlinux.conf"
TAG_BEGIN="# >>> linux-ampere-fourier (managed) >>>"
TAG_END="# <<< linux-ampere-fourier (managed) <<<"
# Copy APPEND from the user's `arch_mainline` label so the managed
# entry inherits the same root= and console= settings the host's
# bootloader already trusts. Falls back to a CoolPi GenBook default
# if no arch_mainline label exists (first-time install on a fresh
# bootloader config).
EXISTING_APPEND=$(awk '
/^[[:space:]]*label[[:space:]]+arch_mainline[[:space:]]*$/ { found=1; next }
found && /^[[:space:]]*append[[:space:]]/ {
sub(/^[[:space:]]*append[[:space:]]+/, "")
print
exit
}
/^[[:space:]]*label[[:space:]]/ { found=0 }
' "$CONF" 2>/dev/null || true)
APPEND="${EXISTING_APPEND:-root=LABEL=arch rw rootwait rootfstype=btrfs rootflags=subvol=@,ssd,discard=async console=ttyS2,1500000 console=tty1 consoleblank=0 loglevel=7 cma=256M coherent_pool=2M}"
ENTRY=$(cat <<EOF
${TAG_BEGIN}
label linux-ampere-fourier
menu label linux-ampere-fourier (managed)
kernel /Image-ampere-fourier
initrd /initramfs-ampere-fourier.img
fdt /rk3588-coolpi-cm5-genbook.dtb-ampere-fourier
append ${APPEND}
${TAG_END}
EOF
)
# Strip any prior managed block, then append fresh
TMP=$(mktemp)
awk -v b="$TAG_BEGIN" -v e="$TAG_END" '
$0==b{skip=1; next}
$0==e{skip=0; next}
!skip{print}
' "$CONF" > "$TMP"
# Post-Remove: kernel files absent → don't re-add the entry
if [ -f "/boot/firmware/Image-ampere-fourier" ] \
&& [ -f "/boot/firmware/rk3588-coolpi-cm5-genbook.dtb-ampere-fourier" ]; then
printf '%s\n' "$ENTRY" >> "$TMP"
echo "linux-ampere-fourier: extlinux entry updated"
else
echo "linux-ampere-fourier: kernel files absent, entry removed"
fi
mv "$TMP" "$CONF"
@@ -0,0 +1,13 @@
# mkinitcpio preset for linux-ampere-fourier
#
# ampere boots from /boot/firmware/ (vfat partition on mmcblk0p1). The
# initramfs lands there too so extlinux can pick it up. Only one PRESET
# because /boot/firmware is ~1G total — no room for a fallback image
# alongside the primary.
ALL_kver="/boot/firmware/Image-ampere-fourier"
ALL_microcode=()
PRESETS=('default')
default_image="/boot/firmware/initramfs-ampere-fourier.img"
+68
View File
@@ -0,0 +1,68 @@
#!/bin/bash
# prebuild — stage the kernel source tarball this PKGBUILD expects.
#
# linux-ampere-fourier's source is a snapshot of marfrit/linux-rk3588-marfrit
# @ f8f3ad9 (260MB), too big to commit to marfrit-packages and currently
# unpushable to Gitea (boltzmann's working clone is shallow; gitea push
# refuses shallow updates). Hosting the tarball outside Gitea would need
# infrastructure setup that's not in scope for the first iteration.
#
# So: produce the tarball locally from the kernel working tree just
# before makepkg runs. Idempotent — if an existing tarball matches the
# expected sha256 we skip the archive step.
#
# Run from this directory: cd arch/linux-ampere-fourier && ./prebuild.sh
# Override the kernel-tree location: LINUX_RK3588_MARFRIT_TREE=/path ./prebuild.sh
#
# Default tree location matches the boltzmann/ampere convention from
# kernel-agent issue #6: $HOME/src/linux-rockchip.
set -euo pipefail
TREE="${LINUX_RK3588_MARFRIT_TREE:-${HOME}/src/linux-rockchip}"
COMMIT=48a8c785de7f5320513052a64e544c6310d7b273
# Generated tarball sha varies with gzip version — script warns-not-fails.
# Leave EXPECTED empty for fresh kafr2 builds; first successful build can
# pin a canonical sha here if a reproducibility audit needs it.
SHA256_EXPECTED=
HERE="$(cd "$(dirname "$0")" && pwd)"
OUTPUT="${HERE}/linux-rk3588-marfrit-${COMMIT:0:7}.tar.gz"
if [ -f "$OUTPUT" ]; then
have=$(sha256sum "$OUTPUT" | cut -d' ' -f1)
if [ "$have" = "$SHA256_EXPECTED" ]; then
echo "prebuild: $OUTPUT already exists with correct sha256"
exit 0
else
echo "prebuild: existing $OUTPUT sha mismatch (have=$have, want=$SHA256_EXPECTED) — regenerating" >&2
rm -f "$OUTPUT"
fi
fi
if [ ! -d "$TREE/.git" ]; then
echo "prebuild: kernel tree not at $TREE" >&2
echo " set LINUX_RK3588_MARFRIT_TREE=/path/to/linux-rockchip and retry" >&2
exit 2
fi
cd "$TREE"
if ! git cat-file -e "$COMMIT" 2>/dev/null; then
echo "prebuild: commit $COMMIT not found in $TREE" >&2
echo " fetch the linux-rk3588-marfrit branch first:" >&2
echo " git fetch <remote> linux-rk3588-marfrit" >&2
exit 3
fi
echo "prebuild: generating archive from $TREE @ $COMMIT..."
git archive --format=tar.gz --prefix=linux-rk3588-marfrit/ "$COMMIT" -o "$OUTPUT"
# git archive emits a deterministic tar stream but gzip compression may
# vary by version. The sha256 check is informational; warn-don't-fail.
have=$(sha256sum "$OUTPUT" | cut -d' ' -f1)
if [ "$have" != "$SHA256_EXPECTED" ]; then
echo "prebuild: WARNING $OUTPUT sha=$have (canonical=$SHA256_EXPECTED)" >&2
echo " probably a gzip-version difference; tar payload should be identical" >&2
fi
echo "prebuild: wrote $OUTPUT ($(du -h "$OUTPUT" | cut -f1), sha=$have)"
@@ -0,0 +1,356 @@
From a202de1646d4c8f8ee2ebc2e4c100b621975754a Mon Sep 17 00:00:00 2001
In-Reply-To: <20260429195306.239666-1-mfritsche@reauktion.de>
References: <20260429195306.239666-1-mfritsche@reauktion.de>
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Sat, 9 May 2026 16:16:07 +0200
Subject: [PATCH RFC v2] media: videobuf2: add opt-in dma_resv producer fence
helper
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
V4L2 producers historically don't propagate buffer-state-done into
the dmabuf's dma_resv exclusive fence. Userspace consumers that
import V4L2-produced dmabufs and wait on the dmabuf's implicit-sync
fence (poll(POLLIN), DMA_BUF_IOCTL_EXPORT_SYNC_FILE,
EGL_LINUX_DMA_BUF_EXT) currently see either zero fences or a stub
fence from dma_fence_get_stub(). This is correct by accident for the
common DQBUF-then-import case but represents a contract gap that
breaks Wayland compositors importing CAPTURE buffers from a stateless
H.264 decoder under continuous playback on implicit-sync GPU stacks
(observed on RK3566 + hantro VPU + Mali-G52 panfrost; manifests as
green frames -- BT.709 limited-range YUV(0,0,0) -> RGB(0,77,0) -- when
the GPU samples the dmabuf before the producer's decode completes).
Add an opt-in API gated by both a per-driver runtime flag
(vb2_queue::supports_release_fences) and a Kconfig
(CONFIG_VIDEOBUF2_RELEASE_FENCES, default n) that lets producers
populate a real dma_resv exclusive write fence on the dmabufs they
export. Drivers call vb2_buffer_attach_release_fence(vb) at a
finite-time-fenced point in their pipeline (typically m2m
device_run, just before the HW kick); vb2_buffer_done() signals and
puts the fence as part of its state transition.
The publish and signal paths are wrapped in
dma_fence_begin_signalling() / dma_fence_end_signalling() so
PROVE_LOCKING can validate that nothing taken in those critical
sections deadlocks against the signal path. dma_resv_lock is
sleepable but not taken on the signal path, so taking it inside the
publish critical section is safe under lockdep.
Skips planes whose vb2_plane.dbuf is NULL -- buffers never exported
via VIDIOC_EXPBUF (or imported via V4L2_MEMORY_DMABUF) have no
dmabuf for userspace to wait on.
Drivers that don't opt in pay nothing: the helper is a no-op stub
when CONFIG_VIDEOBUF2_RELEASE_FENCES=n, and an early-return check
of supports_release_fences when =y but the flag is unset.
Validated on RK3566 PineTab2 with PROVE_LOCKING enabled: 30s of
bbb_1080p30 H.264 stateless decode + zero-copy panfrost EGL import
via dmabuf-wayland (mpv 0.41 + KWin 6.6.4 + Mesa panfrost 26.0.5)
produces 31,816 dma_fence init/signal pairs across 5,724 vb2 buffer
cycles with zero lockdep splats from videobuf2 / dma_resv code paths.
Subsequent patches in this series opt the hantro and rockchip-rga
drivers in.
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Christian König <christian.koenig@amd.com>
Cc: Nicolas Dufresne <nicolas@ndufresne.ca>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Tomasz Figa <tfiga@chromium.org>
Cc: linux-media@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linaro-mm-sig@lists.linaro.org
Signed-off-by: Markus Fritsche <mfritsche@reauktion.de>
---
drivers/media/common/videobuf2/Kconfig | 29 ++++
.../media/common/videobuf2/videobuf2-core.c | 135 ++++++++++++++++++
include/media/videobuf2-core.h | 51 +++++++
3 files changed, 215 insertions(+)
diff --git a/drivers/media/common/videobuf2/Kconfig b/drivers/media/common/videobuf2/Kconfig
index d2223a12c..bbfa26984 100644
--- a/drivers/media/common/videobuf2/Kconfig
+++ b/drivers/media/common/videobuf2/Kconfig
@@ -30,3 +30,32 @@ config VIDEOBUF2_DMA_SG
config VIDEOBUF2_DVB
tristate
select VIDEOBUF2_CORE
+
+config VIDEOBUF2_RELEASE_FENCES
+ bool "videobuf2: opt-in dma_resv producer fences for V4L2 dmabuf exports"
+ depends on VIDEOBUF2_CORE
+ depends on DMA_SHARED_BUFFER
+ default n
+ help
+ Enables an opt-in API that lets vb2 producers populate a dma_resv
+ exclusive write fence on the dmabufs they export to userspace.
+ The fence is signalled when the buffer transitions to
+ VB2_BUF_STATE_DONE.
+
+ This gives userspace consumers that import V4L2-produced dmabufs
+ and wait on the dmabuf's implicit-sync fence (poll(POLLIN),
+ DMA_BUF_IOCTL_EXPORT_SYNC_FILE, EGL_LINUX_DMA_BUF_EXT) a real
+ producer fence to wait on, instead of a stub fence from
+ dma_fence_get_stub() that the dma_buf core substitutes when
+ dma_resv is empty.
+
+ Drivers individually opt in by setting
+ vb2_queue::supports_release_fences = true and calling
+ vb2_buffer_attach_release_fence() at the right point in their
+ pipeline (typically m2m device_run, just before HW kick).
+
+ Distributors leave this off unless targeting Wayland/EGL
+ consumers of V4L2 stateless decoder output on
+ implicit-sync-only GPU stacks (e.g. mainline panfrost).
+
+ If unsure, say N.
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index adf668b21..85d7fddbd 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -26,6 +26,12 @@
#include <linux/freezer.h>
#include <linux/kthread.h>
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+#include <linux/dma-fence.h>
+#include <linux/dma-resv.h>
+#include <linux/dma-buf.h>
+#endif
+
#include <media/videobuf2-core.h>
#include <media/v4l2-mc.h>
@@ -1173,6 +1179,120 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
}
EXPORT_SYMBOL_GPL(vb2_plane_cookie);
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+/*
+ * dma_resv release-fence integration.
+ *
+ * Optional, opt-in path that lets producers publish a real
+ * dma_fence on their CAPTURE-side dmabufs so userspace consumers
+ * (compositors, EGL importers) get spec-clean implicit-sync
+ * semantics instead of the dma_buf core's stub fence. Drivers
+ * call vb2_buffer_attach_release_fence() at a finite-time-fenced
+ * point (typically m2m device_run) and the fence is signalled by
+ * vb2_buffer_done(). Gated at runtime by
+ * vb2_queue::supports_release_fences and at compile time by
+ * CONFIG_VIDEOBUF2_RELEASE_FENCES.
+ */
+
+static const char *vb2_dma_resv_get_driver_name(struct dma_fence *fence)
+{
+ return "videobuf2";
+}
+
+static const char *vb2_dma_resv_get_timeline_name(struct dma_fence *fence)
+{
+ return "vb2-release-fence";
+}
+
+static const struct dma_fence_ops vb2_dma_resv_fence_ops = {
+ .get_driver_name = vb2_dma_resv_get_driver_name,
+ .get_timeline_name = vb2_dma_resv_get_timeline_name,
+};
+
+int vb2_buffer_attach_release_fence(struct vb2_buffer *vb)
+{
+ struct vb2_queue *q = vb->vb2_queue;
+ struct dma_fence *fence;
+ unsigned int plane;
+ bool cookie;
+
+ if (!q->supports_release_fences)
+ return 0;
+
+ if (WARN_ON(vb->release_fence))
+ return -EINVAL;
+
+ fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+ if (!fence)
+ return -ENOMEM;
+
+ dma_fence_init(fence, &vb2_dma_resv_fence_ops, &q->dma_resv_fence_lock,
+ q->dma_resv_fence_context,
+ atomic64_inc_return(&q->dma_resv_fence_seqno));
+
+ /*
+ * Annotate the publish-side critical section. Per
+ * Documentation/driver-api/dma-buf.rst, lockdep validates
+ * that nothing taken in this region can deadlock against
+ * the signal path in vb2_buffer_signal_release_fence().
+ * dma_resv_lock is sleepable but is not taken on the signal
+ * path, so taking it inside the critical section is safe.
+ */
+ cookie = dma_fence_begin_signalling();
+ for (plane = 0; plane < vb->num_planes; plane++) {
+ struct dma_buf *dbuf = vb->planes[plane].dbuf;
+
+ if (!dbuf)
+ continue;
+
+ dma_resv_lock(dbuf->resv, NULL);
+ dma_resv_add_fence(dbuf->resv, fence, DMA_RESV_USAGE_WRITE);
+ dma_resv_unlock(dbuf->resv);
+ }
+ dma_fence_end_signalling(cookie);
+
+ /* One reference for the eventual signal in vb2_buffer_done. */
+ vb->release_fence = dma_fence_get(fence);
+
+ /* The dma_resv held its own reference per plane. Drop ours. */
+ dma_fence_put(fence);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_buffer_attach_release_fence);
+
+static void vb2_buffer_signal_release_fence(struct vb2_buffer *vb,
+ enum vb2_buffer_state state)
+{
+ struct dma_fence *fence = vb->release_fence;
+ bool cookie;
+
+ if (!fence)
+ return;
+
+ cookie = dma_fence_begin_signalling();
+ if (state == VB2_BUF_STATE_ERROR)
+ dma_fence_set_error(fence, -EIO);
+ dma_fence_signal(fence);
+ dma_fence_end_signalling(cookie);
+
+ dma_fence_put(fence);
+ vb->release_fence = NULL;
+}
+#else /* !CONFIG_VIDEOBUF2_RELEASE_FENCES */
+
+int vb2_buffer_attach_release_fence(struct vb2_buffer *vb)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_buffer_attach_release_fence);
+
+static inline void vb2_buffer_signal_release_fence(struct vb2_buffer *vb,
+ enum vb2_buffer_state state)
+{
+}
+#endif /* CONFIG_VIDEOBUF2_RELEASE_FENCES */
+
void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
{
struct vb2_queue *q = vb->vb2_queue;
@@ -1199,6 +1319,9 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
if (state != VB2_BUF_STATE_QUEUED)
__vb2_buf_mem_finish(vb);
+ if (state != VB2_BUF_STATE_QUEUED)
+ vb2_buffer_signal_release_fence(vb, state);
+
spin_lock_irqsave(&q->done_lock, flags);
if (state == VB2_BUF_STATE_QUEUED) {
vb->state = VB2_BUF_STATE_QUEUED;
@@ -2651,6 +2774,18 @@ int vb2_core_queue_init(struct vb2_queue *q)
mutex_init(&q->mmap_lock);
init_waitqueue_head(&q->done_wq);
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+ /*
+ * Per-queue dma_resv release-fence context. Drivers that
+ * opt in via supports_release_fences and call
+ * vb2_buffer_attach_release_fence() use these to allocate
+ * fences on a single per-queue timeline.
+ */
+ q->dma_resv_fence_context = dma_fence_context_alloc(1);
+ atomic64_set(&q->dma_resv_fence_seqno, 0);
+ spin_lock_init(&q->dma_resv_fence_lock);
+#endif
+
q->memory = VB2_MEMORY_UNKNOWN;
if (q->buf_struct_size == 0)
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4424d481d..766ff2194 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -288,6 +288,16 @@ struct vb2_buffer {
unsigned int skip_cache_sync_on_finish:1;
struct vb2_plane planes[VB2_MAX_PLANES];
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+ /*
+ * Producer release fence published on each plane's
+ * dmabuf->resv when the driver opts in via
+ * vb2_buffer_attach_release_fence(). Signalled and put by
+ * vb2_buffer_done() on transition to DONE/ERROR. NULL when
+ * the driver did not opt in for this buffer.
+ */
+ struct dma_fence *release_fence;
+#endif
struct list_head queued_entry;
struct list_head done_entry;
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -648,6 +658,19 @@ struct vb2_queue {
spinlock_t done_lock;
wait_queue_head_t done_wq;
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+ /*
+ * dma_resv release-fence context. Drivers that set
+ * supports_release_fences and call
+ * vb2_buffer_attach_release_fence() use these to allocate
+ * fences on a per-queue timeline.
+ */
+ u64 dma_resv_fence_context;
+ atomic64_t dma_resv_fence_seqno;
+ spinlock_t dma_resv_fence_lock;
+#endif
+
+ unsigned int supports_release_fences:1;
unsigned int streaming:1;
unsigned int start_streaming_called:1;
unsigned int error:1;
@@ -735,6 +758,34 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no);
*/
void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
+/**
+ * vb2_buffer_attach_release_fence() - opt-in dma_resv release fence.
+ * @vb: the buffer being committed to the producer.
+ *
+ * Drivers that have set vb2_queue::supports_release_fences may call
+ * this from any sleepable context where they have committed to
+ * running the operation in finite time -- typically m2m
+ * device_run(), just before the HW kick. The helper allocates a
+ * dma_fence on the queue's per-queue timeline, attaches it as
+ * DMA_RESV_USAGE_WRITE on each plane's dmabuf->resv, and stashes
+ * it in vb->release_fence. vb2_buffer_done() signals and puts the
+ * fence as part of the buffer's state transition.
+ *
+ * Skips planes whose vb2_plane.dbuf is NULL -- buffers never
+ * exported via VIDIOC_EXPBUF (or imported via V4L2_MEMORY_DMABUF)
+ * have no dmabuf for userspace to wait on.
+ *
+ * No-op when vb2_queue::supports_release_fences is not set
+ * (regardless of CONFIG_VIDEOBUF2_RELEASE_FENCES). When
+ * CONFIG_VIDEOBUF2_RELEASE_FENCES=n, this is a stub that returns 0.
+ *
+ * Returns 0 on success or when the no-op stub is in effect,
+ * negative errno on allocation failure when fence publishing was
+ * attempted. Best-effort: drivers should ignore the return value
+ * unless they want diagnostics.
+ */
+int vb2_buffer_attach_release_fence(struct vb2_buffer *vb);
+
/**
* vb2_discard_done() - discard all buffers marked as DONE.
* @q: pointer to &struct vb2_queue with videobuf2 queue.
--
2.53.0
@@ -0,0 +1,95 @@
From 1844c263bde8dd244d7db46f8c508e7c70da459c Mon Sep 17 00:00:00 2001
In-Reply-To: <20260429195306.239666-1-mfritsche@reauktion.de>
References: <20260429195306.239666-1-mfritsche@reauktion.de>
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Sat, 9 May 2026 16:24:01 +0200
Subject: [PATCH RFC v2] media: hantro: attach dma_resv release fence at
device_run
Opt the hantro driver into the new vb2 release-fence helper so its
CAPTURE-side dmabufs carry a real producer fence that wayland
compositors and other implicit-sync consumers can wait on, instead
of the dma_buf core's stub fence.
Attach point is m2m device_run, immediately after
v4l2_m2m_buf_copy_metadata() and before ctx->codec_ops->run().
Per Nicolas Dufresne's v1 review (lore.kernel.org/linux-media/
3d8deeb15581b754e4c061d4c4a13657aa08bc3c.camel@ndufresne.ca/),
this satisfies the dma_fence finite-time contract: the m2m core
has committed to running the job by this point, codec_ops->run
either kicks the HW (decode-complete signals the fence via
vb2_buffer_done) or fails immediately (job_finish with
VB2_BUF_STATE_ERROR signals with -EIO). PM and clocks are already
up by this point, so no allocation context restrictions.
The CAPTURE queue is opted in with supports_release_fences=true at
queue_init.
Userspace consumers that import hantro CAPTURE dmabufs and wait on
their implicit-sync fence (Wayland zwp_linux_dmabuf_v1 +
panfrost EGL_LINUX_DMA_BUF_EXT) now wait on a real fence
representing the producer's actual completion, fixing green-frame
corruption observed on RK3566 PineTab2 + Mali-G52 panfrost (the
GPU was sampling zero pages because the dmabuf's implicit fence
was the dma_buf core's pre-signalled stub).
Validated end-to-end on PineTab2 (RK3566 / hantro G1 / Mali-G52
mainline panfrost): 30s of bbb_1080p30 H.264 stateless decode +
zero-copy panfrost EGL import via dmabuf-wayland (mpv 0.41 +
KWin 6.6.4 + Mesa panfrost 26.0.5) renders correctly with no
green-frame corruption and no PROVE_LOCKING splats.
Cc: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Nicolas Dufresne <nicolas@ndufresne.ca>
Cc: linux-media@vger.kernel.org
Cc: linux-rockchip@lists.infradead.org
Signed-off-by: Markus Fritsche <mfritsche@reauktion.de>
---
.../media/platform/verisilicon/hantro_drv.c | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 2e81877f6..6a66c47ed 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -186,6 +186,22 @@ static void device_run(void *priv)
v4l2_m2m_buf_copy_metadata(src, dst);
+ /*
+ * Attach a producer fence on the CAPTURE-side dmabuf so userspace
+ * importers (e.g. Wayland compositors) get spec-clean implicit-sync
+ * semantics. Called from device_run rather than buf_queue: the
+ * dma_fence finite-time contract requires that once a fence is
+ * published, the producer must signal it in finite time. By the
+ * time we reach device_run, the m2m core has committed to running
+ * this job, and the next hop (codec_ops->run) either kicks the HW
+ * (decode-complete signals the fence via vb2_buffer_done) or
+ * fails immediately (job_finish with VB2_BUF_STATE_ERROR signals
+ * the fence with -EIO). Either path resolves the fence in finite
+ * time. Best-effort: a NOMEM here means we lose implicit-sync
+ * precision for this frame, no functional regression.
+ */
+ (void)vb2_buffer_attach_release_fence(&dst->vb2_buf);
+
if (ctx->codec_ops->run(ctx))
goto err_cancel_job;
@@ -249,6 +265,13 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
dst_vq->lock = &ctx->dev->vpu_mutex;
dst_vq->dev = ctx->dev->v4l2_dev.dev;
+ /*
+ * Opt the CAPTURE queue into vb2 release-fence publishing.
+ * No-op unless CONFIG_VIDEOBUF2_RELEASE_FENCES=y; runtime cost
+ * is one extra fence allocation + dma_resv update per device_run.
+ */
+ dst_vq->supports_release_fences = true;
+
return vb2_queue_init(dst_vq);
}
--
2.53.0
@@ -0,0 +1,117 @@
From 2c63a63bf65739763051dc4ce7ce2ffaf2d514c4 Mon Sep 17 00:00:00 2001
In-Reply-To: <20260429195306.239666-1-mfritsche@reauktion.de>
References: <20260429195306.239666-1-mfritsche@reauktion.de>
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Sat, 9 May 2026 16:50:51 +0200
Subject: [PATCH RFC v2] media: rockchip-rga: attach dma_resv release fence at
device_run
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Opt the rockchip-rga driver into the new vb2 release-fence helper.
Same shape as the hantro patch: attach a producer fence on the
CAPTURE-side dmabuf at m2m device_run, signalled by
vb2_buffer_done() when RGA completes the m2m operation.
Differs from hantro in one mechanical detail: rga's device_run
wraps the entire body in spin_lock_irqsave(&rga->ctrl_lock). Our
helper calls dma_resv_lock(), which is sleepable, so the
buffer-fetch + fence-attach sequence has to run above the spinlock.
Restructure device_run so:
- v4l2_m2m_next_src_buf / next_dst_buf,
- src->sequence increment,
- vb2_buffer_attach_release_fence(&dst->vb2_buf)
run before spin_lock_irqsave; only the rga->curr assignment and
rga_hw_start() (the actual HW kick) remain inside the spinlock.
This is safe under the m2m-job ownership model: by the time
device_run is called, the m2m core has selected this context and
serializes one device_run per context, so v4l2_m2m_next_*_buf
returns stable pointers until the corresponding *_buf_remove in
rga_isr. ctrl_lock was previously protecting per-device state
(rga->curr) and the HW register access, neither of which depends on
the buffer-fetch happening inside the lock.
The CAPTURE queue is opted in with supports_release_fences=true at
queue_init.
Userspace consumers of RGA-produced dmabufs (image-processing
pipelines, screen-rotation servers, gstreamer flows on Rockchip
boards) get spec-clean implicit-sync semantics, matching what
hantro does in the previous patch in this series.
Sven Püschel's ongoing "media: platform: rga: Add RGA3 support"
v5 series (linux-rockchip 2026-04-28) restructures rga.c
substantially. If that lands first, the device_run restructure
here will need a rebase against the new shape; the locking story
itself is invariant.
Cc: Jacob Chen <jacob-chen@iotwrt.com>
Cc: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
Cc: Sven Püschel <s.pueschel@pengutronix.de>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Cc: linux-media@vger.kernel.org
Cc: linux-rockchip@lists.infradead.org
Signed-off-by: Markus Fritsche <mfritsche@reauktion.de>
---
drivers/media/platform/rockchip/rga/rga.c | 27 +++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index fea63b94c..03030c7ea 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -38,15 +38,28 @@ static void device_run(void *prv)
struct vb2_v4l2_buffer *src, *dst;
unsigned long flags;
- spin_lock_irqsave(&rga->ctrl_lock, flags);
-
- rga->curr = ctx;
-
+ /*
+ * Fetch the next-job buffers and (best-effort) attach a producer
+ * fence on CAPTURE before taking ctrl_lock below.
+ * vb2_buffer_attach_release_fence() takes dma_resv_lock, which is
+ * sleepable; ctrl_lock is taken with spin_lock_irqsave so any
+ * sleepable call must happen above it. Buffer ownership is
+ * already committed at this point: the m2m core has selected
+ * this context for device_run and serializes one device_run per
+ * context, so v4l2_m2m_next_*_buf returns stable pointers until
+ * the corresponding *_buf_remove in rga_isr.
+ */
src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
src->sequence = ctx->osequence++;
dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+ (void)vb2_buffer_attach_release_fence(&dst->vb2_buf);
+
+ spin_lock_irqsave(&rga->ctrl_lock, flags);
+
+ rga->curr = ctx;
+
rga_hw_start(rga, vb_to_rga(src), vb_to_rga(dst));
spin_unlock_irqrestore(&rga->ctrl_lock, flags);
@@ -123,6 +136,12 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
dst_vq->lock = &ctx->rga->mutex;
dst_vq->dev = ctx->rga->v4l2_dev.dev;
+ /*
+ * Opt the CAPTURE queue into vb2 release-fence publishing.
+ * Compile-time gated by CONFIG_VIDEOBUF2_RELEASE_FENCES.
+ */
+ dst_vq->supports_release_fences = true;
+
return vb2_queue_init(dst_vq);
}
--
2.53.0
+8 -3
View File
@@ -10,8 +10,8 @@
pkgbase=linux-fresnel-fourier pkgbase=linux-fresnel-fourier
pkgname=("$pkgbase" "$pkgbase-headers") pkgname=("$pkgbase" "$pkgbase-headers")
pkgver=7.0 pkgver=7.0
pkgrel=1 pkgrel=14
pkgdesc='Pinebook Pro kernel (mmind/linux-rockchip v7.0 + OC OPP + PBP DTS tweaks)' pkgdesc='Pinebook Pro kernel (mmind/linux-rockchip v7.0 + OC OPP + PBP DTS tweaks + vb2_dma_resv RFC v2)'
arch=(aarch64) arch=(aarch64)
url='https://git.reauktion.de/marfrit/kernel-agent' url='https://git.reauktion.de/marfrit/kernel-agent'
license=(GPL-2.0-only) license=(GPL-2.0-only)
@@ -23,15 +23,20 @@ makedepends=(
options=('!strip') options=('!strip')
source=( source=(
"https://git.kernel.org/torvalds/t/linux-${pkgver}.tar.gz" "https://git.kernel.org/torvalds/t/linux-${pkgver}.tar.gz"
# board/pinebook-pro
'0001-arm64-dts-rk3399-pinebook-pro-add-OC-OPP-tables-1704-2184.patch' '0001-arm64-dts-rk3399-pinebook-pro-add-OC-OPP-tables-1704-2184.patch'
'0002-arm64-dts-rk3399-pinebook-pro-enable-hdmi-sound.patch' '0002-arm64-dts-rk3399-pinebook-pro-enable-hdmi-sound.patch'
'0003-arm64-dts-rk3399-pinebook-pro-spi1-max-freq-10MHz.patch' '0003-arm64-dts-rk3399-pinebook-pro-spi1-max-freq-10MHz.patch'
# subsystem/media/videobuf2/dma-resv-release-fence (RFC v2, in kernel-agent)
'0004-media-videobuf2-add-opt-in-dma_resv-producer-fence-h.patch'
'0005-media-hantro-attach-dma_resv-release-fence-at-device.patch'
'0006-media-rockchip-rga-attach-dma_resv-release-fence-at-.patch'
'config' # snapshot of fresnel /usr/lib/modules/6.19.10-1-eos-arm/build/.config 'config' # snapshot of fresnel /usr/lib/modules/6.19.10-1-eos-arm/build/.config
'linux-fresnel-fourier.preset' 'linux-fresnel-fourier.preset'
'extlinux-add.hook' 'extlinux-add.hook'
'extlinux-add.sh' 'extlinux-add.sh'
) )
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP') sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
_kernver=${pkgver}.0-fresnel-fourier _kernver=${pkgver}.0-fresnel-fourier
_srcdir=linux-${pkgver} _srcdir=linux-${pkgver}
@@ -0,0 +1,19 @@
# makepkg outputs and intermediate state
src/
pkg/
*.pkg.tar.zst
*.pkg.tar.zst.sig
*-build.log*
*-prepare.log
*-package_*.log
*.tar.xz
*.tar.sign
*.patch.zst
*.patch.zst.sig
logpipe.*
# build-time artifacts that must never be committed
src/
*.tar.xz
*.tar.zst
pkg/
@@ -0,0 +1,247 @@
# Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
# Forked from: linux-pinetab2 by Danct12 <danct12@disroot.org>
# Original Contributor: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
#
# linux-pinetab2-danctnix-besser: linux-pinetab2 + the BESser bes2600
# driver patchset. Soft-upstream fork of linux-pinetab2 — drop-in
# replacement, same kernel version, only the bes2600 staging driver
# differs. See git.reauktion.de/marfrit/besser and
# git.reauktion.de/marfrit/bes2600-dkms for full provenance.
#
# ─────────────────────────────────────────────────────────────────────
# kernel-agent flow (effective pkgrel=4):
#
# The single 0001-bes2600-besser-kernel-agent-cumulative.patch is
# regenerated by `ka-promote ohm` in
# git.reauktion.de/marfrit/kernel-agent against fleet/ohm.yaml. Its
# b2sum below MUST match the cumulative.b2sum recorded in the
# co-located manifest.lock. Sibling manifest.lock pins the source-of-
# truth manifest sha256 and per-include patch sha256s.
#
# To update for a new patch in the manifest:
# 1. Edit kernel-agent:fleet/ohm.yaml (add/remove includes)
# 2. `ka-promote ohm` → writes new cumulative.patch + manifest.lock
# to kernel-agent/build/ohm/v7.0-danctnix1/
# 3. Copy both files into this directory (replacing existing ones)
# 4. Update the b2sum in this PKGBUILD for the cumulative
# 5. Bump pkgrel
# ─────────────────────────────────────────────────────────────────────
pkgbase=linux-pinetab2-danctnix-besser
pkgver=7.0.danctnix1
pkgrel=6
pkgdesc='PineTab2 (BESser bes2600 driver patchset, kernel-agent managed)'
_srcname=linux-pinetab2
_srctag=v${pkgver%.*}-${pkgver##*.}
arch=(aarch64)
_url_git="https://codeberg.org/DanctNIX/${_srcname}"
url="${_url_git}/commits/tag/$_srctag"
license=(GPL-2.0-only)
makedepends=(
bc
cpio
gettext
git
libelf
pahole
perl
python
tar
xz
)
options=(
!debug
!strip
)
source=(
https://cdn.kernel.org/pub/linux/kernel/v${pkgver%%.*}.x/linux-${pkgver%.*}.tar.{xz,sign}
${_url_git}/releases/download/${_srctag}/${_srctag}.patch.zst{,.sig}
0001-bes2600-besser-kernel-agent-cumulative.patch
config
)
validpgpkeys=(
ABAF11C65A2970B130ABE3C479BE3E4300411886 # Linus Torvalds
647F28654894E3BD457199BE38DBBDC86092693E # Greg Kroah-Hartman
F09A933C0FE0331E558CA4E166CAB7EAA45DD781 # Danct12
)
b2sums=('3d9795083c8938f80f480de0d10bfd9c525640e59d5c7f22983de3f12ee42c84c31be902cafb05579ddb1c32bac5ed06b0d4953f9705450be185bd2d9ab08f89'
'SKIP'
'71fe98221e802b315e54b4b10d3e8c8f376695a36bae3541d876e5776a37f3fa33c8f8dfa6e51fcbd6f5396add02e5166634165f2351836a0ea0453c172fe56c'
'SKIP'
'eb179c03f35a4dbaec2e40036f0033ef04985bb6b14ab22419d68e5caaa5874f2ad14e158f7c5b05added97f60fecde8fb8b7f2a6ced33e031e37352fe776ca6'
'656a998ab40cb85ee4c00f087b071a91632a6c091da2c84b0f74236b51d2dea6e9db6886625f80ad81dc249d8494ec47cd79d6dd9ea4f5e44f3cde857f861e10')
export KBUILD_BUILD_HOST=archlinux
export KBUILD_BUILD_USER=$pkgbase
export KBUILD_BUILD_TIMESTAMP="$(date -Ru${SOURCE_DATE_EPOCH:+d @$SOURCE_DATE_EPOCH})"
prepare() {
cd linux-${pkgver%.*}
echo "Setting version..."
echo "-$pkgrel" > localversion.10-pkgrel
echo "${pkgbase#linux}" > localversion.20-pkgname
local src
for src in "${source[@]}"; do
src="${src%%::*}"
src="${src##*/}"
src="${src%.zst}"
[[ $src = *.patch ]] || continue
echo "Applying patch: $src..."
patch -Np1 < "../$src"
done
echo "Setting config..."
cp ../config .config
make olddefconfig
diff -u ../config .config || :
make -s kernelrelease > version
echo "Prepared $pkgbase version $(<version)"
}
build() {
cd linux-${pkgver%.*}
make DTC_FLAGS="-@" all
make -C tools/bpf/bpftool vmlinux.h feature-clang-bpf-co-re=1
}
_package() {
pkgdesc="The $pkgdesc kernel and modules"
depends=(
coreutils
kmod
mkinitcpio
)
optdepends=(
'wireless-regdb: to set the correct wireless channels of your country'
'linux-firmware: firmware images needed for some devices'
)
provides=(
KSMBD-MODULE
WIREGUARD-MODULE
"linux-pinetab2=$pkgver-$pkgrel"
)
conflicts=(linux-pinetab2)
replaces=(
wireguard-arch
)
cd linux-${pkgver%.*}
local modulesdir="$pkgdir/usr/lib/modules/$(<version)"
echo "Installing boot image..."
# systemd expects to find the kernel here to allow hibernation
# https://github.com/systemd/systemd/commit/edda44605f06a41fb86b7ab8128dcf99161d2344
install -Dm644 "$(make -s image_name)" "$modulesdir/vmlinuz"
# Used by mkinitcpio to name the kernel
echo "$pkgbase" | install -Dm644 /dev/stdin "$modulesdir/pkgbase"
echo "Installing modules..."
ZSTD_CLEVEL=19 make INSTALL_MOD_PATH="$pkgdir/usr" INSTALL_MOD_STRIP=1 \
DEPMOD=/doesnt/exist modules_install # Suppress depmod
echo "Installing device trees..."
make INSTALL_DTBS_PATH="$pkgdir/boot/dtbs" dtbs_install
# Removing unnecessary device trees (keep only pinetab2 variants).
# find -delete is robust to nullglob/cwd quirks where a bash for-loop
# silently no-op'd in the makepkg environment.
find "$pkgdir"/boot/dtbs/rockchip/ -mindepth 1 -maxdepth 1 -type f \
! -name 'rk3566-pinetab2-*' -delete
# remove build link
rm "$modulesdir"/build
}
_package-headers() {
pkgdesc="Headers and scripts for building modules for the $pkgdesc kernel"
depends=(pahole)
cd linux-${pkgver%.*}
local builddir="$pkgdir/usr/lib/modules/$(<version)/build"
echo "Installing build files..."
install -Dt "$builddir" -m644 .config Makefile Module.symvers System.map \
localversion.* version vmlinux tools/bpf/bpftool/vmlinux.h
install -Dt "$builddir/kernel" -m644 kernel/Makefile
install -Dt "$builddir/arch/arm64" -m644 arch/arm64/Makefile
cp -t "$builddir" -a scripts
# required when DEBUG_INFO_BTF_MODULES is enabled
install -Dt "$builddir/tools/bpf/resolve_btfids" tools/bpf/resolve_btfids/resolve_btfids
echo "Installing headers..."
cp -t "$builddir" -a include
cp -t "$builddir/arch/arm64" -a arch/arm64/include
install -Dt "$builddir/arch/arm64/kernel" -m644 arch/arm64/kernel/asm-offsets.s
install -Dt "$builddir/drivers/md" -m644 drivers/md/*.h
install -Dt "$builddir/net/mac80211" -m644 net/mac80211/*.h
# https://bugs.archlinux.org/task/13146
install -Dt "$builddir/drivers/media/i2c" -m644 drivers/media/i2c/msp3400-driver.h
# https://bugs.archlinux.org/task/20402
install -Dt "$builddir/drivers/media/usb/dvb-usb" -m644 drivers/media/usb/dvb-usb/*.h
install -Dt "$builddir/drivers/media/dvb-frontends" -m644 drivers/media/dvb-frontends/*.h
install -Dt "$builddir/drivers/media/tuners" -m644 drivers/media/tuners/*.h
# https://bugs.archlinux.org/task/71392
install -Dt "$builddir/drivers/iio/common/hid-sensors" -m644 drivers/iio/common/hid-sensors/*.h
echo "Installing KConfig files..."
find . -name 'Kconfig*' -exec install -Dm644 {} "$builddir/{}" \;
echo "Removing unneeded architectures..."
local arch
for arch in "$builddir"/arch/*/; do
[[ $arch = */arm64/ ]] && continue
echo "Removing $(basename "$arch")"
rm -r "$arch"
done
echo "Removing documentation..."
rm -r "$builddir/Documentation"
echo "Removing broken symlinks..."
find -L "$builddir" -type l -printf 'Removing %P\n' -delete
echo "Removing loose objects..."
find "$builddir" -type f -name '*.o' -printf 'Removing %P\n' -delete
echo "Stripping build tools..."
local file
while read -rd '' file; do
case "$(file -Sib "$file")" in
application/x-sharedlib\;*) # Libraries (.so)
strip -v $STRIP_SHARED "$file" ;;
application/x-archive\;*) # Libraries (.a)
strip -v $STRIP_STATIC "$file" ;;
application/x-executable\;*) # Binaries
strip -v $STRIP_BINARIES "$file" ;;
application/x-pie-executable\;*) # Relocatable binaries
strip -v $STRIP_SHARED "$file" ;;
esac
done < <(find "$builddir" -type f -perm -u+x ! -name vmlinux -print0)
echo "Stripping vmlinux..."
strip -v $STRIP_STATIC "$builddir/vmlinux"
echo "Adding symlink..."
mkdir -p "$pkgdir/usr/src"
ln -sr "$builddir" "$pkgdir/usr/src/$pkgbase"
}
pkgname=(
"$pkgbase"
"$pkgbase-headers"
)
for _p in "${pkgname[@]}"; do
eval "package_$_p() {
$(declare -f "_package${_p#$pkgbase}")
_package${_p#$pkgbase}
}"
done
@@ -0,0 +1,52 @@
# linux-pinetab2-danctnix-besser
DanctNIX PineTab2 kernel + the BESser bes2600 driver patchset.
**kernel-agent managed** as of pkgrel=4 (2026-05-18).
## TL;DR
- **What**: drop-in replacement for `linux-pinetab2` with the BESser
bes2600 patchset applied.
- **For**: PineTab2 (RK3566) with the on-board BES2600 SDIO WiFi/BT chip.
- **Install**: `pacman -U linux-pinetab2-danctnix-besser-*.pkg.tar.zst
linux-pinetab2-danctnix-besser-headers-*.pkg.tar.zst`. It `provides`
and `conflicts` with `linux-pinetab2`, so it slots in cleanly.
- **Source of truth for patches**:
[git.reauktion.de/marfrit/kernel-agent](https://git.reauktion.de/marfrit/kernel-agent)
`fleet/ohm.yaml`.
## How the patch cumulative is built
1. `kernel-agent/fleet/ohm.yaml` lists the patch series-dir includes
for this kernel.
2. `kernel-agent/bin/ka-promote ohm` walks those includes, concatenates
them into a single `cumulative.patch`, and emits a `manifest.lock`
recording per-patch sha256s and the cumulative b2sum.
3. The cumulative is dropped into this directory as
`0001-bes2600-besser-kernel-agent-cumulative.patch`, the b2sum in
`PKGBUILD` is updated to match, and `pkgrel` is bumped.
4. `manifest.lock` is committed alongside the cumulative for an
audit trail (which patches went in, in what order).
## pkgrel history
| pkgrel | Date | Notes |
|--------|------------|-------------------------------------------------|
| 13 | 2026-05-08…05-18 | hand-managed in `marfrit/besser/danctnix-besser-pkgbuild/` (DEPRECATED) |
| 4 | 2026-05-18 | first kernel-agent-managed release; same source contents as the hand-managed pkgrel=3 (Patch I + SCS workaround folded into single cumulative); fixes pkgrel=3's duplicated `0003-arm64-...patch` source-array bug |
## Known caveats
- **`CONFIG_SHADOW_CALL_STACK=n`** in the config: GCC 15.2.1 fails to
build `arch/arm64/lib/xor-neon.c` with `arm_neon.h` `#pragma GCC
target()` blocks and `-fsanitize=shadow-call-stack`. See
`reference_arm64_scs_arm_neon_gcc15` memory and the Makefile
workaround patch included in the cumulative. Track upstream GCC
resolution before re-enabling.
- The `cumulative-c5x-danctnix` series-dir in kernel-agent is currently
a single-file interim (the working hand-curated cumulative) because
the per-series mirrors created in `kernel-agent#17` use DKMS-style
root paths instead of in-tree staging paths and do not apply
cleanly. Per-series reconstruction is a separate kernel-agent
follow-up. The b2sum integrity check in `PKGBUILD` still pins the
exact bytes shipped.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,177 @@
baseline:
ref: v7.0-danctnix1
tree: DanctNIX/linux-pinetab2
upstream_compat: linux-7.0
url: https://codeberg.org/DanctNIX/linux-pinetab2
cumulative:
b2sum: eb179c03f35a4dbaec2e40036f0033ef04985bb6b14ab22419d68e5caaa5874f2ad14e158f7c5b05added97f60fecde8fb8b7f2a6ced33e031e37352fe776ca6
path: cumulative.patch
size: 279554
generated_at: '2026-05-19T13:05:46.476359+00:00'
host: ohm
ka_promote_version: 1
manifest:
path: fleet/ohm.yaml
sha256: 9ac04ddd3170418b7b2d2cf7b31ac225a31ed19be4f03e8477bf28b585bae257
resolved_patches:
- apply_order: 1
from_series: true
include: driver/bes2600/factory-series/0001-bes2600-use-request_firmware-for-factory.txt-read.patch
sha256: a1bc2d13b258709fa37c9ff428dfdc0659464b436470fa2ec69b07edf7592f6f
size: 5456
- apply_order: 2
from_series: true
include: driver/bes2600/factory-series/0002-bes2600-default-STANDARD_FACTORY_EFUSE_FLAG-off-for-PineTab2.patch
sha256: 577d7024ce0b342c4381365872fc29e75a93427ad61223907fead8b829b5a86c
size: 3499
- apply_order: 3
from_series: true
include: driver/bes2600/factory-thread-dev/0001-bes2600-thread-struct-device-through-factory-request_firmware.patch
sha256: e3fac725e6addc11147341836600c2c5cd0116abba960f34ba50bb8094581c75
size: 4406
- apply_order: 4
from_series: true
include: driver/bes2600/pm-gate-on-handshake/0001-bes2600-gate-device-LP-mode-entry-on-successful-handshake.patch
sha256: 9842c0dd66f59fe28898041ba5a816be56965b0665f202410cd461c3e6565474
size: 3914
- apply_order: 5
from_series: true
include: driver/bes2600/remove-chardev-user-interface/0001-bes2600-remove-userspace-dev-bes2600-character-device-interface.patch
sha256: c67d340ae5923aada613ea9c5133e3efa3aeb7986749f4bf3619d1752a1b61fb
size: 22445
- apply_order: 6
from_series: true
include: driver/bes2600/enable-testmode/0001-bes2600-enable-CONFIG_BES2600_TESTMODE-by-default-fix-bitrot.patch
sha256: 5dee74e8753d332fd380882994ea43aa907d1ff97466b0c48aedf38d4076e446
size: 6152
- apply_order: 7
from_series: true
include: driver/bes2600/tx-sdio-dma-oob-danctnix/0001-bes2600-bounce-SDIO-TX-buffers-to-avoid-DMA-OOB-read.patch
sha256: 0dce2fe35450b8376c2d2a7c007119f28c888c1c30b489a67841039caedeebfc
size: 4544
- apply_order: 8
from_series: true
include: driver/bes2600/factory-drop-kernel-write-danctnix/0001-bes2600-drop-kernel_write-persistence-from-factory-cali-save.patch
sha256: a7995b38e210af16b73d284a58ab39b8aecac36ff4a671af3d894b1983f961b3
size: 5704
- apply_order: 9
from_series: true
include: driver/bes2600/drop-dpd-file-paths-danctnix/0001-bes2600-drop-BES2600_WRITE_DPD_TO_FILE-kernel-file-paths.patch
sha256: 0cd8780c245c97c65e4845e42d712c6256a0449658641aea18e4c7d400f63e41
size: 9661
- apply_order: 10
from_series: true
include: driver/bes2600/drop-orphan-file-io-danctnix/0001-bes2600-drop-orphan-DATA_DUMP_OBSERVE-and-access_file-IO.patch
sha256: fd8c297223e6a985c2898f919ae1ab27eb56ab44f09f44d84d75eb35a187527b
size: 5327
- apply_order: 11
from_series: true
include: driver/bes2600/pm-timeout-silence-danctnix/0001-bes2600-demote-wait-pm-ind-timeout-from-bes_err-to-bes_devel.patch
sha256: 3a4fd3255facbcef0419e0e0332cb980316529aa5c225b35bcfd244a42736667
size: 2332
- apply_order: 12
from_series: true
include: driver/bes2600/scan-defer-on-reject-danctnix/0001-bes2600-defer-scan-and-soften-WARN-on-firmware-reject.patch
sha256: 55e16c176bc147c371a20f57b3a57da38c719d3b42417e88f9de243e10102d35
size: 8393
- apply_order: 13
from_series: true
include: driver/bes2600/scan-defer-backoff-tune-danctnix/0001-bes2600-widen-scan-defer-backoff-30s-and-decay-on-quiet.patch
sha256: 70a5b25baaf41c8090701b069c30cbad378883d828bdd06e4eb560a35bc077f1
size: 4924
- apply_order: 14
from_series: true
include: driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0001-bes2600-recover-wedged-firmware-via-mmc_hw_reset-on-link-break.patch
sha256: 3decf33c9684b3aba64004d5ad97ae3d54e1d6dc176d0b0ae539036c65e6dc6c
size: 10604
- apply_order: 15
from_series: true
include: driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0002-bes2600-handle-multi-function-SDIO-cards-in-mmc_hw_reset-bus_reset.patch
sha256: a1acfcc401afc699a9c3676b6df2ec0f092e78826a32616268f90b509d538e33
size: 3321
- apply_order: 16
from_series: true
include: driver/bes2600/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-request-and-track-state.patch
sha256: 049cf3ff9c01fdd10ff73bd18497e14ef0cd8fd1a65486ba86fbc6c1935a5f8e
size: 10269
- apply_order: 17
from_series: true
include: driver/bes2600/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-confirmed-ACTIVE.patch
sha256: c9d19a73816f4c82b418dcd18008176bbb0c49fd4138be53cad45ae142224112
size: 8100
- apply_order: 18
from_series: true
include: driver/bes2600/pm-detect-firmware-unsupported-danctnix/0001-bes2600-self-detect-firmware-does-not-honor-PSM-skip-cycle.patch
sha256: 196dc9d51ffea268718a290d434b6237fb60119f10c2b050a58724c8a775c7a8
size: 9041
- apply_order: 19
from_series: true
include: driver/bes2600/decrypt-storm-fast-recover-danctnix/0001-bes2600-pre-empt-AP-deauth-6-mac80211-reassoc-on-decrypt-fail-storm.patch
sha256: b57ed316005f402c95ccae8ab24ac761bdf34162d73f108f5790af8f8ad2d1fe
size: 9249
- apply_order: 20
from_series: true
include: driver/bes2600/connection-loss-fast-recover-danctnix/0001-bes2600-bus_reset-on-connection-loss-storm-to-dodge-assoc-comeback-blackhole.patch
sha256: cd1eaff97c3f08c58e7b1588e19a12200e8bb2a1f39afe554284f1d818610a67
size: 12184
- apply_order: 21
from_series: true
include: driver/bes2600/cw1200-fix-backports-danctnix/0001-bes2600-replace-atomic_add-with-atomic_inc-cw1200-backport.patch
sha256: 3876c9e512f556c7f2e8d4cfaba1d7df2945ee48af8edfab5f8d09d9de9adf23
size: 3080
- apply_order: 22
from_series: true
include: driver/bes2600/cw1200-fix-backports-danctnix/0002-bes2600-fix-missing-destroy_workqueue-on-error-in-init_common.patch
sha256: 2b82ecb127748349780404479205b952337c244e715278e6d40471c6ecad7602
size: 2230
- apply_order: 23
from_series: true
include: driver/bes2600/cw1200-fix-backports-danctnix/0003-bes2600-fix-concurrency-UAF-in-bes2600_hw_scan-and-sched_scan.patch
sha256: 4c1850ad003ddcac543d3d61edd15c18ccd0cc601367cf4c6dd31e1fbb39ab16
size: 4476
- apply_order: 24
from_series: true
include: driver/bes2600/sdio-rx-no-relay-danctnix/0001-bes2600-drop-sdio_rx_work-relay-IRQ-bh-direct-no-relay-architecture.patch
sha256: f1182150c5893f2497f942900b34c9c4aeb8d5901d9786ae2753dcce38ed6c78
size: 19313
- apply_order: 25
from_series: true
include: driver/bes2600/license-spdx-restore-attribution-danctnix/0001-bes2600-Patch-G-restore-SPDX-identifiers-ST-Ericsson-attribution.patch
sha256: 91dadab0b58f8b8ad2dca80fd04796d478ecb83ce94a1e4b6e97ef8634d97ef1
size: 41521
- apply_order: 26
from_series: true
include: driver/bes2600/ba-lock-atomic-danctnix/0001-bes2600-Patch-D-atomicize-ba_lock-counters-drop-the-spinlock.patch
sha256: a5d4ed2bf545458a756e65670c7eed31997bd0be9262344a10313bee31ea4963
size: 11987
- apply_order: 27
from_series: true
include: driver/bes2600/ps-state-lock-skip-pm-disabled-danctnix/0001-bes2600-Patch-E-skip-ps_state_lock-when-PSM-known-disabled.patch
sha256: 18040a563b37cc95c558703f01bfbf6b7fa23a52f2f4f0f8f1254ad4fa0fe0d6
size: 3396
- apply_order: 28
from_series: true
include: driver/bes2600/rx-list-batch-delivery-danctnix/0001-bes2600-Patch-C2-replace-ieee80211_rx_irqsafe-with-ieee80211_rx_ni.patch
sha256: ffeffd085a9d052c126a717b845d50120ea302e76c12e53c0c3c891291cababf
size: 8377
- apply_order: 29
from_series: true
include: driver/bes2600/bh-c-fossil-cleanup-danctnix/0001-bes2600-Patch-H-bh.c-hygiene-cleanup-drop-fossil-blocks-dead-stubs.patch
sha256: 8fb0c799e3a8ee5ad7bfb647fceaf370c6a1a5f24d8621776fd07bf18a976f81
size: 21082
- apply_order: 30
from_series: true
include: driver/bes2600/scan-filter-5ghz-danctnix/0001-bes2600-filter-5-GHz-scans-at-the-driver-boundary.patch
sha256: 31e67569e00daead0784214aced1e077d3270cf1407baa0b330d474e17ec3931
size: 7735
- apply_order: 31
from_series: true
include: arch/arm64/scs-arm-neon-build-fix/0001-arm64-xor-neon-ffixed-x18-build-fix.patch
sha256: 105e32edc54743d8107c4dcd846833ae97d2df5f918aebc9fe3e67d6f23249cc
size: 1562
- apply_order: 32
from_series: true
include: driver/bes2600/queue-pending-record-lock-bh-danctnix/0001-bes2600-take-pending-record-lock-with-bh.patch
sha256: e0894371c43f750590e1704ae3c77b27b6910548afa4a5b61ebc4d9919580ca2
size: 5270
schema_version: 1
+6 -3
View File
@@ -3,15 +3,18 @@
# Source of truth: git.reauktion.de/marfrit/lmcp # Source of truth: git.reauktion.de/marfrit/lmcp
pkgname=lmcp pkgname=lmcp
pkgver=0.5.4 pkgver=1.2.1
pkgrel=1 pkgrel=1
pkgdesc="Lightweight MCP (Model Context Protocol) server in pure Lua" pkgdesc="Lightweight MCP (Model Context Protocol) server in pure Lua"
arch=('any') arch=('any')
url="https://git.reauktion.de/marfrit/lmcp" url="https://git.reauktion.de/marfrit/lmcp"
license=('MIT') license=('MIT')
depends=('lua' 'lua-socket') depends=('lua' 'lua-socket')
source=("${pkgname}-${pkgver}.tar.gz::https://git.reauktion.de/marfrit/lmcp/archive/v${pkgver}.tar.gz") # The _tag back-translation handles both clean releases (no '_') and
sha256sums=('af72b8c1d88255456b75d2c53cd5c451a8923417e5498ef31858539397e09caf') # pre-release pkgvers (e.g. 1.2.0_rc1 → v1.2.0-rc1).
_tag="v${pkgver//_/-}"
source=("${pkgname}-${pkgver}.tar.gz::https://git.reauktion.de/marfrit/lmcp/archive/${_tag}.tar.gz")
sha256sums=('bf9cce1a84c66b1b74c5aec923c5960d60ae33c221afc8d47ce0d74b8f7ee609')
package() { package() {
cd "${pkgname}" cd "${pkgname}"
@@ -0,0 +1,57 @@
From: claude-noether (on behalf of mfritsche)
Date: 2026-05-19
Subject: panvk: expose VK_KHR/EXT_robustness2 + nullDescriptor on Bifrost (PAN_ARCH 6/7)
Without this, Mesa's Zink driver refuses to use PanVk-Bifrost as its Vulkan
backend, falling back silently to llvmpipe (software rasterizer) for all
GL-via-Zink on Bifrost SBCs. That defeats the entire purpose of having a
Vulkan driver on Bifrost — GL acceleration via Zink is the most natural
near-term consumer.
panvk_vX_nir_lower_descriptors.c:1309 and panvk_vX_shader.c:1355 already
plumb dev->vk.enabled_features.nullDescriptor arch-agnostically — the gate
at panvk_vX_physical_device.c was set conservatively when Bifrost was
unmaintained, not because of hardware incapability.
iter17 of the panvk-bifrost campaign proved fundamental driver functions
on Mali-G52 r1 MC1 (PAN_ARCH=7). This patch is the iter8 follow-up.
robustBufferAccess2 and robustImageAccess2 are NOT flipped — they're
independent rb2 features Zink doesn't require, gated differently
(robustBufferAccess2 = PAN_ARCH >= 11, robustImageAccess2 = false), and
out of scope for iter8.
---
src/panfrost/vulkan/panvk_vX_physical_device.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/panfrost/vulkan/panvk_vX_physical_device.c b/src/panfrost/vulkan/panvk_vX_physical_device.c
--- a/src/panfrost/vulkan/panvk_vX_physical_device.c
+++ b/src/panfrost/vulkan/panvk_vX_physical_device.c
@@ -91,7 +91,7 @@ get_device_extensions(const struct panvk_physical_device *device,
.KHR_pipeline_binary = true,
.KHR_pipeline_executable_properties = true,
.KHR_pipeline_library = true,
- .KHR_robustness2 = PAN_ARCH >= 10,
+ .KHR_robustness2 = true,
.KHR_sampler_mirror_clamp_to_edge = true,
.KHR_sampler_ycbcr_conversion = true,
.KHR_separate_depth_stencil_layouts = true,
@@ -168,7 +168,7 @@ get_device_extensions(const struct panvk_physical_device *device,
.EXT_queue_family_foreign = true,
.EXT_robustness = pan_arch(device->kmod.dev->props.gpu_id) >= 9,
.EXT_image_robustness = true,
- .EXT_robustness2 = PAN_ARCH >= 10,
+ .EXT_robustness2 = true,
.EXT_sampler_filter_minmax = PAN_ARCH >= 10,
.EXT_scalar_block_layout = true,
.EXT_separate_stencil_usage = true,
@@ -493,7 +493,7 @@ get_device_features(const struct panvk_physical_device *device,
/* VK_KHR_robustness2 */
.robustBufferAccess2 = PAN_ARCH >= 11,
.robustImageAccess2 = false,
- .nullDescriptor = PAN_ARCH >= 10,
+ .nullDescriptor = true,
/* VK_KHR_shader_clock */
.shaderSubgroupClock = device->kmod.dev->props.gpu_can_query_timestamp,
@@ -0,0 +1,47 @@
From: claude-noether (on behalf of mfritsche)
Date: 2026-05-20
Subject: panvk: expose Vulkan 1.1 + 1.2 on Bifrost (PAN_ARCH 6/7)
ANGLE (Chromium's GL stack) requires apiVersion >= 1.1 to initialize. Without
this, Brave / Chromium's GPU process fails at GL info collection:
vk_renderer.cpp:2659 (initialize): ANGLE Requires a minimum Vulkan device
version of 1.1
Display::initialize error 0: Internal Vulkan error (-9): The requested
version of Vulkan is not supported by the driver
Stack-up with iter8's robustness2 patch enables ANGLE → PanVk-Bifrost →
Skia (via --enable-features=Vulkan) on Bifrost SBCs.
PanVk-Bifrost already supports the bulk of 1.1-promoted features as extensions
(multiview, maintenance1-3, descriptor update template, 16-bit storage,
descriptor update template, sampler ycbcr, variable pointers, etc. — all
visible in iter0 vulkaninfo). The version bump primarily bundles them.
Risk: Vulkan 1.1 has features beyond what iter17 exercised (protected memory,
full subgroup ops). Specific app failures will be characterizable.
1.2 is also flipped — Brave's Vulkan path may want descriptor indexing,
buffer device address, etc. (all listed in iter0 vulkaninfo as supported
extensions, just gated as 1.0-with-extensions, not 1.2-core).
---
src/panfrost/vulkan/panvk_vX_physical_device.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/panfrost/vulkan/panvk_vX_physical_device.c b/src/panfrost/vulkan/panvk_vX_physical_device.c
--- a/src/panfrost/vulkan/panvk_vX_physical_device.c
+++ b/src/panfrost/vulkan/panvk_vX_physical_device.c
@@ -38,8 +38,8 @@ get_device_extensions(const struct panvk_physical_device *device,
struct vk_device_extension_table *ext)
{
*ext = (struct vk_device_extension_table){
- .KHR_8bit_storage = true,
- .KHR_16bit_storage = true,
- bool has_vk1_1 = PAN_ARCH >= 10;
- bool has_vk1_2 = PAN_ARCH >= 10;
+ .KHR_8bit_storage = true,
+ .KHR_16bit_storage = true,
+ bool has_vk1_1 = true;
+ bool has_vk1_2 = true;
*ext = (struct vk_device_extension_table){
+165
View File
@@ -0,0 +1,165 @@
# Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
#
# mesa-panvk-bifrost — patched Mesa libvulkan_panfrost.so that exposes
# Bifrost-gen Mali (Mali-G31/G52/G72/G76, PAN_ARCH 6/7) to Chromium-family
# browsers' Vulkan compositor.
#
# Campaign: ~/src/panvk-bifrost/ — iter9 close (technical milestone
# 2026-05-20, operator-confirmed Brave window). Goal close requires
# this package built + published + installable per the
# feedback_package_done_means_installable.md 3-point check.
#
# What it does:
# - Builds Mesa 26.0.6 (matching ohm's stock mesa pkg) with two
# patches against src/panfrost/vulkan/panvk_vX_physical_device.c:
# (1) expose VK_KHR/EXT_robustness2 + nullDescriptor on PAN_ARCH 6/7
# (2) set has_vk1_1/has_vk1_2 to true on Bifrost
# - Installs the patched libvulkan_panfrost.so to /usr/lib/panvk-bifrost/
# (NOT /usr/lib — co-installs alongside stock mesa).
# - Registers a custom ICD JSON at a non-default path so the system
# Vulkan loader only picks up our driver when VK_ICD_FILENAMES is set.
# - Ships /usr/bin/brave-vulkan launcher that wires up env vars + flags.
#
# Co-existence: stock /usr/lib/libvulkan_panfrost.so is untouched. Stock
# /usr/share/vulkan/icd.d/panfrost_icd.json is untouched. Users opt in
# via brave-vulkan (or by setting VK_ICD_FILENAMES manually).
#
# Build target: arch-aarch64 runner via marfrit-packages Gitea Actions.
# Mesa build is slow (~30-60min on Cortex-A55). Build deps installed
# inside the runner via pacman -S in the workflow.
pkgname=mesa-panvk-bifrost
_mesaver=26.0.6
pkgver=26.0.6.r2
pkgrel=2
pkgdesc="Patched Mesa libvulkan_panfrost.so exposing Bifrost-gen Mali to Vulkan apps (panvk-bifrost campaign)"
arch=('aarch64')
url="https://github.com/marfrit/panvk-bifrost"
license=('MIT')
# We co-install at /usr/lib/panvk-bifrost/ so no conflicts with stock mesa.
# We DO provide a script that requires brave to be installed.
depends=(
'mesa' # for shared mesa runtime libs (libgallium-mesa etc.)
'libdrm'
'wayland'
'libxcb'
'libx11'
'libxshmfence'
'zlib'
'zstd'
'libdisplay-info'
'expat'
'systemd-libs' # libudev
'spirv-tools'
)
optdepends=(
'brave-bin: for the brave-vulkan launcher script'
)
makedepends=(
'meson'
'ninja'
'pkgconf'
'bison'
'flex'
'python'
'python-yaml'
'python-mako'
'glslang'
'spirv-tools'
'llvm'
'clang'
'libclc'
'spirv-llvm-translator'
'vulkan-headers'
'wayland-protocols'
)
source=(
"https://archive.mesa3d.org/mesa-${_mesaver}.tar.xz"
"0001-panvk-expose-robustness2-nullDescriptor-bifrost.patch"
"0002-panvk-expose-vulkan-1.1-1.2-on-bifrost.patch"
"brave-vulkan"
"icd.json"
)
sha256sums=(
'1d3c3b8a8363b8cc354175bb4a684ad8b035211cc1d6fa17aeb9b9623c513f89' # mesa-26.0.6.tar.xz from archive.mesa3d.org, pinned 2026-05-20 (iter10)
'SKIP'
'SKIP'
'SKIP'
'SKIP'
)
prepare() {
cd "mesa-${_mesaver}"
# iter8 patch: robustness2 + nullDescriptor exposure on Bifrost.
# Three hunks in panvk_vX_physical_device.c. Apply via sed since
# the upstream context drifts between Mesa releases and unified-diff
# patching is brittle (we hit hunk-rejects during manual application).
sed -i 's|\.KHR_robustness2 = PAN_ARCH >= 10,|.KHR_robustness2 = true,|' src/panfrost/vulkan/panvk_vX_physical_device.c
sed -i 's|\.EXT_robustness2 = PAN_ARCH >= 10,|.EXT_robustness2 = true,|' src/panfrost/vulkan/panvk_vX_physical_device.c
sed -i 's|\.nullDescriptor = PAN_ARCH >= 10,|.nullDescriptor = true,|' src/panfrost/vulkan/panvk_vX_physical_device.c
# iter9 patch: bump api version to 1.1/1.2 for Bifrost. NOTE: this only
# affects extension exposure flags, NOT the reported apiVersion (which
# is set by get_api_version() further down and gated separately).
# The brave-vulkan launcher sets MESA_VK_VERSION_OVERRIDE=1.2 at runtime
# to deal with the latter — no source change needed for that path.
sed -i 's|bool has_vk1_1 = PAN_ARCH >= 10;|bool has_vk1_1 = true;|' src/panfrost/vulkan/panvk_vX_physical_device.c
sed -i 's|bool has_vk1_2 = PAN_ARCH >= 10;|bool has_vk1_2 = true;|' src/panfrost/vulkan/panvk_vX_physical_device.c
# Sanity-check the patches landed.
grep -q "KHR_robustness2 = true," src/panfrost/vulkan/panvk_vX_physical_device.c
grep -q "EXT_robustness2 = true," src/panfrost/vulkan/panvk_vX_physical_device.c
grep -q "nullDescriptor = true," src/panfrost/vulkan/panvk_vX_physical_device.c
grep -q "has_vk1_1 = true;" src/panfrost/vulkan/panvk_vX_physical_device.c
grep -q "has_vk1_2 = true;" src/panfrost/vulkan/panvk_vX_physical_device.c
}
build() {
cd "mesa-${_mesaver}"
# Minimal Mesa build — only the panvk Vulkan driver. No GLES/GLX/EGL/
# gallium drivers — keeps the build narrower and avoids pulling in
# the entire Mesa runtime in this package's dep graph.
meson setup build/ \
--prefix=/usr \
--libdir=lib \
--buildtype=release \
-Dvulkan-drivers=panfrost \
-Dgallium-drivers= \
-Dplatforms=wayland,x11 \
-Dglx=disabled \
-Degl=disabled \
-Dgles1=disabled \
-Dgles2=disabled \
-Dvulkan-layers= \
-Dtools= \
-Dgallium-rusticl=false \
-Dmicrosoft-clc=disabled
meson compile -C build
}
package() {
cd "${srcdir}/mesa-${_mesaver}"
# Patched lib — co-install path, NOT /usr/lib (to avoid clashing
# with stock mesa's libvulkan_panfrost.so binary).
install -Dm755 build/src/panfrost/vulkan/libvulkan_panfrost.so \
"$pkgdir/usr/lib/panvk-bifrost/libvulkan_panfrost.so"
# ICD JSON at the standard Vulkan loader search path. The '00-'
# filename prefix gives optical priority but is NOT spec-backed —
# Vulkan loader readdir-order is implementation-defined per Khronos
# LoaderDriverInterface. The brave-vulkan wrapper sets
# VK_LOADER_DRIVERS_SELECT='00-panvk-bifrost*' to make the selection
# deterministic across filesystems. This avoids the VK_ICD_FILENAMES
# full-path override (whose GPU-sandbox survival is fragile) while
# still letting the loader work normally. iter10 result + Phase 5
# hardening.
install -Dm644 "$srcdir/icd.json" \
"$pkgdir/usr/share/vulkan/icd.d/00-panvk-bifrost.json"
# The brave-vulkan launcher wires up env + flags. iter10: no longer
# sets VK_ICD_FILENAMES, no longer passes --no-sandbox /
# --disable-gpu-sandbox.
install -Dm755 "$srcdir/brave-vulkan" "$pkgdir/usr/bin/brave-vulkan"
}
+86
View File
@@ -0,0 +1,86 @@
# mesa-panvk-bifrost
Patched Mesa `libvulkan_panfrost.so` exposing Bifrost-gen Mali GPUs
(Mali-G31/G52/G72/G76, PAN_ARCH 6/7) to Chromium-family browsers'
Vulkan compositor.
Result of the **panvk-bifrost** campaign ([`~/src/panvk-bifrost/`](../../../panvk-bifrost/)),
iter9 close 2026-05-20 (technical milestone — operator-confirmed Brave
window) followed by this package as the actual delivery.
## What it solves
Stock Chromium / Brave on Bifrost SBCs (PineTab2, etc.) currently dies
at GL bindings init:
```
ERROR: ui/gl/gl_context_egl.cc:120 GLES3 is unsupported and ES version fallback is disabled
ERROR: ui/gl/init/gl_factory.cc:111 Requested GL implementation not found
ERROR: components/viz/service/main/viz_main_impl.cc:189 Exiting GPU process due to errors during initialization
```
This package makes Brave's **Vulkan compositor path** work on Bifrost,
side-stepping the failing GL stack. Browser chrome and standard page
rendering work.
## Known limitations (not addressed)
- **WebGL / WebGL2** in-page: blocked. ANGLE needs `VK_EXT_transform_feedback`
to expose GLES3 contexts; PanVk-Bifrost doesn't currently support that.
Sites using WebGL will degrade or refuse.
- **VAAPI hardware video decode**: unrelated to this package — see the
`libva-v4l2-request-fourier` package for that path.
## Install
```sh
# Ensure [marfrit] is in /etc/pacman.conf, then:
sudo pacman -Sy mesa-panvk-bifrost
```
## Use
```sh
brave-vulkan # launches Brave with Vulkan
brave-vulkan https://www.example.com
brave-vulkan --your-flags-here # extra args passed through
```
The launcher sets:
- `PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1` (Mesa upstream gate)
- `MESA_VK_VERSION_OVERRIDE=1.2` (apiVersion bump for ANGLE)
- Brave flags: `--use-gl=disabled --enable-features=Vulkan --use-vulkan=native --ozone-platform=x11 --ignore-gpu-blocklist`
iter10 dropped `VK_ICD_FILENAMES` (ICD now at `/usr/share/vulkan/icd.d/00-panvk-bifrost.json` so the Vulkan loader auto-picks it, pinned deterministically via `VK_LOADER_DRIVERS_SELECT='00-panvk-bifrost*'`) and `--no-sandbox` / `--disable-gpu-sandbox` (env vars survive the GPU sandbox boundary without bypass).
## What's in the package
- `/usr/lib/panvk-bifrost/libvulkan_panfrost.so` — patched Mesa Vulkan driver (Mesa 26.0.6 + 2 sed-applied patches)
- `/usr/share/vulkan/icd.d/00-panvk-bifrost.json` — Vulkan ICD JSON pointing at the patched .so (Vulkan loader picks it deterministically via `VK_LOADER_DRIVERS_SELECT='00-panvk-bifrost*'` set by the launcher)
- `/usr/bin/brave-vulkan` — launcher script
System Mesa's binary `/usr/lib/libvulkan_panfrost.so` is untouched. The
stock `panfrost_icd.json` is also untouched and continues to enumerate
the same Mali-G52 device — apps see both drivers in
`vkEnumeratePhysicalDevices` and pick by index (ANGLE picks first, which
becomes ours by alphabetical priority).
## Co-existence
Both stock Mesa and this package can be installed. Stock Vulkan apps
(`vulkaninfo`, `vkcube`, etc.) use the stock driver by default. Only
apps started via `brave-vulkan` (or with `VK_ICD_FILENAMES` manually
set to our path) use the patched driver.
## Campaign close criterion
Per [`feedback_package_done_means_installable`](file:///home/mfritsche/.claude/projects/-home-mfritsche-src/memory/feedback_package_done_means_installable.md)
three-point check:
1. PR merged to `marfrit-packages`
2. CI green AND `packages.reauktion.de/arch/aarch64/mesa-panvk-bifrost-*.pkg.tar.zst` exists
3. `pacman -Ss mesa-panvk-bifrost` on a fresh consumer host (e.g. ohm
after `pacman -Syu` from clean state) returns the package + brave-vulkan launches
When all three pass, panvk-bifrost iter9 closes.
+68
View File
@@ -0,0 +1,68 @@
#!/bin/bash
# brave-vulkan — launch Brave with the PanVk-Bifrost Vulkan compositor on
# Bifrost SBCs (PineTab2 / Mali-G52 r1 MC1 and similar).
#
# Side-steps the GL stack failures stock Brave hits on Bifrost
# (the README "Consumer-side benefit" path of the panvk-bifrost campaign).
#
# Provided by the mesa-panvk-bifrost package. See:
# /usr/share/doc/mesa-panvk-bifrost/README
# ~/src/panvk-bifrost/phase8_iteration{9,10}_close.md
#
# Usage: brave-vulkan [brave args...]
# Equivalent to: brave [VULKAN_FLAGS] [your args]
#
# iter10 changes vs iter9:
# - dropped VK_ICD_FILENAMES env (ICD now at /usr/share/vulkan/icd.d/
# with '00-' prefix so the Vulkan loader auto-picks ours first)
# - dropped --no-sandbox / --disable-gpu-sandbox (env vars survive the
# GPU sandbox boundary, no bypass needed)
set -e
# Pin the Vulkan ICD selection to our package's ICD. The Vulkan loader's
# readdir-order in /usr/share/vulkan/icd.d/ is implementation-defined
# per Khronos LoaderDriverInterface — the '00-' filename prefix is NOT
# spec-backed. VK_LOADER_DRIVERS_SELECT short-circuits the directory
# enumeration and picks our ICD deterministically. (Phase 5 review
# hardening, iter10.)
export VK_LOADER_DRIVERS_SELECT='00-panvk-bifrost*'
# PanVk's "I know it's not conformant" gate — the patched driver still
# refuses to enumerate Bifrost without this env var (upstream Mesa choice
# for v6/v7, kept for compatibility).
export PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1
# Override apiVersion to 1.2 — ANGLE (Chromium's GL stack) requires
# device.apiVersion >= 1.1. Source patches don't move get_api_version()'s
# PAN_ARCH>=10 hardcode; the env var override does.
export MESA_VK_VERSION_OVERRIDE=1.2
# Find the live Plasma session's Xauthority. On a fresh boot the suffix
# is randomized; pgrep the Xwayland args to find the current one.
if [ -z "${XAUTHORITY:-}" ]; then
XAUTHF=$(pgrep -fa Xwayland 2>/dev/null | grep -oE "/run/user/$(id -u)/xauth_[A-Za-z0-9]+" | head -1)
if [ -n "$XAUTHF" ]; then
export XAUTHORITY="$XAUTHF"
fi
fi
# Standard session env if not already set
: "${XDG_RUNTIME_DIR:=/run/user/$(id -u)}"
export XDG_RUNTIME_DIR
# Default to the active Plasma Wayland session if WAYLAND_DISPLAY unset
: "${WAYLAND_DISPLAY:=wayland-0}"
export WAYLAND_DISPLAY
# Default to the XWayland :1 unless DISPLAY is set
: "${DISPLAY:=:1}"
export DISPLAY
exec brave \
--use-gl=disabled \
--enable-features=Vulkan \
--use-vulkan=native \
--ozone-platform=x11 \
--ignore-gpu-blocklist \
"$@"
+7
View File
@@ -0,0 +1,7 @@
{
"ICD": {
"api_version": "1.4.335",
"library_path": "/usr/lib/panvk-bifrost/libvulkan_panfrost.so"
},
"file_format_version": "1.0.1"
}
+10 -10
View File
@@ -21,14 +21,14 @@
# pkgbase stays as qt6-base so $_pkgfn (= ${pkgbase/6-/} = "qtbase") # pkgbase stays as qt6-base so $_pkgfn (= ${pkgbase/6-/} = "qtbase")
# resolves correctly. The "-fourier" suffix lives only in the # resolves correctly. The "-fourier" suffix lives only in the
# directory name and the commit history; epoch=1 gives our local # directory name and the commit history; epoch=1 gives our local
# build strict precedence over upstream pkgrel=2 until upstream lands # build strict precedence over upstream pkgrel=N until upstream lands
# the GL_R8/ES3 fix and we can drop the epoch. # the GL_R8/ES3 fix and we can drop the epoch.
pkgbase=qt6-base pkgbase=qt6-base
pkgname=(qt6-base-fourier pkgname=(qt6-base-fourier
qt6-xcb-private-headers-fourier) qt6-xcb-private-headers-fourier)
_pkgver=6.11.0 _pkgver=6.11.1
pkgver=${_pkgver/-/} pkgver=${_pkgver/-/}
pkgrel=3 pkgrel=2
epoch=1 epoch=1
arch=(aarch64 x86_64) arch=(aarch64 x86_64)
url='https://www.qt.io' url='https://www.qt.io'
@@ -42,7 +42,6 @@ depends=(brotli
double-conversion double-conversion
fontconfig fontconfig
freetype2 freetype2
gcc-libs
glib2 glib2
glibc glibc
harfbuzz harfbuzz
@@ -51,6 +50,7 @@ depends=(brotli
libb2 libb2
libcups libcups
libdrm libdrm
libgcc
libgl libgl
libice libice
libinput libinput
@@ -58,6 +58,7 @@ depends=(brotli
libpng libpng
libproxy libproxy
libsm libsm
libstdc++
liburing liburing
libx11 libx11
libxcb libxcb
@@ -115,7 +116,7 @@ source=(git+https://code.qt.io/qt/$_pkgfn#tag=v$_pkgver
0001-qopengltextureglyphcache-pick-GL_R8-on-ES3.patch 0001-qopengltextureglyphcache-pick-GL_R8-on-ES3.patch
0002-qrhigles2-RED_OR_ALPHA8-pick-GL_R8-on-ES3.patch 0002-qrhigles2-RED_OR_ALPHA8-pick-GL_R8-on-ES3.patch
0003-qopengltextureuploader-pick-GL_R8-on-ES3.patch) 0003-qopengltextureuploader-pick-GL_R8-on-ES3.patch)
sha256sums=('2223c075e95d86f8dbf6395b025a74d996c418f094453c903290e3c2663fbed2' sha256sums=('2eafe504fae873d20f206b5661e2e10506879455cb2d370f42c5bb72ccf7a8a1'
'5411edbe215c24b30448fac69bd0ba7c882f545e8cf05027b2b6e2227abc5e78' '5411edbe215c24b30448fac69bd0ba7c882f545e8cf05027b2b6e2227abc5e78'
'4b93f6a79039e676a56f9d6990a324a64a36f143916065973ded89adc621e094' '4b93f6a79039e676a56f9d6990a324a64a36f143916065973ded89adc621e094'
'SKIP' 'SKIP'
@@ -126,9 +127,8 @@ prepare() {
patch -d $_pkgfn -p1 < qt6-base-cflags.patch # Use system CFLAGS patch -d $_pkgfn -p1 < qt6-base-cflags.patch # Use system CFLAGS
patch -d $_pkgfn -p1 < qt6-base-nostrip.patch # Don't strip binaries with qmake patch -d $_pkgfn -p1 < qt6-base-nostrip.patch # Don't strip binaries with qmake
# cherry-pick needs git author identity; git-cli refuses without it. # 8b54513cdcf6 (qdbus crash fix) cherry-pick removed: landed upstream
git -C $_pkgfn -c user.email=fourier@build -c user.name='qt6-base-fourier build' \ # in 6.11.1. Re-add if qdbus regressions re-surface.
cherry-pick -n 8b54513cdcf62047376a5d27d784ad68a8f235bf # Fix qdbus crashes
# qt6-base-fourier — three small runtime-checks that pick GL_R8 over # qt6-base-fourier — three small runtime-checks that pick GL_R8 over
# GL_ALPHA when the live GL context is ES 3 or newer. See the # GL_ALPHA when the live GL context is ES 3 or newer. See the
@@ -165,7 +165,7 @@ build() {
-DFEATURE_system_sqlite=ON \ -DFEATURE_system_sqlite=ON \
-DFEATURE_system_xcb_xinput=ON \ -DFEATURE_system_xcb_xinput=ON \
-DFEATURE_no_direct_extern_access=$_no_direct_extern_access \ -DFEATURE_no_direct_extern_access=$_no_direct_extern_access \
-DFEATURE_sql_ibase=OFF \ -DFEATURE_mimetype_database=OFF \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \ -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
-DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_MESSAGE_LOG_LEVEL=STATUS
cmake --build build cmake --build build
@@ -188,7 +188,7 @@ package_qt6-xcb-private-headers-fourier() {
conflicts=(qt6-xcb-private-headers) conflicts=(qt6-xcb-private-headers)
replaces=(qt6-xcb-private-headers) replaces=(qt6-xcb-private-headers)
depends=("qt6-base-fourier=$pkgver") depends=("qt6-base-fourier=$epoch:$pkgver")
optdepends=() optdepends=()
groups=() groups=()
+174
View File
@@ -0,0 +1,174 @@
#!/bin/bash
# Build daedalus-v4l2-dkms_<ver>_all.deb (kernel module via DKMS).
#
# Installs kernel/ source tree to /usr/src/daedalus_v4l2-${PKGVER}/
# plus a dkms.conf. Postinst registers with DKMS (dkms add + build +
# install). Prerm deregisters. Result: the daedalus_v4l2 module
# auto-rebuilds against any installed kernel headers without users
# needing to remember to dkms-add it.
#
# Architecture: all. The kernel module itself is per-kernel-version,
# but the SOURCE package is arch-independent.
#
# Sibling Arch package: ../../arch/daedalus-v4l2-dkms/PKGBUILD
# Sibling userspace package: ../daedalus-v4l2/build-deb.sh
set -euo pipefail
UPSTREAM_COMMIT=481279c9bffd19e32c8f3299897e9b63fc5a24aa
PKGVER=0.1.0+r18+g481279c
PKGREL=1 # reset for new upstream pin (481279c — Phase 8.13 close)
MODULE_NAME=daedalus_v4l2
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build. 2026-05-18 23:00 UTC — Phase 8.13 close.
export SOURCE_DATE_EPOCH=1779231600
work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
curl -sSLfo daedalus-v4l2.tar.gz \
"https://git.reauktion.de/reauktion/daedalus-v4l2/archive/${UPSTREAM_COMMIT}.tar.gz"
tar xzf daedalus-v4l2.tar.gz
SRCDIR=daedalus-v4l2
ROOT="$work/pkgroot"
SRCROOT="$ROOT/usr/src/${MODULE_NAME}-${PKGVER}"
mkdir -p "$SRCROOT/include" \
"$ROOT/DEBIAN" \
"$ROOT/usr/share/doc/daedalus-v4l2-dkms"
# Copy kernel/ source files to the DKMS source dir.
cp -r "$work/$SRCDIR/kernel/." "$SRCROOT/"
# Embed the shared protocol header inline (rather than referencing
# ../include/ which doesn't exist after DKMS extracts the tree).
# Patch the Makefile to find it at $SRCROOT/include/ instead.
install -m 644 "$work/$SRCDIR/include/daedalus_v4l2_proto.h" \
"$SRCROOT/include/daedalus_v4l2_proto.h"
sed -i 's|-I\$(src)/\.\./include|-I$(src)/include|' "$SRCROOT/Makefile"
# Generate dkms.conf with the actual version substituted.
cat > "$SRCROOT/dkms.conf" <<EOF
PACKAGE_NAME="${MODULE_NAME}"
PACKAGE_VERSION="${PKGVER}"
BUILT_MODULE_NAME[0]="${MODULE_NAME}"
DEST_MODULE_LOCATION[0]="/updates"
MAKE[0]="make KERNELDIR=/lib/modules/\${kernelver}/build all"
CLEAN="make KERNELDIR=/lib/modules/\${kernelver}/build clean"
AUTOINSTALL="yes"
EOF
# Doc
install -m 644 "$work/$SRCDIR/README.md" \
"$ROOT/usr/share/doc/daedalus-v4l2-dkms/README.md"
install -Dm644 "$HERE/debian/copyright" "$ROOT/usr/share/doc/daedalus-v4l2-dkms/copyright"
install -Dm644 "$HERE/debian/changelog" "$ROOT/usr/share/doc/daedalus-v4l2-dkms/changelog.Debian"
gzip -9 -n "$ROOT/usr/share/doc/daedalus-v4l2-dkms/changelog.Debian"
# DKMS post-install / pre-remove hooks.
cat > "$ROOT/DEBIAN/postinst" <<EOF
#!/bin/sh
set -e
NAME=${MODULE_NAME}
VERSION=${PKGVER}
KERNELVER=\$(uname -r)
# Yellow + bold ANSI for the warning so it stands out in apt's
# stream of "Setting up" lines. Disable colour on non-TTY.
if [ -t 1 ]; then
Y=\$(printf '\\033[1;33m'); R=\$(printf '\\033[0m')
else
Y=''; R=''
fi
warn() {
printf '%s==> daedalus-v4l2-dkms: %s%s\\n' "\$Y" "\$1" "\$R" >&2
}
if [ "\$1" = "configure" ]; then
if ! command -v dkms >/dev/null 2>&1; then
warn "dkms not installed; module \$NAME/\$VERSION not registered."
warn "Install 'dkms' then run: dkms add \$NAME/\$VERSION && dkms autoinstall"
exit 0
fi
dkms add "\$NAME/\$VERSION" 2>/dev/null || true
# Don't let autoinstall failure mask the actual problem behind '|| true'.
# Run it, capture the result, then verify post-condition.
autoinstall_rc=0
dkms autoinstall "\$NAME/\$VERSION" || autoinstall_rc=\$?
# Verify the module actually built + installed for the running kernel.
status=\$(dkms status -m "\$NAME" -v "\$VERSION" -k "\$KERNELVER" 2>/dev/null || true)
if ! printf '%s\\n' "\$status" | grep -q -E 'installed|loaded'; then
warn ""
warn "DKMS build did NOT land for kernel \$KERNELVER."
warn " dkms status -m \$NAME -v \$VERSION -k \$KERNELVER:"
warn " \$(printf '%s' "\$status" | head -1)"
warn ""
warn "Most likely cause: kernel headers package is missing."
warn " Raspberry Pi OS / Pi 5: apt install linux-headers-rpi-2712"
warn " Debian generic: apt install linux-headers-\$KERNELVER"
warn ""
warn "After installing headers, finish the install with:"
warn " sudo dkms autoinstall \$NAME/\$VERSION"
warn " sudo modprobe daedalus_v4l2"
warn ""
warn "Until then daedalus_v4l2 will NOT be loadable and the"
warn "userspace daedalus-v4l2 daemon will have nothing to talk to."
fi
fi
#DEBHELPER#
EOF
chmod 755 "$ROOT/DEBIAN/postinst"
cat > "$ROOT/DEBIAN/prerm" <<EOF
#!/bin/sh
set -e
NAME=${MODULE_NAME}
VERSION=${PKGVER}
if [ "\$1" = "remove" ] && command -v dkms >/dev/null 2>&1; then
dkms remove "\$NAME/\$VERSION" --all || true
fi
#DEBHELPER#
EOF
chmod 755 "$ROOT/DEBIAN/prerm"
cat > "$ROOT/DEBIAN/control" <<EOF
Package: daedalus-v4l2-dkms
Version: ${PKGVER}-${PKGREL}
Section: kernel
Priority: optional
Architecture: all
Depends: dkms (>= 2.1.0.0)
Recommends: daedalus-v4l2, linux-headers-rpi-2712 | linux-headers-rpi | linux-headers-generic | linux-headers
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Homepage: https://git.reauktion.de/reauktion/daedalus-v4l2
Description: V4L2 stateless decoder shim kernel module (DKMS) — Pi 5 / CM5
Out-of-tree V4L2 m2m kernel module for the daedalus-v4l2 stack on
Raspberry Pi 5 / CM5. Registers /dev/videoNN (V4L2 stateless m2m
decoder), /dev/mediaNN (media controller with request API), and
/dev/daedalus-v4l2 (chardev bridge to the userspace daemon).
.
The actual decode happens in the userspace daemon shipped by the
daedalus-v4l2 package — this module is just the kernel-side V4L2
plumbing. Install both to actually serve VAAPI / V4L2 clients.
.
Built via DKMS against the running kernel's headers.
EOF
DEB_OUT="daedalus-v4l2-dkms_${PKGVER}-${PKGREL}_all.deb"
dpkg-deb --root-owner-group --build "$ROOT" "$HERE/$DEB_OUT"
echo "built: $HERE/$DEB_OUT"
+36
View File
@@ -0,0 +1,36 @@
daedalus-v4l2-dkms (0.1.0+r18+g481279c-1) bookworm trixie; urgency=medium
* Bump to 481279c in lockstep with the userspace daedalus-v4l2
package (which ships the new systemd unit + modules-load.d
drop-in). No kernel-module behaviour change in this commit —
bump is purely to keep DKMS pkgver and userspace pkgver aligned
so /etc/modules-load.d/daedalus-v4l2.conf has a module to load.
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 16:00:00 +0000
daedalus-v4l2-dkms (0.1.0+r17+gf0cd29a-1) bookworm trixie; urgency=medium
* Bump to f0cd29a — Linux 6.18 compatibility fix. v4l2_fh_add /
v4l2_fh_del gained a `struct file *filp` second argument at
v6.18; module source now uses LINUX_VERSION_CODE conditional so
it builds against 6.12 (Pi 5 stock RPi-2712 kernel) AND 6.18+
(RPi-2712 / arm64). Verified DKMS rebuild on higgs
(6.18.29+rpt-rpi-2712) succeeds + /dev/daedalus-v4l2 appears.
* Recommends widened so apt pulls the right kernel-headers
metapackage on RPi OS: linux-headers-rpi-2712 first, then
linux-headers-rpi, then linux-headers-generic, then
linux-headers.
-- Markus Fritsche <mfritsche@reauktion.de> Tue, 20 May 2026 10:30:00 +0000
daedalus-v4l2-dkms (0.1.0+r16+gf55b2cd-1) bookworm trixie; urgency=medium
* Initial Debian DKMS packaging for the daedalus_v4l2 kernel module.
* Pinned to f55b2cd (Phase 8.13 close): kernel-side framework
integration (V4L2 m2m, dmabuf-export, media controller, request
API, NV12 single-plane + NV12M + P010 CAPTURE) that closes the
libva→/dev/video0→daemon round-trip with byte-exact pixels.
* Auto-builds via DKMS against the running kernel's headers.
* Companion userspace package: daedalus-v4l2 (daemon + tools).
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 23:00:00 +0000
+24
View File
@@ -0,0 +1,24 @@
Source: daedalus-v4l2-dkms
Section: kernel
Priority: optional
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Build-Depends: debhelper-compat (= 13)
Standards-Version: 4.6.2
Homepage: https://git.reauktion.de/reauktion/daedalus-v4l2
Package: daedalus-v4l2-dkms
Architecture: all
Depends: ${misc:Depends}, dkms (>= 2.1.0.0)
Recommends: daedalus-v4l2,
linux-headers-rpi-2712 | linux-headers-rpi | linux-headers-generic | linux-headers
Description: V4L2 stateless decoder shim kernel module (DKMS) — Pi 5 / CM5
Out-of-tree V4L2 m2m kernel module for the daedalus-v4l2 stack on
Raspberry Pi 5 / CM5. Registers /dev/videoNN (V4L2 stateless m2m
decoder), /dev/mediaNN (media controller with request API), and
/dev/daedalus-v4l2 (chardev bridge to the userspace daemon).
.
The actual decode happens in the userspace daemon shipped by the
daedalus-v4l2 package — this module is just the kernel-side V4L2
plumbing. Install both to actually serve VAAPI / V4L2 clients.
.
Built via DKMS against the running kernel's headers.
+21
View File
@@ -0,0 +1,21 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: daedalus-v4l2
Upstream-Contact: Markus Fritsche <fritsche.markus@gmail.com>
Source: https://git.reauktion.de/reauktion/daedalus-v4l2
Files: *
Copyright: 2026 Markus Fritsche <fritsche.markus@gmail.com>
License: GPL-2.0-or-later
Comment:
Kernel module (loadable into the Linux kernel) — GPL-2.0-or-later.
The shared protocol header carries an additional Linux-syscall-note
exception so userspace inclusion is BSD-clean.
License: GPL-2.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
On Debian systems, the complete text of the GNU General Public
License v2 can be found in `/usr/share/common-licenses/GPL-2'.
+181
View File
@@ -0,0 +1,181 @@
#!/bin/bash
# Build daedalus-v4l2_<ver>_arm64.deb (userspace daemon + test tools).
#
# Mirrors arch/daedalus-v4l2 (Arch Linux build). The companion DKMS
# package (debian/daedalus-v4l2-dkms) carries the kernel module
# separately so apt/dpkg can split kernel-version-tied and userspace
# upgrade cadence.
#
# Sibling Arch package: ../../arch/daedalus-v4l2/PKGBUILD
# Sibling DKMS package: ../daedalus-v4l2-dkms/build-deb.sh
# Upstream repo: https://git.reauktion.de/reauktion/daedalus-v4l2
set -euo pipefail
# Same pin as the Arch PKGBUILD. 481279c = "Phase 8.13: byte-exact
# end-to-end via libva (consumer target hit)" — first commit where the
# full ffmpeg -hwaccel vaapi → libva → /dev/video0 → daemon path lands
# a pixel-correct decoded frame back in ffmpeg.
UPSTREAM_COMMIT=481279c9bffd19e32c8f3299897e9b63fc5a24aa
PKGVER=0.1.0+r18+g481279c
PKGREL=1 # reset for new upstream pin (481279c — Phase 8.13 close)
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build. 2026-05-18 23:00 UTC — Phase 8.13 close.
export SOURCE_DATE_EPOCH=1779231600
work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
curl -sSLfo daedalus-v4l2.tar.gz \
"https://git.reauktion.de/reauktion/daedalus-v4l2/archive/${UPSTREAM_COMMIT}.tar.gz"
tar xzf daedalus-v4l2.tar.gz
SRCDIR=daedalus-v4l2
# Build daemon (CMake)
cd "$SRCDIR/daemon"
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr
cmake --build build
# Build test tools (in-tree Makefile)
cd "$work/$SRCDIR/tools"
make
# Stage
ROOT="$work/pkgroot"
mkdir -p "$ROOT/DEBIAN" \
"$ROOT/usr/bin" \
"$ROOT/usr/libexec/daedalus-v4l2" \
"$ROOT/usr/include" \
"$ROOT/usr/share/doc/daedalus-v4l2" \
"$ROOT/lib/systemd/system" \
"$ROOT/usr/lib/modules-load.d"
install -m 755 "$work/$SRCDIR/daemon/build/daedalus_v4l2_daemon" \
"$ROOT/usr/bin/daedalus_v4l2_daemon"
install -m 755 "$work/$SRCDIR/tools/test_chardev_pingpong" \
"$ROOT/usr/libexec/daedalus-v4l2/test_chardev_pingpong"
install -m 755 "$work/$SRCDIR/tools/test_m2m_decode" \
"$ROOT/usr/libexec/daedalus-v4l2/test_m2m_decode"
install -m 755 "$work/$SRCDIR/tools/test_m2m_stream" \
"$ROOT/usr/libexec/daedalus-v4l2/test_m2m_stream"
install -m 644 "$work/$SRCDIR/include/daedalus_v4l2_proto.h" \
"$ROOT/usr/include/daedalus_v4l2_proto.h"
# systemd unit + module autoload — without these the daemon never
# starts and the libva/VAAPI consumer's REQ_DECODE has nobody on
# the other end of /dev/daedalus-v4l2.
install -m 644 "$work/$SRCDIR/packaging/systemd/daedalus-v4l2.service" \
"$ROOT/lib/systemd/system/daedalus-v4l2.service"
install -m 644 "$work/$SRCDIR/packaging/systemd/daedalus-v4l2.modules-load" \
"$ROOT/usr/lib/modules-load.d/daedalus-v4l2.conf"
install -m 644 "$work/$SRCDIR/README.md" \
"$ROOT/usr/share/doc/daedalus-v4l2/README.md"
for d in "$work/$SRCDIR/docs/"*.md; do
install -m 644 "$d" "$ROOT/usr/share/doc/daedalus-v4l2/$(basename "$d")"
done
install -Dm644 "$HERE/debian/copyright" "$ROOT/usr/share/doc/daedalus-v4l2/copyright"
install -Dm644 "$HERE/debian/changelog" "$ROOT/usr/share/doc/daedalus-v4l2/changelog.Debian"
gzip -9 -n "$ROOT/usr/share/doc/daedalus-v4l2/changelog.Debian"
# DEBIAN/postinst — enable service + reload modules-load.d so the
# kernel module loads now if daedalus-v4l2-dkms is also installed.
# Does NOT auto-start the service — that requires /dev/daedalus-v4l2
# to already exist (the ConditionPathExists= in the .service file)
# which may not be true on the very first install before the user
# reboots or manually modprobes. Operator decides when to start.
cat > "$ROOT/DEBIAN/postinst" <<'POSTINST'
#!/bin/sh
set -e
if [ "$1" = "configure" ]; then
# Reload systemd so the new unit file is visible.
if command -v systemctl >/dev/null 2>&1; then
systemctl daemon-reload >/dev/null 2>&1 || true
systemctl enable daedalus-v4l2.service >/dev/null 2>&1 || true
fi
# Trigger /usr/lib/modules-load.d/daedalus-v4l2.conf without a
# reboot. Harmless if the module is already loaded; logs to
# journal if it can't load (most common cause: dkms hasn't built
# the module yet for the running kernel — see daedalus-v4l2-dkms
# postinst for the loud-warning path).
if command -v systemd-modules-load >/dev/null 2>&1; then
systemd-modules-load >/dev/null 2>&1 || true
fi
# Auto-start if /dev/daedalus-v4l2 came up (i.e. module loaded
# successfully). ConditionPathExists in the unit file means
# `systemctl start` is a no-op if the device isn't there yet —
# avoids spurious failures during apt install on a host where
# daedalus-v4l2-dkms hasn't built yet.
if [ -e /dev/daedalus-v4l2 ] && command -v systemctl >/dev/null 2>&1; then
systemctl start daedalus-v4l2.service >/dev/null 2>&1 || true
fi
fi
#DEBHELPER#
POSTINST
chmod 755 "$ROOT/DEBIAN/postinst"
cat > "$ROOT/DEBIAN/prerm" <<'PRERM'
#!/bin/sh
set -e
if [ "$1" = "remove" ] && command -v systemctl >/dev/null 2>&1; then
systemctl stop daedalus-v4l2.service >/dev/null 2>&1 || true
systemctl disable daedalus-v4l2.service >/dev/null 2>&1 || true
fi
#DEBHELPER#
PRERM
chmod 755 "$ROOT/DEBIAN/prerm"
cat > "$ROOT/DEBIAN/postrm" <<'POSTRM'
#!/bin/sh
set -e
if command -v systemctl >/dev/null 2>&1; then
systemctl daemon-reload >/dev/null 2>&1 || true
fi
#DEBHELPER#
POSTRM
chmod 755 "$ROOT/DEBIAN/postrm"
cat > "$ROOT/DEBIAN/control" <<EOF
Package: daedalus-v4l2
Version: ${PKGVER}-${PKGREL}
Section: video
Priority: optional
Architecture: arm64
Depends: ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier), libdrm2
Recommends: daedalus-v4l2-dkms
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Homepage: https://git.reauktion.de/reauktion/daedalus-v4l2
Description: Userspace daemon for the daedalus_v4l2 stateless decoder shim
daedalus-v4l2 ships the userspace daemon that backs the daedalus_v4l2
out-of-tree V4L2 kernel module on Raspberry Pi 5 / CM5. Together they
expose /dev/videoNN + /dev/mediaNN as a V4L2 stateless decoder for
VP9, AV1, and H.264 — actual decoding happens in this single-threaded
daemon via dlopen'd FFmpeg, with decoded NV12 / P010 frames shipped
back through dmabuf.
.
Consumed end-to-end by libva-v4l2-request-fourier (>= 1.0.0+r376) so
that 'ffmpeg -hwaccel vaapi' against vp9_small.ivf produces a
byte-exact NV12 frame.
.
The kernel module ships separately in daedalus-v4l2-dkms; install
both to actually serve V4L2 clients.
EOF
DEB_OUT="daedalus-v4l2_${PKGVER}-${PKGREL}_arm64.deb"
dpkg-deb --root-owner-group --build "$ROOT" "$HERE/$DEB_OUT"
echo "built: $HERE/$DEB_OUT"
+38
View File
@@ -0,0 +1,38 @@
daedalus-v4l2 (0.1.0+r18+g481279c-1) bookworm trixie; urgency=medium
* Bump to 481279c. Upstream landed the systemd unit + modules-load.d
drop-in (packaging/systemd/daedalus-v4l2.{service,modules-load}).
* Package now ships /lib/systemd/system/daedalus-v4l2.service and
/usr/lib/modules-load.d/daedalus-v4l2.conf.
* postinst: daemon-reload, enable the service, trigger
systemd-modules-load, and start if /dev/daedalus-v4l2 is already
present. Operator no longer needs to remember the modprobe +
systemctl-enable dance after install.
* prerm/postrm: stop + disable + daemon-reload.
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 16:00:00 +0000
daedalus-v4l2 (0.1.0+r17+gf0cd29a-1) bookworm trixie; urgency=medium
* Bump to f0cd29a alongside daedalus-v4l2-dkms. No userspace
change — the daemon binary in this release is bit-identical to
the f55b2cd one (the f0cd29a commit only touches kernel/). Bump
keeps the userspace + DKMS pkgver lockstep so depmod /
LIBVA_DRIVER_NAME selection stays correct on hosts that
upgrade.
-- Markus Fritsche <mfritsche@reauktion.de> Tue, 20 May 2026 10:30:00 +0000
daedalus-v4l2 (0.1.0+r16+gf55b2cd-1) bookworm trixie; urgency=medium
* Initial Debian packaging for the daedalus-v4l2 userspace daemon.
* Pinned to f55b2cd (Phase 8.13 close): first commit where the full
ffmpeg -hwaccel vaapi → libva-v4l2-request-fourier → /dev/video0
→ daemon path lands a pixel-correct decoded NV12 frame back in
ffmpeg.
* Codecs: VP9, AV1, H.264 (all via dlopen'd FFmpeg 7.1.3).
* Capture formats: NV12M (2 plane), NV12 (1 plane, for libva),
P010 (10-bit single plane).
* Companion package: daedalus-v4l2-dkms (kernel module).
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 23:00:00 +0000
+34
View File
@@ -0,0 +1,34 @@
Source: daedalus-v4l2
Section: video
Priority: optional
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Build-Depends: debhelper-compat (= 13),
cmake,
ninja-build,
pkg-config,
libavformat-dev (>= 7.1),
libavcodec-dev (>= 7.1),
libavutil-dev (>= 7.1)
Standards-Version: 4.6.2
Homepage: https://git.reauktion.de/reauktion/daedalus-v4l2
Package: daedalus-v4l2
Architecture: arm64
Depends: ${misc:Depends}, ${shlibs:Depends},
ffmpeg (>= 7.1),
libdrm2
Recommends: daedalus-v4l2-dkms
Description: Userspace daemon for the daedalus_v4l2 stateless decoder shim
daedalus-v4l2 ships the userspace daemon that backs the daedalus_v4l2
out-of-tree V4L2 kernel module on Raspberry Pi 5 / CM5. Together they
expose /dev/videoNN + /dev/mediaNN as a V4L2 stateless decoder for
VP9, AV1, and H.264 — actual decoding happens in this single-threaded
daemon via dlopen'd FFmpeg, with decoded NV12 / P010 frames shipped
back through dmabuf.
.
Consumed end-to-end by libva-v4l2-request-fourier (>= 1.0.0+r376) so
that 'ffmpeg -hwaccel vaapi' against vp9_small.ivf produces a
byte-exact NV12 frame.
.
The kernel module ships separately in daedalus-v4l2-dkms; install
both to actually serve V4L2 clients.
+40
View File
@@ -0,0 +1,40 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: daedalus-v4l2
Upstream-Contact: Markus Fritsche <fritsche.markus@gmail.com>
Source: https://git.reauktion.de/reauktion/daedalus-v4l2
Files: *
Copyright: 2026 Markus Fritsche <fritsche.markus@gmail.com>
License: BSD-2-Clause
Files: include/daedalus_v4l2_proto.h
Copyright: 2026 Markus Fritsche <fritsche.markus@gmail.com>
License: GPL-2.0-or-later WITH Linux-syscall-note
Comment:
Shared kernel↔daemon wire-protocol header. GPL-2.0-or-later (matches
the kernel module that includes it) with the standard
Linux-syscall-note exception so userspace inclusion is BSD-clean.
License: BSD-2-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
.
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED.
License: GPL-2.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
On Debian systems, the complete text of the GNU General Public
License v2 can be found in `/usr/share/common-licenses/GPL-2'.
@@ -0,0 +1,166 @@
--- a/libavutil/hwcontext_v4l2request.c
+++ b/libavutil/hwcontext_v4l2request.c
@@ -19,12 +19,13 @@
#include "config.h"
#include <fcntl.h>
#include <linux/dma-buf.h>
#include <linux/media.h>
#include <sys/ioctl.h>
+#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <drm_fourcc.h>
#include <libudev.h>
@@ -690,12 +691,125 @@
}
udev_enumerate_unref(enumerate);
return ret;
}
+/*
+ * Brute-force fallback used when libudev's scan fails (e.g. inside firefox's
+ * RDD sandbox where Mozilla's broker rejects fd-relative openat used by
+ * systemd's chase() symlink resolver). Iterates /dev/video[0..63], picks the
+ * one whose major/minor matches the requested devnum.
+ */
+static char *v4l2request_devnum_to_video_path_brute(dev_t devnum)
+{
+ char path[32];
+ struct stat st;
+ for (int i = 0; i < 64; i++) {
+ snprintf(path, sizeof(path), "/dev/video%d", i);
+ if (stat(path, &st) < 0)
+ continue;
+ if (st.st_rdev == devnum)
+ return av_strdup(path);
+ }
+ return NULL;
+}
+
+/* Brute-force version of v4l2request_probe_video_devices: replaces the
+ * udev_device_new_from_devnum + udev_device_get_devnode flow with
+ * stat()-based major/minor matching against /dev/video[0..63]. */
+static int v4l2request_probe_video_devices_brute(AVHWFramesContext *hwfc,
+ uint32_t pixelformat,
+ uint32_t buffersize)
+{
+ AVV4L2RequestFramesContext *fctx = hwfc->hwctx;
+ AVV4L2RequestFramesContextInternal *fctxi = fctx->internal;
+ struct media_device_info device_info;
+ struct media_v2_topology topology = {0};
+ struct media_v2_interface *interfaces;
+ char *path;
+ dev_t devnum;
+ int ret;
+
+ if (ioctl(fctxi->media_fd, MEDIA_IOC_DEVICE_INFO, &device_info) < 0)
+ return AVERROR(errno);
+
+ if (ioctl(fctxi->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology) < 0)
+ return AVERROR(errno);
+
+ if (!topology.num_interfaces)
+ return AVERROR(ENOENT);
+
+ interfaces = av_calloc(topology.num_interfaces,
+ sizeof(struct media_v2_interface));
+ if (!interfaces)
+ return AVERROR(ENOMEM);
+
+ topology.ptr_interfaces = (__u64)(uintptr_t)interfaces;
+ if (ioctl(fctxi->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology) < 0) {
+ ret = AVERROR(errno);
+ goto fail;
+ }
+
+ ret = AVERROR(ENOENT);
+ for (unsigned i = 0; i < topology.num_interfaces; i++) {
+ if (interfaces[i].intf_type != MEDIA_INTF_T_V4L_VIDEO)
+ continue;
+
+ devnum = makedev(interfaces[i].devnode.major,
+ interfaces[i].devnode.minor);
+ path = v4l2request_devnum_to_video_path_brute(devnum);
+ if (!path)
+ continue;
+
+ ret = v4l2request_probe_video_device(hwfc, path, pixelformat, buffersize);
+ if (!ret) {
+ av_log(hwfc, AV_LOG_INFO,
+ "Using V4L2 media driver %s (brute-force) for %s\n",
+ device_info.driver, av_fourcc2str(pixelformat));
+ av_free(path);
+ break;
+ }
+ av_free(path);
+ }
+
+fail:
+ av_free(interfaces);
+ return ret;
+}
+
+/* Brute-force fallback for v4l2request_probe_media_devices(). Iterates
+ * /dev/media[0..15], opens each, probes via topology+stat. */
+static int v4l2request_probe_media_devices_brute(AVHWFramesContext *hwfc,
+ uint32_t pixelformat,
+ uint32_t buffersize)
+{
+ AVV4L2RequestFramesContext *fctx = hwfc->hwctx;
+ AVV4L2RequestFramesContextInternal *fctxi = fctx->internal;
+ char path[32];
+ int ret = AVERROR(ENOENT);
+
+ for (int i = 0; i < 16; i++) {
+ snprintf(path, sizeof(path), "/dev/media%d", i);
+
+ fctxi->media_fd = open(path, O_RDWR);
+ if (fctxi->media_fd < 0)
+ continue;
+
+ ret = v4l2request_probe_video_devices_brute(hwfc, pixelformat,
+ buffersize);
+ if (!ret)
+ return 0;
+
+ close(fctxi->media_fd);
+ fctxi->media_fd = -1;
+ }
+
+ return ret;
+}
+
static int v4l2request_open_decoder(AVHWFramesContext *hwfc)
{
AVV4L2RequestFramesContext *fctx = hwfc->hwctx;
uint32_t buffersize;
struct udev *udev;
int ret;
@@ -712,12 +826,23 @@
buffersize = FFMAX(hwfc->width * hwfc->height * 3 / 2, 256 * 1024);
// Probe all media devices (auto-detection)
ret = v4l2request_probe_media_devices(hwfc, udev, fctx->pixelformat, buffersize);
+ // Brute-force fallback when libudev fails. Firefox-fourier hits this
+ // because Mozilla's RDD sandbox blocks fd-relative openat used by
+ // systemd's chase() symlink resolver inside udev_enumerate_scan_devices.
+ if (ret < 0) {
+ av_log(hwfc, AV_LOG_INFO,
+ "libudev probe failed (%d), falling back to brute-force /dev/media*\n",
+ ret);
+ ret = v4l2request_probe_media_devices_brute(hwfc, fctx->pixelformat,
+ buffersize);
+ }
+
udev_unref(udev);
return ret;
}
static AVBufferRef *v4l2request_v4l2_buffer_alloc(AVHWFramesContext *hwfc,
struct v4l2_format *format)
@@ -0,0 +1,178 @@
From 0cd6e669735e453ec8772f111065bbb2f70a5bc6 Mon Sep 17 00:00:00 2001
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Mon, 18 May 2026 07:27:10 +0000
Subject: [PATCH] avutil/hwcontext_v4l2request: unpack NV15 to P010 in
transfer_data_from
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
V4L2_PIX_FMT_NV15 (RK3399/RK3588 rkvdec 10-bit 4:2:0 capture) is mapped to
sw_format = AV_PIX_FMT_YUV420P10 in v4l2request_capture_pixelformats[]. The
existing transfer_get_formats explicitly blanked the format list for that
sw_format, so 'ffmpeg -hwaccel v4l2request -vf hwdownload,format=p010le' on
a Hi10P / Main10 input failed at filter init with EINVAL before reaching
the actual decode (which itself succeeds — 2 frames decoded cleanly).
Expose AV_PIX_FMT_P010 as the transfer target for NV15-backed surfaces and
unpack the packed 10-bit samples into the standard high-bits-of-16 layout
inside transfer_data_from. Luma and chroma share the same packing format
(5 bytes per 4 samples, little endian); chroma plane is W × H/2 samples
for 4:2:0.
The other 'needs custom unpack' sw_formats (YUV420P / Allwinner NV12_32L32
tiled and YUV422P10 / rkvdec NV20) keep the original ENOSYS path because
they need different unpack code that isn't covered by this patch.
Closes marfrit/marfrit-packages#21.
---
libavutil/hwcontext_v4l2request.c | 111 +++++++++++++++++++++++++++++-
1 file changed, 110 insertions(+), 1 deletion(-)
diff --git a/libavutil/hwcontext_v4l2request.c b/libavutil/hwcontext_v4l2request.c
index b6633d9081..3842160dfb 100644
--- a/libavutil/hwcontext_v4l2request.c
+++ b/libavutil/hwcontext_v4l2request.c
@@ -1073,6 +1073,56 @@ fail:
return ret;
}
+/*
+ * Unpack one NV15-packed 10-bit plane (5 bytes per 4 samples, little endian)
+ * into a P010-style plane (10 bits in the high bits of a 16-bit container).
+ * `dst_stride` is in bytes; `src_stride` is bytes per row of NV15 data.
+ */
+static void v4l2request_nv15_unpack_plane_to_p010(const uint8_t *src,
+ uint16_t *dst,
+ unsigned width,
+ unsigned height,
+ unsigned src_stride,
+ unsigned dst_stride)
+{
+ for (unsigned y = 0; y < height; y++) {
+ const uint8_t *s = src + y * src_stride;
+ uint16_t *d = (uint16_t *)((uint8_t *)dst + y * dst_stride);
+ unsigned x;
+
+ for (x = 0; x + 4 <= width; x += 4) {
+ uint16_t a = (uint16_t)s[0] | ((uint16_t)(s[1] & 0x03) << 8);
+ uint16_t b = ((uint16_t)s[1] >> 2) | ((uint16_t)(s[2] & 0x0F) << 6);
+ uint16_t c = ((uint16_t)s[2] >> 4) | ((uint16_t)(s[3] & 0x3F) << 4);
+ uint16_t e = ((uint16_t)s[3] >> 6) | ((uint16_t)s[4] << 2);
+
+ d[0] = (uint16_t)(a << 6);
+ d[1] = (uint16_t)(b << 6);
+ d[2] = (uint16_t)(c << 6);
+ d[3] = (uint16_t)(e << 6);
+
+ d += 4;
+ s += 5;
+ }
+
+ if (x < width) {
+ unsigned rem = width - x;
+ uint16_t pix[4] = { 0, 0, 0, 0 };
+
+ pix[0] = (uint16_t)s[0] | ((uint16_t)(s[1] & 0x03) << 8);
+ if (rem >= 2)
+ pix[1] = ((uint16_t)s[1] >> 2) | ((uint16_t)(s[2] & 0x0F) << 6);
+ if (rem >= 3)
+ pix[2] = ((uint16_t)s[2] >> 4) | ((uint16_t)(s[3] & 0x3F) << 4);
+ if (rem >= 4)
+ pix[3] = ((uint16_t)s[3] >> 6) | ((uint16_t)s[4] << 2);
+
+ for (unsigned j = 0; j < rem; j++)
+ d[j] = (uint16_t)(pix[j] << 6);
+ }
+ }
+}
+
static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
enum AVHWFrameTransferDirection dir,
enum AVPixelFormat **formats)
@@ -1082,6 +1132,22 @@ static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
if (dir == AV_HWFRAME_TRANSFER_DIRECTION_TO)
return AVERROR(ENOSYS);
+ /*
+ * NV15-backed surfaces (sw_format = YUV420P10) are exposed as P010 to
+ * downstream filters: the unpack below converts the packed 10-bit
+ * samples into the standard high-bits-of-16 layout. Hi10P / Main10
+ * VAAPI/v4l2-request decode reaches userspace through this path.
+ */
+ if (hwfc->sw_format == AV_PIX_FMT_YUV420P10) {
+ fmts = av_malloc_array(2, sizeof(*fmts));
+ if (!fmts)
+ return AVERROR(ENOMEM);
+ fmts[0] = AV_PIX_FMT_P010;
+ fmts[1] = AV_PIX_FMT_NONE;
+ *formats = fmts;
+ return 0;
+ }
+
fmts = av_malloc_array(2, sizeof(*fmts));
if (!fmts)
return AVERROR(ENOMEM);
@@ -1089,8 +1155,13 @@ static int v4l2request_transfer_get_formats(AVHWFramesContext *hwfc,
fmts[0] = hwfc->sw_format;
fmts[1] = AV_PIX_FMT_NONE;
+ /*
+ * Tiled-NV12-32L32 (Allwinner) and NV20 (rkvdec 4:2:2 10-bit) still need
+ * dedicated unpacks before hwdownload can consume them; leave them as
+ * "no transfer formats" so the filter graph reports the limitation
+ * rather than silently producing garbage.
+ */
if (hwfc->sw_format == AV_PIX_FMT_YUV420P ||
- hwfc->sw_format == AV_PIX_FMT_YUV420P10 ||
hwfc->sw_format == AV_PIX_FMT_YUV422P10)
fmts[0] = AV_PIX_FMT_NONE;
@@ -1110,6 +1181,44 @@ static int v4l2request_transfer_data_from(AVHWFramesContext *hwfc,
map = av_frame_alloc();
if (!map)
return AVERROR(ENOMEM);
+
+ /*
+ * For NV15→P010, map the raw NV15 bytes (sw_format) and unpack into
+ * dst's P010 storage. Otherwise fall through to the original byte-copy
+ * path used for 1:1 sw_format matches (NV12, NV16, AFBC handled by DRM).
+ */
+ if (hwfc->sw_format == AV_PIX_FMT_YUV420P10) {
+ /*
+ * Only P010 is advertised by transfer_get_formats for this sw_format;
+ * a caller that bypasses get_formats and asks for anything else would
+ * silently corrupt output via av_frame_copy on NV15-packed bytes.
+ * Reject explicitly.
+ */
+ if (dst->format != AV_PIX_FMT_P010) {
+ ret = AVERROR(ENOSYS);
+ goto fail;
+ }
+
+ map->format = hwfc->sw_format;
+ ret = v4l2request_map_frame(hwfc, map, src);
+ if (ret)
+ goto fail;
+
+ v4l2request_nv15_unpack_plane_to_p010(map->data[0],
+ (uint16_t *)dst->data[0],
+ dst->width, dst->height,
+ map->linesize[0],
+ dst->linesize[0]);
+ /* NV15 chroma plane is W × H/2 samples (4:2:0, UV interleaved). */
+ v4l2request_nv15_unpack_plane_to_p010(map->data[1],
+ (uint16_t *)dst->data[1],
+ dst->width, dst->height / 2,
+ map->linesize[1],
+ dst->linesize[1]);
+ ret = 0;
+ goto fail;
+ }
+
map->format = dst->format;
ret = v4l2request_map_frame(hwfc, map, src);
--
2.47.3
+221
View File
@@ -0,0 +1,221 @@
#!/bin/bash
# Build ffmpeg-v4l2-request-fourier_<ver>_arm64.deb (the Kwiboo FFmpeg
# fork with the V4L2-Request API hwaccel patches).
#
# Mirror of arch/ffmpeg-v4l2-request-fourier into the Debian tree.
# Provides the patched `ffmpeg` + `ffprobe` binaries plus the shared
# libav* libraries with v4l2-request support, so consumers like
# mpv-fourier (and the kdirect bit-exact reference test rig) work
# end-to-end without a stock-Debian FFmpeg fallback.
#
# **Private prefix /opt/fourier** (Path A per fourier-debian
# architecture discussion 2026-05-19). Stock Debian trixie ships
# FFmpeg 7.1.x = libavcodec.so.61; this package ships FFmpeg 8.1 =
# libavcodec.so.62 — different SOVERSION, NOT a drop-in for trixie's
# KDE/VLC/etc. Living in /opt/fourier/lib keeps the stock system
# intact; only fourier-aware consumers (firefox-fourier, mpv-fourier,
# daedalus-v4l2) RPATH into /opt/fourier/lib. Postinst drops an
# ld.so.conf.d entry so dlopen-based consumers (firefox at runtime)
# find the libs by SONAME without LD_LIBRARY_PATH wrappers.
#
# Big build: 25-40 min on a runner. Output is a single .deb that
# bundles ffmpeg/ffprobe + libavcodec.so.62 + libavformat.so.62 etc.
# all together — no split per-library subpackages. Easier to consume,
# trades off finer-grained downgrades.
#
# Sibling Arch package: ../../arch/ffmpeg-v4l2-request-fourier/PKGBUILD
# Upstream: https://github.com/Kwiboo/FFmpeg (branch v4l2-request-n8.1)
set -euo pipefail
# Same pin as arch/ — v4l2-request-n8.1 tip 2026-04-24.
UPSTREAM_COMMIT=b57fbbe50c9b2656fad86a1a7eeabfd2b2a50935
FFMPEG_VERSION=8.1
# epoch 2 matches Debian's stock ffmpeg (currently 7:7.1.x in trixie);
# +rfourier suffix to avoid colliding with upstream/Debian rebuilds.
PKGVER=2:${FFMPEG_VERSION}+rfourier+gb57fbbe
PKGREL=2 # pkgrel=2 — Path A move to /opt/fourier prefix (2026-05-19)
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build. 2026-05-18 23:00 UTC — Phase 8.13 close.
export SOURCE_DATE_EPOCH=1779231600
work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
git clone --depth 1 \
--branch v4l2-request-n8.1 \
https://github.com/Kwiboo/FFmpeg.git FFmpeg
cd FFmpeg
# git fetch the specific commit (depth=1 of branch tip might not be it)
if [ "$(git rev-parse HEAD)" != "$UPSTREAM_COMMIT" ]; then
git fetch origin "$UPSTREAM_COMMIT"
git checkout "$UPSTREAM_COMMIT"
fi
# Apply patches (same as Arch).
patch -Np1 -i "$HERE/0001-libudev-bypass-fallback.patch"
patch -Np1 -i "$HERE/0002-nv15-to-p010-unpack.patch"
# Configure with Arch-parity flags. Drops the same set of features
# (X11, AMF, CUDA, FireWire, AviSynth, Bluray, OpenMPT, JPEG-XL,
# Theora, XVid, rsvg, soxr, ssh, vidstab, modplug, SDL2, Vulkan,
# JACK, GSM, Speex) — not needed on the Fourier fleet, keeps the .deb
# smaller and the dependency graph tighter.
./configure \
--prefix=/opt/fourier \
--bindir=/opt/fourier/bin \
--libdir=/opt/fourier/lib \
--shlibdir=/opt/fourier/lib \
--incdir=/opt/fourier/include \
--datadir=/opt/fourier/share/ffmpeg \
--mandir=/opt/fourier/share/man \
--extra-ldexeflags='-Wl,-rpath,/opt/fourier/lib' \
--extra-ldsoflags='-Wl,-rpath,/opt/fourier/lib' \
--disable-debug \
--disable-static \
--disable-doc \
--disable-stripping \
--enable-shared \
--enable-gpl \
--enable-version3 \
--enable-pic \
--enable-neon \
--arch=aarch64 \
--enable-libdrm \
--enable-libv4l2 \
--enable-libudev \
--enable-v4l2-request \
--enable-v4l2_m2m \
--enable-vaapi \
--enable-opengl \
--enable-gnutls \
--enable-fontconfig \
--enable-libass \
--enable-libfreetype \
--enable-libfribidi \
--enable-libxml2 \
--enable-libpulse \
--enable-libdav1d \
--enable-libopus \
--enable-libvorbis \
--enable-libmp3lame \
--enable-libvpx \
--enable-libx264 \
--enable-libx265 \
--enable-libwebp \
--host-cflags='-fPIC'
make -j"$(nproc)"
make tools/qt-faststart
# Stage
ROOT="$work/pkgroot"
make DESTDIR="$ROOT" install
install -Dm755 tools/qt-faststart "$ROOT/opt/fourier/bin/qt-faststart"
# ld.so.conf.d entry so dlopen-based consumers (firefox-fourier at
# runtime) find /opt/fourier/lib/libavcodec.so.62 by SONAME without an
# LD_LIBRARY_PATH wrapper. No risk of contaminating stock binaries:
# stock KDE/VLC link against libavcodec.so.61 (different SONAME), so
# the loader never sees our .so.62 as a match for their .so.61.
install -Dm644 /dev/stdin "$ROOT/etc/ld.so.conf.d/fourier.conf" <<EOF
# fourier campaign: FFmpeg 8.1 fork + libVA fork in private prefix.
/opt/fourier/lib
EOF
# Optional /usr/bin shims so users can call ffmpeg-fourier without
# remembering the /opt path. No conflict with stock /usr/bin/ffmpeg.
install -d "$ROOT/usr/bin"
ln -sf /opt/fourier/bin/ffmpeg "$ROOT/usr/bin/ffmpeg-fourier"
ln -sf /opt/fourier/bin/ffprobe "$ROOT/usr/bin/ffprobe-fourier"
# Doc
mkdir -p "$ROOT/usr/share/doc/ffmpeg-v4l2-request-fourier" "$ROOT/DEBIAN"
install -Dm644 "$HERE/debian/copyright" \
"$ROOT/usr/share/doc/ffmpeg-v4l2-request-fourier/copyright"
install -Dm644 "$HERE/debian/changelog" \
"$ROOT/usr/share/doc/ffmpeg-v4l2-request-fourier/changelog.Debian"
gzip -9 -n "$ROOT/usr/share/doc/ffmpeg-v4l2-request-fourier/changelog.Debian"
cat > "$ROOT/DEBIAN/control" <<EOF
Package: ffmpeg-v4l2-request-fourier
Version: ${PKGVER}-${PKGREL}
Section: video
Priority: optional
Architecture: arm64
Depends: libc6,
libdrm2,
libfontconfig1,
libfreetype6,
libfribidi0,
libxml2,
libpulse0,
libdav1d7 | libdav1d6,
libopus0,
libvorbis0a,
libvorbisenc2,
libmp3lame0,
libvpx9 | libvpx8 | libvpx7,
libx264-164 | libx264-163,
libx265-215 | libx265-209 | libx265-199,
libwebp7 | libwebp6,
libwebpmux3,
libass9,
libgnutls30,
libudev1,
libv4l-0,
libva2,
libva-drm2
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Homepage: https://github.com/Kwiboo/FFmpeg
Description: FFmpeg with V4L2 Request API hwaccel (Kwiboo fork, /opt/fourier prefix)
FFmpeg ${FFMPEG_VERSION} patched with the V4L2 Request API stateless
video decoder hwaccel — Kwiboo's long-running rebase of Jernej
Škrabec's v4l2-request patchset onto FFmpeg release tags.
.
Provides 'ffmpeg -hwaccel v4l2request' / '-hwaccel drm' routes that
drive rkvdec / hantro / cedrus / rpi-hevc-dec / daedalus_v4l2
stateless decoders directly through libavcodec's hwdevice DRM path,
bypassing libva. Used by mpv-fourier and firefox-fourier as their
backing FFmpeg, and as the kdirect bit-exact reference in libva-v4l2-
request-fourier validation.
.
INSTALLED TO /opt/fourier (NOT /usr): this is FFmpeg 8.1 (libav*.so.62)
sitting alongside Debian trixie's stock FFmpeg 7.1 (libav*.so.61) —
different SONAMEs, no symbol clash. Consumer binaries RPATH into
/opt/fourier/lib; ld.so.conf.d/fourier.conf adds the path to ld.so
cache for dlopen-by-SONAME (firefox). /usr/bin/ffmpeg-fourier and
/usr/bin/ffprobe-fourier are convenience symlinks to /opt/fourier/bin.
Stock 'ffmpeg' command unaffected.
.
Drops X11/AMF/CUDA/Bluray/JACK/Vulkan/SDL2/Theora/XVid/Speex/JPEG-XL
per Fourier fleet policy (Wayland + ARM + video-decode focus).
No 'ffplay' binary; mpv-fourier covers interactive playback.
EOF
# ldconfig must be re-run after install so /opt/fourier/lib is in the cache.
cat > "$ROOT/DEBIAN/postinst" <<'PEOF'
#!/bin/sh
set -e
if [ "$1" = "configure" ]; then
ldconfig
fi
#DEBHELPER#
PEOF
chmod 755 "$ROOT/DEBIAN/postinst"
cat > "$ROOT/DEBIAN/postrm" <<'PEOF'
#!/bin/sh
set -e
if [ "$1" = "remove" ] || [ "$1" = "purge" ]; then
ldconfig
fi
#DEBHELPER#
PEOF
chmod 755 "$ROOT/DEBIAN/postrm"
DEB_OUT="ffmpeg-v4l2-request-fourier_${PKGVER//:/%3a}-${PKGREL}_arm64.deb"
dpkg-deb --root-owner-group --build "$ROOT" "$HERE/$DEB_OUT"
echo "built: $HERE/$DEB_OUT"
+14
View File
@@ -0,0 +1,14 @@
ffmpeg-v4l2-request-fourier (2:8.1+rfourier+gb57fbbe-1) bookworm trixie; urgency=medium
* Initial Debian packaging for the Kwiboo FFmpeg fork with V4L2
Request API hwaccel patches.
* Mirror of arch/ffmpeg-v4l2-request-fourier (same pin b57fbbe,
same configure flags, same 2 patches: libudev-bypass-fallback +
nv15-to-p010-unpack).
* Drop-in replacement for Debian's stock ffmpeg + libav*; takes
epoch 2 to win the apt version comparison.
* Required by mpv-fourier and firefox-fourier; not strictly
required for the VAAPI-only path on daedalus-v4l2 hosts (stock
libva + Debian ffmpeg works there).
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 23:00:00 +0000
+61
View File
@@ -0,0 +1,61 @@
Source: ffmpeg-v4l2-request-fourier
Section: video
Priority: optional
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Build-Depends: debhelper-compat (= 13),
git,
nasm,
pkg-config,
libass-dev,
libdrm-dev,
libfontconfig1-dev,
libfreetype6-dev,
libfribidi-dev,
libgnutls28-dev,
libmp3lame-dev,
libopus-dev,
libpulse-dev,
libudev-dev,
libv4l-dev,
libva-dev,
libvorbis-dev,
libvpx-dev,
libwebp-dev,
libx264-dev,
libx265-dev,
libxml2-dev,
libdav1d-dev,
linux-libc-dev
Standards-Version: 4.6.2
Homepage: https://github.com/Kwiboo/FFmpeg
Package: ffmpeg-v4l2-request-fourier
Architecture: arm64
Depends: ${misc:Depends}, ${shlibs:Depends}
Conflicts: ffmpeg,
libavcodec61, libavformat61, libavutil59,
libswresample5, libswscale8, libavdevice61, libavfilter10,
libpostproc58
Replaces: ffmpeg,
libavcodec61, libavformat61, libavutil59,
libswresample5, libswscale8, libavdevice61, libavfilter10,
libpostproc58
Provides: ffmpeg (= ${binary:Version}),
libavcodec.so.61,
libavformat.so.61,
libavutil.so.59
Description: FFmpeg with V4L2 Request API hwaccel (Kwiboo fork)
FFmpeg 8.1 patched with the V4L2 Request API stateless video decoder
hwaccel — Kwiboo's long-running rebase of Jernej Škrabec's
v4l2-request patchset onto FFmpeg release tags.
.
Provides 'ffmpeg -hwaccel v4l2request' / '-hwaccel drm' routes that
drive rkvdec / hantro / cedrus / rpi-hevc-dec / daedalus_v4l2
stateless decoders directly through libavcodec's hwdevice DRM path,
bypassing libva. Used by mpv-fourier and firefox-fourier as their
backing FFmpeg, and as the kdirect bit-exact reference in
libva-v4l2-request-fourier validation.
.
Drops X11/AMF/CUDA/Bluray/JACK/Vulkan/SDL2/Theora/XVid/Speex/JPEG-XL
per Fourier fleet policy (Wayland + ARM + video-decode focus). No
'ffplay' binary; mpv-fourier covers interactive playback.
+21
View File
@@ -0,0 +1,21 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: FFmpeg (Kwiboo v4l2-request fork)
Upstream-Contact: Niklas Haas <niklas@haasn.dev>, Jernej Škrabec, Kwiboo
Source: https://github.com/Kwiboo/FFmpeg
Files: *
Copyright: 2000-2026 The FFmpeg developers
License: GPL-3.0-or-later
Files: 0001-libudev-bypass-fallback.patch 0002-nv15-to-p010-unpack.patch
Copyright: 2024-2026 Markus Fritsche <fritsche.markus@gmail.com>
License: GPL-3.0-or-later
License: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
.
On Debian systems, the complete text of the GNU General Public
License v3 can be found in `/usr/share/common-licenses/GPL-3'.
+74
View File
@@ -0,0 +1,74 @@
#!/bin/bash
# Build libva-v4l2-request-fourier_<ver>_arm64.deb.
#
# Compiles the libva ICD from the marfrit/libva-v4l2-request-fourier
# tip pinned in PKGVER below. Mirrors arch/libva-v4l2-request-fourier
# (Arch Linux build). Output is a single arm64 .deb that ships the
# VA-API driver as /usr/lib/aarch64-linux-gnu/dri/v4l2_request_drv_video.so.
#
# Sibling Arch package: ../../arch/libva-v4l2-request-fourier/PKGBUILD
# Upstream fork: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
set -euo pipefail
# Same pin as the Arch PKGBUILD. de27e95 = "v4l2: log error_idx +
# failing ctrl id on S_EXT_CTRLS failure" (Phase 8.13 diagnostic).
UPSTREAM_COMMIT=de27e95571b67ef34619c23a12db4698f9b3454e
PKGVER=1.0.0+r376+gde27e95
PKGREL=1
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build. 2026-05-18 23:00 UTC — Phase 8.13 close.
export SOURCE_DATE_EPOCH=1779231600
work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
curl -sSLfo libva-fourier.tar.gz \
"https://git.reauktion.de/marfrit/libva-v4l2-request-fourier/archive/${UPSTREAM_COMMIT}.tar.gz"
tar xzf libva-fourier.tar.gz
SRCDIR=$(echo libva-v4l2-request-fourier)
cd "$SRCDIR"
meson setup build \
--buildtype=release \
--prefix=/usr \
--libdir=lib/aarch64-linux-gnu \
-Db_lto=false
meson compile -C build
ROOT="$work/pkgroot"
DESTDIR="$ROOT" meson install -C build
# Strip any non-package debug, then drop dependencies + control.
install -Dm644 "$HERE/debian/copyright" "$ROOT/usr/share/doc/libva-v4l2-request-fourier/copyright"
install -Dm644 "$HERE/debian/changelog" "$ROOT/usr/share/doc/libva-v4l2-request-fourier/changelog.Debian"
gzip -9 -n "$ROOT/usr/share/doc/libva-v4l2-request-fourier/changelog.Debian"
mkdir -p "$ROOT/DEBIAN"
cat > "$ROOT/DEBIAN/control" <<EOF
Package: libva-v4l2-request-fourier
Version: ${PKGVER}-${PKGREL}
Section: libs
Priority: optional
Architecture: arm64
Depends: libva2, libdrm2
Conflicts: libva-v4l2-request
Replaces: libva-v4l2-request
Provides: libva-driver, libva-v4l2-request (= ${PKGVER}-${PKGREL})
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Homepage: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
Description: VA-API backend for V4L2 stateless decoders (fourier fork)
LibVA implementation for the Linux Video4Linux2 Request API, multiplanar
fork of bootlin/libva-v4l2-request. Drives rkvdec / hantro / cedrus /
rpi-hevc-dec / daedalus_v4l2 stateless decoders for H.264, HEVC, VP8,
VP9, AV1, and MPEG-2.
.
Auto-detected by VAAPI consumers (ffmpeg -hwaccel vaapi, mpv --hwdec=vaapi,
Firefox VAAPI accel) when LIBVA_DRIVER_NAME=v4l2_request is set.
EOF
DEB_OUT="libva-v4l2-request-fourier_${PKGVER}-${PKGREL}_arm64.deb"
dpkg-deb --root-owner-group --build "$ROOT" "$HERE/$DEB_OUT"
echo "built: $HERE/$DEB_OUT"
+15
View File
@@ -0,0 +1,15 @@
libva-v4l2-request-fourier (1.0.0+r376+gde27e95-1) bookworm trixie; urgency=medium
* Initial Debian packaging (sibling to existing
arch/libva-v4l2-request-fourier).
* Pinned to fork tip de27e95: "v4l2: log error_idx + failing ctrl id
on S_EXT_CTRLS failure" — Phase 8.13 diagnostic that surfaced the
real root cause of the libva→daedalus_v4l2 request-completion
timeout.
* Includes daedalus_v4l2 probe slot (b5b3acf) and meson option gate
(2146341) for the Pi 5 daemon-backed decoder shim.
* Backward-compatible on rkvdec / hantro / cedrus / rpi-hevc-dec
hosts — daedalus probe is off by default unless the kernel module
is present.
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 23:00:00 +0000
+27
View File
@@ -0,0 +1,27 @@
Source: libva-v4l2-request-fourier
Section: libs
Priority: optional
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Build-Depends: debhelper-compat (= 13),
libva-dev,
libdrm-dev,
meson (>= 0.43),
ninja-build,
pkg-config
Standards-Version: 4.6.2
Homepage: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
Package: libva-v4l2-request-fourier
Architecture: arm64
Depends: ${misc:Depends}, ${shlibs:Depends}, libva2, libdrm2
Conflicts: libva-v4l2-request
Replaces: libva-v4l2-request
Provides: libva-driver, libva-v4l2-request (= ${binary:Version})
Description: VA-API backend for V4L2 stateless decoders (fourier fork)
LibVA implementation for the Linux Video4Linux2 Request API, multiplanar
fork of bootlin/libva-v4l2-request. Drives rkvdec / hantro / cedrus /
rpi-hevc-dec / daedalus_v4l2 stateless decoders for H.264, HEVC, VP8,
VP9, AV1, and MPEG-2.
.
Auto-detected by VAAPI consumers (ffmpeg -hwaccel vaapi, mpv --hwdec=vaapi,
Firefox VAAPI accel) when LIBVA_DRIVER_NAME=v4l2_request is set.
+38
View File
@@ -0,0 +1,38 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: libva-v4l2-request-fourier
Upstream-Contact: Markus Fritsche <fritsche.markus@gmail.com>
Source: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
Comment:
Fork of bootlin/libva-v4l2-request with multi-codec / multi-device
enhancements for the fourier campaign (RK3399 / RK3588 / RK3566 / BCM2712).
Per-file SPDX headers are the canonical declaration; this summary
covers the aggregate.
Files: *
Copyright: 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
2018-2026 The libva-v4l2-request authors
2024-2026 Markus Fritsche <fritsche.markus@gmail.com>
License: LGPL-2.1+ or MIT
License: LGPL-2.1+
This package is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
.
On Debian systems, the complete text of the GNU Lesser General
Public License v2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'.
License: MIT
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject
to the following conditions:
.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
+4 -3
View File
@@ -7,9 +7,10 @@
# package (Architecture: all, depends on lua + lua-socket). # package (Architecture: all, depends on lua + lua-socket).
set -euo pipefail set -euo pipefail
PKGVER=0.5.4 PKGVER=1.2.1
UPSTREAM_TAG=v1.2.1
PKGREL=1 PKGREL=1
LMCP_TARBALL_SHA256=af72b8c1d88255456b75d2c53cd5c451a8923417e5498ef31858539397e09caf LMCP_TARBALL_SHA256=bf9cce1a84c66b1b74c5aec923c5960d60ae33c221afc8d47ce0d74b8f7ee609
HERE=$(dirname "$(readlink -f "$0")") HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build: pin all file mtimes + ar member timestamps to a fixed # Reproducible build: pin all file mtimes + ar member timestamps to a fixed
@@ -22,7 +23,7 @@ work=$(mktemp -d)
trap "rm -rf $work" EXIT trap "rm -rf $work" EXIT
cd "$work" cd "$work"
curl -sSLfo lmcp.tar.gz "https://git.reauktion.de/marfrit/lmcp/archive/v${PKGVER}.tar.gz" curl -sSLfo lmcp.tar.gz "https://git.reauktion.de/marfrit/lmcp/archive/${UPSTREAM_TAG}.tar.gz"
echo "$LMCP_TARBALL_SHA256 lmcp.tar.gz" | sha256sum -c echo "$LMCP_TARBALL_SHA256 lmcp.tar.gz" | sha256sum -c
tar xzf lmcp.tar.gz tar xzf lmcp.tar.gz
+80
View File
@@ -1,3 +1,83 @@
lmcp (1.2.1-1) bookworm trixie; urgency=medium
* tools.d/ plugin scan (closes lmcp#22): server.lua now scans
LMCP_TOOLS_DIR (default /opt/lmcp/tools.d on POSIX) for *.lua
files and invokes each as a function receiving (server, run).
Lets hosts ship local tool extensions alongside the packaged
generics without forking server.lua. Existing single-file
deployments without a tools.d/ directory: no behaviour change.
* LMCP_HOST + LMCP_CONF env vars: packaged server.lua now threads
these into lmcp.new(opts.host, opts.conf). Hosts that need
single-interface binding (e.g. hertz on 192.168.88.18) or a
conf-file-based bearer token (e.g. /opt/herding/etc/hertz-tools.conf)
can drive the packaged entrypoint directly via systemd env
instead of carrying a forked server.lua.
* Together with the above, hertz, ampere, and any future host with
custom tools can migrate from /opt/lmcp/server.lua forks to a
plain plugin file + standard systemd env. apt upgrade then
delivers all packaged improvements automatically.
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 01:30:00 +0000
lmcp (1.1.1-1) bookworm trixie; urgency=medium
* Bug fix: omit empty inputSchema.properties at tool registration.
The json.lua empty-table-as-array gotcha (same one that bit
`ping` in v1.0.0-rc1) was re-surfacing on tool inputSchemas
declared with `properties = {}` — spec-strict MCP clients (Zod)
rejected the tools/list with "expected: record, received: array".
lmcp:tool() now normalises empty properties tables by dropping
the key entirely (JSON Schema permits omitting `properties` on
`type:object`, meaning "any object — no constraints").
Discovered live on a hertz-tools deployment where two custom
no-arg tools (lxc_list, network_status) tripped the Zod check
and caused Claude Code to mark the entire MCP endpoint as
disconnected.
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 00:55:00 +0000
lmcp (1.1.0-1) bookworm trixie; urgency=medium
* Concurrent handler dispatch (closes #20): tool handlers run in
cooperative coroutines. server.lua:run()'s sleep_ms yields to
the event loop instead of blocking. Slow shell commands no
longer serialise other requests — fast ping during a slow
`sleep N` returns in ~10ms (was ~N seconds).
* Progress + cancellation notifications (closes #11): tool
handler ctx gains progress(p, total?, message?) and cancelled().
Client→server notifications/cancelled flips a flag the running
handler sees within ~420ms (poll interval capped when ctx
present). Cancelled requests get a JSON-RPC -32800 error
response (spec wording is "SHOULD NOT respond" but the practical
UX wins; see upstream issue for the FD-inheritance trade-off).
* Windows MSI build sync (closes #18): windows/sync.sh script
refreshes windows/pkg/{lmcp,server,json}.lua from root before
WiX is invoked. Closes the drift trap that left the MSI ~6
months behind master in April 2026.
* Zero handler source-code changes; all existing tools (shell,
fetch, web_search, hub remote_*) benefit from concurrency and
auto-cancellation transparently via the run() helper.
-- Markus Fritsche <mfritsche@reauktion.de> Sun, 17 May 2026 19:45:00 +0000
lmcp (1.0.0~rc1-1) bookworm trixie; urgency=medium
* Full MCP 2025-06-18 surface (release candidate). Closes 14
upstream issues. New primitives: Resources, Prompts, Completion,
Logging, Sampling, Roots, fetch, web_search. Protocol: cursor
pagination, structuredContent, _meta passthrough, tool annotations
(readOnlyHint/destructiveHint/idempotentHint/openWorldHint).
Transports: stdio (LMCP_TRANSPORT=stdio) for Claude Desktop / IDE
clients; full Streamable HTTP rewrite with select()-based event
loop, sessions (Mcp-Session-Id), persistent SSE, server-initiated
requests, heartbeat, DELETE.
* json.lua: UTF-16 surrogate-pair combination + json.empty_object
sentinel for spec-correct {} emission (fixes ping's result:[]
bug).
* Backwards compatible with all existing sessionless-POST clients.
-- Markus Fritsche <mfritsche@reauktion.de> Sun, 17 May 2026 17:25:00 +0000
lmcp (0.5.4-1) bookworm trixie; urgency=medium lmcp (0.5.4-1) bookworm trixie; urgency=medium
* Ship examples/lmcp.service systemd unit template alongside the * Ship examples/lmcp.service systemd unit template alongside the
@@ -0,0 +1,56 @@
From 9d3bbd3651eb8405b8609e4f5e8c4978056483d0 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 18 Aug 2024 17:42:14 -0700
Subject: [PATCH 1/2] meson: add detection logic for v4l2request support
We will probably adjust this to look for a specific libavutil version after
v4l2request support is merged upstream, but this check is fine for now.
---
meson.build | 11 +++++++++++
meson.options | 1 +
2 files changed, 12 insertions(+)
diff --git a/meson.build b/meson.build
index d4c75a907f..540f279dc7 100644
--- a/meson.build
+++ b/meson.build
@@ -1444,6 +1444,16 @@ if features['ios-gl']
sources += files('video/out/hwdec/hwdec_ios_gl.m')
endif
+v4l2request = get_option('v4l2request').require(
+ cc.has_header_symbol('libavutil/hwcontext.h',
+ 'AV_HWDEVICE_TYPE_V4L2REQUEST',
+ dependencies: libavutil)
+)
+features += {'v4l2request': v4l2request.allowed()}
+if features['v4l2request']
+ sources += files('video/v4l2request.c')
+endif
+
libva = dependency('libva', version: '>= 1.1.0', required: get_option('vaapi'))
vaapi_drm = dependency('libva-drm', version: '>= 1.1.0', required:
@@ -1911,6 +1921,7 @@ summary({'cocoa': features['cocoa'] and features['swift'],
'libmpv': get_option('libmpv'),
'lua': features['lua'],
'opengl': features['gl'],
+ 'v4l2request': features['v4l2request'],
'vulkan': features['vulkan'],
'wayland': features['wayland'],
'x11': features['x11']},
diff --git a/meson.options b/meson.options
index 836d16d03f..54ec2dccfc 100644
--- a/meson.options
+++ b/meson.options
@@ -103,6 +103,7 @@ option('d3d-hwaccel', type: 'feature', value: 'auto', description: 'D3D11VA hwac
option('d3d9-hwaccel', type: 'feature', value: 'auto', description: 'DXVA2 hwaccel')
option('gl-dxinterop-d3d9', type: 'feature', value: 'auto', description: 'OpenGL/DirectX DXVA2 hwaccel')
option('ios-gl', type: 'feature', value: 'auto', description: 'iOS OpenGL ES interop support')
+option('v4l2request', type: 'feature', value: 'auto', description: 'V4L2 Request API hwaccel')
option('videotoolbox-gl', type: 'feature', value: 'auto', description: 'Videotoolbox with OpenGL')
option('videotoolbox-pl', type: 'feature', value: 'auto', description: 'Videotoolbox with libplacebo')
--
2.52.0
@@ -0,0 +1,81 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Fri, 8 May 2026 23:30:00 +0000
Subject: [PATCH] vo_dmabuf_wayland: explicit DMA_BUF_IOCTL_SYNC on import fds
V4L2 does not attach implicit fences (dma_resv) to CAPTURE buffers
on VIDIOC_DQBUF. When the buffer is forwarded to a Wayland compositor
that imports it via wl_dmabuf and samples in the GPU, the GPU may
read from physical memory before the producer's writes have flushed,
producing all-zero output (manifests as solid green for BT.601
limited-range YUV(0,0,0) -> RGB(0, 135, 0) on the consumer side).
Issue an explicit DMA_BUF_IOCTL_SYNC(SYNC_START|SYNC_RW) +
SYNC_END(SYNC_RW) round-trip on each unique dma_buf fd before
zwp_linux_buffer_params_v1_add(). This invokes the producer driver's
dma_buf_ops->begin_cpu_access / end_cpu_access, which on most ARM
SoCs flushes write buffers and synchronizes coherent memory before
the compositor's GPU import.
This is a userspace workaround. Root cause is the missing implicit
fence on V4L2 CAPTURE DQBUF and is being addressed upstream via
the vb2_dma_resv RFC.
Without this patch, on RK3566 (hantro VPU + Mali-G52 panfrost +
KDE Plasma 6 / KWin 6.6.4), `mpv --hwdec=vaapi --vo=dmabuf-wayland`
shows solid green frames for all hardware-decoded content. With
this patch, decoded frames are presented correctly.
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
---
diff --git a/video/out/vo_dmabuf_wayland.c b/video/out/vo_dmabuf_wayland.c
index 6b7c511..16e3d18 100644
--- a/video/out/vo_dmabuf_wayland.c
+++ b/video/out/vo_dmabuf_wayland.c
@@ -27,6 +27,12 @@
#include <va/va_drmcommon.h>
#endif
+/* fourier patch: explicit dma_buf cache sync workaround for missing
+ * implicit-fence on V4L2 stateless CAPTURE buffers. Applies to both
+ * VAAPI and DRMPrime import paths. */
+#include <linux/dma-buf.h>
+#include <sys/ioctl.h>
+
#include "gpu/hwdec.h"
#include "gpu/video.h"
#include "mpv_talloc.h"
@@ -205,6 +211,14 @@ static void vaapi_dmabuf_importer(struct buffer *buf, struct mp_image *src,
buf->drm_format = 0;
goto done;
}
+ /* fourier patch: explicit cache coherency sync on each dma_buf fd
+ * before submitting to the compositor. See top-of-file comment. */
+ for (int obj_no = 0; obj_no < desc.num_objects; obj_no++) {
+ struct dma_buf_sync sync = { .flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW };
+ (void)ioctl(desc.objects[obj_no].fd, DMA_BUF_IOCTL_SYNC, &sync);
+ sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
+ (void)ioctl(desc.objects[obj_no].fd, DMA_BUF_IOCTL_SYNC, &sync);
+ }
for (int plane_no = 0; plane_no < desc.layers[layer_no].num_planes; ++plane_no) {
int object = desc.layers[layer_no].object_index[plane_no];
uint64_t modifier = desc.objects[object].drm_format_modifier;
@@ -258,6 +272,16 @@ static void drmprime_dmabuf_importer(struct buffer *buf, struct mp_image *src,
return;
buf->id = drmprime_surface_id(src);
+
+ /* fourier patch: explicit cache coherency sync on each dma_buf fd
+ * before submitting to the compositor. See top-of-file comment. */
+ for (int obj_no = 0; obj_no < desc->nb_objects; obj_no++) {
+ struct dma_buf_sync sync = { .flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW };
+ (void)ioctl(desc->objects[obj_no].fd, DMA_BUF_IOCTL_SYNC, &sync);
+ sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
+ (void)ioctl(desc->objects[obj_no].fd, DMA_BUF_IOCTL_SYNC, &sync);
+ }
+
for (layer_no = 0; layer_no < desc->nb_layers; layer_no++) {
AVDRMLayerDescriptor layer = desc->layers[layer_no];
--
2.51.0
@@ -0,0 +1,435 @@
From dd1e1fd6fe884d66c49dc26af715e1423c7471a3 Mon Sep 17 00:00:00 2001
From: Philip Langdale <philipl@overt.org>
Date: Sun, 18 Aug 2024 17:43:41 -0700
Subject: [PATCH 2/2] vo: hwdec: drmprime: add separate hwdecs for v4l2request
With all the machinery in place, we can now add the v4l2request hwdecs with a
different hw device type, and a different initialisation path. This applies to
both the drmprime and drmprime_overlay hwdecs.
At the moment, the device initialisation is done in the bare minimum way, but
it can be extended to take a device path (for example) if that makes sense as
we better understand what meaningful configuration will be.
Co-authored-by: Jonas Karlman <jonas@kwiboo.se>
---
video/hwdec.c | 3 +
video/hwdec.h | 1 +
video/out/gpu/hwdec.c | 6 ++
video/out/hwdec/hwdec_drmprime.c | 125 +++++++++++++++++------
video/out/hwdec/hwdec_drmprime_overlay.c | 81 +++++++++++++--
video/out/vo_dmabuf_wayland.c | 1 +
video/v4l2request.c | 34 ++++++
7 files changed, 210 insertions(+), 41 deletions(-)
create mode 100644 video/v4l2request.c
diff --git a/video/hwdec.c b/video/hwdec.c
index deba518e82..de2ffecc40 100644
--- a/video/hwdec.c
+++ b/video/hwdec.c
@@ -125,6 +125,9 @@ static const struct hwcontext_fns *const hwcontext_fns[] = {
#if HAVE_DRM
&hwcontext_fns_drmprime,
#endif
+#if HAVE_V4L2REQUEST
+ &hwcontext_fns_v4l2request,
+#endif
#if HAVE_VAAPI
&hwcontext_fns_vaapi,
#endif
diff --git a/video/hwdec.h b/video/hwdec.h
index e7734e5d7e..bf337389cb 100644
--- a/video/hwdec.h
+++ b/video/hwdec.h
@@ -119,6 +119,7 @@ extern const struct hwcontext_fns hwcontext_fns_cuda;
extern const struct hwcontext_fns hwcontext_fns_d3d11;
extern const struct hwcontext_fns hwcontext_fns_drmprime;
extern const struct hwcontext_fns hwcontext_fns_dxva2;
+extern const struct hwcontext_fns hwcontext_fns_v4l2request;
extern const struct hwcontext_fns hwcontext_fns_vaapi;
extern const struct hwcontext_fns hwcontext_fns_vdpau;
diff --git a/video/out/gpu/hwdec.c b/video/out/gpu/hwdec.c
index be39c507d0..f50b927851 100644
--- a/video/out/gpu/hwdec.c
+++ b/video/out/gpu/hwdec.c
@@ -38,6 +38,8 @@ extern const struct ra_hwdec_driver ra_hwdec_drmprime;
extern const struct ra_hwdec_driver ra_hwdec_drmprime_overlay;
extern const struct ra_hwdec_driver ra_hwdec_aimagereader;
extern const struct ra_hwdec_driver ra_hwdec_vulkan;
+extern const struct ra_hwdec_driver ra_hwdec_v4l2request;
+extern const struct ra_hwdec_driver ra_hwdec_v4l2request_overlay;
const struct ra_hwdec_driver *const ra_hwdec_drivers[] = {
#if HAVE_D3D_HWACCEL
@@ -73,6 +75,10 @@ const struct ra_hwdec_driver *const ra_hwdec_drivers[] = {
&ra_hwdec_drmprime,
&ra_hwdec_drmprime_overlay,
#endif
+#if HAVE_V4L2REQUEST
+ &ra_hwdec_v4l2request,
+ &ra_hwdec_v4l2request_overlay,
+#endif
#if HAVE_ANDROID_MEDIA_NDK
&ra_hwdec_aimagereader,
#endif
diff --git a/video/out/hwdec/hwdec_drmprime.c b/video/out/hwdec/hwdec_drmprime.c
index 7869eb124a..446f63de44 100644
--- a/video/out/hwdec/hwdec_drmprime.c
+++ b/video/out/hwdec/hwdec_drmprime.c
@@ -77,7 +77,7 @@ static const char *forked_pix_fmt_names[] = {
"rpi4_10",
};
-static int init(struct ra_hwdec *hw)
+static int pre_init(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;
@@ -92,36 +92,12 @@ static int init(struct ra_hwdec *hw)
return -1;
}
- /*
- * The drm_params resource is not provided when using X11 or Wayland, but
- * there are extensions that supposedly provide this information from the
- * drivers. Not properly documented. Of course.
- */
- mpv_opengl_drm_params_v2 *params = ra_get_native_resource(hw->ra_ctx->ra,
- "drm_params_v2");
-
- /*
- * Respect drm_device option, so there is a way to control this when not
- * using a DRM gpu context. If drm_params_v2 are present, they will already
- * respect this option.
- */
- void *tmp = talloc_new(NULL);
- struct drm_opts *drm_opts = mp_get_config_group(tmp, hw->global, &drm_conf);
- const char *opt_path = drm_opts->device_path;
-
- const char *device_path = params && params->render_fd > -1 ?
- drmGetRenderDeviceNameFromFd(params->render_fd) :
- opt_path ? opt_path : "/dev/dri/renderD128";
- MP_VERBOSE(hw, "Using DRM device: %s\n", device_path);
+ return 0;
+}
- int ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
- AV_HWDEVICE_TYPE_DRM,
- device_path, NULL, 0);
- talloc_free(tmp);
- if (ret != 0) {
- MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
- return -1;
- }
+static int post_init(struct ra_hwdec *hw)
+{
+ struct priv_owner *p = hw->priv;
/*
* At the moment, there is no way to discover compatible formats
@@ -154,6 +130,75 @@ static int init(struct ra_hwdec *hw)
return 0;
}
+static int init_drmprime(struct ra_hwdec *hw)
+{
+ struct priv_owner *p = hw->priv;
+
+ int ret = pre_init(hw);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * The drm_params resource is not provided when using X11 or Wayland, but
+ * there are extensions that supposedly provide this information from the
+ * drivers. Not properly documented. Of course.
+ */
+ mpv_opengl_drm_params_v2 *params = ra_get_native_resource(hw->ra_ctx->ra,
+ "drm_params_v2");
+
+ /*
+ * Respect drm_device option, so there is a way to control this when not
+ * using a DRM gpu context. If drm_params_v2 are present, they will already
+ * respect this option.
+ */
+ void *tmp = talloc_new(NULL);
+ struct drm_opts *drm_opts = mp_get_config_group(tmp, hw->global, &drm_conf);
+ const char *opt_path = drm_opts->device_path;
+
+ const char *device_path = params && params->render_fd > -1 ?
+ drmGetRenderDeviceNameFromFd(params->render_fd) :
+ opt_path ? opt_path : "/dev/dri/renderD128";
+ MP_VERBOSE(hw, "Using DRM device: %s\n", device_path);
+
+ ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
+ AV_HWDEVICE_TYPE_DRM,
+ device_path, NULL, 0);
+ talloc_free(tmp);
+ if (ret < 0) {
+ MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
+ return ret;
+ }
+
+ return post_init(hw);
+}
+
+#if HAVE_V4L2REQUEST
+static int init_v4l2request(struct ra_hwdec *hw)
+{
+ struct priv_owner *p = hw->priv;
+
+ int ret = pre_init(hw);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * AVCodecHWConfig contains a combo of a pixel format and hwdevice type,
+ * correct type must be created here or hwaccel will fail.
+ *
+ * FIXME: Create hwdevice based on type in AVCodecHWConfig
+ */
+ ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
+ AV_HWDEVICE_TYPE_V4L2REQUEST,
+ NULL, NULL, 0);
+ if (ret < 0) {
+ MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
+ return ret;
+ }
+
+ return post_init(hw);
+}
+#endif
+
static void mapper_unmap(struct ra_hwdec_mapper *mapper)
{
struct priv_owner *p_owner = mapper->owner->priv;
@@ -308,7 +353,7 @@ const struct ra_hwdec_driver ra_hwdec_drmprime = {
.priv_size = sizeof(struct priv_owner),
.imgfmts = {IMGFMT_DRMPRIME, 0},
.device_type = AV_HWDEVICE_TYPE_DRM,
- .init = init,
+ .init = init_drmprime,
.uninit = uninit,
.mapper = &(const struct ra_hwdec_mapper_driver){
.priv_size = sizeof(struct dmabuf_interop_priv),
@@ -318,3 +363,21 @@ const struct ra_hwdec_driver ra_hwdec_drmprime = {
.unmap = mapper_unmap,
},
};
+
+#if HAVE_V4L2REQUEST
+const struct ra_hwdec_driver ra_hwdec_v4l2request = {
+ .name = "v4l2request",
+ .priv_size = sizeof(struct priv_owner),
+ .imgfmts = {IMGFMT_DRMPRIME, 0},
+ .device_type = AV_HWDEVICE_TYPE_V4L2REQUEST,
+ .init = init_v4l2request,
+ .uninit = uninit,
+ .mapper = &(const struct ra_hwdec_mapper_driver){
+ .priv_size = sizeof(struct dmabuf_interop_priv),
+ .init = mapper_init,
+ .uninit = mapper_uninit,
+ .map = mapper_map,
+ .unmap = mapper_unmap,
+ },
+};
+#endif
diff --git a/video/out/hwdec/hwdec_drmprime_overlay.c b/video/out/hwdec/hwdec_drmprime_overlay.c
index 61514f8e89..689e9b04e5 100644
--- a/video/out/hwdec/hwdec_drmprime_overlay.c
+++ b/video/out/hwdec/hwdec_drmprime_overlay.c
@@ -246,7 +246,7 @@ static void uninit(struct ra_hwdec *hw)
}
}
-static int init(struct ra_hwdec *hw)
+static int pre_init(struct ra_hwdec *hw)
{
struct priv *p = hw->priv;
int draw_plane, drmprime_video_plane;
@@ -267,15 +267,15 @@ static int init(struct ra_hwdec *hw)
drm_params->connector_id, draw_plane, drmprime_video_plane);
if (!p->ctx) {
mp_err(p->log, "Failed to retrieve DRM atomic context.\n");
- goto err;
+ return -1;
}
if (!p->ctx->drmprime_video_plane) {
mp_warn(p->log, "No drmprime video plane. You might need to specify it manually using --drm-drmprime-video-plane\n");
- goto err;
+ return -1;
}
} else {
mp_verbose(p->log, "Failed to retrieve DRM fd from native display.\n");
- goto err;
+ return -1;
}
drmModeCrtcPtr crtc;
@@ -289,7 +289,7 @@ static int init(struct ra_hwdec *hw)
uint64_t has_prime;
if (drmGetCap(p->ctx->fd, DRM_CAP_PRIME, &has_prime) < 0) {
MP_ERR(hw, "Card does not support prime handles.\n");
- goto err;
+ return -1;
}
if (has_prime) {
@@ -298,19 +298,67 @@ static int init(struct ra_hwdec *hw)
disable_video_plane(hw);
+ return 0;
+}
+
+static int init_drmprime(struct ra_hwdec *hw)
+{
+ struct priv *p = hw->priv;
+
+ int ret = pre_init(hw);
+ if (ret < 0)
+ goto err;
+
p->hwctx = (struct mp_hwdec_ctx) {
.driver_name = hw->driver->name,
.hw_imgfmt = IMGFMT_DRMPRIME,
};
char *device = drmGetDeviceNameFromFd2(p->ctx->fd);
- int ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
- AV_HWDEVICE_TYPE_DRM, device, NULL, 0);
+ ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
+ AV_HWDEVICE_TYPE_DRM, device, NULL, 0);
if (device)
free(device);
- if (ret != 0) {
+ if (ret < 0) {
+ MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
+ goto err;
+ }
+
+ hwdec_devices_add(hw->devs, &p->hwctx);
+
+ return 0;
+
+err:
+ uninit(hw);
+ return ret;
+}
+
+#if HAVE_V4L2REQUEST
+static int init_v4l2request(struct ra_hwdec *hw)
+{
+ struct priv *p = hw->priv;
+
+ int ret = pre_init(hw);
+ if (ret < 0)
+ goto err;
+
+ p->hwctx = (struct mp_hwdec_ctx) {
+ .driver_name = hw->driver->name,
+ .hw_imgfmt = IMGFMT_DRMPRIME,
+ };
+
+ /*
+ * AVCodecHWConfig contains a combo of a pixel format and hwdevice type,
+ * correct type must be created here or hwaccel will fail.
+ *
+ * FIXME: Create hwdevice based on type in AVCodecHWConfig
+ */
+ ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
+ AV_HWDEVICE_TYPE_V4L2REQUEST,
+ NULL, NULL, 0);
+ if (ret < 0) {
MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
goto err;
}
@@ -321,15 +369,28 @@ static int init(struct ra_hwdec *hw)
err:
uninit(hw);
- return -1;
+ return ret;
}
+#endif
const struct ra_hwdec_driver ra_hwdec_drmprime_overlay = {
.name = "drmprime-overlay",
.priv_size = sizeof(struct priv),
.imgfmts = {IMGFMT_DRMPRIME, 0},
.device_type = AV_HWDEVICE_TYPE_DRM,
- .init = init,
+ .init = init_drmprime,
+ .overlay_frame = overlay_frame,
+ .uninit = uninit,
+};
+
+#if HAVE_V4L2REQUEST
+const struct ra_hwdec_driver ra_hwdec_v4l2request_overlay = {
+ .name = "v4l2request-overlay",
+ .priv_size = sizeof(struct priv),
+ .imgfmts = {IMGFMT_DRMPRIME, 0},
+ .device_type = AV_HWDEVICE_TYPE_V4L2REQUEST,
+ .init = init_v4l2request,
.overlay_frame = overlay_frame,
.uninit = uninit,
};
+#endif
diff --git a/video/out/vo_dmabuf_wayland.c b/video/out/vo_dmabuf_wayland.c
index 9b06643544..6d62849568 100644
--- a/video/out/vo_dmabuf_wayland.c
+++ b/video/out/vo_dmabuf_wayland.c
@@ -860,6 +860,7 @@ static int preinit(struct vo *vo)
// Initialize all possible hwdec drivers.
ra_hwdec_ctx_init(&p->hwdec_ctx, vo->hwdec_devs, "vaapi", false);
ra_hwdec_ctx_init(&p->hwdec_ctx, vo->hwdec_devs, "drmprime", false);
+ ra_hwdec_ctx_init(&p->hwdec_ctx, vo->hwdec_devs, "v4l2request", false);
p->src = (struct mp_rect){0, 0, 0, 0};
return 0;
diff --git a/video/v4l2request.c b/video/v4l2request.c
new file mode 100644
index 0000000000..2aa4d14fea
--- /dev/null
+++ b/video/v4l2request.c
@@ -0,0 +1,34 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libavutil/hwcontext.h>
+
+#include "hwdec.h"
+
+static struct AVBufferRef *v4l2request_create_standalone(struct mpv_global *global,
+ struct mp_log *log, struct hwcontext_create_dev_params *params)
+{
+ AVBufferRef* ref = NULL;
+ av_hwdevice_ctx_create(&ref, AV_HWDEVICE_TYPE_V4L2REQUEST, NULL, NULL, 0);
+
+ return ref;
+}
+
+const struct hwcontext_fns hwcontext_fns_v4l2request = {
+ .av_hwdevice_type = AV_HWDEVICE_TYPE_V4L2REQUEST,
+ .create_dev = v4l2request_create_standalone,
+};
--
2.52.0
+134
View File
@@ -0,0 +1,134 @@
#!/bin/bash
# Build mpv-fourier_<ver>_arm64.deb (mpv with v4l2request hwdec wiring +
# vo_dmabuf_wayland cache-sync fix).
#
# Mirror of arch/mpv-fourier into the Debian tree. Same source pin
# (mpv 0.41.0), same 3 patches, same meson options.
#
# Depends on ffmpeg-v4l2-request-fourier for the libavcodec backing
# library — the v4l2request hwdec mpv now offers requires
# AV_HWDEVICE_TYPE_V4L2REQUEST which only exists in Kwiboo's FFmpeg
# fork, not in Debian stock ffmpeg.
#
# Conflicts: mpv — drop-in replacement. Pi 5 / CM5 hosts using stock
# Firefox + VAAPI don't need this; the firefox-fourier / kdirect
# bench-test paths do.
#
# Sibling Arch package: ../../arch/mpv-fourier/PKGBUILD
# Sibling FFmpeg package: ../ffmpeg-v4l2-request-fourier/build-deb.sh
# Upstream: https://github.com/mpv-player/mpv
set -euo pipefail
MPV_VERSION=0.41.0
PKGVER=1:${MPV_VERSION}+rfourier
PKGREL=1
MPV_TARBALL_SHA256=ee21092a5ee427353392360929dc64645c54479aefdb5babc5cfbb5fad626209
HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build. 2026-05-18 23:00 UTC — Phase 8.13 close.
export SOURCE_DATE_EPOCH=1779231600
work=$(mktemp -d)
trap "rm -rf $work" EXIT
cd "$work"
curl -sSLfo mpv.tar.gz \
"https://github.com/mpv-player/mpv/archive/v${MPV_VERSION}/mpv-${MPV_VERSION}.tar.gz"
echo "$MPV_TARBALL_SHA256 mpv.tar.gz" | sha256sum -c
tar xzf mpv.tar.gz
cd "mpv-${MPV_VERSION}"
# Apply the 3 fourier patches.
patch -p1 < "$HERE/0001-meson-add-detection-logic-for-v4l2request-support.patch"
patch -p1 < "$HERE/0002-vo-hwdec-drmprime-add-separate-hwdecs-for-v4l2reques.patch"
patch -p1 < "$HERE/0001-vo_dmabuf_wayland-explicit-cache-sync-on-import-fd.patch"
# Configure. Same shape as arch/mpv-fourier's meson options.
meson setup build \
--prefix=/usr \
--libdir=lib/aarch64-linux-gnu \
--buildtype=release \
--auto-features=auto \
-Dv4l2request=enabled \
-Dlibmpv=true \
-Dgl-x11=enabled \
-Dcaca=disabled \
-Dcdda=enabled \
-Ddrm=enabled \
-Ddvbin=enabled \
-Ddvdnav=enabled \
-Dlibarchive=enabled \
-Dopenal=enabled \
-Dsdl2-audio=enabled \
-Dsdl2-video=enabled \
-Dsdl2-gamepad=enabled
meson compile -C build -j"$(nproc)"
# Stage
ROOT="$work/pkgroot"
DESTDIR="$ROOT" meson install -C build
# Drop private linkage entries from the .pc (only matter for static linking).
sed -i -e '/Requires.private/d' -e '/Libs.private/d' \
"$ROOT/usr/lib/aarch64-linux-gnu/pkgconfig/mpv.pc"
# Docs
mkdir -p "$ROOT/usr/share/doc/mpv-fourier" "$ROOT/DEBIAN"
install -m 644 DOCS/encoding.rst "$ROOT/usr/share/doc/mpv-fourier/"
install -m 644 DOCS/tech-overview.txt "$ROOT/usr/share/doc/mpv-fourier/"
install -Dm644 "$HERE/debian/copyright" "$ROOT/usr/share/doc/mpv-fourier/copyright"
install -Dm644 "$HERE/debian/changelog" "$ROOT/usr/share/doc/mpv-fourier/changelog.Debian"
gzip -9 -n "$ROOT/usr/share/doc/mpv-fourier/changelog.Debian"
# TOOLS scripts
mkdir -p "$ROOT/usr/share/mpv/scripts"
install -m 644 TOOLS/umpv TOOLS/mpv_identify.sh TOOLS/stats-conv.py TOOLS/idet.sh \
"$ROOT/usr/share/mpv/scripts/" 2>/dev/null || true
[ -d TOOLS/lua ] && cp TOOLS/lua/* "$ROOT/usr/share/mpv/scripts/" 2>/dev/null || true
cat > "$ROOT/DEBIAN/control" <<EOF
Package: mpv-fourier
Version: ${PKGVER}-${PKGREL}
Section: video
Priority: optional
Architecture: arm64
Depends: ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier),
libc6, libdrm2,
libass9, libbluray2, libcdio19, libcdio-paranoia2,
libdvdnav4, libdvdread8,
libegl1, libgl1, libjpeg62-turbo | libjpeg62,
libplacebo338 | libplacebo208,
libpulse0, libsixel1, libluajit-5.1-2,
libmujs3 | libmujs2 | libmujs1,
libpipewire-0.3-0, librubberband2, libsdl2-2.0-0,
libopenal1, libuchardet0, libvulkan1,
libwayland-client0, libwayland-egl1, libwayland-cursor0,
libxkbcommon0, libxext6, libxpresent1,
libxrandr2, libxss1, libxv1, libx11-6,
zlib1g
Conflicts: mpv, libmpv2, libmpv1
Replaces: mpv, libmpv2, libmpv1
Provides: mpv (= ${PKGVER}-${PKGREL}), libmpv.so.2
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Homepage: https://mpv.io/
Description: mpv media player with V4L2-Request hwdec (fourier fork)
mpv ${MPV_VERSION} patched with:
- Kwiboo + Langdale v4l2request hwdec wiring (meson detection +
vo_hwdec_drmprime separate hwdec instance for AV_HWDEVICE_TYPE_
V4L2REQUEST) so '--hwdec=v4l2request' actually engages on
dmabuf-wayland.
- vo_dmabuf_wayland explicit DMA_BUF_IOCTL_SYNC on import fds
(iter1 of dmabuf-modifier-triage) — workaround for missing
implicit-fence on V4L2 stateless CAPTURE buffers. Fixes the
KWin-on-RK3566 dark-green chroma readback regression on ohm.
.
Requires ffmpeg-v4l2-request-fourier as the backing libavcodec.
Stock Debian ffmpeg does not provide AV_HWDEVICE_TYPE_V4L2REQUEST.
EOF
DEB_OUT="mpv-fourier_${PKGVER//:/%3a}-${PKGREL}_arm64.deb"
dpkg-deb --root-owner-group --build "$ROOT" "$HERE/$DEB_OUT"
echo "built: $HERE/$DEB_OUT"
+12
View File
@@ -0,0 +1,12 @@
mpv-fourier (1:0.41.0+rfourier-1) bookworm trixie; urgency=medium
* Initial Debian packaging for mpv with the fourier-umbrella patches.
* Mirror of arch/mpv-fourier (same source tarball pin 0.41.0,
same 3 patches: v4l2request meson detection, drmprime hwdec
wiring, vo_dmabuf_wayland explicit cache-sync).
* Depends on ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier) — the
v4l2request hwdec requires AV_HWDEVICE_TYPE_V4L2REQUEST which
only exists in Kwiboo's FFmpeg fork.
* Drop-in replacement for Debian's stock mpv; takes epoch 1.
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 23:00:00 +0000
+70
View File
@@ -0,0 +1,70 @@
Source: mpv-fourier
Section: video
Priority: optional
Maintainer: Markus Fritsche <mfritsche@reauktion.de>
Build-Depends: debhelper-compat (= 13),
meson (>= 1.0),
ninja-build,
pkg-config,
python3-docutils,
ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier),
libdrm-dev,
libass-dev,
libbluray-dev,
libcdio-dev,
libcdio-paranoia-dev,
libdvdnav-dev,
libdvdread-dev,
libegl-dev,
libgl-dev,
libjpeg-dev,
libplacebo-dev,
libpulse-dev,
libsixel-dev,
libluajit-5.1-dev,
libmujs-dev,
libpipewire-0.3-dev,
librubberband-dev,
libsdl2-dev,
libopenal-dev,
libuchardet-dev,
libvulkan-dev,
libwayland-dev,
wayland-protocols,
libxkbcommon-dev,
libxext-dev,
libxpresent-dev,
libxrandr-dev,
libxss-dev,
libxv-dev,
libx11-dev,
libv4l-dev,
libudev-dev,
libsystemd-dev,
libarchive-dev,
libxml2-dev,
libdvbpsi-dev,
zlib1g-dev
Standards-Version: 4.6.2
Homepage: https://mpv.io/
Package: mpv-fourier
Architecture: arm64
Depends: ${misc:Depends}, ${shlibs:Depends},
ffmpeg-v4l2-request-fourier (>= 2:8.1+rfourier)
Conflicts: mpv, libmpv2, libmpv1
Replaces: mpv, libmpv2, libmpv1
Provides: mpv (= ${binary:Version}), libmpv.so.2
Description: mpv media player with V4L2-Request hwdec (fourier fork)
mpv 0.41.0 patched with:
- Kwiboo + Langdale v4l2request hwdec wiring (meson detection +
vo_hwdec_drmprime separate hwdec instance for AV_HWDEVICE_TYPE_
V4L2REQUEST) so '--hwdec=v4l2request' actually engages on
dmabuf-wayland.
- vo_dmabuf_wayland explicit DMA_BUF_IOCTL_SYNC on import fds
(iter1 of dmabuf-modifier-triage) — workaround for missing
implicit-fence on V4L2 stateless CAPTURE buffers. Fixes the
KWin-on-RK3566 dark-green chroma readback regression on ohm.
.
Requires ffmpeg-v4l2-request-fourier as the backing libavcodec.
Stock Debian ffmpeg does not provide AV_HWDEVICE_TYPE_V4L2REQUEST.
+25
View File
@@ -0,0 +1,25 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: mpv
Upstream-Contact: https://github.com/mpv-player/mpv/issues
Source: https://github.com/mpv-player/mpv
Files: *
Copyright: 2000-2026 The mpv developers
License: GPL-2.0-or-later AND LGPL-2.1-or-later
Files: 0001-meson-add-detection-logic-for-v4l2request-support.patch
0002-vo-hwdec-drmprime-add-separate-hwdecs-for-v4l2reques.patch
Copyright: 2024 Kwiboo, Niklas Haas, contributors
License: LGPL-2.1-or-later
Files: 0001-vo_dmabuf_wayland-explicit-cache-sync-on-import-fd.patch
Copyright: 2026 Markus Fritsche <fritsche.markus@gmail.com>
License: LGPL-2.1-or-later
License: GPL-2.0-or-later
On Debian systems, the complete text of the GNU General Public
License v2 can be found in `/usr/share/common-licenses/GPL-2'.
License: LGPL-2.1-or-later
On Debian systems, the complete text of the GNU Lesser General
Public License v2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'.