# 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.r9
pkgrel=1
pkgdesc="Patched Mesa libvulkan_panfrost.so exposing Bifrost-gen Mali to Vulkan apps (panvk-bifrost campaign)"
arch=('aarch64')
url="https://git.reauktion.de/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"
    "0005-panvk-bifrost-fragment-stores-atomics.patch"
    "0006-panvk-bifrost-legacy-dithering.patch"
    "0007-panvk-bifrost-xfb-component-base-fix.patch"
    "0008-panvk-bifrost-bump-max-image-dim-3d-for-dawn.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'
    '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"

    # r5 (2026-05-23): advertise .fragmentStoresAndAtomics = true on Bifrost
    # to satisfy Chromium Dawn's WebGPU init gate
    # (third_party/dawn/src/dawn/native/vulkan/PhysicalDeviceVk.cpp:250).
    # Backports Mesa main's unconditional flip (same line as on main as of
    # 2026-05-06). Disjunction with instance->force_enable_shader_atomics
    # is preserved as a documented kill-switch even though the compiler
    # folds it away. Closes marfrit/panvk-bifrost#2.
    # Verify-before-ship: dEQP-VK.glsl.atomic_operations.* and
    # dEQP-VK.image.store.* show no new Failed vs r4 baseline.
    patch -p1 < "${srcdir}/0005-panvk-bifrost-fragment-stores-atomics.patch"

    # r6 (2026-05-25): advertise VK_EXT_legacy_dithering. Backports Mesa
    # main's unconditional flip. Pure-software composition; vk_render_pass
    # already gates on enabled_features.legacyDithering and panvk_vX_blend
    # + pan_format already plumb the dithered BLEND descriptor (BFMT2 table
    # has MALI_BLEND_AU encodings for RGB565/RGB5A1/RGBA4/RGB10A2 on
    # PAN_ARCH 7). Closes the EXT_legacy_dithering gap surfaced by
    # marfrit/panvk-bifrost research/r6_r7_*. ARM blob r51p0 confirms the
    # extension as Mali-G52-architecture supported.
    patch -p1 < "${srcdir}/0006-panvk-bifrost-legacy-dithering.patch"

    # r7 (2026-05-25): XFB store channel-extract fix for packed varyings.
    # Eliminates a reliable SIGSEGV in vkCreateGraphicsPipeline whenever
    # an XFB-bound vertex output is declared with non-zero
    # `layout (component=N)`. Surfaced by dEQP-VK.transform_feedback.
    # simple.holes_vert (now Fails on color-check rather than crashing;
    # the color-check residual is a separate iter20 finding).
    # Phase-doc context: ~/src/panvk-bifrost/iter19/phase{0,1,2,3}_*.md.
    # Phase 5 reviewed; release-mode-elision defensive guards applied.
    patch -p1 < "${srcdir}/0007-panvk-bifrost-xfb-component-base-fix.patch"

    # r9 (2026-05-25): bump maxImageDimension3D from 512 to 2048 on Bifrost,
    # unblocking Dawn/WebGPU adapter acceptance for Brave's GPU process. Was
    # under WebGPU's 2048 minimum (dawn PhysicalDeviceVk.cpp:746). Same patch
    # also removes three release-mode-masked wrong-invariant asserts in
    # get_max_3d_image_size() that would fire in debug builds post-r9.
    # Phase-doc context: ~/src/panvk-bifrost/iter22/phase0to2_max3d_close.md.
    patch -p1 < "${srcdir}/0008-panvk-bifrost-bump-max-image-dim-3d-for-dawn.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
    # r5 sanity: fragmentStoresAndAtomics = true patch landed
    grep -q "fragmentStoresAndAtomics = true ||" src/panfrost/vulkan/panvk_vX_physical_device.c
    # r6 sanity: VK_EXT_legacy_dithering advertised
    grep -q '\.EXT_legacy_dithering = true,' src/panfrost/vulkan/panvk_vX_physical_device.c
    grep -q '\.legacyDithering = true,' src/panfrost/vulkan/panvk_vX_physical_device.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
    # r7 sanity: XFB channel-base correction landed
    grep -q "iter19: nir_intrinsic_component(intr) is the source-channel base" src/panfrost/vulkan/panvk_vX_xfb_lower.c
    grep -q "mask << src_channel" src/panfrost/vulkan/panvk_vX_xfb_lower.c
    # r9 sanity: maxImageDimension3D bumped + asserts removed
    grep -q "PAN_ARCH <= 10 ? (1 << 11) : (1 << 14)" src/panfrost/vulkan/panvk_vX_physical_device.c
    ! grep -q "assert(ret\.width >= phys_dev->vk\.properties\.maxImageDimension3D)" src/panfrost/vulkan/panvk_physical_device.c
}

build() {
    cd "mesa-${_mesaver}"
    # Minimal Mesa build — only the panvk Vulkan driver. No GLES/GLX/EGL/
    # gallium drivers — keeps the build narrower and avoids pulling in
    # the entire Mesa runtime in this package's dep graph.
    meson setup build/ \
        --prefix=/usr \
        --libdir=lib \
        --buildtype=release \
        -Dvulkan-drivers=panfrost \
        -Dgallium-drivers= \
        -Dplatforms=wayland,x11 \
        -Dglx=disabled \
        -Degl=disabled \
        -Dgles1=disabled \
        -Dgles2=disabled \
        -Dvulkan-layers= \
        -Dtools= \
        -Dgallium-rusticl=false \
        -Dmicrosoft-clc=disabled
    meson compile -C build
}

package() {
    cd "${srcdir}/mesa-${_mesaver}"

    # Patched lib — co-install path, NOT /usr/lib (to avoid clashing
    # with stock mesa's libvulkan_panfrost.so).
    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"
}
