Hello to everyone.
This report documents the complete process of cross-compiling Chromium 146.0.7680.177 for FreeBSD 15.0 AArch64 patching it with the default patches but then patching the remaining code manually,error after error with the goal to compile the code with ninja to speed up the process of about the 20% ,skipping the use of a VM. The target is the Radxa Zero 3W single-board computer (Rockchip RK3566 SoC), with full hardware-accelerated video decode via the Hantro G1 VPU using VA-API. The build host is an x86_64 FreeBSD 14.3 machine running inside a ZFS environment.
If you find this work useful,it makes me happy and feel free to ask.
The end result is a fully working Chromium build with:
- Hardware-accelerated GPU compositing, Canvas, WebGL, WebGPU (via Panfrost/DRM)
- Hardware-accelerated H.264 video decode (via VA-API → Hantro VPU → /dev/dri/renderD128)
---
Hardware and Software
---
1. Build Configuration (args.gn)
The complete args.gn for cross-compiling from x86_64 FreeBSD to AArch64 FreeBSD:
Critical note: use_v4l2_codec and use_vaapi are mutually exclusive in Chromium's build system (media/gpu/BUILD.gn asserts !(use_v4l2_codec && use_vaapi)). Also, use_vaapi defaults to false for non-Linux and for ARM targets — it must be explicitly set to true in args.gn.
---
2. Sysroot: VA-API Stub Libraries
The cross-compilation sysroot needs link-time stubs for libva, libva-drm, and libva-x11. These are empty shared libraries that satisfy the linker — the real libraries live on the target device.
Copy VA headers from the target Radxa:
# On the target
# pkg.conf files
Build ARM64 stub .so files on the build host:
---
3. Launch Flags
The following flags are required at runtime:
Flag: LIBVA_DRIVER_NAME=hantro
Why it is needed: Tells libva to load hantro_drv_video.so instead of auto-detecting
────────────────────────────────────────
Flag: --ignore-gpu-blocklist
Why it is needed: Chrome's GPU blocklist disables acceleration for unknown/untested GPUs; Panfrost is not on the allowlist
────────────────────────────────────────
Flag: --disable-features=FallbackToSWIfGLES3NotSupported
Why it is needed: Panfrost exposes OpenGL 3.1, not 4.x. ANGLE cannot initialise GLES3. Without this flag,Chrome falls back to software rendering entirely instead of allowing a GLES2 fallback
────────────────────────────────────────
Flag: --enable-features=AcceleratedVideoDecoder
Why it is needed: The VA-API video decode feature is named "AcceleratedVideoDecoder" in media/base/media_switches.cc, not "VaapiVideoDecoder". It defaults to disabled when USE_VAAPI=0 at compile time; our build has USE_VAAPI=1 but the flag is still needed to override the default for FreeBSD
────────────────────────────────────────
Flag: --enable-features=VaapiIgnoreDriverChecks
Why it is needed: Skips Chrome's internal VA-API driver version/vendor checks
────────────────────────────────────────
Flag: --enable-accelerated-video-decode
Why it is needed: Legacy command-line switch, kept for compatibility
---
4. Verification
After launching Chrome with the flags above:
chrome://gpu shows :
Video Decode: Hardware accelerated
During H.264 video playback, the Hantro VPU accesses the DRM render node:
---
5. What Does NOT Work (yet)
- Hardware video encode: hantro_drv_video.so v0.1 does not implement VA-API encode entrypoints. Encode remains software-only.
- Vulkan: LLVMpipe Vulkan does not work with Chrome's ANGLE Vulkan renderer on this platform.
- WebRTC hardware encode: Same limitation as video encode above.
---
6. Files Changed (summary for patch submission)
The first two patches address general FreeBSD ARM64 portability issues unrelated to VA-API and would benefit any Chromium build on ARM SoCs. Patches 3 and 4 are specific to VA-API on drivers (like Hantro) that do not fully implement the VA-API surface attribute query interface.
---
Tested on: Radxa Zero 3W (RK3566), FreeBSD 15.0-CURRENT AArch64, Chromium 146.0.7680.177, April 2026.
---
Patches and this report may be submitted to :
- FreeBSD ports tree: www/chromium maintainer
- FreeBSD forums: https://forums.freebsd.org
- FreeBSD Phabricator / GitHub mirror for patch review
This report documents the complete process of cross-compiling Chromium 146.0.7680.177 for FreeBSD 15.0 AArch64 patching it with the default patches but then patching the remaining code manually,error after error with the goal to compile the code with ninja to speed up the process of about the 20% ,skipping the use of a VM. The target is the Radxa Zero 3W single-board computer (Rockchip RK3566 SoC), with full hardware-accelerated video decode via the Hantro G1 VPU using VA-API. The build host is an x86_64 FreeBSD 14.3 machine running inside a ZFS environment.
If you find this work useful,it makes me happy and feel free to ask.
The end result is a fully working Chromium build with:
- Hardware-accelerated GPU compositing, Canvas, WebGL, WebGPU (via Panfrost/DRM)
- Hardware-accelerated H.264 video decode (via VA-API → Hantro VPU → /dev/dri/renderD128)
---
Hardware and Software
Code:
┌──────────────────┬──────────────────────────────────────────────────────┐
│ Component │ Detail │
├──────────────────┼──────────────────────────────────────────────────────┤
│ Target board │ Radxa Zero 3W (Rockchip RK3566) │
├──────────────────┼──────────────────────────────────────────────────────┤
│ Target OS │ FreeBSD 15.0-CURRENT AArch64 │
├──────────────────┼──────────────────────────────────────────────────────┤
│ Build host │ FreeBSD 14.x x86_64 (Linuxulator) │
├──────────────────┼──────────────────────────────────────────────────────┤
│ Chromium version │ 146.0.7680.177 │
├──────────────────┼──────────────────────────────────────────────────────┤
│ Compiler │ Clang/LLVM 19 (cross, aarch64-unknown-freebsd15.0) │
├──────────────────┼──────────────────────────────────────────────────────┤
│ Rust │ 1.92 (cross, custom sysroot with real aarch64 rlibs) │
├──────────────────┼──────────────────────────────────────────────────────┤
│ GPU driver │ Panfrost (DRM/KMS, OpenGL 3.1) │
├──────────────────┼──────────────────────────────────────────────────────┤
│ Video decode │ Hantro G1 VPU via hantro_drv_video.so (VA-API) │
└──────────────────┴──────────────────────────────────────────────────────┘
---
1. Build Configuration (args.gn)
The complete args.gn for cross-compiling from x86_64 FreeBSD to AArch64 FreeBSD:
Code:
target_os = "freebsd"
target_cpu = "arm64"
host_os = "freebsd"
host_cpu = "x64"
is_clang = true
clang_use_chrome_plugins = false
use_lld = true
is_debug = false
custom_toolchain = "//build/toolchain/freebsd:clang_arm64"
use_sysroot = false
target_sysroot = "/path/to/aarch64-sysroot"
clang_base_path = "/usr/local/llvm19"
clang_version = "19"
cc_wrapper = "ccache"
enable_backup_ref_ptr_support = false
fatal_linker_warnings = false
icu_use_data_file = false
optimize_webui = true
toolkit_views = true
treat_warnings_as_errors = false
use_allocator_shim = false
use_aura = true
use_custom_libcxx = true
use_custom_libunwind = true
use_partition_alloc = true
use_partition_alloc_as_malloc = false
use_system_harfbuzz = true
use_system_libffi = true
use_system_libjpeg = true
use_udev = false
use_dbus = true
use_gio = true
enable_rust = true
rust_sysroot_absolute = "/path/to/rust-arm64-sysroot"
added_rust_stdlib_libs = [ "adler2", "rustc_literal_escaper" ]
removed_rust_stdlib_libs = [ "adler" ]
proprietary_codecs = true
ffmpeg_branding = "Chrome"
enable_av1_decoder = true
enable_dav1d_decoder = true
use_v4l2_codec = false # must be false when use_vaapi = true
use_vaapi = true # enable VA-API for hardware video decode
enable_widevine = true
use_ozone = true
ozone_platform_x11 = true
ozone_platform_wayland = true
enable_webrtc = true
enable_pdf = true
enable_print_preview = true
use_cups = true
enable_extensions = true
enable_hangout_services_extension = true
use_pangocairo = true
use_pulseaudio = true
use_sndio = false
rtc_use_pipewire = false
use_qt5 = false
use_qt6 = false
arm_control_flow_integrity = "none"
concurrent_links = 2
symbol_level = 1
blink_symbol_level = 0
is_component_build = false
Critical note: use_v4l2_codec and use_vaapi are mutually exclusive in Chromium's build system (media/gpu/BUILD.gn asserts !(use_v4l2_codec && use_vaapi)). Also, use_vaapi defaults to false for non-Linux and for ARM targets — it must be explicitly set to true in args.gn.
---
2. Sysroot: VA-API Stub Libraries
The cross-compilation sysroot needs link-time stubs for libva, libva-drm, and libva-x11. These are empty shared libraries that satisfy the linker — the real libraries live on the target device.
Copy VA headers from the target Radxa:
# On the target
Code:
scp -r /usr/local/include/va/ buildhost:/path/to/aarch64-sysroot/usr/local/include/
# pkg.conf files
Code:
scp /usr/local/libdata/pkgconfig/libva*.pc buildhost:/path/to/aarch64-sysroot/usr/local/libdata/pkgconfig/
Build ARM64 stub .so files on the build host:
Code:
CC=/usr/local/bin/clang
TRIPLE=aarch64-unknown-freebsd15.0
SYSROOT=/path/to/aarch64-sysroot
# libva stub — list all symbols from the real libva.so.2 on your target:
# nm -D /usr/local/lib/libva.so.2 | awk '$2=="T"{print "void "$3"(void) {}"}' > libva_stub.c
$CC --target=$TRIPLE --sysroot=$SYSROOT -shared -fPIC -o $SYSROOT/usr/local/lib/libva.so libva_stub.c
# libva-drm stub
echo 'void vaGetDisplayDRM(void) {}' > libva_drm_stub.c
$CC --target=$TRIPLE --sysroot=$SYSROOT -shared -fPIC -o $SYSROOT/usr/local/lib/libva-drm.so
libva_drm_stub.c
# libva-x11 stub — include vaGetDisplay, vaPutSurface, VA_DRI2* symbols
$CC --target=$TRIPLE --sysroot=$SYSROOT -shared -fPIC -o $SYSROOT/usr/local/lib/libva-x11.so
libva_x11_stub.c
# Symlink pkgconfig
ln -s /usr/local/libdata/pkgconfig/libva.pc $SYSROOT/usr/local/lib/pkgconfig/libva.pc
# (repeat for libva-drm.pc and libva-x11.pc)
---
3. Launch Flags
The following flags are required at runtime:
Code:
DISPLAY=:0 LIBVA_DRIVER_NAME=hantro /path/to/chrome \
--no-sandbox \
--ignore-gpu-blocklist \
--disable-features=FallbackToSWIfGLES3NotSupported \
--enable-features=AcceleratedVideoDecoder,VaapiIgnoreDriverChecks \
--enable-accelerated-video-decode
Flag: LIBVA_DRIVER_NAME=hantro
Why it is needed: Tells libva to load hantro_drv_video.so instead of auto-detecting
────────────────────────────────────────
Flag: --ignore-gpu-blocklist
Why it is needed: Chrome's GPU blocklist disables acceleration for unknown/untested GPUs; Panfrost is not on the allowlist
────────────────────────────────────────
Flag: --disable-features=FallbackToSWIfGLES3NotSupported
Why it is needed: Panfrost exposes OpenGL 3.1, not 4.x. ANGLE cannot initialise GLES3. Without this flag,Chrome falls back to software rendering entirely instead of allowing a GLES2 fallback
────────────────────────────────────────
Flag: --enable-features=AcceleratedVideoDecoder
Why it is needed: The VA-API video decode feature is named "AcceleratedVideoDecoder" in media/base/media_switches.cc, not "VaapiVideoDecoder". It defaults to disabled when USE_VAAPI=0 at compile time; our build has USE_VAAPI=1 but the flag is still needed to override the default for FreeBSD
────────────────────────────────────────
Flag: --enable-features=VaapiIgnoreDriverChecks
Why it is needed: Skips Chrome's internal VA-API driver version/vendor checks
────────────────────────────────────────
Flag: --enable-accelerated-video-decode
Why it is needed: Legacy command-line switch, kept for compatibility
---
4. Verification
After launching Chrome with the flags above:
chrome://gpu shows :
Video Decode: Hardware accelerated
During H.264 video playback, the Hantro VPU accesses the DRM render node:
Code:
fstat | grep -E 'hantro|dri|video'
# Expected output:
# chrome <pid> <fd> /dev 112 crw-rw---- dri/renderD128 rw
hantro_drv_video.so uses /dev/dri/renderD128 (the DRM render node), not /dev/hantro0 directly.
---
5. What Does NOT Work (yet)
- Hardware video encode: hantro_drv_video.so v0.1 does not implement VA-API encode entrypoints. Encode remains software-only.
- Vulkan: LLVMpipe Vulkan does not work with Chrome's ANGLE Vulkan renderer on this platform.
- WebRTC hardware encode: Same limitation as video encode above.
---
6. Files Changed (summary for patch submission)
Code:
┌──────────────────────────────────────────────────────────┬───────────────────────────────────────────┐
│ File │ Change │
├──────────────────────────────────────────────────────────┼───────────────────────────────────────────┤
│ out/freebsd-arm64/args.gn │ use_vaapi=true, use_v4l2_codec=false │
├──────────────────────────────────────────────────────────┼───────────────────────────────────────────┤
│ third_party/angle/src/gpu_info_util/SystemInfo_linux.cpp │ Placeholder GPU entry for ARM SoCs with │
│ │ no PCI bus │
├──────────────────────────────────────────────────────────┼───────────────────────────────────────────┤
│ media/gpu/vaapi/vaapi_jpeg_encoder.cc │ Replace 4 static_assert with DCHECK for │
│ │ Clang 19 compatibility │
├──────────────────────────────────────────────────────────┼───────────────────────────────────────────┤
│ media/gpu/vaapi/vaapi_wrapper.cc │ Fallback max resolution when VA-API │
│ │ driver returns none │
└──────────────────────────────────────────────────────────┴───────────────────────────────────────────┘
The first two patches address general FreeBSD ARM64 portability issues unrelated to VA-API and would benefit any Chromium build on ARM SoCs. Patches 3 and 4 are specific to VA-API on drivers (like Hantro) that do not fully implement the VA-API surface attribute query interface.
---
Tested on: Radxa Zero 3W (RK3566), FreeBSD 15.0-CURRENT AArch64, Chromium 146.0.7680.177, April 2026.
---
Patches and this report may be submitted to :
- FreeBSD ports tree: www/chromium maintainer
- FreeBSD forums: https://forums.freebsd.org
- FreeBSD Phabricator / GitHub mirror for patch review