GPU driver
The two GPU stacks in the image, which one boots, and how to change it
The image has two ways to drive the Mali-G31: the ARM binary driver (libmali in user space, mali_kbase in the kernel) and Mesa 26.1.3 with the Panfrost Gallium driver. Both are built and installed, and only one is active at a time.
The system boots libmali. That is the current default, not Panfrost.
Why libmali is the default right now
gpu.driver defaults to libmali on a fresh install. Switching is guarded: the gpudriver script writes a sentinel (/storage/.config/gpudriver.attempting) before loading the new driver and can force libmali on the boot after a crash. It loads the module asynchronously so a blocked probe cannot hang the boot, and tries the other driver when the requested one does not attach to the GPU.
Changing the driver
In archr-launcher, open Settings › System › GPU driver and choose libmali or panfrost. The row says Requires reboot to apply, and the launcher offers to reboot right away.
You can also change it over SSH by editing /storage/.config/system/configs/system.cfg:
gpu.driver=panfrostThen reboot. Set it back to libmali the same way. There is nothing else to change: the boot script reads that one key.
What happens at boot
An autostart hook runs /usr/bin/gpudriver --start, which:
- Reads
gpu.driver, defaulting tolibmaliwhen it is empty. - Loads the matching kernel module,
mali_kbaseorpanfrost. - Bind-mounts the matching user-space GL libraries into place. For libmali that means
/usr/lib/mali/*over Mesa'slibEGL.so,libGLESv2.soand friends, plus/dev/nulloverlibGL.soso nothing picks up Mesa by accident. For Panfrost it unmounts all of that so Mesa is visible again. - Checks that the driver really attached: a DRM card exists, the driver-specific node is there (
/sys/bus/platform/drivers/panfrost/*.gpuor/dev/mali0), and at least one connector readsconnected. - If the selected driver fails that check, the script tries the other one and saves it as the new
gpu.driveronly if it passes. Recovery is not guaranteed: if both fail, the system runs with software rendering.
Everything it does is logged to /storage/.config/gpudriver.log, which survives reboots. When Panfrost is selected it also drops the kernel messages from around the probe next to it.
Boot-loop protection
Before touching the driver, the script writes the driver name to /storage/.config/gpudriver.attempting with a synchronous write, and removes it once the driver is up. If that file is still there on the next boot, the previous attempt crashed the board before it could recover. A leftover sentinel forces libmali and rewrites the setting only when the configured driver still matches the failed non-libmali attempt. This stops a bad Panfrost probe from turning into an endless reboot cycle.
Differences that matter
| libmali | Panfrost | |
|---|---|---|
| Source | ARM binary driver, version g24p0 for the G31 | Mesa 26.1.3, open source |
| Kernel side | mali_kbase, out of tree | panfrost, in the mainline kernel |
| API | OpenGL ES | OpenGL and OpenGL ES |
| Vulkan | not on this board | not on this board |
| Updates | whatever the vendor drop contains | follows Mesa releases |
No Vulkan driver is built for RK3326 either way. Mesa is configured with an empty -Dvulkan-drivers=, and the libmali package only installs Vulkan libraries on other SoCs. Emulators that probe for Vulkan here will not find it and fall back to GLES.
Mesa tuning
/etc/profile.d/041-panfrost is sourced by /etc/profile, so these reach every emulator launched through runemu.sh and the start_*.sh scripts:
MESA_NO_ERROR=1 # emulators do not check glGetError
MESA_SHADER_CACHE_DIR=/var/cache/mesa
MESA_SHADER_CACHE_MAX_SIZE=128MB/var/cache/mesa is a symlink onto /storage/.cache/mesa_shader_cache, so the shader cache survives reboots.
PAN_MESA_DEBUG=forcepack is not set globally. runemu.sh enables forcepack only when the effective forcepack setting is On.
/etc/profile.d/mali-priority.sh sets MALI_SCHED_RT_THREAD_PRIORITY=95 for the libmali path.
Troubleshooting
Black screen after setting gpu.driver=panfrost. Power off, take the card out, mount the storage partition on a PC and set gpu.driver=libmali back. If the previous boot crashed while loading Panfrost, the sentinel may already have switched back to libmali.
You set panfrost but the system came up on libmali. Either the bind check failed and the fallback ran, or the boot-loop sentinel switched the setting back. /storage/.config/gpudriver.log says which of the three conditions (card, bind, display) was not met, with the relevant dmesg lines under it.
Switching does not seem to take effect immediately. It cannot. Neither module can be unloaded safely while the other is running, so the change only applies on the next boot.