forked from marfrit/marfrit-packages
Compare commits
147 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9bf97fdb49 | |||
| a536e20218 | |||
| a1dba5f630 | |||
| 88a65cb6d0 | |||
| e641d679d3 | |||
| 877238bd1b | |||
| 27617e4cb0 | |||
| a2daab1b28 | |||
| 9146e83710 | |||
| abf8fb3077 | |||
| 1414dfeac2 | |||
| 41c1e0b6b9 | |||
| c9a4b82f2c | |||
| 736b6da176 | |||
| 34972ae9c1 | |||
| a9f1b833b9 | |||
| 83e8eca56d | |||
| 1c8c186681 | |||
| a0be2dcc9f | |||
| eb89f12c3e | |||
| ce2fff1a4f | |||
| 9301894997 | |||
| f21c1ff80a | |||
| e15b887d8d | |||
| b69db65037 | |||
| adcc824bf7 | |||
| 7213b23861 | |||
| 2cd3acd680 | |||
| 22ac3c9845 | |||
| 3275d06728 | |||
| 33b91cf7dc | |||
| a640633ea7 | |||
| 5f21a71770 | |||
| de3c2c6744 | |||
| e7e79e5a76 | |||
| 130a259c69 | |||
| 9580f33cb6 | |||
| eab66cfab8 | |||
| d2cecbcd05 | |||
| 2028eccc3c | |||
| 70c8c2b417 | |||
| 793187ff9e | |||
| 42bf6b1633 | |||
| 40719efc43 | |||
| e540384f50 | |||
| 9ca97374c8 | |||
| 902e855d92 | |||
| 64269d69ee | |||
| e976c88016 | |||
| 29cc145d44 | |||
| b16a3f1a77 | |||
| c2018413aa | |||
| 243e05ca5e | |||
| a29fe71666 | |||
| b0ffd4d74f | |||
| ab60acd9f4 | |||
| 6a417fcc9d | |||
| 1c77b05f68 | |||
| 051da5e8dc | |||
| a1ff6de652 | |||
| b471847b1c | |||
| 3abfdff943 | |||
| fce33b02a2 | |||
| da60fa7c49 | |||
| 20161d231f | |||
| c7bb14f369 | |||
| f8d1257d35 | |||
| f3b1087ac7 | |||
| 2299d7a02f | |||
| 489d6e3862 | |||
| 265bf669c8 | |||
| df09c1c55d | |||
| e8a5490d44 | |||
| ff9db4e273 | |||
| 108a3dabe6 | |||
| 31da35a549 | |||
| b4d1a47d6b | |||
| 3548a761a5 | |||
| 6f65462ec4 | |||
| a0e0d123b2 | |||
| f22f8f03ac | |||
| e236ec1f42 | |||
| 57e6bac3d4 | |||
| c818445611 | |||
| 45604801fa | |||
| 0a922a9f36 | |||
| 9b170e942c | |||
| cf169fd13e | |||
| 81895f991b | |||
| 011667c8e4 | |||
| 0e6f97f041 | |||
| fae7a7b80c | |||
| b851861931 | |||
| 45f4b5e56f | |||
| 3ddc45d625 | |||
| 1bd11eaf27 | |||
| 4776dc01d2 | |||
| de358b9461 | |||
| f3dd1c1886 | |||
| add049f0bd | |||
| 249e8461bb | |||
| 3293cd6542 | |||
| 6de7268b49 | |||
| dbae9832b6 | |||
| e49797ab21 | |||
| 47dfb33e98 | |||
| 5e16fbd603 | |||
| ab553ef008 | |||
| 7a5587c0c6 | |||
| 05bf33a1ec | |||
| 3f1a26cc1b | |||
| b248aa2ac8 | |||
| 06023bcf9d | |||
| 7542989f2b | |||
| 9e9447502e | |||
| eb1782e86f | |||
| a168342fa8 | |||
| 4820e53b18 | |||
| 248bef5503 | |||
| 8a49ac6061 | |||
| 4764f5f37f | |||
| dcb1da2f59 | |||
| 238c5cee7e | |||
| 70c943e948 | |||
| d6c4260eb8 | |||
| 1fed626900 | |||
| 0b2393cecc | |||
| 697413103d | |||
| b648276122 | |||
| 2e2c9b6361 | |||
| 0d311d61b4 | |||
| efc1bfd66a | |||
| 154fa2f14a | |||
| 2af63ce988 | |||
| e9bc6ebd27 | |||
| 201e671d61 | |||
| d63d1cef72 | |||
| 108c725c58 | |||
| 75dadb2925 | |||
| fedcc4a357 | |||
| 860ebf2df5 | |||
| 109858eae5 | |||
| 9041c1bf51 | |||
| f41e9a117b | |||
| 2f78136479 | |||
| 62a594ab59 | |||
| 81cc050bf3 |
Executable
+230
@@ -0,0 +1,230 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# check-already-published.sh <recipe-dir>
|
||||||
|
#
|
||||||
|
# Decide whether a given recipe (arch/<name> or debian/<name>) is already
|
||||||
|
# present in https://packages.reauktion.de/. Emits exactly one line to
|
||||||
|
# stdout:
|
||||||
|
#
|
||||||
|
# skip=1 — package with this version-pkgrel-arch tuple already lives in
|
||||||
|
# the pool; CI should short-circuit.
|
||||||
|
# skip=0 — file is missing or HEAD failed; CI should build + publish.
|
||||||
|
#
|
||||||
|
# Design notes:
|
||||||
|
# * For Arch recipes we source the PKGBUILD in a clean subshell so
|
||||||
|
# shell expansions (epoch=, ${_pkgver/-/}, pkgname=() arrays) resolve
|
||||||
|
# naturally. Only the first element of pkgname[] is checked — split
|
||||||
|
# packages share one source tarball / one build, so any-one-missing
|
||||||
|
# forces the full rebuild anyway.
|
||||||
|
# * For Debian recipes we extract the bare top-level PKGVER= /
|
||||||
|
# PKGREL= assignments (plus any other top-level VAR=value lines they
|
||||||
|
# reference) via grep and re-evaluate them in an isolated subshell —
|
||||||
|
# sourcing the entire build-deb.sh would run curl/tar/dpkg-deb
|
||||||
|
# against a tempdir we don't want to materialise here.
|
||||||
|
# * Epoch handling differs by ecosystem: Arch keeps `<epoch>:` in the
|
||||||
|
# pool filename, Debian/reprepro strips it.
|
||||||
|
# * curl --head with -f maps non-2xx to non-zero exit, which is what we
|
||||||
|
# want — 404 means "build it". -L follows mirrors. --max-time caps
|
||||||
|
# the worst-case latency per HEAD.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_BASE="${REPO_BASE:-https://packages.reauktion.de}"
|
||||||
|
HEAD_TIMEOUT="${HEAD_TIMEOUT:-15}"
|
||||||
|
|
||||||
|
RECIPE_DIR="${1:?usage: $0 <recipe-dir> (e.g. arch/distcc-avahi or debian/lmcp)}"
|
||||||
|
|
||||||
|
# Resolve relative to repo root if a leading path is passed; allow
|
||||||
|
# both `arch/foo` and absolute paths.
|
||||||
|
if [ ! -d "$RECIPE_DIR" ]; then
|
||||||
|
echo "error: recipe dir not found: $RECIPE_DIR" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
ecosystem="${RECIPE_DIR%%/*}"
|
||||||
|
|
||||||
|
http_head() {
|
||||||
|
local url="$1"
|
||||||
|
curl -sS -L --max-time "$HEAD_TIMEOUT" -o /dev/null \
|
||||||
|
-w '%{http_code}' --head "$url" || echo "000"
|
||||||
|
}
|
||||||
|
|
||||||
|
emit() {
|
||||||
|
# one-line GITHUB_OUTPUT-compatible kv
|
||||||
|
echo "skip=$1"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$ecosystem" in
|
||||||
|
arch)
|
||||||
|
pkgbuild="$RECIPE_DIR/PKGBUILD"
|
||||||
|
[ -f "$pkgbuild" ] || { echo "error: $pkgbuild missing" >&2; exit 2; }
|
||||||
|
|
||||||
|
# Source in a fresh bash to capture variables. Some PKGBUILDs run
|
||||||
|
# functions or call commands at top level — keep this fast by
|
||||||
|
# restricting PATH and trapping side effects.
|
||||||
|
eval "$(
|
||||||
|
bash --noprofile --norc -c "
|
||||||
|
set +e
|
||||||
|
# Stub out anything that might shell out; we only need variable
|
||||||
|
# assignments to land.
|
||||||
|
cd '$RECIPE_DIR'
|
||||||
|
source ./PKGBUILD >/dev/null 2>&1 || true
|
||||||
|
# pkgname may be array; print first element.
|
||||||
|
if declare -p pkgname 2>/dev/null | grep -q 'declare -a'; then
|
||||||
|
first_name=\"\${pkgname[0]}\"
|
||||||
|
else
|
||||||
|
first_name=\"\$pkgname\"
|
||||||
|
fi
|
||||||
|
if declare -p arch 2>/dev/null | grep -q 'declare -a'; then
|
||||||
|
first_arch=\"\${arch[0]}\"
|
||||||
|
else
|
||||||
|
first_arch=\"\$arch\"
|
||||||
|
fi
|
||||||
|
printf 'PB_NAME=%q\n' \"\$first_name\"
|
||||||
|
printf 'PB_VER=%q\n' \"\$pkgver\"
|
||||||
|
printf 'PB_REL=%q\n' \"\$pkgrel\"
|
||||||
|
printf 'PB_EPOCH=%q\n' \"\${epoch:-}\"
|
||||||
|
printf 'PB_ARCH=%q\n' \"\$first_arch\"
|
||||||
|
"
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [ -z "${PB_NAME:-}" ] || [ -z "${PB_VER:-}" ] || [ -z "${PB_REL:-}" ]; then
|
||||||
|
echo "error: failed to parse PKGBUILD ($RECIPE_DIR)" >&2
|
||||||
|
emit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Pool arch:
|
||||||
|
# arch=('any') → any
|
||||||
|
# arch=('aarch64' 'x86_64') → aarch64 (we publish for both, but the
|
||||||
|
# aarch64 artifact is the canonical CI build)
|
||||||
|
# arch=('aarch64') → aarch64
|
||||||
|
case "$PB_ARCH" in
|
||||||
|
any) pool_arch=any ;;
|
||||||
|
*) pool_arch=aarch64 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Version string with optional epoch (epoch:pkgver-pkgrel).
|
||||||
|
if [ -n "${PB_EPOCH:-}" ]; then
|
||||||
|
ver_full="${PB_EPOCH}:${PB_VER}-${PB_REL}"
|
||||||
|
else
|
||||||
|
ver_full="${PB_VER}-${PB_REL}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Pool URL path (arch keeps any/aarch64 split; 'any' lands in the
|
||||||
|
# aarch64 dir per current marfrit layout — both arches share the
|
||||||
|
# blob via the publish-to-both-arches step in build.yml).
|
||||||
|
pool_dir="arch/aarch64"
|
||||||
|
|
||||||
|
base_url="${REPO_BASE}/${pool_dir}/${PB_NAME}-${ver_full}-${pool_arch}.pkg.tar"
|
||||||
|
for ext in zst xz gz; do
|
||||||
|
code=$(http_head "${base_url}.${ext}")
|
||||||
|
if [ "$code" = "200" ]; then
|
||||||
|
emit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
emit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
debian)
|
||||||
|
bd="$RECIPE_DIR/build-deb.sh"
|
||||||
|
ctrl="$RECIPE_DIR/control"
|
||||||
|
[ -f "$bd" ] || { echo "error: $bd missing" >&2; exit 2; }
|
||||||
|
|
||||||
|
# Pull top-level `VAR=value` lines until we've passed PKGREL, and
|
||||||
|
# only those whose RHS is safe to re-evaluate (no command
|
||||||
|
# substitution `$(...)`, no escaped `\$`, no embedded commands like
|
||||||
|
# `DESTDIR=... meson ...`). This deliberately undershoots: we just
|
||||||
|
# need PKGVER/PKGREL plus any version vars they reference. Anything
|
||||||
|
# else (HERE=$(readlink ...), KERNELVER=\$(uname -r) inside a
|
||||||
|
# HEREDOC, etc.) gets dropped.
|
||||||
|
assigns=$(awk '
|
||||||
|
/^[A-Z_][A-Z0-9_]*=/ {
|
||||||
|
# split into LHS and RHS
|
||||||
|
eq = index($0, "=")
|
||||||
|
lhs = substr($0, 1, eq - 1)
|
||||||
|
rhs = substr($0, eq + 1)
|
||||||
|
# strip inline `# comment`
|
||||||
|
hash = index(rhs, "#")
|
||||||
|
if (hash > 1 && substr(rhs, hash-1, 1) == " ") rhs = substr(rhs, 1, hash - 2)
|
||||||
|
# reject lines with command-subst or escaped-dollar or naked commands
|
||||||
|
if (rhs ~ /\$\(/) next
|
||||||
|
if (rhs ~ /\\\$/) next
|
||||||
|
if (rhs ~ / [a-z]/) next # e.g. `DESTDIR="$ROOT" meson ...`
|
||||||
|
print lhs "=" rhs
|
||||||
|
if (lhs == "PKGREL") exit
|
||||||
|
}
|
||||||
|
' "$bd")
|
||||||
|
|
||||||
|
eval "$(
|
||||||
|
bash --noprofile --norc -c "
|
||||||
|
set +e
|
||||||
|
$assigns
|
||||||
|
printf 'PKGVER=%q\n' \"\${PKGVER:-}\"
|
||||||
|
printf 'PKGREL=%q\n' \"\${PKGREL:-}\"
|
||||||
|
"
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [ -z "${PKGVER:-}" ] || [ -z "${PKGREL:-}" ]; then
|
||||||
|
echo "error: failed to parse PKGVER/PKGREL from $bd" >&2
|
||||||
|
emit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Strip epoch (`N:` prefix) — debian pool filenames omit it.
|
||||||
|
ver_no_epoch="${PKGVER#*:}"
|
||||||
|
# If PKGVER had no colon, ${PKGVER#*:} returns PKGVER unchanged (bash quirk:
|
||||||
|
# the pattern must match for the prefix to be stripped). Guard explicitly.
|
||||||
|
case "$PKGVER" in
|
||||||
|
*:*) : ;;
|
||||||
|
*) ver_no_epoch="$PKGVER" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ver_full="${ver_no_epoch}-${PKGREL}"
|
||||||
|
|
||||||
|
# Architecture: parse control's `Architecture:` field.
|
||||||
|
if [ ! -f "$ctrl" ]; then
|
||||||
|
# Some recipes ship debian/control instead of ./control
|
||||||
|
ctrl="$RECIPE_DIR/debian/control"
|
||||||
|
fi
|
||||||
|
ctrl_arch=$(grep -m1 '^Architecture:' "$ctrl" 2>/dev/null | awk '{print $2}')
|
||||||
|
case "$ctrl_arch" in
|
||||||
|
all) file_arch=all ;;
|
||||||
|
arm64|any) file_arch=arm64 ;;
|
||||||
|
amd64) file_arch=amd64 ;;
|
||||||
|
*) file_arch=arm64 ;; # conservative default
|
||||||
|
esac
|
||||||
|
|
||||||
|
pkg_name=$(basename "$RECIPE_DIR")
|
||||||
|
|
||||||
|
# Compare against the canonical Packages index (what apt actually
|
||||||
|
# consults). reprepro refuses lower-version uploads, so checking
|
||||||
|
# only an exact source-pkgrel URL produces an endless-rebuild trap
|
||||||
|
# whenever source PKGREL has rolled back below pool head. We skip
|
||||||
|
# if pools published version >= source version-tuple.
|
||||||
|
source_full="${ver_full}"
|
||||||
|
if [ -n "${PKGVER#*:}" ] && [ "${PKGVER}" != "${PKGVER#*:}" ]; then
|
||||||
|
# PKGVER had an epoch — keep it for dpkg --compare-versions.
|
||||||
|
source_full="${PKGVER}-${PKGREL}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine suite: most recipes publish to both bookworm and trixie;
|
||||||
|
# checking trixie is sufficient (changelogs share Distribution).
|
||||||
|
suite="trixie"
|
||||||
|
pkg_arch_label="$file_arch"
|
||||||
|
[ "$file_arch" = "all" ] && pkg_arch_label="all"
|
||||||
|
packages_url="${REPO_BASE}/debian/dists/${suite}/main/binary-arm64/Packages"
|
||||||
|
[ "$file_arch" = "amd64" ] && packages_url="${REPO_BASE}/debian/dists/${suite}/main/binary-amd64/Packages"
|
||||||
|
|
||||||
|
pool_ver=$(set +o pipefail; curl -sS --max-time "$HEAD_TIMEOUT" "$packages_url" 2>/dev/null | awk -v p="$pkg_name" '$1=="Package:" && $2==p {found=1; next} found && $1=="Version:" {print $2; exit}')
|
||||||
|
|
||||||
|
if [ -n "$pool_ver" ] && command -v dpkg >/dev/null && dpkg --compare-versions "$pool_ver" ge "$source_full"; then
|
||||||
|
echo "pool has $pool_ver >= source $source_full" >&2
|
||||||
|
emit 1
|
||||||
|
fi
|
||||||
|
echo "pool has $pool_ver, source wants $source_full — build" >&2
|
||||||
|
emit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "error: unsupported ecosystem '$ecosystem' (recipe-dir=$RECIPE_DIR)" >&2
|
||||||
|
emit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
+640
-4
@@ -16,13 +16,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh arch/distcc-avahi)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
- name: bootstrap runner (idempotent)
|
- name: bootstrap runner (idempotent)
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { 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 avahi popt python python-setuptools
|
retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo avahi popt python python-setuptools
|
||||||
|
|
||||||
- name: import signing key
|
- name: import signing key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
||||||
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
||||||
@@ -37,6 +47,7 @@ jobs:
|
|||||||
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
||||||
|
|
||||||
- name: install deploy ssh key
|
- name: install deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
||||||
run: |
|
run: |
|
||||||
@@ -46,6 +57,7 @@ jobs:
|
|||||||
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 distcc-avahi
|
- name: makepkg distcc-avahi
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
rm -rf /tmp/build-distcc-avahi
|
rm -rf /tmp/build-distcc-avahi
|
||||||
@@ -56,6 +68,7 @@ jobs:
|
|||||||
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
||||||
|
|
||||||
- name: sign distcc-avahi
|
- name: sign distcc-avahi
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
cd /tmp/build-distcc-avahi
|
cd /tmp/build-distcc-avahi
|
||||||
@@ -66,6 +79,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: update aarch64 repo db
|
- name: update aarch64 repo db
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
mkdir -p /tmp/arch-stage
|
mkdir -p /tmp/arch-stage
|
||||||
@@ -105,6 +119,7 @@ jobs:
|
|||||||
rm -f marfrit.files.sig
|
rm -f marfrit.files.sig
|
||||||
|
|
||||||
- name: publish to aarch64
|
- name: publish to aarch64
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
|
||||||
@@ -129,13 +144,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh debian/lmcp)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
- name: install dpkg
|
- name: install dpkg
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { 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
|
retry pacman -Syu --noconfirm --needed dpkg openssh rsync curl
|
||||||
|
|
||||||
- name: install hertz deploy ssh key
|
- name: install hertz deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }}
|
KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }}
|
||||||
run: |
|
run: |
|
||||||
@@ -145,6 +170,7 @@ jobs:
|
|||||||
ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null
|
ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null
|
||||||
|
|
||||||
- name: build lmcp .deb
|
- name: build lmcp .deb
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
cd debian/lmcp
|
cd debian/lmcp
|
||||||
@@ -152,6 +178,7 @@ jobs:
|
|||||||
ls -la *.deb
|
ls -la *.deb
|
||||||
|
|
||||||
- name: upload + publish to suites
|
- name: upload + publish to suites
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
|
||||||
@@ -182,13 +209,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh arch/lmcp)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
- name: bootstrap runner (idempotent)
|
- name: bootstrap runner (idempotent)
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { 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 lua lua-socket
|
retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo lua lua-socket
|
||||||
|
|
||||||
- name: import signing key
|
- name: import signing key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
||||||
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
||||||
@@ -203,6 +240,7 @@ jobs:
|
|||||||
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
||||||
|
|
||||||
- name: install deploy ssh key
|
- name: install deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
||||||
run: |
|
run: |
|
||||||
@@ -212,6 +250,7 @@ jobs:
|
|||||||
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 lmcp
|
- name: makepkg lmcp
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
rm -rf /tmp/build-lmcp
|
rm -rf /tmp/build-lmcp
|
||||||
@@ -222,6 +261,7 @@ jobs:
|
|||||||
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
||||||
|
|
||||||
- name: sign lmcp
|
- name: sign lmcp
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
cd /tmp/build-lmcp
|
cd /tmp/build-lmcp
|
||||||
@@ -232,6 +272,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: publish lmcp to both arches
|
- name: publish lmcp to both arches
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
|
||||||
@@ -283,13 +324,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh arch/claude-his-agent)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
- name: bootstrap runner (idempotent)
|
- name: bootstrap runner (idempotent)
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { 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
|
retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo
|
||||||
|
|
||||||
- name: import signing key
|
- name: import signing key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
||||||
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
||||||
@@ -304,6 +355,7 @@ jobs:
|
|||||||
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
||||||
|
|
||||||
- name: install deploy ssh key
|
- name: install deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
||||||
run: |
|
run: |
|
||||||
@@ -313,6 +365,7 @@ jobs:
|
|||||||
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 claude-his-agent
|
- name: makepkg claude-his-agent
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
rm -rf /tmp/build-his
|
rm -rf /tmp/build-his
|
||||||
@@ -323,6 +376,7 @@ jobs:
|
|||||||
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
||||||
|
|
||||||
- name: sign claude-his-agent
|
- name: sign claude-his-agent
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
cd /tmp/build-his
|
cd /tmp/build-his
|
||||||
@@ -333,6 +387,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: publish claude-his-agent to both arches
|
- name: publish claude-his-agent to both arches
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
|
||||||
@@ -375,7 +430,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.
|
||||||
@@ -387,13 +442,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh arch/ffmpeg-v4l2-request-fourier)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
- name: bootstrap runner (idempotent)
|
- name: bootstrap runner (idempotent)
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { 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 nasm
|
retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo nasm
|
||||||
|
|
||||||
- name: import signing key
|
- name: import signing key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
||||||
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
||||||
@@ -408,6 +473,7 @@ jobs:
|
|||||||
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
||||||
|
|
||||||
- name: install deploy ssh key
|
- name: install deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
||||||
run: |
|
run: |
|
||||||
@@ -416,11 +482,12 @@ 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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
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 +496,8 @@ 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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
cd /tmp/build-ffmpeg-v4l2
|
cd /tmp/build-ffmpeg-v4l2
|
||||||
@@ -440,6 +508,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: update aarch64 repo db
|
- name: update aarch64 repo db
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
mkdir -p /tmp/arch-stage-ffmpeg
|
mkdir -p /tmp/arch-stage-ffmpeg
|
||||||
@@ -475,6 +544,7 @@ jobs:
|
|||||||
rm -f marfrit.files.sig
|
rm -f marfrit.files.sig
|
||||||
|
|
||||||
- name: publish to aarch64
|
- name: publish to aarch64
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
|
||||||
@@ -500,13 +570,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh arch/libva-v4l2-request-fourier)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
- name: bootstrap runner (idempotent)
|
- name: bootstrap runner (idempotent)
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { 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
|
retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo
|
||||||
|
|
||||||
- name: import signing key
|
- name: import signing key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
||||||
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
||||||
@@ -521,6 +601,7 @@ jobs:
|
|||||||
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
||||||
|
|
||||||
- name: install deploy ssh key
|
- name: install deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
||||||
run: |
|
run: |
|
||||||
@@ -530,6 +611,7 @@ jobs:
|
|||||||
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 libva-v4l2-request-fourier
|
- name: makepkg libva-v4l2-request-fourier
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
rm -rf /tmp/build-libva-v4l2
|
rm -rf /tmp/build-libva-v4l2
|
||||||
@@ -541,6 +623,7 @@ jobs:
|
|||||||
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
||||||
|
|
||||||
- name: sign libva-v4l2-request-fourier
|
- name: sign libva-v4l2-request-fourier
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
cd /tmp/build-libva-v4l2
|
cd /tmp/build-libva-v4l2
|
||||||
@@ -551,6 +634,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: update aarch64 repo db
|
- name: update aarch64 repo db
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
mkdir -p /tmp/arch-stage-libva
|
mkdir -p /tmp/arch-stage-libva
|
||||||
@@ -586,6 +670,7 @@ jobs:
|
|||||||
rm -f marfrit.files.sig
|
rm -f marfrit.files.sig
|
||||||
|
|
||||||
- name: publish to aarch64
|
- name: publish to aarch64
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
|
||||||
@@ -611,13 +696,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh arch/mpv-fourier)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
- name: bootstrap runner (idempotent)
|
- name: bootstrap runner (idempotent)
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { 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
|
retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo
|
||||||
|
|
||||||
- name: import signing key
|
- name: import signing key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
||||||
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
||||||
@@ -632,6 +727,7 @@ jobs:
|
|||||||
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
||||||
|
|
||||||
- name: install deploy ssh key
|
- name: install deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
||||||
run: |
|
run: |
|
||||||
@@ -641,6 +737,7 @@ jobs:
|
|||||||
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: configure [marfrit] repo + pre-install ffmpeg-v4l2-request-fourier
|
- name: configure [marfrit] repo + pre-install ffmpeg-v4l2-request-fourier
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
# mpv-fourier links libavcodec at build time. If the build host pulls
|
# mpv-fourier links libavcodec at build time. If the build host pulls
|
||||||
@@ -668,6 +765,7 @@ jobs:
|
|||||||
printf 'y\ny\ny\n' | pacman -S marfrit/ffmpeg-v4l2-request-fourier
|
printf 'y\ny\ny\n' | pacman -S marfrit/ffmpeg-v4l2-request-fourier
|
||||||
|
|
||||||
- name: makepkg mpv-fourier
|
- name: makepkg mpv-fourier
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
rm -rf /tmp/build-mpv
|
rm -rf /tmp/build-mpv
|
||||||
@@ -679,6 +777,7 @@ jobs:
|
|||||||
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
||||||
|
|
||||||
- name: sign mpv-fourier
|
- name: sign mpv-fourier
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
cd /tmp/build-mpv
|
cd /tmp/build-mpv
|
||||||
@@ -689,6 +788,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: update aarch64 repo db
|
- name: update aarch64 repo db
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
mkdir -p /tmp/arch-stage-mpv
|
mkdir -p /tmp/arch-stage-mpv
|
||||||
@@ -724,6 +824,7 @@ jobs:
|
|||||||
rm -f marfrit.files.sig
|
rm -f marfrit.files.sig
|
||||||
|
|
||||||
- name: publish to aarch64
|
- name: publish to aarch64
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
|
||||||
@@ -746,13 +847,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh debian/claude-his-agent)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
- name: install dpkg
|
- name: install dpkg
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { 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
|
retry pacman -Syu --noconfirm --needed dpkg openssh rsync curl
|
||||||
|
|
||||||
- name: install hertz deploy ssh key
|
- name: install hertz deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
env:
|
env:
|
||||||
KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }}
|
KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }}
|
||||||
run: |
|
run: |
|
||||||
@@ -762,6 +873,7 @@ jobs:
|
|||||||
ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null
|
ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null
|
||||||
|
|
||||||
- name: build claude-his-agent .deb
|
- name: build claude-his-agent .deb
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
cd debian/claude-his-agent
|
cd debian/claude-his-agent
|
||||||
@@ -769,6 +881,7 @@ jobs:
|
|||||||
ls -la *.deb
|
ls -la *.deb
|
||||||
|
|
||||||
- name: upload + publish to suites
|
- name: upload + publish to suites
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
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() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
|
||||||
@@ -784,3 +897,526 @@ 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: debian-aarch64
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh debian/ffmpeg-v4l2-request-fourier)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
|
- name: install build-deps (Arch pkg names; build-deb.sh links natively)
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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; }
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
retry apt-get update -qq
|
||||||
|
# Debian build-deps for the FFmpeg fourier-fork build. These
|
||||||
|
# map 1:1 to the previous Arch list; libav*-dev intentionally
|
||||||
|
# absent (we are FFmpeg itself, providing those libs).
|
||||||
|
retry apt-get install -y --no-install-recommends \
|
||||||
|
build-essential cmake ninja-build git pkg-config nasm yasm \
|
||||||
|
linux-libc-dev libgl1-mesa-dev libasound2-dev libbz2-dev \
|
||||||
|
libfontconfig-dev libfribidi-dev libgmp-dev libgnutls28-dev \
|
||||||
|
libmp3lame-dev libass-dev libdav1d-dev libdrm-dev \
|
||||||
|
libfreetype-dev libpulse-dev libva-dev libvorbis-dev libvpx-dev \
|
||||||
|
libwebp-dev libx264-dev libx265-dev libxml2-dev libopus-dev \
|
||||||
|
libvulkan-dev glslang-tools \
|
||||||
|
v4l-utils liblzma-dev zlib1g-dev \
|
||||||
|
curl ca-certificates openssh-client rsync dpkg-dev
|
||||||
|
|
||||||
|
- name: install hertz deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
cd debian/ffmpeg-v4l2-request-fourier
|
||||||
|
./build-deb.sh
|
||||||
|
ls -la *.deb
|
||||||
|
|
||||||
|
- name: upload + publish to suites
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
# Native Debian trixie runner — the driver bakes __vaDriverInit_1_<MINOR>
|
||||||
|
# at compile time from <va/va.h>. Building on Arch (libva 2.23) produced
|
||||||
|
# __vaDriverInit_1_23, which trixie's libva 2.22 runtime cannot bind: the
|
||||||
|
# .deb installed but vaInitialize() returned -1 on every host. A native
|
||||||
|
# trixie runner avoids the cross-distro ABI skew entirely.
|
||||||
|
runs-on: debian-aarch64
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh debian/libva-v4l2-request-fourier)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
|
- name: install build-deps
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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; }
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
retry apt-get update -qq
|
||||||
|
retry apt-get install -y --no-install-recommends \
|
||||||
|
build-essential meson ninja-build pkg-config \
|
||||||
|
libva-dev libdrm-dev \
|
||||||
|
curl openssh-client rsync ca-certificates git dpkg-dev
|
||||||
|
|
||||||
|
- name: install hertz deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
cd debian/libva-v4l2-request-fourier
|
||||||
|
./build-deb.sh
|
||||||
|
ls -la *.deb
|
||||||
|
|
||||||
|
- name: upload + publish to suites
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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: debian-aarch64
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh debian/mpv-fourier)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
|
- name: install build-deps
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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; }
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
retry apt-get update -qq
|
||||||
|
# Debian libav*-dev is ABI-compatible with the fourier ffmpeg
|
||||||
|
# fork at the header level; mpv link-binds against system
|
||||||
|
# libav at build time, runtime dlopen picks up the fourier
|
||||||
|
# libs if installed. The previous [marfrit] pre-install of
|
||||||
|
# ffmpeg-v4l2-request-fourier under pacman is unnecessary
|
||||||
|
# under apt: stock Debian libav*-dev provides the trixie
|
||||||
|
# ABI mpv-fourier's binary will encounter.
|
||||||
|
retry apt-get install -y --no-install-recommends \
|
||||||
|
build-essential git meson ninja-build pkg-config python3-docutils \
|
||||||
|
ladspa-sdk wayland-protocols libvulkan-dev libwayland-dev \
|
||||||
|
libasound2-dev desktop-file-utils libc6-dev hicolor-icon-theme \
|
||||||
|
libjack-jackd2-dev liblcms2-dev libarchive-dev libass-dev \
|
||||||
|
libbluray-dev libcdio-dev libcdio-paranoia-dev libdisplay-info-dev \
|
||||||
|
libdrm-dev libdvdnav-dev libdvdread-dev libegl-dev libgl-dev \
|
||||||
|
libglvnd-dev libjpeg-dev libplacebo-dev libpulse-dev libsixel-dev \
|
||||||
|
libva-dev libvdpau-dev libx11-dev libxext-dev libxkbcommon-dev \
|
||||||
|
libxpresent-dev libxrandr-dev libxss-dev libxv-dev libluajit-5.1-dev \
|
||||||
|
libmujs-dev libpipewire-0.3-dev librubberband-dev libsdl2-dev \
|
||||||
|
libopenal-dev libuchardet-dev libvapoursynth-dev liblzma-dev \
|
||||||
|
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev \
|
||||||
|
zlib1g-dev \
|
||||||
|
curl ca-certificates openssh-client rsync dpkg-dev
|
||||||
|
|
||||||
|
- name: install hertz deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
cd debian/mpv-fourier
|
||||||
|
./build-deb.sh
|
||||||
|
ls -la *.deb
|
||||||
|
|
||||||
|
- name: upload + publish to suites
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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: debian-aarch64
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh debian/daedalus-v4l2)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
|
- name: install build-deps
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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; }
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
retry apt-get update -qq
|
||||||
|
# FFmpeg headers + sonames the daemon dlopens. As of
|
||||||
|
# daedalus-v4l2 PR #16 (commit 514da29), the daemon targets
|
||||||
|
# the Kwiboo fork's libavcodec.so.62 / libavformat.so.62 /
|
||||||
|
# libavutil.so.60 at /opt/fourier — so the build needs
|
||||||
|
# /opt/fourier/include and /opt/fourier/lib/pkgconfig.
|
||||||
|
# ffmpeg-v4l2-request-fourier provides both (plus the
|
||||||
|
# runtime libs the .deb will dlopen on the target host;
|
||||||
|
# we install it as a build-dep here and the dpkg-shlibdeps
|
||||||
|
# step pulls it into the daemon .deb's Depends automatically).
|
||||||
|
# Debian-stock libav*-dev removed — would conflict on
|
||||||
|
# /usr/include/libavcodec/avcodec.h vs /opt/fourier's copy.
|
||||||
|
#
|
||||||
|
# libvulkan-dev + glslang-tools: needed by the in-build
|
||||||
|
# daedalus-fourier fetch (build-deb.sh fetches the sibling
|
||||||
|
# library, cmake-builds it into a temp prefix, then the
|
||||||
|
# daedalus daemon static-links against it via pkg-config).
|
||||||
|
# Without these, daedalus-fourier's find_package(Vulkan)
|
||||||
|
# and glslangValidator find_program both fail at configure
|
||||||
|
# time. See marfrit/daedalus-fourier PR #1 +
|
||||||
|
# reauktion/daedalus-v4l2 PR #13.
|
||||||
|
retry apt-get install -y --no-install-recommends \
|
||||||
|
build-essential cmake ninja-build pkg-config git \
|
||||||
|
ffmpeg-v4l2-request-fourier libdrm-dev \
|
||||||
|
libvulkan-dev glslang-tools \
|
||||||
|
linux-libc-dev \
|
||||||
|
curl ca-certificates openssh-client rsync dpkg-dev
|
||||||
|
|
||||||
|
- name: install hertz deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
cd debian/daedalus-v4l2
|
||||||
|
./build-deb.sh
|
||||||
|
ls -la *.deb
|
||||||
|
|
||||||
|
- name: upload + publish to suites
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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: debian-aarch64
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh debian/daedalus-v4l2-dkms)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
|
- name: install tooling
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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; }
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
retry apt-get update -qq
|
||||||
|
retry apt-get install -y --no-install-recommends \
|
||||||
|
dpkg-dev openssh-client rsync curl ca-certificates tar gzip
|
||||||
|
|
||||||
|
- name: install hertz deploy ssh key
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
cd debian/daedalus-v4l2-dkms
|
||||||
|
./build-deb.sh
|
||||||
|
ls -la *.deb
|
||||||
|
|
||||||
|
- name: upload + publish to suites
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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: skip if already published
|
||||||
|
id: skip-check
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
result=$(./.gitea/scripts/check-already-published.sh arch/mesa-panvk-bifrost)
|
||||||
|
echo "$result" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "decision: $result"
|
||||||
|
|
||||||
|
- name: bootstrap runner (idempotent)
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
if: steps.skip-check.outputs.skip != '1'
|
||||||
|
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
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
# 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.
|
||||||
|
# 5d8b436 reverts PRs #7 + #8 (parking design that broke libva's
|
||||||
|
# 1:1 contract — see daedalus-v4l2#9 + #10). Tree is
|
||||||
|
# content-equivalent to f0d4186 plus PR #4 (cosmetic menu ctrls).
|
||||||
|
# PROTO_VERSION drops 1 → 0; lock-step install with
|
||||||
|
# daedalus-v4l2 0.1.0.r33.5d8b436 REQUIRED.
|
||||||
|
_commit=5d8b4369e58ab947d1c56b1f718293c57c6065b5
|
||||||
|
|
||||||
|
pkgver=0.1.0.r33.5d8b436
|
||||||
|
pkgrel=1 # reset for new upstream pin (5d8b436 — revert parking design)
|
||||||
|
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.
|
||||||
|
:
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
# 6e6dfa1 = picks up daedalus-v4l2 PR #16 — daemon now dlopens
|
||||||
|
# the Kwiboo fourier fork's libavcodec.so.62 / libavformat.so.62 /
|
||||||
|
# libavutil.so.60 at /opt/fourier instead of Debian-stock soname
|
||||||
|
# 61/61/59. First step on the daedalus-fourier substitution arc
|
||||||
|
# (daedalus-v4l2#11). Daemon still needs daedalus-fourier at
|
||||||
|
# build time (Arch packaging for that is a follow-up; Debian side
|
||||||
|
# fetches inline via build-deb.sh).
|
||||||
|
_commit=6e6dfa144da7bc7fa8be50c8da91d7d1c6132a2c
|
||||||
|
|
||||||
|
# 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.r41.6e6dfa1
|
||||||
|
pkgrel=1 # reset for new upstream pin (6e6dfa1 — soname 62 via /opt/fourier)
|
||||||
|
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-v4l2-request-fourier' '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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
From f760c0541586f43334c02611fcb4c212c08ad576 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Markus Fritsche <mfritsche@reauktion.de>
|
||||||
|
Date: Thu, 21 May 2026 21:40:22 +0200
|
||||||
|
Subject: [PATCH] avcodec/aarch64/h264dsp: route H.264 4x4 IDCT through
|
||||||
|
daedalus-fourier
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
H264DSPContext.idct_add (called per 4x4 block from the intra-4x4
|
||||||
|
decode path in h264_mb.c) now dispatches through
|
||||||
|
daedalus_recipe_dispatch_h264_idct4 instead of ff_h264_idct_add_neon.
|
||||||
|
|
||||||
|
The recipe layer picks the substrate; for cycle 6 (H.264 IDCT 4x4)
|
||||||
|
the recipe is CPU NEON, so this is effectively a NEON-to-NEON
|
||||||
|
substitution with one extra dispatch call and recipe-table lookup.
|
||||||
|
Provides the first end-to-end exercise of the daedalus-fourier
|
||||||
|
kernel pack inside the libavcodec.so decode hot path; follow-up
|
||||||
|
patches wire IDCT 8x8, luma-v deblock, and qpel mc20.
|
||||||
|
|
||||||
|
The library context is process-global, lazily initialised under
|
||||||
|
pthread_once on first call. We pick the no-QPU constructor because
|
||||||
|
libavcodec.so is loaded into arbitrary host processes
|
||||||
|
(firefox-fourier, mpv-fourier, daedalus_v4l2_daemon, ...) and we
|
||||||
|
cannot assume the host has a usable Vulkan instance. Higher cycles
|
||||||
|
(deblock luma-v, MC) that benefit from the QPU will provision their
|
||||||
|
own recipe-selected context once that path is wired.
|
||||||
|
|
||||||
|
Bulk paths (idct_add16, idct_add16intra, idct_add8 — used for
|
||||||
|
non-intra4x4 macroblocks) remain on the stock NEON .S implementations
|
||||||
|
and will be batched through daedalus_recipe_dispatch_h264_idct4 with
|
||||||
|
n_blocks>1 in a follow-up.
|
||||||
|
|
||||||
|
Bit-exact against ff_h264_idct_add_neon (daedalus-fourier cycle 6
|
||||||
|
green; see marfrit/daedalus-fourier/CYCLE_LOGS.md).
|
||||||
|
|
||||||
|
Refs reauktion/daedalus-v4l2#11 — substitution arc step 2.
|
||||||
|
---
|
||||||
|
libavcodec/aarch64/Makefile | 3 +-
|
||||||
|
libavcodec/aarch64/h264_idct_daedalus.c | 49 +++++++++++++++++++++++
|
||||||
|
libavcodec/aarch64/h264dsp_init_aarch64.c | 3 +-
|
||||||
|
3 files changed, 53 insertions(+), 2 deletions(-)
|
||||||
|
create mode 100644 libavcodec/aarch64/h264_idct_daedalus.c
|
||||||
|
|
||||||
|
diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile
|
||||||
|
index 41ab025..7b95fb1 100644
|
||||||
|
--- a/libavcodec/aarch64/Makefile
|
||||||
|
+++ b/libavcodec/aarch64/Makefile
|
||||||
|
@@ -3,7 +3,8 @@ OBJS-$(CONFIG_AC3DSP) += aarch64/ac3dsp_init_aarch64.o
|
||||||
|
OBJS-$(CONFIG_FDCTDSP) += aarch64/fdctdsp_init_aarch64.o
|
||||||
|
OBJS-$(CONFIG_FMTCONVERT) += aarch64/fmtconvert_init.o
|
||||||
|
OBJS-$(CONFIG_H264CHROMA) += aarch64/h264chroma_init_aarch64.o
|
||||||
|
-OBJS-$(CONFIG_H264DSP) += aarch64/h264dsp_init_aarch64.o
|
||||||
|
+OBJS-$(CONFIG_H264DSP) += aarch64/h264dsp_init_aarch64.o \
|
||||||
|
+ aarch64/h264_idct_daedalus.o
|
||||||
|
OBJS-$(CONFIG_HUFFYUVDSP) += aarch64/huffyuvdsp_init_aarch64.o
|
||||||
|
OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_init.o
|
||||||
|
OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_init_aarch64.o
|
||||||
|
diff --git a/libavcodec/aarch64/h264_idct_daedalus.c b/libavcodec/aarch64/h264_idct_daedalus.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..538d223
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libavcodec/aarch64/h264_idct_daedalus.c
|
||||||
|
@@ -0,0 +1,49 @@
|
||||||
|
+/*
|
||||||
|
+ * H.264 4x4 IDCT + add — daedalus-fourier substitution shim.
|
||||||
|
+ *
|
||||||
|
+ * Routes H264DSPContext.idct_add through
|
||||||
|
+ * daedalus_recipe_dispatch_h264_idct4 instead of ff_h264_idct_add_neon.
|
||||||
|
+ * The recipe layer picks the substrate (CPU NEON by default for
|
||||||
|
+ * cycle 6; future cycles may dispatch to V3D opportunistically).
|
||||||
|
+ *
|
||||||
|
+ * FFmpeg's 4x4 block memory layout matches daedalus's column-major
|
||||||
|
+ * convention: block[r + 4*c] = coefficient at (row r, col c). Both
|
||||||
|
+ * sides destructively zero the block after the transform.
|
||||||
|
+ *
|
||||||
|
+ * The library context is process-global and lazily initialised under
|
||||||
|
+ * pthread_once. We pick the no-QPU constructor here because
|
||||||
|
+ * libavcodec.so is loaded into arbitrary host processes
|
||||||
|
+ * (firefox-fourier, mpv-fourier, daedalus_v4l2_daemon, ...) and we
|
||||||
|
+ * cannot assume the host has a usable Vulkan instance. Higher cycles
|
||||||
|
+ * (deblock, MC) that benefit from the QPU initialise their own
|
||||||
|
+ * recipe-selected context once that path is wired.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <pthread.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <stdint.h>
|
||||||
|
+
|
||||||
|
+#include <daedalus.h>
|
||||||
|
+
|
||||||
|
+#include "libavutil/attributes.h"
|
||||||
|
+#include "libavcodec/h264dsp.h"
|
||||||
|
+
|
||||||
|
+static daedalus_ctx *g_dctx;
|
||||||
|
+static pthread_once_t g_dctx_once = PTHREAD_ONCE_INIT;
|
||||||
|
+
|
||||||
|
+static void daedalus_ctx_init_once(void)
|
||||||
|
+{
|
||||||
|
+ g_dctx = daedalus_ctx_create_no_qpu();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void ff_h264_idct_add_daedalus(uint8_t *dst, int16_t *block, int stride);
|
||||||
|
+
|
||||||
|
+void ff_h264_idct_add_daedalus(uint8_t *dst, int16_t *block, int stride)
|
||||||
|
+{
|
||||||
|
+ static const daedalus_h264_block_meta meta = { .dst_off = 0 };
|
||||||
|
+
|
||||||
|
+ pthread_once(&g_dctx_once, daedalus_ctx_init_once);
|
||||||
|
+
|
||||||
|
+ daedalus_recipe_dispatch_h264_idct4(g_dctx, dst, (size_t)stride,
|
||||||
|
+ block, 1, &meta);
|
||||||
|
+}
|
||||||
|
diff --git a/libavcodec/aarch64/h264dsp_init_aarch64.c b/libavcodec/aarch64/h264dsp_init_aarch64.c
|
||||||
|
index c684574..b993df2 100644
|
||||||
|
--- a/libavcodec/aarch64/h264dsp_init_aarch64.c
|
||||||
|
+++ b/libavcodec/aarch64/h264dsp_init_aarch64.c
|
||||||
|
@@ -66,6 +66,7 @@ void ff_biweight_h264_pixels_4_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride
|
||||||
|
int weights, int offset);
|
||||||
|
|
||||||
|
void ff_h264_idct_add_neon(uint8_t *dst, int16_t *block, int stride);
|
||||||
|
+void ff_h264_idct_add_daedalus(uint8_t *dst, int16_t *block, int stride);
|
||||||
|
void ff_h264_idct_dc_add_neon(uint8_t *dst, int16_t *block, int stride);
|
||||||
|
void ff_h264_idct_add16_neon(uint8_t *dst, const int *block_offset,
|
||||||
|
int16_t *block, int stride,
|
||||||
|
@@ -139,7 +140,7 @@ av_cold void ff_h264dsp_init_aarch64(H264DSPContext *c, const int bit_depth,
|
||||||
|
c->biweight_pixels_tab[1] = ff_biweight_h264_pixels_8_neon;
|
||||||
|
c->biweight_pixels_tab[2] = ff_biweight_h264_pixels_4_neon;
|
||||||
|
|
||||||
|
- c->idct_add = ff_h264_idct_add_neon;
|
||||||
|
+ c->idct_add = ff_h264_idct_add_daedalus;
|
||||||
|
c->idct_dc_add = ff_h264_idct_dc_add_neon;
|
||||||
|
c->idct_add16 = ff_h264_idct_add16_neon;
|
||||||
|
c->idct_add16intra = ff_h264_idct_add16intra_neon;
|
||||||
|
--
|
||||||
|
2.47.3
|
||||||
|
|
||||||
@@ -24,8 +24,13 @@ _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=6 # pkgrel=6 — H.264 IDCT 4x4 daedalus-fourier substitution (2026-05-21)
|
||||||
epoch=2
|
epoch=2
|
||||||
|
|
||||||
|
# daedalus-fourier pin — first kernel substitution in libavcodec
|
||||||
|
# (cycle 6 H.264 IDCT 4x4). Same SHA as the daedalus-v4l2 daemon's
|
||||||
|
# inline build; lockstep with that until the public API rolls.
|
||||||
|
_daedalus_fourier_commit='d87239d8172307d9a1b93c95cbed116d175b85cc'
|
||||||
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')
|
||||||
url='https://github.com/Kwiboo/FFmpeg'
|
url='https://github.com/Kwiboo/FFmpeg'
|
||||||
@@ -34,6 +39,7 @@ depends=(
|
|||||||
alsa-lib
|
alsa-lib
|
||||||
bzip2
|
bzip2
|
||||||
fontconfig
|
fontconfig
|
||||||
|
vulkan-icd-loader
|
||||||
fribidi
|
fribidi
|
||||||
gmp
|
gmp
|
||||||
gnutls
|
gnutls
|
||||||
@@ -59,10 +65,13 @@ depends=(
|
|||||||
zlib
|
zlib
|
||||||
)
|
)
|
||||||
makedepends=(
|
makedepends=(
|
||||||
|
cmake
|
||||||
git
|
git
|
||||||
linux-api-headers
|
linux-api-headers
|
||||||
mesa
|
mesa
|
||||||
nasm
|
nasm
|
||||||
|
ninja
|
||||||
|
vulkan-headers
|
||||||
)
|
)
|
||||||
provides=(
|
provides=(
|
||||||
libavcodec.so
|
libavcodec.so
|
||||||
@@ -78,8 +87,11 @@ 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')
|
"daedalus-fourier-${_daedalus_fourier_commit}.tar.gz::https://git.reauktion.de/marfrit/daedalus-fourier/archive/${_daedalus_fourier_commit}.tar.gz"
|
||||||
sha256sums=('SKIP' 'SKIP')
|
'0001-libudev-bypass-fallback.patch'
|
||||||
|
'0002-nv15-to-p010-unpack.patch'
|
||||||
|
'0003-h264-idct4-daedalus-fourier.patch')
|
||||||
|
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
|
||||||
|
|
||||||
pkgver() {
|
pkgver() {
|
||||||
cd "${_srcname}"
|
cd "${_srcname}"
|
||||||
@@ -91,9 +103,26 @@ 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"
|
||||||
|
patch -Np1 -i "${srcdir}/0003-h264-idct4-daedalus-fourier.patch"
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
|
# --- daedalus-fourier: build static .a with PIC, install to a
|
||||||
|
# per-build prefix; libavcodec.so links it into the shared object so
|
||||||
|
# H264DSPContext.idct_add (and follow-up kernels) dispatch through
|
||||||
|
# the daedalus recipe layer instead of the in-tree NEON .S code. ---
|
||||||
|
local _fourier_prefix="${srcdir}/fourier-prefix"
|
||||||
|
mkdir -p "${_fourier_prefix}"
|
||||||
|
pushd "${srcdir}"/daedalus-fourier >/dev/null
|
||||||
|
cmake -B build -G Ninja \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="${_fourier_prefix}"
|
||||||
|
cmake --build build --target daedalus_core
|
||||||
|
cmake --install build
|
||||||
|
popd >/dev/null
|
||||||
|
|
||||||
cd "${_srcname}"
|
cd "${_srcname}"
|
||||||
|
|
||||||
# FFmpeg's configure resolves the compiler via `which` and bakes the
|
# FFmpeg's configure resolves the compiler via `which` and bakes the
|
||||||
@@ -145,6 +174,9 @@ build() {
|
|||||||
--enable-libx265 \
|
--enable-libx265 \
|
||||||
--enable-libwebp \
|
--enable-libwebp \
|
||||||
\
|
\
|
||||||
|
--extra-cflags="-I${_fourier_prefix}/include" \
|
||||||
|
--extra-ldflags="-L${_fourier_prefix}/lib" \
|
||||||
|
--extra-libs="-ldaedalus_core -lvulkan -lpthread" \
|
||||||
--host-cflags='-fPIC'
|
--host-cflags='-fPIC'
|
||||||
|
|
||||||
make
|
make
|
||||||
+23
-22
@@ -18,27 +18,30 @@ This patch adds a sibling init path, `InitV4L2RequestDecoder`, that:
|
|||||||
* looks up the codec via two complementary mechanisms libavcodec
|
* looks up the codec via two complementary mechanisms libavcodec
|
||||||
uses for v4l2_request:
|
uses for v4l2_request:
|
||||||
- **named codec** (`h264_v4l2request`, `vp8_v4l2request`, etc.):
|
- **named codec** (`h264_v4l2request`, `vp8_v4l2request`, etc.):
|
||||||
the legacy AVCodec-per-hwaccel registration. ALARM, Debian,
|
the legacy AVCodec-per-hwaccel registration.
|
||||||
and most distros building with --enable-v4l2-request expose
|
- **generic codec + hw_configs walk**: the modern hwaccel
|
||||||
this (avcodec_find_decoder_by_name lookup).
|
registration. Accepts EITHER AV_HWDEVICE_TYPE_DRM (legacy
|
||||||
- **generic codec + AV_HWDEVICE_TYPE_DRM** in `hw_configs`:
|
ffmpeg-v4l2-request-fork output prior to FFmpeg 7.1) OR
|
||||||
the modern hwaccel registration on some upstream-only ffmpeg
|
AV_HWDEVICE_TYPE_V4L2REQUEST (FFmpeg 7.1+ dedicated enum,
|
||||||
builds.
|
value 13 on Kwiboo's no-AMF tree, 14 on upstream-AMF tree).
|
||||||
|
Mozilla's bundled libavutil headers may not have the V4L2REQUEST
|
||||||
|
enumerator, so the test is on the integer value via `(int)cast`.
|
||||||
Probes named-codec first (explicit, portable) and falls back to
|
Probes named-codec first (explicit, portable) and falls back to
|
||||||
walking the generic codec's `hw_configs` for the DRM device type;
|
walking the generic codec's `hw_configs` for either device type;
|
||||||
* creates an `AV_HWDEVICE_TYPE_DRM` hwdevice context bound to
|
* creates an hwdevice context bound to `/dev/dri/renderD128`. Uses
|
||||||
`/dev/dri/renderD128` via the new `av_hwdevice_ctx_create` wrapper
|
integer 13 (V4L2REQUEST as defined by Kwiboo's v4l2-request-n7.1.3
|
||||||
(patch 2/4) and attaches it to the codec context;
|
tree, what our libavcodec61-fourier emits) cast to enum
|
||||||
|
AVHWDeviceType for the av_hwdevice_ctx_create call;
|
||||||
* reuses the existing `ChooseV4L2PixelFormat` get-format callback
|
* reuses the existing `ChooseV4L2PixelFormat` get-format callback
|
||||||
(already returns `AV_PIX_FMT_DRM_PRIME`) and the existing
|
(already returns `AV_PIX_FMT_DRM_PRIME`) and the existing
|
||||||
`apply_cropping = 0` constraint.
|
`apply_cropping = 0` constraint.
|
||||||
|
|
||||||
`InitV4L2RequestDecoder` is invoked **before** `InitV4L2Decoder` in
|
`InitV4L2RequestDecoder` is invoked **before** `InitV4L2Decoder` in
|
||||||
`InitHWDecoderIfAllowed`. On Rockchip mainline it succeeds via either
|
`InitHWDecoderIfAllowed`. On Rockchip mainline it succeeds via either
|
||||||
mechanism (ALARM uses the named codec). On Pi4 / Mediatek /
|
mechanism. On Pi4 / Mediatek / vendor-MPP-stateful boards neither
|
||||||
vendor-MPP-stateful boards neither mechanism is registered for the
|
mechanism is registered for the codec, the function bails out, and the
|
||||||
codec, the function bails out, and the existing stateful
|
existing stateful `InitV4L2Decoder` runs as before. No regression of
|
||||||
`InitV4L2Decoder` runs as before. No regression of stateful boards.
|
stateful boards.
|
||||||
|
|
||||||
`mDRMDeviceContext` is unconditionally `av_buffer_unref`'d in
|
`mDRMDeviceContext` is unconditionally `av_buffer_unref`'d in
|
||||||
`ProcessShutdown` (no-op when null). Gated behind
|
`ProcessShutdown` (no-op when null). Gated behind
|
||||||
@@ -46,9 +49,8 @@ codec, the function bails out, and the existing stateful
|
|||||||
|
|
||||||
Bug 1969297.
|
Bug 1969297.
|
||||||
|
|
||||||
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
|
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h 2026-05-21 04:57:59.570946601 +0000
|
||||||
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h 2026-03-18 19:22:14.000000000 +0000
|
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h 2026-05-21 04:57:59.876488776 +0000
|
||||||
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h 2026-04-27 20:43:39.347992674 +0000
|
|
||||||
@@ -225,7 +225,12 @@
|
@@ -225,7 +225,12 @@
|
||||||
bool IsLinuxHDR() const;
|
bool IsLinuxHDR() const;
|
||||||
MediaResult InitVAAPIDecoder();
|
MediaResult InitVAAPIDecoder();
|
||||||
@@ -73,9 +75,8 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platfor
|
|||||||
// If video overlay is used we want to upload SW decoded frames to
|
// If video overlay is used we want to upload SW decoded frames to
|
||||||
// DMABuf and present it as a external texture to rendering pipeline.
|
// DMABuf and present it as a external texture to rendering pipeline.
|
||||||
bool mUploadSWDecodeToDMABuf = false;
|
bool mUploadSWDecodeToDMABuf = false;
|
||||||
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
|
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2026-05-21 04:57:59.566685221 +0000
|
||||||
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2026-04-27 16:09:10.000000000 +0200
|
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2026-05-21 04:58:00.136004159 +0000
|
||||||
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2026-04-29 00:10:00.098884335 +0200
|
|
||||||
@@ -403,6 +403,129 @@
|
@@ -403,6 +403,129 @@
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@@ -90,7 +91,7 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf
|
|||||||
+ }
|
+ }
|
||||||
+ const char* drmDevice = "/dev/dri/renderD128";
|
+ const char* drmDevice = "/dev/dri/renderD128";
|
||||||
+ if (mLib->av_hwdevice_ctx_create(&mDRMDeviceContext,
|
+ if (mLib->av_hwdevice_ctx_create(&mDRMDeviceContext,
|
||||||
+ AV_HWDEVICE_TYPE_DRM, drmDevice,
|
+ (enum AVHWDeviceType)13, drmDevice,
|
||||||
+ nullptr, 0) < 0) {
|
+ nullptr, 0) < 0) {
|
||||||
+ FFMPEG_LOG(" av_hwdevice_ctx_create(DRM, %s) failed", drmDevice);
|
+ FFMPEG_LOG(" av_hwdevice_ctx_create(DRM, %s) failed", drmDevice);
|
||||||
+ return false;
|
+ return false;
|
||||||
@@ -143,7 +144,7 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf
|
|||||||
+ for (int i = 0;; i++) {
|
+ for (int i = 0;; i++) {
|
||||||
+ const AVCodecHWConfig* cfg = mLib->avcodec_get_hw_config(generic, i);
|
+ const AVCodecHWConfig* cfg = mLib->avcodec_get_hw_config(generic, i);
|
||||||
+ if (!cfg) break;
|
+ if (!cfg) break;
|
||||||
+ if (cfg->device_type == AV_HWDEVICE_TYPE_DRM) {
|
+ if (cfg->device_type == AV_HWDEVICE_TYPE_DRM || (int)cfg->device_type == 13 || (int)cfg->device_type == 14) {
|
||||||
+ codec = generic;
|
+ codec = generic;
|
||||||
+ FFMPEG_LOG(" using generic codec %s with DRM hwaccel", codec->name);
|
+ FFMPEG_LOG(" using generic codec %s with DRM hwaccel", codec->name);
|
||||||
+ break;
|
+ break;
|
||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
+295
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+28
@@ -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
|
||||||
@@ -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);
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
#
|
#
|
||||||
@@ -18,18 +21,32 @@
|
|||||||
# Alternative: boltzmann via his subagent + marfrit-publish.
|
# Alternative: boltzmann via his subagent + marfrit-publish.
|
||||||
|
|
||||||
pkgname=libva-v4l2-request-fourier
|
pkgname=libva-v4l2-request-fourier
|
||||||
|
epoch=1
|
||||||
_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. c454618 = PR #16 merge "picture, request_pool:
|
||||||
# — last commit on master before fresnel-fourier work started layering
|
# transparent OUTPUT-pool resize on bitstream overrun (#15)" —
|
||||||
# MPEG-2 rewrites on top of it (2026-05-08). The libva-multiplanar campaign
|
# follow-up root-cause fix to #13/#14. On a mid-stream bitstream-
|
||||||
# closed iter8 at this commit; promote to a later pin only after a future
|
# budget overrun (typical cause: SPS-driven resolution upshift in an
|
||||||
# iteration closes cleanly.
|
# adaptive-bitrate stream), codec_store_buffer now snapshots the in-
|
||||||
_commit=65969da3ee901442a8ca4e1f7f9697d5461d368a
|
# flight surface's accumulated bytes, releases its OUTPUT pool slot,
|
||||||
|
# calls request_pool_resize (STREAMOFF → REQBUFS(0) → S_FMT with
|
||||||
|
# 2×sizeimage hint, capped at 1 GiB, page-aligned → CREATE_BUFS →
|
||||||
|
# mmap → media_request_alloc → STREAMON), re-acquires a slot, re-
|
||||||
|
# mirrors the surface's source_{data,size,request_fd}, restores the
|
||||||
|
# bytes, and continues. The frame survives instead of being dropped
|
||||||
|
# back to libavcodec for surface recreation. CAPTURE side untouched
|
||||||
|
# (per-queue V4L2 streaming independence).
|
||||||
|
#
|
||||||
|
# Prior pin (2860d75) = PR #14 merge — codec_store_buffer bounds-
|
||||||
|
# check floor (#13).
|
||||||
|
_commit=c454618ae11addce2e17b560f4deeacbed067d98
|
||||||
|
|
||||||
# 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.r390.c454618
|
||||||
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 +72,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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; }"
|
||||||
@@ -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
|
||||||
@@ -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"
|
||||||
Executable
+68
@@ -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)"
|
||||||
+356
@@ -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
|
||||||
|
|
||||||
+95
@@ -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
|
||||||
|
|
||||||
+117
@@ -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
|
||||||
|
|
||||||
@@ -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/
|
||||||
+4647
File diff suppressed because it is too large
Load Diff
@@ -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=5
|
||||||
|
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'
|
||||||
|
'50397711a6a3ba522283685a9e7397aeed6663f353f7cba214d4bb88bc98516065b2fca9a36ce13c52644617879f69f39c5305e86db5d9fb25c4dae5434eb9c4'
|
||||||
|
'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 |
|
||||||
|
|--------|------------|-------------------------------------------------|
|
||||||
|
| 1–3 | 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,37 @@
|
|||||||
|
baseline:
|
||||||
|
ref: v7.0-danctnix1
|
||||||
|
tree: DanctNIX/linux-pinetab2
|
||||||
|
upstream_compat: linux-7.0
|
||||||
|
url: https://codeberg.org/DanctNIX/linux-pinetab2
|
||||||
|
cumulative:
|
||||||
|
b2sum: 50397711a6a3ba522283685a9e7397aeed6663f353f7cba214d4bb88bc98516065b2fca9a36ce13c52644617879f69f39c5305e86db5d9fb25c4dae5434eb9c4
|
||||||
|
path: cumulative.patch
|
||||||
|
size: 162716
|
||||||
|
generated_at: '2026-05-18T17:16:06.455474+00:00'
|
||||||
|
host: ohm
|
||||||
|
ka_promote_version: 1
|
||||||
|
manifest:
|
||||||
|
path: fleet/ohm.yaml
|
||||||
|
sha256: da59ac2c965e5ad9c5004a115b10a37abf47ed3ecc8b7f5ab426470d2ee7b442
|
||||||
|
resolved_patches:
|
||||||
|
- apply_order: 1
|
||||||
|
from_series: true
|
||||||
|
include: driver/bes2600/cumulative-c5x-danctnix/0001-bes2600-besser-cumulative-series.patch
|
||||||
|
sha256: e477a170567487fef84fe13be5b0a1f0498247ff1f201000d0085a2e49ff9026
|
||||||
|
size: 148149
|
||||||
|
- apply_order: 2
|
||||||
|
from_series: true
|
||||||
|
include: driver/bes2600/scan-filter-5ghz-danctnix/0001-bes2600-filter-5ghz-scan-and-allow-single-channel.patch
|
||||||
|
sha256: 31e67569e00daead0784214aced1e077d3270cf1407baa0b330d474e17ec3931
|
||||||
|
size: 7735
|
||||||
|
- apply_order: 3
|
||||||
|
from_series: true
|
||||||
|
include: arch/arm64/xor-neon-ffixed-x18-scs-build-fix-danctnix/0001-arm64-xor-neon-ffixed-x18-build-fix.patch
|
||||||
|
sha256: a49c50f0ebffc499970c24908b832c3e61c96ed87de35b3a82178eff587f94f1
|
||||||
|
size: 1574
|
||||||
|
- apply_order: 4
|
||||||
|
from_series: true
|
||||||
|
include: driver/bes2600/queue-pending-record-lock-bh-danctnix/0001-bes2600-take-pending-record-lock-with-bh.patch
|
||||||
|
sha256: 089862e5f6da5783ed0db979144e4fa07cff7f743809a0bebd715c75a3bb8eb5
|
||||||
|
size: 5258
|
||||||
|
schema_version: 1
|
||||||
+6
-3
@@ -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.
|
||||||
|
|
||||||
|
iter1–7 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 iter1–7 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){
|
||||||
@@ -0,0 +1,328 @@
|
|||||||
|
--- a/src/panfrost/vulkan/panvk_shader.h 2026-04-29 22:19:00.000000000 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/panvk_shader.h 2026-05-20 18:52:53.312698258 +0200
|
||||||
|
@@ -150,6 +150,10 @@
|
||||||
|
struct {
|
||||||
|
#if PAN_ARCH < 9
|
||||||
|
int32_t raw_vertex_offset;
|
||||||
|
+ uint32_t num_vertices; /* iter13: XFB needs per-draw vertex count */
|
||||||
|
+ /* aligned_u64 attribute below inserts the 4-byte alignment gap
|
||||||
|
+ * after num_vertices automatically — no explicit pad needed. */
|
||||||
|
+ aligned_u64 xfb_address[4]; /* iter13: 4 transform feedback buffer base addresses */
|
||||||
|
#endif
|
||||||
|
int32_t first_vertex;
|
||||||
|
int32_t base_instance;
|
||||||
|
--- a/src/panfrost/vulkan/panvk_vX_physical_device.c 2026-05-20 19:09:29.711145446 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/panvk_vX_physical_device.c 2026-05-20 18:52:54.832720445 +0200
|
||||||
|
@@ -169,6 +169,7 @@
|
||||||
|
.EXT_provoking_vertex = true,
|
||||||
|
.EXT_queue_family_foreign = true,
|
||||||
|
.EXT_robustness2 = true,
|
||||||
|
+ .EXT_transform_feedback = PAN_ARCH < 9, /* iter13: JM-class only for now */
|
||||||
|
.EXT_sampler_filter_minmax = PAN_ARCH >= 10,
|
||||||
|
.EXT_scalar_block_layout = true,
|
||||||
|
.EXT_separate_stencil_usage = true,
|
||||||
|
@@ -495,6 +496,10 @@
|
||||||
|
.robustImageAccess2 = false,
|
||||||
|
.nullDescriptor = true,
|
||||||
|
|
||||||
|
+ /* VK_EXT_transform_feedback (iter13) */
|
||||||
|
+ .transformFeedback = PAN_ARCH < 9,
|
||||||
|
+ .geometryStreams = false,
|
||||||
|
+
|
||||||
|
/* VK_KHR_shader_clock */
|
||||||
|
.shaderSubgroupClock = device->kmod.dev->props.gpu_can_query_timestamp,
|
||||||
|
.shaderDeviceClock = device->kmod.dev->props.timestamp_device_coherent,
|
||||||
|
@@ -1020,6 +1025,18 @@
|
||||||
|
.robustStorageBufferAccessSizeAlignment = 1,
|
||||||
|
.robustUniformBufferAccessSizeAlignment = 1,
|
||||||
|
|
||||||
|
+ /* VK_EXT_transform_feedback (iter13) */
|
||||||
|
+ .maxTransformFeedbackStreams = 1,
|
||||||
|
+ .maxTransformFeedbackBuffers = 4,
|
||||||
|
+ .maxTransformFeedbackBufferSize = UINT32_MAX,
|
||||||
|
+ .maxTransformFeedbackStreamDataSize = 512,
|
||||||
|
+ .maxTransformFeedbackBufferDataSize = 512,
|
||||||
|
+ .maxTransformFeedbackBufferDataStride = 2048,
|
||||||
|
+ .transformFeedbackQueries = false,
|
||||||
|
+ .transformFeedbackStreamsLinesTriangles = false,
|
||||||
|
+ .transformFeedbackRasterizationStreamSelect = false,
|
||||||
|
+ .transformFeedbackDraw = false,
|
||||||
|
+
|
||||||
|
/* VK_EXT_shader_object */
|
||||||
|
/* We do not currently support VK_EXT_shader_object but this is used
|
||||||
|
* internally by vk_shader
|
||||||
|
--- a/src/panfrost/vulkan/panvk_vX_shader.c 2026-04-29 22:19:00.000000000 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/panvk_vX_shader.c 2026-05-20 18:52:56.556745611 +0200
|
||||||
|
@@ -21,6 +21,7 @@
|
||||||
|
#include "panvk_physical_device.h"
|
||||||
|
#include "panvk_sampler.h"
|
||||||
|
#include "panvk_shader.h"
|
||||||
|
+#include "pan_nir.h" /* iter13: pan_nir_lower_xfb */
|
||||||
|
|
||||||
|
#include "spirv/nir_spirv.h"
|
||||||
|
#include "util/memstream.h"
|
||||||
|
@@ -100,6 +101,20 @@
|
||||||
|
case nir_intrinsic_load_raw_vertex_offset_pan:
|
||||||
|
val = load_sysval(b, graphics, bit_size, vs.raw_vertex_offset);
|
||||||
|
break;
|
||||||
|
+ case nir_intrinsic_load_num_vertices: /* iter13: XFB index calc */
|
||||||
|
+ val = load_sysval(b, graphics, bit_size, vs.num_vertices);
|
||||||
|
+ break;
|
||||||
|
+ case nir_intrinsic_load_xfb_address: { /* iter13: XFB buffer N base address */
|
||||||
|
+ unsigned idx = nir_intrinsic_base(intr);
|
||||||
|
+ switch (idx) {
|
||||||
|
+ case 0: val = load_sysval(b, graphics, bit_size, vs.xfb_address[0]); break;
|
||||||
|
+ case 1: val = load_sysval(b, graphics, bit_size, vs.xfb_address[1]); break;
|
||||||
|
+ case 2: val = load_sysval(b, graphics, bit_size, vs.xfb_address[2]); break;
|
||||||
|
+ case 3: val = load_sysval(b, graphics, bit_size, vs.xfb_address[3]); break;
|
||||||
|
+ default: return false;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
case nir_intrinsic_load_layer_id:
|
||||||
|
assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);
|
||||||
|
val = load_sysval(b, graphics, bit_size, layer_id);
|
||||||
|
@@ -457,6 +472,7 @@
|
||||||
|
core_max_id);
|
||||||
|
|
||||||
|
pan_preprocess_nir(nir, pdev->kmod.dev->props.gpu_id);
|
||||||
|
+
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -870,6 +886,18 @@
|
||||||
|
nir_var_shader_in | nir_var_shader_out, UINT32_MAX);
|
||||||
|
NIR_PASS(_, nir, nir_lower_io, nir_var_shader_in | nir_var_shader_out,
|
||||||
|
glsl_type_size, nir_lower_io_use_interpolated_input_intrinsics);
|
||||||
|
+
|
||||||
|
+#if PAN_ARCH < 9
|
||||||
|
+ /* iter13: VK_EXT_transform_feedback — runs AFTER nir_lower_io so that
|
||||||
|
+ * shader outputs are now store_output intrinsics that pan_nir_lower_xfb
|
||||||
|
+ * can rewrite to nir_store_global+nir_load_xfb_address. */
|
||||||
|
+ if (nir->info.stage == MESA_SHADER_VERTEX &&
|
||||||
|
+ nir->info.has_transform_feedback_varyings) {
|
||||||
|
+ NIR_PASS(_, nir, nir_opt_constant_folding);
|
||||||
|
+ NIR_PASS(_, nir, nir_io_add_intrinsic_xfb_info);
|
||||||
|
+ NIR_PASS(_, nir, pan_nir_lower_xfb);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkResult
|
||||||
|
@@ -1288,6 +1316,9 @@
|
||||||
|
.view_mask = (state && state->rp) ? state->rp->view_mask : 0,
|
||||||
|
.robust2_modes = robust2_modes,
|
||||||
|
.robust_descriptors = dev->vk.enabled_features.nullDescriptor,
|
||||||
|
+ /* iter13: XFB shaders must disable IDVS (matches Panfrost-Gallium). */
|
||||||
|
+ .no_idvs = (info->stage == MESA_SHADER_VERTEX) &&
|
||||||
|
+ info->nir->info.has_transform_feedback_varyings,
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (info->stage) {
|
||||||
|
--- a/src/panfrost/vulkan/panvk_cmd_draw.h 2026-04-29 22:19:00.000000000 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/panvk_cmd_draw.h 2026-05-20 18:52:57.748763011 +0200
|
||||||
|
@@ -135,6 +135,19 @@
|
||||||
|
struct panvk_graphics_sysvals sysvals;
|
||||||
|
|
||||||
|
#if PAN_ARCH < 9
|
||||||
|
+ /* iter13: VK_EXT_transform_feedback state (JM-class only for now). */
|
||||||
|
+ struct {
|
||||||
|
+ bool active;
|
||||||
|
+ uint32_t buffer_count;
|
||||||
|
+ struct {
|
||||||
|
+ uint64_t addr;
|
||||||
|
+ uint64_t offset;
|
||||||
|
+ uint64_t size;
|
||||||
|
+ } buffers[4];
|
||||||
|
+ } xfb;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#if PAN_ARCH < 9
|
||||||
|
struct panvk_shader_link link;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
--- a/src/panfrost/vulkan/panvk_vX_cmd_draw.c 2026-04-29 22:19:00.000000000 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/panvk_vX_cmd_draw.c 2026-05-20 19:10:23.031919662 +0200
|
||||||
|
@@ -10,6 +10,7 @@
|
||||||
|
#include "panvk_entrypoints.h"
|
||||||
|
|
||||||
|
#include "pan_desc.h"
|
||||||
|
+#include "pan_compiler.h" /* PAN_SHADER_OOB_ADDRESS */
|
||||||
|
#include "pan_util.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -722,6 +723,35 @@
|
||||||
|
set_gfx_sysval(cmdbuf, dirty_sysvals, vs.raw_vertex_offset,
|
||||||
|
info->vertex.raw_offset);
|
||||||
|
set_gfx_sysval(cmdbuf, dirty_sysvals, layer_id, info->layer_id);
|
||||||
|
+
|
||||||
|
+ /* iter13: VK_EXT_transform_feedback sysvals — always set (per draw),
|
||||||
|
+ * reflect bound XFB state. set_gfx_sysval is a no-op if value unchanged. */
|
||||||
|
+ set_gfx_sysval(cmdbuf, dirty_sysvals, vs.num_vertices, info->vertex.count);
|
||||||
|
+ {
|
||||||
|
+ const struct panvk_cmd_graphics_state *_gfx = &cmdbuf->state.gfx;
|
||||||
|
+ /* iter13: default each XFB buffer address to PAN_SHADER_OOB_ADDRESS
|
||||||
|
+ * (= 1<<63). This is the Panfrost-Gallium memory-sink idiom — the
|
||||||
|
+ * Bifrost MMU silently discards stores to this address, so a pipeline
|
||||||
|
+ * with XFB outputs used in a non-XFB draw (or in an XFB draw with
|
||||||
|
+ * fewer bound buffers than the shader declares) is safe instead of
|
||||||
|
+ * faulting. See gallium/drivers/panfrost/pan_cmdstream.c PAN_SYSVAL_XFB. */
|
||||||
|
+ uint64_t _xa0 = PAN_SHADER_OOB_ADDRESS, _xa1 = PAN_SHADER_OOB_ADDRESS,
|
||||||
|
+ _xa2 = PAN_SHADER_OOB_ADDRESS, _xa3 = PAN_SHADER_OOB_ADDRESS;
|
||||||
|
+ if (_gfx->xfb.active) {
|
||||||
|
+ if (_gfx->xfb.buffer_count > 0 && _gfx->xfb.buffers[0].addr)
|
||||||
|
+ _xa0 = _gfx->xfb.buffers[0].addr + _gfx->xfb.buffers[0].offset;
|
||||||
|
+ if (_gfx->xfb.buffer_count > 1 && _gfx->xfb.buffers[1].addr)
|
||||||
|
+ _xa1 = _gfx->xfb.buffers[1].addr + _gfx->xfb.buffers[1].offset;
|
||||||
|
+ if (_gfx->xfb.buffer_count > 2 && _gfx->xfb.buffers[2].addr)
|
||||||
|
+ _xa2 = _gfx->xfb.buffers[2].addr + _gfx->xfb.buffers[2].offset;
|
||||||
|
+ if (_gfx->xfb.buffer_count > 3 && _gfx->xfb.buffers[3].addr)
|
||||||
|
+ _xa3 = _gfx->xfb.buffers[3].addr + _gfx->xfb.buffers[3].offset;
|
||||||
|
+ }
|
||||||
|
+ set_gfx_sysval(cmdbuf, dirty_sysvals, vs.xfb_address[0], _xa0);
|
||||||
|
+ set_gfx_sysval(cmdbuf, dirty_sysvals, vs.xfb_address[1], _xa1);
|
||||||
|
+ set_gfx_sysval(cmdbuf, dirty_sysvals, vs.xfb_address[2], _xa2);
|
||||||
|
+ set_gfx_sysval(cmdbuf, dirty_sysvals, vs.xfb_address[3], _xa3);
|
||||||
|
+ }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (dyn_gfx_state_dirty(cmdbuf, CB_BLEND_CONSTANTS)) {
|
||||||
|
--- a/src/panfrost/vulkan/meson.build 2026-04-29 22:19:00.000000000 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/meson.build 2026-05-20 18:53:04.484861338 +0200
|
||||||
|
@@ -73,6 +73,7 @@
|
||||||
|
jm_inc_dir = ['jm']
|
||||||
|
jm_files = [
|
||||||
|
'jm/panvk_vX_bind_queue.c',
|
||||||
|
+ 'jm/panvk_vX_cmd_xfb.c', # iter13
|
||||||
|
'jm/panvk_vX_cmd_buffer.c',
|
||||||
|
'jm/panvk_vX_cmd_dispatch.c',
|
||||||
|
'jm/panvk_vX_cmd_draw.c',
|
||||||
|
--- a/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c 2026-04-29 22:19:00.000000000 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c 2026-05-20 19:10:26.163965149 +0200
|
||||||
|
@@ -473,5 +473,12 @@
|
||||||
|
|
||||||
|
vk_command_buffer_begin(&cmdbuf->vk, pBeginInfo);
|
||||||
|
|
||||||
|
+#if PAN_ARCH < 9
|
||||||
|
+ /* iter13: clear XFB state on Begin so a reused command buffer does not
|
||||||
|
+ * inherit stale xfb.buffer_count / xfb.active / xfb.buffers[] from a
|
||||||
|
+ * prior recording. */
|
||||||
|
+ memset(&cmdbuf->state.gfx.xfb, 0, sizeof(cmdbuf->state.gfx.xfb));
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
--- a/src/panfrost/vulkan/jm/panvk_vX_cmd_xfb.c 2026-05-18 12:50:53.067999996 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/jm/panvk_vX_cmd_xfb.c 2026-05-20 19:10:27.175979847 +0200
|
||||||
|
@@ -0,0 +1,111 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright © 2026 mfritsche / claude-noether
|
||||||
|
+ * SPDX-License-Identifier: MIT
|
||||||
|
+ *
|
||||||
|
+ * iter13: VK_EXT_transform_feedback command handlers for the JM
|
||||||
|
+ * architecture path (Bifrost v6/v7 + Valhall-JM v9).
|
||||||
|
+ *
|
||||||
|
+ * The runtime contract:
|
||||||
|
+ * - vkCmdBindTransformFeedbackBuffersEXT: stash (gpu_addr, offset, size)
|
||||||
|
+ * for each slot into cmdbuf->state.gfx.xfb.buffers[].
|
||||||
|
+ * - vkCmdBeginTransformFeedbackEXT: set cmdbuf->state.gfx.xfb.active = true.
|
||||||
|
+ * Mark sysvals dirty so the next draw re-emits vs.xfb_address[].
|
||||||
|
+ * - vkCmdEndTransformFeedbackEXT: set active = false.
|
||||||
|
+ *
|
||||||
|
+ * Counter buffers (firstCounterBuffer/counterBufferCount/pCounterBuffers/
|
||||||
|
+ * pCounterBufferOffsets) are accepted by API but ignored — v1 doesn't
|
||||||
|
+ * support pause/resume. transformFeedbackDraw is advertised as false.
|
||||||
|
+ *
|
||||||
|
+ * Per-draw integration: jm/panvk_vX_cmd_draw.c reads cmdbuf->state.gfx.xfb
|
||||||
|
+ * and populates vs.xfb_address[i] for shader use. The pan_nir_lower_xfb
|
||||||
|
+ * pass in panvk_vX_shader.c emits nir_load_xfb_address(i) which lowers
|
||||||
|
+ * (via panvk_vX_shader.c sysval handler) to a load from the per-draw
|
||||||
|
+ * sysval push area.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "vk_log.h"
|
||||||
|
+#include "util/log.h"
|
||||||
|
+
|
||||||
|
+#include "panvk_cmd_buffer.h"
|
||||||
|
+#include "panvk_cmd_draw.h"
|
||||||
|
+#include "panvk_buffer.h"
|
||||||
|
+#include "panvk_entrypoints.h"
|
||||||
|
+
|
||||||
|
+VKAPI_ATTR void VKAPI_CALL
|
||||||
|
+panvk_per_arch(CmdBindTransformFeedbackBuffersEXT)(
|
||||||
|
+ VkCommandBuffer commandBuffer,
|
||||||
|
+ uint32_t firstBinding,
|
||||||
|
+ uint32_t bindingCount,
|
||||||
|
+ const VkBuffer *pBuffers,
|
||||||
|
+ const VkDeviceSize *pOffsets,
|
||||||
|
+ const VkDeviceSize *pSizes)
|
||||||
|
+{
|
||||||
|
+ VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
|
||||||
|
+ struct panvk_cmd_graphics_state *gfx = &cmdbuf->state.gfx;
|
||||||
|
+
|
||||||
|
+ for (uint32_t i = 0; i < bindingCount; i++) {
|
||||||
|
+ uint32_t slot = firstBinding + i;
|
||||||
|
+ if (slot >= 4)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ VK_FROM_HANDLE(panvk_buffer, buf, pBuffers[i]);
|
||||||
|
+ gfx->xfb.buffers[slot].addr = panvk_buffer_gpu_ptr(buf, 0);
|
||||||
|
+ gfx->xfb.buffers[slot].offset = pOffsets[i];
|
||||||
|
+ gfx->xfb.buffers[slot].size =
|
||||||
|
+ (pSizes != NULL && pSizes[i] != VK_WHOLE_SIZE)
|
||||||
|
+ ? pSizes[i]
|
||||||
|
+ : (buf->vk.size - pOffsets[i]);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (firstBinding + bindingCount > gfx->xfb.buffer_count)
|
||||||
|
+ gfx->xfb.buffer_count = firstBinding + bindingCount;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+VKAPI_ATTR void VKAPI_CALL
|
||||||
|
+panvk_per_arch(CmdBeginTransformFeedbackEXT)(
|
||||||
|
+ VkCommandBuffer commandBuffer,
|
||||||
|
+ uint32_t firstCounterBuffer,
|
||||||
|
+ uint32_t counterBufferCount,
|
||||||
|
+ const VkBuffer *pCounterBuffers,
|
||||||
|
+ const VkDeviceSize *pCounterBufferOffsets)
|
||||||
|
+{
|
||||||
|
+ VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
|
||||||
|
+ struct panvk_cmd_graphics_state *gfx = &cmdbuf->state.gfx;
|
||||||
|
+
|
||||||
|
+ /* Counter buffers ignored in v1 — see VkPhysicalDeviceTransformFeedback
|
||||||
|
+ * PropertiesEXT.transformFeedbackDraw = false in panvk_vX_physical_device.c.
|
||||||
|
+ * App is spec-compliant if it does not pass counter buffers (which our
|
||||||
|
+ * features advertisement allows), but warn loudly if it does so we do not
|
||||||
|
+ * silently produce wrong capture state. */
|
||||||
|
+ (void)firstCounterBuffer;
|
||||||
|
+ (void)pCounterBufferOffsets;
|
||||||
|
+ if (counterBufferCount > 0 && pCounterBuffers != NULL) {
|
||||||
|
+ mesa_logw("panvk: CmdBeginTransformFeedbackEXT: counter buffers not "
|
||||||
|
+ "implemented (transformFeedbackDraw=false); XFB resume will "
|
||||||
|
+ "restart at buffer offset 0");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ gfx->xfb.active = true;
|
||||||
|
+ /* Per-draw set_gfx_sysval picks up the change automatically — no
|
||||||
|
+ * explicit dirty marking required (set_gfx_sysval uses memcmp +
|
||||||
|
+ * BITSET to detect state diffs and re-emit sysvals). */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+VKAPI_ATTR void VKAPI_CALL
|
||||||
|
+panvk_per_arch(CmdEndTransformFeedbackEXT)(
|
||||||
|
+ VkCommandBuffer commandBuffer,
|
||||||
|
+ uint32_t firstCounterBuffer,
|
||||||
|
+ uint32_t counterBufferCount,
|
||||||
|
+ const VkBuffer *pCounterBuffers,
|
||||||
|
+ const VkDeviceSize *pCounterBufferOffsets)
|
||||||
|
+{
|
||||||
|
+ VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
|
||||||
|
+ struct panvk_cmd_graphics_state *gfx = &cmdbuf->state.gfx;
|
||||||
|
+
|
||||||
|
+ (void)firstCounterBuffer;
|
||||||
|
+ (void)counterBufferCount;
|
||||||
|
+ (void)pCounterBuffers;
|
||||||
|
+ (void)pCounterBufferOffsets;
|
||||||
|
+
|
||||||
|
+ gfx->xfb.active = false;
|
||||||
|
+}
|
||||||
@@ -0,0 +1,629 @@
|
|||||||
|
diff -urN a/src/panfrost/vulkan/meson.build b/src/panfrost/vulkan/meson.build
|
||||||
|
--- a/src/panfrost/vulkan/meson.build 2026-05-21 14:04:02.529474145 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/meson.build 2026-05-21 14:04:04.106755486 +0200
|
||||||
|
@@ -123,6 +123,7 @@
|
||||||
|
'panvk_vX_nir_lower_input_attachment_loads.c',
|
||||||
|
'panvk_vX_sampler.c',
|
||||||
|
'panvk_vX_shader.c',
|
||||||
|
+ 'panvk_vX_xfb_lower.c',
|
||||||
|
sha1_h,
|
||||||
|
]
|
||||||
|
|
||||||
|
diff -urN a/src/panfrost/vulkan/panvk_shader.h b/src/panfrost/vulkan/panvk_shader.h
|
||||||
|
--- a/src/panfrost/vulkan/panvk_shader.h 2026-05-21 14:04:02.525251986 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/panvk_shader.h 2026-05-21 14:04:04.084251800 +0200
|
||||||
|
@@ -154,6 +154,8 @@
|
||||||
|
/* aligned_u64 attribute below inserts the 4-byte alignment gap
|
||||||
|
* after num_vertices automatically — no explicit pad needed. */
|
||||||
|
aligned_u64 xfb_address[4]; /* iter13: 4 transform feedback buffer base addresses */
|
||||||
|
+ uint32_t xfb_topology; /* iter17: panvk_xfb_topology enum value */
|
||||||
|
+ uint32_t xfb_output_count; /* iter17: per-instance output verts after decomp */
|
||||||
|
#endif
|
||||||
|
int32_t first_vertex;
|
||||||
|
int32_t base_instance;
|
||||||
|
@@ -569,4 +571,76 @@
|
||||||
|
struct pan_compute_dim local_size, const void *bin_ptr, size_t bin_size,
|
||||||
|
struct panvk_shader **shader_out);
|
||||||
|
|
||||||
|
+
|
||||||
|
+#if PAN_ARCH < 9
|
||||||
|
+/* iter17: encoding for vs.xfb_topology sysval. Maps VkPrimitiveTopology values
|
||||||
|
+ * we need to distinguish at shader runtime for XFB capture. LIST topologies
|
||||||
|
+ * use the iter13 single-store fast path; non-LIST need per-vertex decomposition. */
|
||||||
|
+enum panvk_xfb_topology {
|
||||||
|
+ PANVK_XFB_TOPO_LIST = 0,
|
||||||
|
+ PANVK_XFB_TOPO_LINE_STRIP = 1,
|
||||||
|
+ PANVK_XFB_TOPO_TRI_STRIP = 2,
|
||||||
|
+ PANVK_XFB_TOPO_TRI_FAN = 3,
|
||||||
|
+ PANVK_XFB_TOPO_LINE_LIST_ADJ = 4,
|
||||||
|
+ PANVK_XFB_TOPO_LINE_STRIP_ADJ = 5,
|
||||||
|
+ PANVK_XFB_TOPO_TRI_LIST_ADJ = 6,
|
||||||
|
+ PANVK_XFB_TOPO_TRI_STRIP_ADJ = 7,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#include "panvk_macros.h"
|
||||||
|
+struct nir_shader;
|
||||||
|
+bool panvk_per_arch(nir_lower_xfb)(struct nir_shader *nir);
|
||||||
|
+
|
||||||
|
+/* Map VkPrimitiveTopology to panvk_xfb_topology enum (driver-side helper). */
|
||||||
|
+static inline uint32_t
|
||||||
|
+panvk_vk_topology_to_xfb_enum(VkPrimitiveTopology topo)
|
||||||
|
+{
|
||||||
|
+ switch (topo) {
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
|
||||||
|
+ return PANVK_XFB_TOPO_LINE_STRIP;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
|
||||||
|
+ return PANVK_XFB_TOPO_TRI_STRIP;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
|
||||||
|
+ return PANVK_XFB_TOPO_TRI_FAN;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
|
||||||
|
+ return PANVK_XFB_TOPO_LINE_LIST_ADJ;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
|
||||||
|
+ return PANVK_XFB_TOPO_LINE_STRIP_ADJ;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
|
||||||
|
+ return PANVK_XFB_TOPO_TRI_LIST_ADJ;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
|
||||||
|
+ return PANVK_XFB_TOPO_TRI_STRIP_ADJ;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
|
||||||
|
+ default:
|
||||||
|
+ return PANVK_XFB_TOPO_LIST;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Compute the per-instance output vertex count for a given (topology, input count). */
|
||||||
|
+static inline uint32_t
|
||||||
|
+panvk_xfb_output_count(VkPrimitiveTopology topo, uint32_t input_count)
|
||||||
|
+{
|
||||||
|
+ switch (topo) {
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
|
||||||
|
+ return input_count >= 1 ? 2u * (input_count - 1u) : 0u;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
|
||||||
|
+ return input_count >= 2 ? 3u * (input_count - 2u) : 0u;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
|
||||||
|
+ return (input_count / 4u) * 2u;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
|
||||||
|
+ return input_count >= 3 ? 2u * (input_count - 3u) : 0u;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
|
||||||
|
+ return (input_count / 6u) * 3u;
|
||||||
|
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
|
||||||
|
+ return input_count >= 6 ? 3u * (input_count / 2u - 2u) : 0u;
|
||||||
|
+ default:
|
||||||
|
+ return input_count; /* LIST topologies: 1:1 mapping */
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
diff -urN a/src/panfrost/vulkan/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/panvk_vX_cmd_draw.c
|
||||||
|
--- a/src/panfrost/vulkan/panvk_vX_cmd_draw.c 2026-05-21 14:04:02.528576354 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/panvk_vX_cmd_draw.c 2026-05-21 14:04:04.091357598 +0200
|
||||||
|
@@ -727,6 +727,20 @@
|
||||||
|
/* iter13: VK_EXT_transform_feedback sysvals — always set (per draw),
|
||||||
|
* reflect bound XFB state. set_gfx_sysval is a no-op if value unchanged. */
|
||||||
|
set_gfx_sysval(cmdbuf, dirty_sysvals, vs.num_vertices, info->vertex.count);
|
||||||
|
+
|
||||||
|
+ /* iter17: XFB primitive-decomposition sysvals.
|
||||||
|
+ * xfb_topology = enum value for the current bound topology.
|
||||||
|
+ * xfb_output_count = per-instance output vertex count after decomposition.
|
||||||
|
+ * For LIST topologies, output_count == input vertex count and the shader
|
||||||
|
+ * takes the iter13 single-store fast path. */
|
||||||
|
+ {
|
||||||
|
+ VkPrimitiveTopology vk_topo =
|
||||||
|
+ cmdbuf->vk.dynamic_graphics_state.ia.primitive_topology;
|
||||||
|
+ uint32_t topo_enum = panvk_vk_topology_to_xfb_enum(vk_topo);
|
||||||
|
+ uint32_t out_count = panvk_xfb_output_count(vk_topo, info->vertex.count);
|
||||||
|
+ set_gfx_sysval(cmdbuf, dirty_sysvals, vs.xfb_topology, topo_enum);
|
||||||
|
+ set_gfx_sysval(cmdbuf, dirty_sysvals, vs.xfb_output_count, out_count);
|
||||||
|
+ }
|
||||||
|
{
|
||||||
|
const struct panvk_cmd_graphics_state *_gfx = &cmdbuf->state.gfx;
|
||||||
|
/* iter13: default each XFB buffer address to PAN_SHADER_OOB_ADDRESS
|
||||||
|
diff -urN a/src/panfrost/vulkan/panvk_vX_shader.c b/src/panfrost/vulkan/panvk_vX_shader.c
|
||||||
|
--- a/src/panfrost/vulkan/panvk_vX_shader.c 2026-05-21 14:04:02.527576494 +0200
|
||||||
|
+++ b/src/panfrost/vulkan/panvk_vX_shader.c 2026-05-21 14:04:04.098356619 +0200
|
||||||
|
@@ -895,7 +895,10 @@
|
||||||
|
nir->info.has_transform_feedback_varyings) {
|
||||||
|
NIR_PASS(_, nir, nir_opt_constant_folding);
|
||||||
|
NIR_PASS(_, nir, nir_io_add_intrinsic_xfb_info);
|
||||||
|
- NIR_PASS(_, nir, pan_nir_lower_xfb);
|
||||||
|
+ /* iter17: panvk-specific replacement for pan_nir_lower_xfb that handles
|
||||||
|
+ * primitive decomposition for non-LIST topologies. Single-store LIST
|
||||||
|
+ * fast path matches iter13 behavior. */
|
||||||
|
+ NIR_PASS(_, nir, panvk_per_arch(nir_lower_xfb));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
diff -urN a/src/panfrost/vulkan/panvk_vX_xfb_lower.c b/src/panfrost/vulkan/panvk_vX_xfb_lower.c
|
||||||
|
--- a/src/panfrost/vulkan/panvk_vX_xfb_lower.c 1970-01-01 01:00:00.000000000 +0100
|
||||||
|
+++ b/src/panfrost/vulkan/panvk_vX_xfb_lower.c 2026-05-21 14:04:04.115354242 +0200
|
||||||
|
@@ -0,0 +1,486 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright © 2026 mfritsche / claude-noether
|
||||||
|
+ * SPDX-License-Identifier: MIT
|
||||||
|
+ *
|
||||||
|
+ * iter17: panvk-specific replacement for pan_nir_lower_xfb that handles
|
||||||
|
+ * primitive decomposition for transform_feedback on non-LIST topologies
|
||||||
|
+ * (TRIANGLE_STRIP/FAN, LINE_STRIP, *_WITH_ADJACENCY).
|
||||||
|
+ *
|
||||||
|
+ * Approach: emit a topology dispatch at the start of each store_output
|
||||||
|
+ * lowering. The shader reads vs.xfb_topology sysval at runtime and branches
|
||||||
|
+ * into per-topology emission logic. For each affected topology, the lowered
|
||||||
|
+ * code emits guarded conditional stores — one per primitive this vertex
|
||||||
|
+ * contributes to, computing the output buffer position via primitive index
|
||||||
|
+ * and slot within the decomposed primitive.
|
||||||
|
+ *
|
||||||
|
+ * For LIST topologies (POINT/LINE/TRIANGLE LIST), takes a fast path that
|
||||||
|
+ * matches iter13's single-store behavior.
|
||||||
|
+ *
|
||||||
|
+ * For TRIANGLE_FAN, the central vertex (v=0) contributes to ALL primitives
|
||||||
|
+ * as slot 2 — handled via a NIR loop bounded by num_vertices.
|
||||||
|
+ *
|
||||||
|
+ * See ~/src/panvk-bifrost/iter17/phase{0,1,2}_*.md for full design context.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "panvk_macros.h"
|
||||||
|
+
|
||||||
|
+#if PAN_ARCH < 9
|
||||||
|
+
|
||||||
|
+#include "panvk_shader.h"
|
||||||
|
+
|
||||||
|
+#include "compiler/nir/nir_builder.h"
|
||||||
|
+#include "pan_nir.h"
|
||||||
|
+
|
||||||
|
+#include <vulkan/vulkan_core.h>
|
||||||
|
+
|
||||||
|
+/* ----- Address arithmetic ----- */
|
||||||
|
+
|
||||||
|
+static nir_def *
|
||||||
|
+xfb_store_addr(nir_builder *b, nir_def *buf, nir_def *out_idx,
|
||||||
|
+ uint16_t stride, uint16_t offset_bytes)
|
||||||
|
+{
|
||||||
|
+ nir_def *byte_off = nir_iadd_imm(b,
|
||||||
|
+ nir_imul_imm(b, out_idx, stride), offset_bytes);
|
||||||
|
+ return nir_iadd(b, buf, nir_u2u64(b, byte_off));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+emit_list_store(nir_builder *b, nir_def *buf, nir_def *output_count,
|
||||||
|
+ nir_def *instance_id, nir_def *raw_vid, nir_def *value,
|
||||||
|
+ uint16_t stride, uint16_t offset_bytes)
|
||||||
|
+{
|
||||||
|
+ nir_def *out_idx = nir_iadd(b,
|
||||||
|
+ nir_imul(b, instance_id, output_count), raw_vid);
|
||||||
|
+ nir_def *addr = xfb_store_addr(b, buf, out_idx, stride, offset_bytes);
|
||||||
|
+ nir_store_global(b, value, addr);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+emit_prim_store(nir_builder *b, nir_def *buf, nir_def *output_count,
|
||||||
|
+ nir_def *instance_id, nir_def *eligible,
|
||||||
|
+ nir_def *prim_idx, nir_def *slot,
|
||||||
|
+ uint32_t verts_per_prim,
|
||||||
|
+ nir_def *value, uint16_t stride, uint16_t offset_bytes)
|
||||||
|
+{
|
||||||
|
+ nir_push_if(b, eligible);
|
||||||
|
+ {
|
||||||
|
+ nir_def *out_idx = nir_iadd(b,
|
||||||
|
+ nir_imul(b, instance_id, output_count),
|
||||||
|
+ nir_iadd(b, nir_imul_imm(b, prim_idx, verts_per_prim), slot));
|
||||||
|
+ nir_def *addr = xfb_store_addr(b, buf, out_idx, stride, offset_bytes);
|
||||||
|
+ nir_store_global(b, value, addr);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* ----- Per-topology emission ----- */
|
||||||
|
+
|
||||||
|
+/* TRIANGLE_STRIP: vertex v contributes to prims v, v-1, v-2 (per eligibility). */
|
||||||
|
+static void
|
||||||
|
+emit_tri_strip(nir_builder *b, nir_def *v, nir_def *N,
|
||||||
|
+ nir_def *buf, nir_def *output_count, nir_def *instance_id,
|
||||||
|
+ nir_def *value, uint16_t stride, uint16_t offset_bytes)
|
||||||
|
+{
|
||||||
|
+ nir_def *Nm2 = nir_iadd_imm(b, N, -2);
|
||||||
|
+ nir_def *Nm1 = nir_iadd_imm(b, N, -1);
|
||||||
|
+
|
||||||
|
+ /* Prim v, slot 0: v < N-2 */
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id,
|
||||||
|
+ nir_ult(b, v, Nm2),
|
||||||
|
+ v, nir_imm_int(b, 0), 3, value, stride, offset_bytes);
|
||||||
|
+
|
||||||
|
+ /* Prim v-1, slot = 1 if prim even else 2: 1 <= v < N-1 */
|
||||||
|
+ {
|
||||||
|
+ nir_def *prim = nir_iadd_imm(b, v, -1);
|
||||||
|
+ nir_def *parity = nir_iand_imm(b, prim, 1u);
|
||||||
|
+ nir_def *slot = nir_iadd_imm(b, parity, 1);
|
||||||
|
+ nir_def *eligible = nir_iand(b,
|
||||||
|
+ nir_uge(b, v, nir_imm_int(b, 1)),
|
||||||
|
+ nir_ult(b, v, Nm1));
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id, eligible,
|
||||||
|
+ prim, slot, 3, value, stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Prim v-2, slot = 2 if prim even else 1: 2 <= v < N */
|
||||||
|
+ {
|
||||||
|
+ nir_def *prim = nir_iadd_imm(b, v, -2);
|
||||||
|
+ nir_def *parity = nir_iand_imm(b, prim, 1u);
|
||||||
|
+ nir_def *slot = nir_isub(b, nir_imm_int(b, 2), parity);
|
||||||
|
+ nir_def *eligible = nir_iand(b,
|
||||||
|
+ nir_uge(b, v, nir_imm_int(b, 2)),
|
||||||
|
+ nir_ult(b, v, N));
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id, eligible,
|
||||||
|
+ prim, slot, 3, value, stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* LINE_STRIP: vertex v contributes to prim v slot 0 + prim v-1 slot 1. */
|
||||||
|
+static void
|
||||||
|
+emit_line_strip(nir_builder *b, nir_def *v, nir_def *N,
|
||||||
|
+ nir_def *buf, nir_def *output_count, nir_def *instance_id,
|
||||||
|
+ nir_def *value, uint16_t stride, uint16_t offset_bytes)
|
||||||
|
+{
|
||||||
|
+ nir_def *Nm1 = nir_iadd_imm(b, N, -1);
|
||||||
|
+
|
||||||
|
+ /* Prim v, slot 0: v < N-1 */
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id,
|
||||||
|
+ nir_ult(b, v, Nm1),
|
||||||
|
+ v, nir_imm_int(b, 0), 2, value, stride, offset_bytes);
|
||||||
|
+
|
||||||
|
+ /* Prim v-1, slot 1: 1 <= v < N */
|
||||||
|
+ {
|
||||||
|
+ nir_def *prim = nir_iadd_imm(b, v, -1);
|
||||||
|
+ nir_def *eligible = nir_iand(b,
|
||||||
|
+ nir_uge(b, v, nir_imm_int(b, 1)),
|
||||||
|
+ nir_ult(b, v, N));
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id, eligible,
|
||||||
|
+ prim, nir_imm_int(b, 1), 2, value, stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* TRIANGLE_FAN: prim p emits {p+1, p+2, 0}.
|
||||||
|
+ * vertex v=0: contributes to ALL prims as slot 2 (loop required)
|
||||||
|
+ * vertex v>=1: contributes to prim v-1 as slot 0 (if 1 <= v <= N-2)
|
||||||
|
+ * vertex v>=2: contributes to prim v-2 as slot 1 (if 2 <= v <= N-1)
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+emit_tri_fan(nir_builder *b, nir_def *v, nir_def *N,
|
||||||
|
+ nir_def *buf, nir_def *output_count, nir_def *instance_id,
|
||||||
|
+ nir_def *value, uint16_t stride, uint16_t offset_bytes)
|
||||||
|
+{
|
||||||
|
+ nir_def *Nm1 = nir_iadd_imm(b, N, -1);
|
||||||
|
+ nir_def *Nm2 = nir_iadd_imm(b, N, -2);
|
||||||
|
+
|
||||||
|
+ /* Prim v-1, slot 0: 1 <= v < N-1 */
|
||||||
|
+ {
|
||||||
|
+ nir_def *prim = nir_iadd_imm(b, v, -1);
|
||||||
|
+ nir_def *eligible = nir_iand(b,
|
||||||
|
+ nir_uge(b, v, nir_imm_int(b, 1)),
|
||||||
|
+ nir_ult(b, v, Nm1));
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id, eligible,
|
||||||
|
+ prim, nir_imm_int(b, 0), 3, value, stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Prim v-2, slot 1: 2 <= v < N */
|
||||||
|
+ {
|
||||||
|
+ nir_def *prim = nir_iadd_imm(b, v, -2);
|
||||||
|
+ nir_def *eligible = nir_iand(b,
|
||||||
|
+ nir_uge(b, v, nir_imm_int(b, 2)),
|
||||||
|
+ nir_ult(b, v, N));
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id, eligible,
|
||||||
|
+ prim, nir_imm_int(b, 1), 3, value, stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Central vertex (v == 0): loop over all prims, write to slot 2. */
|
||||||
|
+ nir_push_if(b, nir_ieq_imm(b, v, 0));
|
||||||
|
+ {
|
||||||
|
+ nir_variable *p_var = nir_local_variable_create(b->impl,
|
||||||
|
+ glsl_uint_type(), "fan_p");
|
||||||
|
+ nir_store_var(b, p_var, nir_imm_int(b, 0), 0x1);
|
||||||
|
+ nir_push_loop(b);
|
||||||
|
+ {
|
||||||
|
+ nir_def *p = nir_load_var(b, p_var);
|
||||||
|
+ nir_push_if(b, nir_uge(b, p, Nm2));
|
||||||
|
+ {
|
||||||
|
+ nir_jump(b, nir_jump_break);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+
|
||||||
|
+ nir_def *out_idx = nir_iadd(b,
|
||||||
|
+ nir_imul(b, instance_id, output_count),
|
||||||
|
+ nir_iadd_imm(b, nir_imul_imm(b, p, 3), 2));
|
||||||
|
+ nir_def *addr = xfb_store_addr(b, buf, out_idx, stride, offset_bytes);
|
||||||
|
+ nir_store_global(b, value, addr);
|
||||||
|
+
|
||||||
|
+ nir_store_var(b, p_var, nir_iadd_imm(b, p, 1), 0x1);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_loop(b, NULL);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* LINE_LIST_WITH_ADJACENCY: 4-vertex groups [4i..4i+3]; output {4i+1, 4i+2}.
|
||||||
|
+ * v contributes if v%4 == 1: prim v/4 slot 0
|
||||||
|
+ * v contributes if v%4 == 2: prim v/4 slot 1
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+emit_line_list_adj(nir_builder *b, nir_def *v, nir_def *N,
|
||||||
|
+ nir_def *buf, nir_def *output_count, nir_def *instance_id,
|
||||||
|
+ nir_def *value, uint16_t stride, uint16_t offset_bytes)
|
||||||
|
+{
|
||||||
|
+ (void)N; /* eligibility is mod-based, not range-based */
|
||||||
|
+ nir_def *vmod4 = nir_iand_imm(b, v, 3u);
|
||||||
|
+ nir_def *prim = nir_ushr_imm(b, v, 2); /* v / 4 */
|
||||||
|
+
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id,
|
||||||
|
+ nir_ieq_imm(b, vmod4, 1),
|
||||||
|
+ prim, nir_imm_int(b, 0), 2, value, stride, offset_bytes);
|
||||||
|
+
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id,
|
||||||
|
+ nir_ieq_imm(b, vmod4, 2),
|
||||||
|
+ prim, nir_imm_int(b, 1), 2, value, stride, offset_bytes);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* LINE_STRIP_WITH_ADJACENCY: prim p emits {p+1, p+2}.
|
||||||
|
+ * v contributes to prim v-1 slot 0 (1 <= v <= N-2)
|
||||||
|
+ * v contributes to prim v-2 slot 1 (2 <= v <= N-1)
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+emit_line_strip_adj(nir_builder *b, nir_def *v, nir_def *N,
|
||||||
|
+ nir_def *buf, nir_def *output_count, nir_def *instance_id,
|
||||||
|
+ nir_def *value, uint16_t stride, uint16_t offset_bytes)
|
||||||
|
+{
|
||||||
|
+ nir_def *Nm1 = nir_iadd_imm(b, N, -1);
|
||||||
|
+ nir_def *Nm2 = nir_iadd_imm(b, N, -2);
|
||||||
|
+
|
||||||
|
+ /* Prim v-1, slot 0: 1 <= v <= N-2 ⇔ v >= 1 AND v <= N-2 ⇔ v >= 1 AND v < N-1 */
|
||||||
|
+ {
|
||||||
|
+ nir_def *prim = nir_iadd_imm(b, v, -1);
|
||||||
|
+ nir_def *eligible = nir_iand(b,
|
||||||
|
+ nir_uge(b, v, nir_imm_int(b, 1)),
|
||||||
|
+ nir_ult(b, v, Nm1));
|
||||||
|
+ (void)Nm2;
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id, eligible,
|
||||||
|
+ prim, nir_imm_int(b, 0), 2, value, stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Prim v-2, slot 1: 2 <= v <= N-1 ⇔ v >= 2 AND v < N */
|
||||||
|
+ {
|
||||||
|
+ nir_def *prim = nir_iadd_imm(b, v, -2);
|
||||||
|
+ nir_def *eligible = nir_iand(b,
|
||||||
|
+ nir_uge(b, v, nir_imm_int(b, 2)),
|
||||||
|
+ nir_ult(b, v, N));
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id, eligible,
|
||||||
|
+ prim, nir_imm_int(b, 1), 2, value, stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* TRIANGLE_LIST_WITH_ADJACENCY: 6-vertex groups; output {6i, 6i+2, 6i+4}.
|
||||||
|
+ * v contributes if v%6 == 0: prim v/6 slot 0
|
||||||
|
+ * v contributes if v%6 == 2: prim v/6 slot 1
|
||||||
|
+ * v contributes if v%6 == 4: prim v/6 slot 2
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+emit_tri_list_adj(nir_builder *b, nir_def *v, nir_def *N,
|
||||||
|
+ nir_def *buf, nir_def *output_count, nir_def *instance_id,
|
||||||
|
+ nir_def *value, uint16_t stride, uint16_t offset_bytes)
|
||||||
|
+{
|
||||||
|
+ (void)N;
|
||||||
|
+ nir_def *vmod6 = nir_umod_imm(b, v, 6);
|
||||||
|
+ nir_def *prim = nir_udiv_imm(b, v, 6);
|
||||||
|
+
|
||||||
|
+ for (uint32_t slot = 0; slot < 3; slot++) {
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id,
|
||||||
|
+ nir_ieq_imm(b, vmod6, slot * 2),
|
||||||
|
+ prim, nir_imm_int(b, slot), 3, value, stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* TRIANGLE_STRIP_WITH_ADJACENCY: prim i emits:
|
||||||
|
+ * even i: {2i, 2i+2, 2i+4} (slots 0, 1, 2 ← input indices 2i, 2i+2, 2i+4)
|
||||||
|
+ * odd i: {2i, 2i+4, 2i+2} (slots 0, 1, 2 ← input indices 2i, 2i+4, 2i+2)
|
||||||
|
+ *
|
||||||
|
+ * Only EVEN input vertices contribute (since all output indices are 2*something).
|
||||||
|
+ * For even input v:
|
||||||
|
+ * prim v/2 slot 0 (always, if v/2 < N/2-2)
|
||||||
|
+ * prim (v-2)/2 slot 1 if (v-2)/2 even, slot 2 if odd (when v >= 2)
|
||||||
|
+ * prim (v-4)/2 slot 2 if (v-4)/2 even, slot 1 if odd (when v >= 4)
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+emit_tri_strip_adj(nir_builder *b, nir_def *v, nir_def *N,
|
||||||
|
+ nir_def *buf, nir_def *output_count, nir_def *instance_id,
|
||||||
|
+ nir_def *value, uint16_t stride, uint16_t offset_bytes)
|
||||||
|
+{
|
||||||
|
+ /* Bail for odd input vertices — they never contribute. */
|
||||||
|
+ nir_def *v_is_even = nir_ieq_imm(b, nir_iand_imm(b, v, 1u), 0);
|
||||||
|
+ nir_push_if(b, v_is_even);
|
||||||
|
+ {
|
||||||
|
+ nir_def *N_half = nir_ushr_imm(b, N, 1);
|
||||||
|
+ nir_def *max_prim = nir_iadd_imm(b, N_half, -2); /* N/2 - 2 */
|
||||||
|
+ nir_def *v_half = nir_ushr_imm(b, v, 1);
|
||||||
|
+
|
||||||
|
+ /* Prim v/2 slot 0: v/2 < N/2 - 2 */
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id,
|
||||||
|
+ nir_ult(b, v_half, max_prim),
|
||||||
|
+ v_half, nir_imm_int(b, 0), 3, value, stride, offset_bytes);
|
||||||
|
+
|
||||||
|
+ /* Prim (v-2)/2 = v/2 - 1: v >= 2 AND prim < N/2-2 */
|
||||||
|
+ {
|
||||||
|
+ nir_def *prim = nir_iadd_imm(b, v_half, -1);
|
||||||
|
+ nir_def *parity = nir_iand_imm(b, prim, 1u);
|
||||||
|
+ nir_def *slot = nir_iadd_imm(b, parity, 1); /* even→1, odd→2 */
|
||||||
|
+ nir_def *eligible = nir_iand(b,
|
||||||
|
+ nir_uge(b, v, nir_imm_int(b, 2)),
|
||||||
|
+ nir_ult(b, prim, max_prim));
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id, eligible,
|
||||||
|
+ prim, slot, 3, value, stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Prim (v-4)/2 = v/2 - 2: v >= 4 AND prim < N/2-2 */
|
||||||
|
+ {
|
||||||
|
+ nir_def *prim = nir_iadd_imm(b, v_half, -2);
|
||||||
|
+ nir_def *parity = nir_iand_imm(b, prim, 1u);
|
||||||
|
+ nir_def *slot = nir_isub(b, nir_imm_int(b, 2), parity); /* even→2, odd→1 */
|
||||||
|
+ nir_def *eligible = nir_iand(b,
|
||||||
|
+ nir_uge(b, v, nir_imm_int(b, 4)),
|
||||||
|
+ nir_ult(b, prim, max_prim));
|
||||||
|
+ emit_prim_store(b, buf, output_count, instance_id, eligible,
|
||||||
|
+ prim, slot, 3, value, stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* ----- Main lowering: per store_output XFB channel ----- */
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+lower_xfb_output_iter17(nir_builder *b, nir_intrinsic_instr *intr,
|
||||||
|
+ unsigned channel_idx, unsigned num_components,
|
||||||
|
+ unsigned buffer, unsigned offset_words)
|
||||||
|
+{
|
||||||
|
+ assert(buffer < MAX_XFB_BUFFERS);
|
||||||
|
+ assert(nir_intrinsic_component(intr) == 0);
|
||||||
|
+
|
||||||
|
+ uint16_t stride = b->shader->info.xfb_stride[buffer] * 4;
|
||||||
|
+ assert(stride != 0);
|
||||||
|
+ uint16_t offset_bytes = offset_words * 4;
|
||||||
|
+
|
||||||
|
+ BITSET_SET(b->shader->info.system_values_read, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE);
|
||||||
|
+ BITSET_SET(b->shader->info.system_values_read, SYSTEM_VALUE_INSTANCE_ID);
|
||||||
|
+
|
||||||
|
+ nir_def *topology = load_sysval(b, graphics, 32, vs.xfb_topology);
|
||||||
|
+ nir_def *out_count = load_sysval(b, graphics, 32, vs.xfb_output_count);
|
||||||
|
+ nir_def *N = nir_load_num_vertices(b);
|
||||||
|
+ nir_def *v = nir_load_raw_vertex_id_pan(b);
|
||||||
|
+ nir_def *instance = nir_load_instance_id(b);
|
||||||
|
+ nir_def *buf = nir_load_xfb_address(b, 64, .base = buffer);
|
||||||
|
+
|
||||||
|
+ nir_def *src = intr->src[0].ssa;
|
||||||
|
+ nir_component_mask_t mask = nir_component_mask(num_components);
|
||||||
|
+ nir_def *value = nir_channels(b, src, mask << channel_idx);
|
||||||
|
+
|
||||||
|
+ /* Topology dispatch ladder. LIST first (fast path). */
|
||||||
|
+ nir_push_if(b, nir_ieq_imm(b, topology, PANVK_XFB_TOPO_LIST));
|
||||||
|
+ {
|
||||||
|
+ emit_list_store(b, buf, out_count, instance, v, value,
|
||||||
|
+ stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+ nir_push_else(b, NULL);
|
||||||
|
+ {
|
||||||
|
+ /* iter17 Janet Finding 3: gate all non-LIST emission on
|
||||||
|
+ * output_count > 0. For degenerate input counts (N < min required
|
||||||
|
+ * for the topology), output_count is 0 and we must emit NO stores
|
||||||
|
+ * — otherwise N-2 / N-3 / etc. arithmetic underflows in the
|
||||||
|
+ * eligibility predicates and we falsely fire stores. */
|
||||||
|
+ nir_push_if(b, nir_ult(b, nir_imm_int(b, 0), out_count));
|
||||||
|
+ {
|
||||||
|
+ nir_push_if(b, nir_ieq_imm(b, topology, PANVK_XFB_TOPO_TRI_STRIP));
|
||||||
|
+ {
|
||||||
|
+ emit_tri_strip(b, v, N, buf, out_count, instance, value,
|
||||||
|
+ stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+ nir_push_else(b, NULL);
|
||||||
|
+ {
|
||||||
|
+ nir_push_if(b, nir_ieq_imm(b, topology, PANVK_XFB_TOPO_LINE_STRIP));
|
||||||
|
+ {
|
||||||
|
+ emit_line_strip(b, v, N, buf, out_count, instance, value,
|
||||||
|
+ stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+ nir_push_else(b, NULL);
|
||||||
|
+ {
|
||||||
|
+ nir_push_if(b, nir_ieq_imm(b, topology, PANVK_XFB_TOPO_TRI_FAN));
|
||||||
|
+ {
|
||||||
|
+ emit_tri_fan(b, v, N, buf, out_count, instance, value,
|
||||||
|
+ stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+ nir_push_else(b, NULL);
|
||||||
|
+ {
|
||||||
|
+ nir_push_if(b, nir_ieq_imm(b, topology, PANVK_XFB_TOPO_LINE_LIST_ADJ));
|
||||||
|
+ {
|
||||||
|
+ emit_line_list_adj(b, v, N, buf, out_count, instance, value,
|
||||||
|
+ stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+ nir_push_else(b, NULL);
|
||||||
|
+ {
|
||||||
|
+ nir_push_if(b, nir_ieq_imm(b, topology, PANVK_XFB_TOPO_LINE_STRIP_ADJ));
|
||||||
|
+ {
|
||||||
|
+ emit_line_strip_adj(b, v, N, buf, out_count, instance, value,
|
||||||
|
+ stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+ nir_push_else(b, NULL);
|
||||||
|
+ {
|
||||||
|
+ nir_push_if(b, nir_ieq_imm(b, topology, PANVK_XFB_TOPO_TRI_LIST_ADJ));
|
||||||
|
+ {
|
||||||
|
+ emit_tri_list_adj(b, v, N, buf, out_count, instance, value,
|
||||||
|
+ stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+ nir_push_else(b, NULL);
|
||||||
|
+ {
|
||||||
|
+ /* TRI_STRIP_ADJ — last case */
|
||||||
|
+ emit_tri_strip_adj(b, v, N, buf, out_count, instance, value,
|
||||||
|
+ stride, offset_bytes);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL); /* Janet Finding 3: close output_count > 0 guard */
|
||||||
|
+ }
|
||||||
|
+ nir_pop_if(b, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Mirror of pan_nir_lower_xfb's lower_xfb: load_vertex_id rewrite +
|
||||||
|
+ * dispatch store_output through our topology-aware emission. */
|
||||||
|
+static bool
|
||||||
|
+lower_xfb_iter17(nir_builder *b, nir_intrinsic_instr *intr,
|
||||||
|
+ UNUSED void *data)
|
||||||
|
+{
|
||||||
|
+ if (intr->intrinsic == nir_intrinsic_load_vertex_id) {
|
||||||
|
+ b->cursor = nir_instr_remove(&intr->instr);
|
||||||
|
+ nir_def *repl = nir_iadd(b, nir_load_raw_vertex_id_pan(b),
|
||||||
|
+ nir_load_raw_vertex_offset_pan(b));
|
||||||
|
+ nir_def_rewrite_uses(&intr->def, repl);
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (intr->intrinsic != nir_intrinsic_store_output)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ bool progress = false;
|
||||||
|
+ b->cursor = nir_before_instr(&intr->instr);
|
||||||
|
+
|
||||||
|
+ /* io_xfb has only out[0,1]; the other 2 channels are in io_xfb2.
|
||||||
|
+ * Outer loop selects which annotation; inner picks which channel. */
|
||||||
|
+ for (unsigned i = 0; i < 2; ++i) {
|
||||||
|
+ nir_io_xfb xfb = i ? nir_intrinsic_io_xfb2(intr)
|
||||||
|
+ : nir_intrinsic_io_xfb(intr);
|
||||||
|
+ for (unsigned j = 0; j < 2; ++j) {
|
||||||
|
+ if (!xfb.out[j].num_components)
|
||||||
|
+ continue;
|
||||||
|
+ lower_xfb_output_iter17(b, intr, i * 2 + j, xfb.out[j].num_components,
|
||||||
|
+ xfb.out[j].buffer, xfb.out[j].offset);
|
||||||
|
+ progress = true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (progress)
|
||||||
|
+ nir_instr_remove(&intr->instr);
|
||||||
|
+ return progress;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+bool
|
||||||
|
+panvk_per_arch(nir_lower_xfb)(nir_shader *nir)
|
||||||
|
+{
|
||||||
|
+ return nir_shader_intrinsics_pass(
|
||||||
|
+ nir, lower_xfb_iter17, nir_metadata_control_flow, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif /* PAN_ARCH < 9 */
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
# 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.r4
|
||||||
|
pkgrel=1
|
||||||
|
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"
|
||||||
|
"0003-panvk-bifrost-vk-ext-transform-feedback.patch"
|
||||||
|
"0004-panvk-bifrost-xfb-primitive-decomposition.patch"
|
||||||
|
"brave-vulkan"
|
||||||
|
"icd.json"
|
||||||
|
)
|
||||||
|
sha256sums=(
|
||||||
|
'SKIP' # TODO: pin once we know the upstream tarball is stable. archive.mesa3d.org tarballs are stable, so we can hash-pin in iter10.
|
||||||
|
'SKIP'
|
||||||
|
'SKIP'
|
||||||
|
'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
|
||||||
|
|
||||||
|
# iter13: VK_EXT_transform_feedback implementation for Bifrost (PAN_ARCH<9).
|
||||||
|
# Applied as a real unified-diff patch — the change is too large for sed.
|
||||||
|
# Phase-doc context: ~/src/panvk-bifrost/phase{4,5,6}_iter13_close.md.
|
||||||
|
# Unlocks ANGLE-Vulkan → GLES3 → WebGL2 / WebGPU on Brave (chrome://gpu
|
||||||
|
# reports "Hardware accelerated" across the board for the affected paths).
|
||||||
|
patch -p1 < "${srcdir}/0003-panvk-bifrost-vk-ext-transform-feedback.patch"
|
||||||
|
|
||||||
|
# iter17: XFB primitive decomposition for non-LIST topologies (TRI_STRIP,
|
||||||
|
# TRI_FAN, LINE_STRIP, *_WITH_ADJACENCY). Replacement panvk-specific
|
||||||
|
# NIR pass (panvk_per_arch(nir_lower_xfb)) substituted for upstream
|
||||||
|
# pan_nir_lower_xfb. Closes the 162 dEQP-VK winding_* failures from
|
||||||
|
# iter15 (958 P / 81 F / 0 Crash on full XFB CTS — remaining 81 fails
|
||||||
|
# are by-design resume_* tests, transformFeedbackDraw=false).
|
||||||
|
# Phase-doc context: ~/src/panvk-bifrost/iter17/phase{0,1,2,4,5,6,8}_*.md.
|
||||||
|
patch -p1 < "${srcdir}/0004-panvk-bifrost-xfb-primitive-decomposition.patch"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# iter13 sanity:
|
||||||
|
grep -q "EXT_transform_feedback = PAN_ARCH < 9," src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||||
|
test -f src/panfrost/vulkan/jm/panvk_vX_cmd_xfb.c
|
||||||
|
# iter17 sanity: pan_nir_lower_xfb call site has been replaced; new file present.
|
||||||
|
grep -q "panvk_per_arch(nir_lower_xfb)" src/panfrost/vulkan/panvk_vX_shader.c
|
||||||
|
grep -q "xfb_topology" src/panfrost/vulkan/panvk_shader.h
|
||||||
|
grep -q "panvk_xfb_topology" src/panfrost/vulkan/panvk_shader.h
|
||||||
|
test -f src/panfrost/vulkan/panvk_vX_xfb_lower.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).
|
||||||
|
install -Dm755 build/src/panfrost/vulkan/libvulkan_panfrost.so \
|
||||||
|
"$pkgdir/usr/lib/panvk-bifrost/libvulkan_panfrost.so"
|
||||||
|
|
||||||
|
# Custom ICD JSON. NOT under /usr/share/vulkan/icd.d/ (the default
|
||||||
|
# loader search path) — the user has to opt in via VK_ICD_FILENAMES.
|
||||||
|
install -Dm644 "$srcdir/icd.json" \
|
||||||
|
"$pkgdir/usr/lib/panvk-bifrost/icd.json"
|
||||||
|
|
||||||
|
# The brave-vulkan launcher wires up env + flags.
|
||||||
|
install -Dm755 "$srcdir/brave-vulkan" "$pkgdir/usr/bin/brave-vulkan"
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# 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:
|
||||||
|
|
||||||
|
- `VK_ICD_FILENAMES=/usr/lib/panvk-bifrost/icd.json` (the patched driver)
|
||||||
|
- `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 --no-sandbox --disable-gpu-sandbox --ignore-gpu-blocklist`
|
||||||
|
|
||||||
|
## 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/lib/panvk-bifrost/icd.json` — Vulkan ICD JSON pointing at the patched .so (NOT auto-loaded; only via `VK_ICD_FILENAMES`)
|
||||||
|
- `/usr/bin/brave-vulkan` — launcher script
|
||||||
|
|
||||||
|
System Mesa is untouched. The stock `/usr/lib/libvulkan_panfrost.so` and
|
||||||
|
`/usr/share/vulkan/icd.d/panfrost_icd.json` continue to work for any
|
||||||
|
other Vulkan app.
|
||||||
|
|
||||||
|
## 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.
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#!/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_iteration9_close.md (campaign close)
|
||||||
|
#
|
||||||
|
# Usage: brave-vulkan [brave args...]
|
||||||
|
# Equivalent to: brave [VULKAN_FLAGS] [your args]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Patched Vulkan driver (from this package) — must point at the custom path
|
||||||
|
# so we don't clash with the stock /usr/share/vulkan/icd.d/panfrost_icd.json
|
||||||
|
export VK_ICD_FILENAMES=/usr/lib/panvk-bifrost/icd.json
|
||||||
|
|
||||||
|
# PanVk's "I know it's not conformant" gate — the patched driver still
|
||||||
|
# refuses to enumerate Bifrost without this env var (Mesa upstream choice,
|
||||||
|
# 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. The patched libvulkan_panfrost.so still has
|
||||||
|
# a PAN_ARCH>=10 gate inside get_api_version(); easier to override at
|
||||||
|
# runtime via this Mesa env var than to add a third patch.
|
||||||
|
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 \
|
||||||
|
--no-sandbox \
|
||||||
|
--disable-gpu-sandbox \
|
||||||
|
--ignore-gpu-blocklist \
|
||||||
|
"$@"
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -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=()
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -16,7 +16,7 @@ work=$(mktemp -d)
|
|||||||
trap "rm -rf $work" EXIT
|
trap "rm -rf $work" EXIT
|
||||||
|
|
||||||
cd "$work"
|
cd "$work"
|
||||||
curl -sSLfo his.tar.gz \
|
curl --connect-timeout 10 --max-time 600 --retry 3 --retry-delay 5 -sSLfo his.tar.gz \
|
||||||
"https://git.reauktion.de/marfrit/claude-his-agent/archive/v${PKGVER}.tar.gz"
|
"https://git.reauktion.de/marfrit/claude-his-agent/archive/v${PKGVER}.tar.gz"
|
||||||
echo "$HIS_TARBALL_SHA256 his.tar.gz" | sha256sum -c
|
echo "$HIS_TARBALL_SHA256 his.tar.gz" | sha256sum -c
|
||||||
tar xzf his.tar.gz
|
tar xzf his.tar.gz
|
||||||
|
|||||||
+200
@@ -0,0 +1,200 @@
|
|||||||
|
#!/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=5d8b4369e58ab947d1c56b1f718293c57c6065b5
|
||||||
|
PKGVER=0.1.0+r33+g5d8b436
|
||||||
|
PKGREL=1 # reset for new upstream pin (5d8b436 — revert parking design); still carries the #64 multi-kernel postinst fix
|
||||||
|
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 --connect-timeout 10 --max-time 600 --retry 3 --retry-delay 5 -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}
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Enumerate every kernel whose headers are actually present
|
||||||
|
# (/lib/modules/<kver>/build resolves to a directory). We iterate
|
||||||
|
# all of them — not just \$(uname -r) — so that installing this
|
||||||
|
# package after a kernel update covers the newly-installed kernel
|
||||||
|
# too, and so that a later kernel-headers install for a previously
|
||||||
|
# uncovered version gets picked up on dpkg-reconfigure. Without
|
||||||
|
# this, autoinstall (which targets only the running kernel) leaves
|
||||||
|
# /dev/daedalus-v4l2 absent after a kernel switch + reboot
|
||||||
|
# (marfrit/marfrit-packages#64).
|
||||||
|
kvers=''
|
||||||
|
for d in /lib/modules/*/build; do
|
||||||
|
[ -d "\$d" ] || continue
|
||||||
|
k=\$(basename "\$(dirname "\$d")")
|
||||||
|
kvers="\$kvers \$k"
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "\$kvers" ]; then
|
||||||
|
warn ""
|
||||||
|
warn "No kernels with headers found under /lib/modules/*/build."
|
||||||
|
warn "Install kernel headers (e.g. linux-headers-rpi-2712 on Pi OS)"
|
||||||
|
warn "then finish with:"
|
||||||
|
warn " sudo dkms autoinstall \$NAME/\$VERSION"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
failed=''
|
||||||
|
for k in \$kvers; do
|
||||||
|
dkms autoinstall -k "\$k" "\$NAME/\$VERSION" >/dev/null 2>&1 || true
|
||||||
|
s=\$(dkms status -m "\$NAME" -v "\$VERSION" -k "\$k" 2>/dev/null || true)
|
||||||
|
if ! printf '%s\\n' "\$s" | grep -q -E 'installed|loaded'; then
|
||||||
|
failed="\$failed \$k"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "\$failed" ]; then
|
||||||
|
warn ""
|
||||||
|
warn "DKMS build did NOT land for kernel(s):\$failed"
|
||||||
|
warn ""
|
||||||
|
warn "Most likely cause: kernel headers missing for those versions."
|
||||||
|
warn " Raspberry Pi OS / Pi 5: apt install linux-headers-rpi-2712"
|
||||||
|
warn " Debian generic: apt install linux-headers-<version>"
|
||||||
|
warn ""
|
||||||
|
warn "After installing headers, finish with:"
|
||||||
|
for k in \$failed; do
|
||||||
|
warn " sudo dkms autoinstall -k \$k \$NAME/\$VERSION"
|
||||||
|
done
|
||||||
|
warn " sudo modprobe daedalus_v4l2 (after booting that kernel)"
|
||||||
|
warn ""
|
||||||
|
warn "Until then daedalus_v4l2 will NOT be loadable on those kernels"
|
||||||
|
warn "and the 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"
|
||||||
+146
@@ -0,0 +1,146 @@
|
|||||||
|
daedalus-v4l2-dkms (0.1.0+r33+g5d8b436-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 5d8b436 — reverts daedalus-v4l2 PRs #7 + #8. Kernel
|
||||||
|
module returns to the pre-#7 buf_done_and_job_finish completion
|
||||||
|
model: no src/dst lifecycle decoupling, no parked dst_bufs, no
|
||||||
|
1:1-contract violation against libva-v4l2-request-fourier
|
||||||
|
(closes daedalus-v4l2#9 + #10 as won't-fix at this layer; proper
|
||||||
|
fix tracked at daedalus-v4l2#11).
|
||||||
|
* Wire-protocol drops 1 → 0; lock-step install with daedalus-v4l2
|
||||||
|
0.1.0+r33+g5d8b436 REQUIRED.
|
||||||
|
* Carries forward the #64 multi-kernel postinst fix.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 14:50:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2-dkms (0.1.0+r30+g6ffe92b-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 6ffe92b — fixes the kernel panic regression introduced
|
||||||
|
by 79256dc's split-completion design (closes daedalus-v4l2#8).
|
||||||
|
`device_run` now removes both src + dst from `m2m_ctx`'s
|
||||||
|
rdy_queue at pickup time, not at `buf_done` time. Without
|
||||||
|
this, after `SRC_CONSUMED`'s `job_finish` released the m2m
|
||||||
|
scheduler, the NEXT `device_run` saw the still-queued parked
|
||||||
|
dst_buf and paired it with a fresh src — two inflight entries
|
||||||
|
referencing the same vb2_buffer, the later `HAS_PIXELS`
|
||||||
|
triggered list_del on an already-detached list_head, smashing
|
||||||
|
the rdy_queue → hard reboot on Pi CM5 during `mpv vaapi-copy`
|
||||||
|
playback of 720p H.264 (2026-05-21).
|
||||||
|
* Wire protocol unchanged — DAEDALUS_PROTO_VERSION stays at 1.
|
||||||
|
Daemon (userspace daedalus-v4l2 package) need NOT bump in
|
||||||
|
lockstep with this DKMS update; the existing
|
||||||
|
daedalus-v4l2 0.1.0+r28+g79256dc is wire-compatible with
|
||||||
|
daedalus-v4l2-dkms 0.1.0+r30+g6ffe92b.
|
||||||
|
* Carries forward the #64 multi-kernel postinst fix.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 14:00:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2-dkms (0.1.0+r28+g79256dc-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 79256dc — H.264 B-frame display reorder fix (closes
|
||||||
|
daedalus-v4l2#6). libavcodec's H.264 decoder reorders output to
|
||||||
|
display order before returning from avcodec_receive_frame; the
|
||||||
|
daemon was binding each REQ_DECODE's pixels to the cookie of the
|
||||||
|
bitstream that triggered the receive_frame call, not the cookie
|
||||||
|
of the bitstream that actually produced the picture. For B-frame
|
||||||
|
sequences this paired cookie N's CAPTURE buffer with cookie N-2's
|
||||||
|
pixels and silently lost intermediate frames — visible as
|
||||||
|
"2 1 4 3 6 5" frame pairing in mpv / Firefox on Pi CM5.
|
||||||
|
* Wire-protocol bump (DAEDALUS_PROTO_VERSION 0 → 1): REQ_DECODE
|
||||||
|
gains __u64 src_pts; RESP_FRAME gains __u32 flags +
|
||||||
|
__u64 output_src_pts. Kernel + daemon must install atomically
|
||||||
|
(this package + daedalus-v4l2 0.1.0+r28+g79256dc).
|
||||||
|
* Carries forward the #64 multi-kernel postinst fix from -2:
|
||||||
|
autoinstall for every /lib/modules/*/build that resolves to real
|
||||||
|
headers, not just $(uname -r).
|
||||||
|
* Closes #64.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 12:00:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2-dkms (0.1.0+r24+gf0d4186-2) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* postinst: autoinstall for every installed kernel with headers, not
|
||||||
|
just the running one. Previously `dkms autoinstall $NAME/$VERSION`
|
||||||
|
built only against `$(uname -r)`, so installing the package on
|
||||||
|
kernel A and then rebooting into a separately-installed kernel B
|
||||||
|
left /lib/modules/B/updates/dkms/ empty — /dev/daedalus-v4l2 absent,
|
||||||
|
daedalus daemon nothing to talk to, browser/VAAPI silently falling
|
||||||
|
back to software with no obvious diagnostic. Now we enumerate every
|
||||||
|
/lib/modules/*/build that resolves to a real directory and run
|
||||||
|
`dkms autoinstall -k <kver>` for each, reporting per-kernel failure
|
||||||
|
only when headers are missing. Closes #64.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 09:30:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2-dkms (0.1.0+r24+gf0d4186-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to f0d4186 — per-ctx vb2 lock fix. daedalus_queue_init now
|
||||||
|
uses ctx->vb_mutex instead of ctx->dev->m2m_lock for each
|
||||||
|
vb2_queue's lock, unblocking Firefox's multi-process VAAPI
|
||||||
|
clients (they were colliding on the device-wide mutex and one
|
||||||
|
would EBUSY-fail S_FMT while another was mid-streamon).
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 23:00:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2-dkms (0.1.0+r22+g462aa4b-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 462aa4b — kernel device_run() now calls
|
||||||
|
v4l2_ctrl_request_setup() before reading the H.264 stateless
|
||||||
|
control values from the bound media_request, so the values
|
||||||
|
daedalus ships to the userspace daemon match what the V4L2
|
||||||
|
client (libva-v4l2-request-fourier) actually set. Closes the
|
||||||
|
libva→kernel control-binding gap that was causing decoded
|
||||||
|
frames to come back as best-effort zero garbage from libavcodec.
|
||||||
|
* Wire-ABI lockstep with daedalus-v4l2 0.1.0+r22+g462aa4b.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 22:00:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2-dkms (0.1.0+r20+g3dd0eb0-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 3dd0eb0 — DAEMON-PPS kernel-side changes. device_run()
|
||||||
|
now reads the V4L2 H.264 stateless control values from the bound
|
||||||
|
media_request and ships them to the daemon inside REQ_DECODE
|
||||||
|
via the new struct daedalus_h264_meta block (gated on
|
||||||
|
DAEDALUS_REQ_FLAG_H264_META). Required for H.264 decode to
|
||||||
|
work via the libva-v4l2-request -> daedalus daemon path; daemon
|
||||||
|
synthesises AnnexB SPS+PPS NAL units from the structs.
|
||||||
|
* Wire-ABI lockstep with daedalus-v4l2 0.1.0+r20+g3dd0eb0 — install
|
||||||
|
both packages together.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 21:00:00 +0000
|
||||||
|
|
||||||
|
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
@@ -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
@@ -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'.
|
||||||
+214
@@ -0,0 +1,214 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
|
# 6e6dfa1 = picks up daedalus-v4l2 PR #16 — daemon now dlopens
|
||||||
|
# the Kwiboo fourier fork's libavcodec.so.62 / libavformat.so.62 /
|
||||||
|
# libavutil.so.60 at /opt/fourier instead of Debian-stock soname
|
||||||
|
# 61/61/59. First step on the daedalus-fourier substitution arc
|
||||||
|
# (daedalus-v4l2#11): routes the daemon through the libavcodec
|
||||||
|
# source tree we own in marfrit-packages. Headers + .pc files
|
||||||
|
# come from ffmpeg-v4l2-request-fourier (installed by the CI
|
||||||
|
# workflow before this script runs; see PKG_CONFIG_PATH below).
|
||||||
|
UPSTREAM_COMMIT=6e6dfa144da7bc7fa8be50c8da91d7d1c6132a2c
|
||||||
|
PKGVER=0.1.0+r41+g6e6dfa1
|
||||||
|
PKGREL=1 # reset for new upstream pin (6e6dfa1 — soname 62 via /opt/fourier)
|
||||||
|
|
||||||
|
# daedalus-fourier pin. d87239d = marfrit/daedalus-fourier PR #1 merge
|
||||||
|
# (install rules + pkg-config, enables this consumer to find_package
|
||||||
|
# + link). Bump in lockstep with the upstream daemon when daedalus-
|
||||||
|
# fourier's API or installed shaders are changed by a new consumer.
|
||||||
|
DAEDALUS_FOURIER_COMMIT=d87239d8172307d9a1b93c95cbed116d175b85cc
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# --- daedalus-fourier: fetch + build + install to per-build prefix ---
|
||||||
|
#
|
||||||
|
# Static-linked into the daemon, so the temp prefix is only for the
|
||||||
|
# duration of this build script. Requires libvulkan-dev + glslang-tools
|
||||||
|
# on the runner (already needed for the daedalus-fourier benches).
|
||||||
|
FOURIER_PREFIX=$work/fourier-prefix
|
||||||
|
mkdir -p "$FOURIER_PREFIX"
|
||||||
|
|
||||||
|
cd "$work"
|
||||||
|
curl --connect-timeout 10 --max-time 600 --retry 3 --retry-delay 5 -sSLfo daedalus-fourier.tar.gz \
|
||||||
|
"https://git.reauktion.de/marfrit/daedalus-fourier/archive/${DAEDALUS_FOURIER_COMMIT}.tar.gz"
|
||||||
|
tar xzf daedalus-fourier.tar.gz
|
||||||
|
cd daedalus-fourier
|
||||||
|
cmake -B build -G Ninja \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="$FOURIER_PREFIX"
|
||||||
|
cmake --build build --target daedalus_core
|
||||||
|
cmake --install build
|
||||||
|
|
||||||
|
# --- daedalus-v4l2: fetch + build daemon against installed daedalus-fourier ---
|
||||||
|
|
||||||
|
cd "$work"
|
||||||
|
curl --connect-timeout 10 --max-time 600 --retry 3 --retry-delay 5 -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) — point pkg-config at the daedalus-fourier
|
||||||
|
# temp prefix so pkg_check_modules(DAEDALUS_FOURIER …) resolves to it.
|
||||||
|
cd "$SRCDIR/daemon"
|
||||||
|
PKG_CONFIG_PATH="$FOURIER_PREFIX/lib/pkgconfig:/opt/fourier/lib/pkgconfig" \
|
||||||
|
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"
|
||||||
+207
@@ -0,0 +1,207 @@
|
|||||||
|
daedalus-v4l2 (0.1.0+r41+g6e6dfa1-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 6e6dfa1 — daedalus-v4l2 PR #16. Daemon dlopens Kwiboo
|
||||||
|
fourier fork's libavcodec.so.62 / libavformat.so.62 /
|
||||||
|
libavutil.so.60 at /opt/fourier instead of Debian-stock
|
||||||
|
soname 61/61/59. First step on the daedalus-fourier
|
||||||
|
substitution arc (daedalus-v4l2#11): the next PR series
|
||||||
|
layers daedalus_recipe_dispatch_h264_* substitution patches
|
||||||
|
into ffmpeg-v4l2-request-fourier's H264DSPContext NEON init,
|
||||||
|
reaching the daemon's production decode path.
|
||||||
|
* Build: PKG_CONFIG_PATH now includes /opt/fourier/lib/pkgconfig
|
||||||
|
so daemon's pkg_check_modules picks up the Kwiboo .pc files.
|
||||||
|
* CI workflow build-deps: libavcodec-dev / libavformat-dev /
|
||||||
|
libavutil-dev (Debian stock 7.1.3) → ffmpeg-v4l2-request-fourier
|
||||||
|
(provides /opt/fourier/include + .pc files).
|
||||||
|
* Wire protocol unchanged. No daedalus-v4l2-dkms bump.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 21:30:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2 (0.1.0+r39+g3bc0da1-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 3bc0da1 — picks up daedalus-v4l2 PR #15. Per-frame
|
||||||
|
`decoder: OK ...` log line gains `decode_us=N` (libavcodec
|
||||||
|
send_packet + receive_frame wall-clock cost in microseconds).
|
||||||
|
New `decoder stats` summary line every 60 decoded frames with
|
||||||
|
codec, fps, avg decode_us, MBs/s throughput, B/MB bitrate.
|
||||||
|
* Pure observability — no decode-path behaviour change.
|
||||||
|
Establishes baseline metrics for the substitution work in
|
||||||
|
daedalus-v4l2#11 step 2 (replacing libavcodec primitives with
|
||||||
|
daedalus-fourier kernels one cycle at a time).
|
||||||
|
* On Pi CM5 / bbb 720p H.264 baseline: ~4 ms decode_us / 24 fps
|
||||||
|
/ 90 K MBs/s — workload is well under 1 % of any single
|
||||||
|
daedalus-fourier kernel's NEON ceiling.
|
||||||
|
* Wire protocol unchanged. No daedalus-v4l2-dkms bump needed.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 18:30:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2 (0.1.0+r37+g77e14e5-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 77e14e5 — picks up daedalus-v4l2 PRs #12 + #13.
|
||||||
|
* #12 (LOW_DELAY half-measure): the daemon now sets
|
||||||
|
AV_CODEC_FLAG_LOW_DELAY on the H.264 AVCodecContext so libavcodec
|
||||||
|
emits frames in decode order ~99% of the time (a few stragglers
|
||||||
|
at GOP boundaries when the stream's SPS num_reorder_frames
|
||||||
|
overrides the flag). Visible improvement vs the 2-1-4-3
|
||||||
|
pair-swap on Firefox YouTube + mpv playback; not a permanent
|
||||||
|
fix (see #11 for the architectural plan).
|
||||||
|
* #13 (daedalus-fourier linkage): the daemon now pkg-config-links
|
||||||
|
against the daedalus-fourier kernel library (marfrit/
|
||||||
|
daedalus-fourier) and logs substrate availability at startup.
|
||||||
|
No kernels dispatched yet — this is the build-time / link-time
|
||||||
|
foundation for the H.264 daemon-rewrite plan in #11
|
||||||
|
(substituting daedalus-fourier IDCT 4×4 / IDCT 8×8 / luma
|
||||||
|
deblock primitives for libavcodec's per-MB pixel math, one
|
||||||
|
cycle at a time, measuring CPU saved per substitution).
|
||||||
|
* Build-deb.sh now fetches + builds + installs daedalus-fourier
|
||||||
|
(pinned at d87239d, marfrit/daedalus-fourier PR #1) into a
|
||||||
|
per-build temp prefix, then builds the daemon with
|
||||||
|
PKG_CONFIG_PATH pointing at it. daedalus-fourier is
|
||||||
|
statically linked into the daemon binary, so the resulting
|
||||||
|
.deb has no new runtime deps. Requires libvulkan-dev +
|
||||||
|
glslang-tools on the CI runner (the daedalus-fourier benches
|
||||||
|
already needed those).
|
||||||
|
* Wire protocol unchanged — DAEDALUS_PROTO_VERSION stays at 0.
|
||||||
|
No daedalus-v4l2-dkms bump needed.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 16:30:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2 (0.1.0+r33+g5d8b436-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 5d8b436 — reverts daedalus-v4l2 PRs #7 + #8 (the parking
|
||||||
|
design that broke libva-v4l2-request-fourier's 1:1 CAPTURE
|
||||||
|
contract; see daedalus-v4l2#9 + #10). After daemon-r28+g79256dc
|
||||||
|
landed, mpv (--hwdec=vaapi-copy) failed pre-playing with
|
||||||
|
"Unable to dequeue buffer: Resource temporarily unavailable" /
|
||||||
|
"Failed to end picture decode" because the daemon parked CAPTURE
|
||||||
|
buffers waiting for libavcodec to release H.264 B-frames in
|
||||||
|
display order — violating the V4L2 stateless 1:1 contract.
|
||||||
|
Firefox tolerated the mess (visible "2 1 4 3" pair-swap); mpv
|
||||||
|
bailed.
|
||||||
|
* This bump restores f0d4186-equivalent behaviour, plus PR #4
|
||||||
|
(cosmetic H.264 DECODE_MODE / START_CODE menu controls). PR #7
|
||||||
|
+ PR #8 wire-protocol additions (src_pts / output_src_pts /
|
||||||
|
RESP_FRAME flags) are reverted — DAEDALUS_PROTO_VERSION drops
|
||||||
|
back from 1 → 0. Lock-step install with daedalus-v4l2-dkms
|
||||||
|
0.1.0+r33+g5d8b436 REQUIRED.
|
||||||
|
* Visible regression: H.264 B-frame streams in Firefox revert to
|
||||||
|
the original "2 1 4 3 6 5" pair-swap visual. The proper fix
|
||||||
|
(concurrent in-flight requests in daemon + display-order reorder
|
||||||
|
in libva-v4l2-request-fourier) is tracked at daedalus-v4l2#11.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 14:50:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2 (0.1.0+r28+g79256dc-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 79256dc — H.264 B-frame display reorder fix (closes
|
||||||
|
daedalus-v4l2#6 + #4 menu controls). Daemon side: the
|
||||||
|
avcodec_send_packet → receive_frame loop now stamps pkt->pts =
|
||||||
|
req->src_pts so libavcodec's display-ordered frame->pts identifies
|
||||||
|
which OUTPUT bitstream's pixels each drained frame belongs to.
|
||||||
|
chardev_client maintains a (src_pts → cookie) lookup table so the
|
||||||
|
daemon can ship pixels to the cookie of the *originating*
|
||||||
|
bitstream, not the cookie of whatever REQ triggered the
|
||||||
|
receive_frame call. Multiple RESP_FRAME messages per REQ_DECODE
|
||||||
|
are now possible (one for the just-consumed src, one or more for
|
||||||
|
drained pixels).
|
||||||
|
* Wire-protocol bump (DAEDALUS_PROTO_VERSION 0 → 1): REQ_DECODE
|
||||||
|
gains __u64 src_pts; RESP_FRAME gains __u32 flags +
|
||||||
|
__u64 output_src_pts. Daemon + kernel must install atomically
|
||||||
|
(this package + daedalus-v4l2-dkms 0.1.0+r28+g79256dc).
|
||||||
|
* Also subsumes 79256dc's predecessor 7ff2d89 — H.264 DECODE_MODE +
|
||||||
|
START_CODE menu-control registration that retires the
|
||||||
|
"Unable to set control(s) error_idx=2/2" warning libva-v4l2-
|
||||||
|
request emitted on every context init.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 12:00:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2 (0.1.0+r24+gf0d4186-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to f0d4186 — kernel per-ctx vb2 lock fix. daedalus_queue_init
|
||||||
|
was wiring src_vq->lock and dst_vq->lock to ctx->dev->m2m_lock (a
|
||||||
|
device-wide mutex), serialising every vb2 ioctl across all
|
||||||
|
concurrent clients of /dev/video0. For Firefox (which spawns
|
||||||
|
separate content + RDD + GPU processes that each open the device
|
||||||
|
and run libva probe simultaneously), one libva session's
|
||||||
|
S_FMT(OUTPUT_MPLANE) hit EBUSY while another was mid-streamon —
|
||||||
|
Firefox VAAPI playback fell apart at startup.
|
||||||
|
* Fix gives each open() its own ctx->vb_mutex; vb2 ioctls run
|
||||||
|
independently per client. Matches cedrus / rkvdec / hantro
|
||||||
|
pattern.
|
||||||
|
* Verified on higgs: Firefox YouTube playback engages VAAPI cleanly,
|
||||||
|
sustained ~230 fps decode at 640x368 through the daedalus daemon,
|
||||||
|
zero EBUSY in stderr or daemon journal.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 23:00:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2 (0.1.0+r22+g462aa4b-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 462aa4b — kernel-side fix for control-binding gap that
|
||||||
|
closes the libva→daemon SPS/PPS pipeline. Kernel device_run now
|
||||||
|
calls v4l2_ctrl_request_setup() before reading ctrl->p_cur, so
|
||||||
|
the daemon's daedalus_h264_meta block actually carries THIS
|
||||||
|
request's V4L2 stateless H.264 control values instead of stale
|
||||||
|
/default ones. Pairs with libva-v4l2-request-fourier r382+gc1bb444
|
||||||
|
(Fix 3 + Fix 4 from issue libva-v4l2-request-fourier#8).
|
||||||
|
* After-fix on higgs (Pi CM5): ffmpeg -hwaccel vaapi -i h264.mp4
|
||||||
|
produces unique decoded P-frames (per-frame fnv1a hashes differ)
|
||||||
|
and zero "error while decoding MB" / "reference frames exceeds
|
||||||
|
max" warnings.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 22:00:00 +0000
|
||||||
|
|
||||||
|
daedalus-v4l2 (0.1.0+r20+g3dd0eb0-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 3dd0eb0 — DAEMON-PPS H.264 SPS/PPS NAL synthesiser.
|
||||||
|
Daemon now reconstructs AnnexB SPS+PPS NAL units from the V4L2
|
||||||
|
stateless H.264 control structs (forwarded by the kernel via
|
||||||
|
a new struct daedalus_h264_meta block in REQ_DECODE) and
|
||||||
|
prepends them to the slice bitstream before feeding libavcodec.
|
||||||
|
Without this, ffmpeg -hwaccel vaapi on H.264 sources failed
|
||||||
|
with "non-existing PPS 0 referenced" even after LIBVA-1/-2
|
||||||
|
routing correctly delivered the request.
|
||||||
|
* Wire protocol: new DAEDALUS_REQ_FLAG_H264_META bit + struct
|
||||||
|
daedalus_h264_meta; daemon and kernel must be installed in
|
||||||
|
lockstep (this package + daedalus-v4l2-dkms 0.1.0+r20+g3dd0eb0).
|
||||||
|
* VP9 / AV1 paths unchanged.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 21:00:00 +0000
|
||||||
|
|
||||||
|
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
|
||||||
Vendored
+34
@@ -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
@@ -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
|
||||||
|
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
From f760c0541586f43334c02611fcb4c212c08ad576 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Markus Fritsche <mfritsche@reauktion.de>
|
||||||
|
Date: Thu, 21 May 2026 21:40:22 +0200
|
||||||
|
Subject: [PATCH] avcodec/aarch64/h264dsp: route H.264 4x4 IDCT through
|
||||||
|
daedalus-fourier
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
H264DSPContext.idct_add (called per 4x4 block from the intra-4x4
|
||||||
|
decode path in h264_mb.c) now dispatches through
|
||||||
|
daedalus_recipe_dispatch_h264_idct4 instead of ff_h264_idct_add_neon.
|
||||||
|
|
||||||
|
The recipe layer picks the substrate; for cycle 6 (H.264 IDCT 4x4)
|
||||||
|
the recipe is CPU NEON, so this is effectively a NEON-to-NEON
|
||||||
|
substitution with one extra dispatch call and recipe-table lookup.
|
||||||
|
Provides the first end-to-end exercise of the daedalus-fourier
|
||||||
|
kernel pack inside the libavcodec.so decode hot path; follow-up
|
||||||
|
patches wire IDCT 8x8, luma-v deblock, and qpel mc20.
|
||||||
|
|
||||||
|
The library context is process-global, lazily initialised under
|
||||||
|
pthread_once on first call. We pick the no-QPU constructor because
|
||||||
|
libavcodec.so is loaded into arbitrary host processes
|
||||||
|
(firefox-fourier, mpv-fourier, daedalus_v4l2_daemon, ...) and we
|
||||||
|
cannot assume the host has a usable Vulkan instance. Higher cycles
|
||||||
|
(deblock luma-v, MC) that benefit from the QPU will provision their
|
||||||
|
own recipe-selected context once that path is wired.
|
||||||
|
|
||||||
|
Bulk paths (idct_add16, idct_add16intra, idct_add8 — used for
|
||||||
|
non-intra4x4 macroblocks) remain on the stock NEON .S implementations
|
||||||
|
and will be batched through daedalus_recipe_dispatch_h264_idct4 with
|
||||||
|
n_blocks>1 in a follow-up.
|
||||||
|
|
||||||
|
Bit-exact against ff_h264_idct_add_neon (daedalus-fourier cycle 6
|
||||||
|
green; see marfrit/daedalus-fourier/CYCLE_LOGS.md).
|
||||||
|
|
||||||
|
Refs reauktion/daedalus-v4l2#11 — substitution arc step 2.
|
||||||
|
---
|
||||||
|
libavcodec/aarch64/Makefile | 3 +-
|
||||||
|
libavcodec/aarch64/h264_idct_daedalus.c | 49 +++++++++++++++++++++++
|
||||||
|
libavcodec/aarch64/h264dsp_init_aarch64.c | 3 +-
|
||||||
|
3 files changed, 53 insertions(+), 2 deletions(-)
|
||||||
|
create mode 100644 libavcodec/aarch64/h264_idct_daedalus.c
|
||||||
|
|
||||||
|
diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile
|
||||||
|
index 41ab025..7b95fb1 100644
|
||||||
|
--- a/libavcodec/aarch64/Makefile
|
||||||
|
+++ b/libavcodec/aarch64/Makefile
|
||||||
|
@@ -3,7 +3,8 @@ OBJS-$(CONFIG_AC3DSP) += aarch64/ac3dsp_init_aarch64.o
|
||||||
|
OBJS-$(CONFIG_FDCTDSP) += aarch64/fdctdsp_init_aarch64.o
|
||||||
|
OBJS-$(CONFIG_FMTCONVERT) += aarch64/fmtconvert_init.o
|
||||||
|
OBJS-$(CONFIG_H264CHROMA) += aarch64/h264chroma_init_aarch64.o
|
||||||
|
-OBJS-$(CONFIG_H264DSP) += aarch64/h264dsp_init_aarch64.o
|
||||||
|
+OBJS-$(CONFIG_H264DSP) += aarch64/h264dsp_init_aarch64.o \
|
||||||
|
+ aarch64/h264_idct_daedalus.o
|
||||||
|
OBJS-$(CONFIG_HUFFYUVDSP) += aarch64/huffyuvdsp_init_aarch64.o
|
||||||
|
OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_init.o
|
||||||
|
OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_init_aarch64.o
|
||||||
|
diff --git a/libavcodec/aarch64/h264_idct_daedalus.c b/libavcodec/aarch64/h264_idct_daedalus.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..538d223
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libavcodec/aarch64/h264_idct_daedalus.c
|
||||||
|
@@ -0,0 +1,49 @@
|
||||||
|
+/*
|
||||||
|
+ * H.264 4x4 IDCT + add — daedalus-fourier substitution shim.
|
||||||
|
+ *
|
||||||
|
+ * Routes H264DSPContext.idct_add through
|
||||||
|
+ * daedalus_recipe_dispatch_h264_idct4 instead of ff_h264_idct_add_neon.
|
||||||
|
+ * The recipe layer picks the substrate (CPU NEON by default for
|
||||||
|
+ * cycle 6; future cycles may dispatch to V3D opportunistically).
|
||||||
|
+ *
|
||||||
|
+ * FFmpeg's 4x4 block memory layout matches daedalus's column-major
|
||||||
|
+ * convention: block[r + 4*c] = coefficient at (row r, col c). Both
|
||||||
|
+ * sides destructively zero the block after the transform.
|
||||||
|
+ *
|
||||||
|
+ * The library context is process-global and lazily initialised under
|
||||||
|
+ * pthread_once. We pick the no-QPU constructor here because
|
||||||
|
+ * libavcodec.so is loaded into arbitrary host processes
|
||||||
|
+ * (firefox-fourier, mpv-fourier, daedalus_v4l2_daemon, ...) and we
|
||||||
|
+ * cannot assume the host has a usable Vulkan instance. Higher cycles
|
||||||
|
+ * (deblock, MC) that benefit from the QPU initialise their own
|
||||||
|
+ * recipe-selected context once that path is wired.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <pthread.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <stdint.h>
|
||||||
|
+
|
||||||
|
+#include <daedalus.h>
|
||||||
|
+
|
||||||
|
+#include "libavutil/attributes.h"
|
||||||
|
+#include "libavcodec/h264dsp.h"
|
||||||
|
+
|
||||||
|
+static daedalus_ctx *g_dctx;
|
||||||
|
+static pthread_once_t g_dctx_once = PTHREAD_ONCE_INIT;
|
||||||
|
+
|
||||||
|
+static void daedalus_ctx_init_once(void)
|
||||||
|
+{
|
||||||
|
+ g_dctx = daedalus_ctx_create_no_qpu();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void ff_h264_idct_add_daedalus(uint8_t *dst, int16_t *block, int stride);
|
||||||
|
+
|
||||||
|
+void ff_h264_idct_add_daedalus(uint8_t *dst, int16_t *block, int stride)
|
||||||
|
+{
|
||||||
|
+ static const daedalus_h264_block_meta meta = { .dst_off = 0 };
|
||||||
|
+
|
||||||
|
+ pthread_once(&g_dctx_once, daedalus_ctx_init_once);
|
||||||
|
+
|
||||||
|
+ daedalus_recipe_dispatch_h264_idct4(g_dctx, dst, (size_t)stride,
|
||||||
|
+ block, 1, &meta);
|
||||||
|
+}
|
||||||
|
diff --git a/libavcodec/aarch64/h264dsp_init_aarch64.c b/libavcodec/aarch64/h264dsp_init_aarch64.c
|
||||||
|
index c684574..b993df2 100644
|
||||||
|
--- a/libavcodec/aarch64/h264dsp_init_aarch64.c
|
||||||
|
+++ b/libavcodec/aarch64/h264dsp_init_aarch64.c
|
||||||
|
@@ -66,6 +66,7 @@ void ff_biweight_h264_pixels_4_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride
|
||||||
|
int weights, int offset);
|
||||||
|
|
||||||
|
void ff_h264_idct_add_neon(uint8_t *dst, int16_t *block, int stride);
|
||||||
|
+void ff_h264_idct_add_daedalus(uint8_t *dst, int16_t *block, int stride);
|
||||||
|
void ff_h264_idct_dc_add_neon(uint8_t *dst, int16_t *block, int stride);
|
||||||
|
void ff_h264_idct_add16_neon(uint8_t *dst, const int *block_offset,
|
||||||
|
int16_t *block, int stride,
|
||||||
|
@@ -139,7 +140,7 @@ av_cold void ff_h264dsp_init_aarch64(H264DSPContext *c, const int bit_depth,
|
||||||
|
c->biweight_pixels_tab[1] = ff_biweight_h264_pixels_8_neon;
|
||||||
|
c->biweight_pixels_tab[2] = ff_biweight_h264_pixels_4_neon;
|
||||||
|
|
||||||
|
- c->idct_add = ff_h264_idct_add_neon;
|
||||||
|
+ c->idct_add = ff_h264_idct_add_daedalus;
|
||||||
|
c->idct_dc_add = ff_h264_idct_dc_add_neon;
|
||||||
|
c->idct_add16 = ff_h264_idct_add16_neon;
|
||||||
|
c->idct_add16intra = ff_h264_idct_add16intra_neon;
|
||||||
|
--
|
||||||
|
2.47.3
|
||||||
|
|
||||||
+261
@@ -0,0 +1,261 @@
|
|||||||
|
#!/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=5 # pkgrel=5 — H.264 IDCT 4x4 daedalus-fourier substitution; skip past
|
||||||
|
# an orphan -4 .deb sitting in the apt pool that made
|
||||||
|
# check-already-published.sh's `pool_ver ge source_full` short-
|
||||||
|
# circuit the previous -3 build (PR #76). (2026-05-21)
|
||||||
|
|
||||||
|
# daedalus-fourier pin — first kernel substitution in libavcodec (cycle 6
|
||||||
|
# H.264 IDCT 4x4). Same SHA as the daedalus-v4l2 daemon already ships
|
||||||
|
# inline; rev in lockstep with the daemon when the public API rolls.
|
||||||
|
DAEDALUS_FOURIER_COMMIT=d87239d8172307d9a1b93c95cbed116d175b85cc
|
||||||
|
|
||||||
|
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"
|
||||||
|
patch -Np1 -i "$HERE/0003-h264-idct4-daedalus-fourier.patch"
|
||||||
|
|
||||||
|
# --- daedalus-fourier: fetch + build static .a with PIC, install to a
|
||||||
|
# per-build prefix; libavcodec.so links it into the shared object so
|
||||||
|
# H264DSPContext.idct_add (and follow-up kernels) dispatch through the
|
||||||
|
# daedalus recipe layer instead of the in-tree NEON .S code. ---
|
||||||
|
#
|
||||||
|
# PIC is mandatory — the static .a is linked into a .so, so all object
|
||||||
|
# code must be relocatable. Vulkan is PUBLIC-linked by daedalus_core
|
||||||
|
# (queryable QPU substrate); we add libvulkan1 to Debian Depends below
|
||||||
|
# so dlopen of libavcodec.so.62 succeeds on stock trixie.
|
||||||
|
FOURIER_PREFIX=$work/fourier-prefix
|
||||||
|
mkdir -p "$FOURIER_PREFIX"
|
||||||
|
|
||||||
|
pushd "$work" >/dev/null
|
||||||
|
curl --connect-timeout 10 --max-time 600 --retry 3 --retry-delay 5 -sSLfo daedalus-fourier.tar.gz \
|
||||||
|
"https://git.reauktion.de/marfrit/daedalus-fourier/archive/${DAEDALUS_FOURIER_COMMIT}.tar.gz"
|
||||||
|
tar xzf daedalus-fourier.tar.gz
|
||||||
|
pushd daedalus-fourier >/dev/null
|
||||||
|
cmake -B build -G Ninja \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="$FOURIER_PREFIX"
|
||||||
|
cmake --build build --target daedalus_core
|
||||||
|
cmake --install build
|
||||||
|
popd >/dev/null
|
||||||
|
popd >/dev/null
|
||||||
|
cd "$work/FFmpeg"
|
||||||
|
|
||||||
|
# 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' \
|
||||||
|
--extra-cflags="-I${FOURIER_PREFIX}/include" \
|
||||||
|
--extra-ldflags="-L${FOURIER_PREFIX}/lib" \
|
||||||
|
--extra-libs="-ldaedalus_core -lvulkan -lpthread" \
|
||||||
|
--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,
|
||||||
|
libvulkan1,
|
||||||
|
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"
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
ffmpeg-v4l2-request-fourier (2:8.1+rfourier+gb57fbbe-5) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* pkgrel-only bump (3 → 5) to force a rebuild of the H.264 IDCT 4x4
|
||||||
|
daedalus-fourier substitution that landed in marfrit-packages PR
|
||||||
|
#76. An orphan -4 .deb already sat in the apt pool (dated
|
||||||
|
2026-05-19, no matching source commit in main); CI's
|
||||||
|
check-already-published.sh compares with `dpkg --compare-versions
|
||||||
|
pool_ver ge source_full`, which short-circuited PR #76's -3
|
||||||
|
build. Skipping past -4 lets the CI workflow actually publish the
|
||||||
|
substitution.
|
||||||
|
* No source code change beyond PKGREL and this changelog entry.
|
||||||
|
Substitution + control + build-deb.sh wiring stay as PR #76 left
|
||||||
|
them.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 21:30:00 +0000
|
||||||
|
|
||||||
|
ffmpeg-v4l2-request-fourier (2:8.1+rfourier+gb57fbbe-3) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Add 0003-h264-idct4-daedalus-fourier.patch — H264DSPContext.idct_add
|
||||||
|
(per-block 4x4 IDCT, called from the intra-4x4 decode path in
|
||||||
|
libavcodec/h264_mb.c) now dispatches through
|
||||||
|
daedalus_recipe_dispatch_h264_idct4 instead of
|
||||||
|
ff_h264_idct_add_neon. First end-to-end exercise of the
|
||||||
|
daedalus-fourier kernel pack inside libavcodec.so on the
|
||||||
|
production decode hot path (daedalus-v4l2#11 step 2 — cycle 6
|
||||||
|
H.264 IDCT 4x4, NEON-by-recipe).
|
||||||
|
* build-deb.sh: fetches + builds daedalus-fourier (pinned at
|
||||||
|
d87239d, lockstep with the daemon's static link) with
|
||||||
|
-fPIC into a per-build temp prefix, then passes
|
||||||
|
--extra-cflags=-I.../include --extra-ldflags=-L.../lib
|
||||||
|
--extra-libs="-ldaedalus_core -lvulkan -lpthread" to FFmpeg
|
||||||
|
configure. Static-linked into libavcodec.so.62.
|
||||||
|
* Bulk paths (idct_add16 / idct_add16intra / idct_add8) remain on
|
||||||
|
the stock NEON .S code and will be batched through
|
||||||
|
daedalus_recipe_dispatch_h264_idct4 with n_blocks>1 in a
|
||||||
|
follow-up. Cycles 7/8/9 (IDCT 8x8 / luma-v deblock / qpel mc20)
|
||||||
|
land in subsequent patches.
|
||||||
|
* Depends gains libvulkan1 — daedalus_core PUBLIC-links Vulkan
|
||||||
|
(queryable QPU substrate); the no-QPU constructor still works,
|
||||||
|
but the loader refuses libavcodec.so.62 at dlopen time without
|
||||||
|
libvulkan.so.1 present.
|
||||||
|
* No ABI change; SONAMEs stay 62/62/60.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Thu, 21 May 2026 20:00:00 +0000
|
||||||
|
|
||||||
|
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
|
||||||
@@ -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.
|
||||||
@@ -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'.
|
||||||
+111
@@ -0,0 +1,111 @@
|
|||||||
|
#!/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. c454618 = PR #16 merge "picture,
|
||||||
|
# request_pool: transparent OUTPUT-pool resize on bitstream overrun
|
||||||
|
# (#15)" — follow-up root-cause fix to #13/#14. On a mid-stream
|
||||||
|
# bitstream-budget overrun (typical cause: SPS-driven resolution
|
||||||
|
# upshift in an adaptive-bitrate stream), codec_store_buffer now
|
||||||
|
# snapshots the in-flight surface's accumulated bytes, releases its
|
||||||
|
# OUTPUT pool slot, calls request_pool_resize (STREAMOFF →
|
||||||
|
# REQBUFS(0) → S_FMT with 2×sizeimage hint, capped at 1 GiB, page-
|
||||||
|
# aligned → CREATE_BUFS → mmap → media_request_alloc → STREAMON),
|
||||||
|
# re-acquires a slot, re-mirrors the surface's source_{data,size,
|
||||||
|
# request_fd}, restores the bytes, and continues. The frame
|
||||||
|
# survives instead of being dropped back to libavcodec for surface
|
||||||
|
# recreation. CAPTURE side untouched (per-queue V4L2 streaming
|
||||||
|
# independence).
|
||||||
|
#
|
||||||
|
# Prior pin (2860d75) = PR #14 merge — codec_store_buffer bounds-
|
||||||
|
# check floor (#13).
|
||||||
|
UPSTREAM_COMMIT=c454618ae11addce2e17b560f4deeacbed067d98
|
||||||
|
PKGVER=1.0.0+r390+gc454618
|
||||||
|
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 --connect-timeout 10 --max-time 600 --retry 3 --retry-delay 5 -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
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# ABI sanity check: the produced .so MUST export __vaDriverInit_1_<MINOR>
|
||||||
|
# matching the install target's libva runtime. Build is expected to run on
|
||||||
|
# a Debian trixie runner where <va/va.h>'s VA_MINOR is 22 — see
|
||||||
|
# .gitea/workflows/build.yml (runs-on: actrunner-debian-aarch64-bohr). If a future
|
||||||
|
# runner change lands the build on a host with a different libva-dev
|
||||||
|
# version, the produced symbol won't bind on the install target and ffmpeg/
|
||||||
|
# vainfo/firefox-vaapi will all fail with "has no function
|
||||||
|
# __vaDriverInit_1_0". Fail loud at build time instead of shipping a
|
||||||
|
# silently-broken .deb (which is what happened in -1).
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
SO=$(find build -name 'v4l2_request_drv_video.so' | head -1)
|
||||||
|
if ! nm -D --defined-only "$SO" | grep -q '__vaDriverInit_1_22'; then
|
||||||
|
echo "FATAL: built driver does not export __vaDriverInit_1_22."
|
||||||
|
echo " Build host's <va/va.h> VA_MINOR_VERSION is likely != 22."
|
||||||
|
echo " Expected runner: actrunner-debian-aarch64-bohr (trixie, libva 2.22)."
|
||||||
|
echo " Symbol exports found:"
|
||||||
|
nm -D --defined-only "$SO" | grep -i vadriverinit || echo " (none)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "ABI check: $SO exports __vaDriverInit_1_22 (matches trixie libva 2.22)"
|
||||||
|
|
||||||
|
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"
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
libva-v4l2-request-fourier (1.0.0+r380+g9898331-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to 9898331 — LIBVA-2 close. Adds video_fd_daedalus to
|
||||||
|
any_fd_supports_output_format's probe list in config.c so the
|
||||||
|
profile enumerator actually sees daedalus_v4l2's OUTPUT formats
|
||||||
|
(VP9F + AV1F + S264). Before this commit, ffmpeg vaapi against
|
||||||
|
H.264 on higgs bailed with "No support for codec h264 profile 578"
|
||||||
|
because RequestQueryConfigProfiles only walked rkvdec/hantro/
|
||||||
|
rpi-hevc-dec/vpu981 fds and never asked daedalus what it could do.
|
||||||
|
* Backward-compatible on RK3399/3588 — new slot gated by
|
||||||
|
HAVE_DAEDALUS_V4L2 *and* video_fd_daedalus >= 0; both false in
|
||||||
|
those deployments.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 19:30:00 +0000
|
||||||
|
|
||||||
|
libva-v4l2-request-fourier (1.0.0+r378+gc332d34-2) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Rebuild on a native Debian trixie runner (actrunner-debian-aarch64-bohr) so
|
||||||
|
the driver picks up trixie's libva-dev (2.22) and exports
|
||||||
|
__vaDriverInit_1_22 — the symbol trixie's libva runtime looks up.
|
||||||
|
Previous -1 build used the Arch CI runner (libva 2.23.0) and
|
||||||
|
exported __vaDriverInit_1_23, which trixie's loader cannot bind:
|
||||||
|
vaInitialize() returns -1 ("has no function __vaDriverInit_1_0")
|
||||||
|
and ffmpeg -hwaccel vaapi fails on startup.
|
||||||
|
* No source change; pure build-env fix. CI workflow's
|
||||||
|
libva-v4l2-request-fourier-debian job moved from runs-on:
|
||||||
|
arch-aarch64 to runs-on: actrunner-debian-aarch64-bohr; build-deps installed
|
||||||
|
via apt-get instead of pacman.
|
||||||
|
* Hard sanity check kept in build-deb.sh: build fails if the
|
||||||
|
resulting .so doesn't export __vaDriverInit_1_22 (preempts the
|
||||||
|
silent install-then-refuse-to-load failure mode).
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 18:00:00 +0000
|
||||||
|
|
||||||
|
libva-v4l2-request-fourier (1.0.0+r378+gc332d34-1) bookworm trixie; urgency=medium
|
||||||
|
|
||||||
|
* Bump to c332d34 — LIBVA-1 per-codec dispatch close. Pi 5 mixed
|
||||||
|
deployment (rpi-hevc-dec + daedalus_v4l2 both loaded) now correctly
|
||||||
|
opens BOTH decoders: VP9/AV1/H.264 route to daedalus via new 'd'
|
||||||
|
kind, HEVC stays on 'p' (rpi-hevc-dec). Before this commit
|
||||||
|
find_codec_device picked rpi-hevc-dec as the sole primary and the
|
||||||
|
daedalus_v4l2 slot stayed -1, so VP9/AV1/H.264 frames failed.
|
||||||
|
* Also closes a small fd leak in RequestTerminate (daedalus pair).
|
||||||
|
* Backward-compatible: new branches gated by HAVE_DAEDALUS_V4L2
|
||||||
|
*and* video_fd_daedalus >= 0 — RK3399/RK3588 boxes unaffected.
|
||||||
|
|
||||||
|
-- Markus Fritsche <mfritsche@reauktion.de> Wed, 20 May 2026 17:30:00 +0000
|
||||||
|
|
||||||
|
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
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
Vendored
+4
-3
@@ -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 --connect-timeout 10 --max-time 600 --retry 3 --retry-delay 5 -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
|
||||||
|
|
||||||
|
|||||||
Vendored
+80
@@ -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
|
||||||
|
|||||||
+56
@@ -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
|
||||||
|
|
||||||
+81
@@ -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
|
||||||
+435
@@ -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
@@ -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 --connect-timeout 10 --max-time 600 --retry 3 --retry-delay 5 -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"
|
||||||
Vendored
+12
@@ -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
|
||||||
Vendored
+70
@@ -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.
|
||||||
Vendored
+25
@@ -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'.
|
||||||
Reference in New Issue
Block a user