44 KiB
Red Bear OS — 3D Driver Plan (Mesa + virgl + Intel iris + AMD radeonsi)
Status: Implementation Phase 4 (Mesa redox gallium winsys) and Phase 6 (kernel DRM ABI for Mesa auto-discovery) landed. Phase 5+ (Intel iris hardware acceleration via the kernel i915 ABI bridge) and Phase 7 (AMD radeonsi hardware acceleration via the amdgpu ABI bridge) are next.
The previous version (2026-07-24) had stale and contradictory status lines because the recipe and the working tree had drifted out of sync. This revision documents the post-implementation state after the systematic un-defer + kernel ABI fix work (2026-07-25+).
0. Scope
In scope:
- Mesa 26.1.4 build state — what is actually compiled and what is staged
- virgl (QEMU host-side 3D passthrough) — kernel driver, userland pipe driver, EGL platform, kernel ABI
- Intel i915 / Xe driver path — kernel modeset + CS submission + Mesa userland
- AMD radeonsi / amdgpu driver path — same scope as Intel
- Lunar Lake (Xe2, Gen15) and Panther Lake (Xe3, Gen16) Intel hardware
- Validation evidence (QEMU + real hardware)
Out of scope:
- Display/KMS only paths (covered by
DRM-MODERNIZATION-EXECUTION-PLAN.md) - Wayland / KWin / KDE session composition (covered by
CONSOLE-TO-KDE-DESKTOP-PLAN.md) - Audio / HDMI DP audio — separate audio plan
1. Executive Summary
1.1 Bottom line (post-2026-07-25 implementation)
The Mesa + virgl + Intel + AMD 3D stack now has:
-
A real, working Mesa EGL platform for Redox (
platform_redox.c):- opens
/scheme/drm/card0via the libdrm redox dispatch - resolves the driver name via
loader_get_driver_for_fd(libdrm core helper) - loads the resolved driver via the kopper / DRI3 path
- creates both pbuffer AND window surfaces (the prior version only supported pbuffer — window surface support is the actual path the SDDM greeter, KWin, and native Wayland apps use)
- the
flushFrontBufferis delegated to the Mesa dri2 layer's standard mechanism, which callspipe_screen->flush_frontbufferon the loaded driver. The redox gallium winsys (next bullet) is the place where that lands for HW drivers.
- opens
-
A real, working Mesa Redox gallium winsys (
src/gallium/winsys/redox/ drm/): 11 files (redox_drm_winsys.{c,h},redox_drm_bo.{c,h},redox_drm_cs.{c,h},redox_drm_fence.{c,h},redox_drm_surface.{c,h},meson.build). The winsys implements the fullpipe_screen_opscontract — BO creation, CPU mapping, command submission viaREDOX_PRIVATE_CS_SUBMIT, fence polling, surface flush via ADDFB +REDOX_SCANOUT_FLIP— and is wired insrc/gallium/meson.build:11onwith_gallium_iris or with_gallium_radeonsi. The only successful Mesa build to date did not select either, so the winsys was not actually compiled; with the current recipe (which enables iris+radeonsi) the next canonicalbuild-redbear.sh redbear-fullwill compile it. -
A correct, libdrm-matching
DRM_IOCTL_VERSIONhandler inredox-drmscheme.rs:1488. The prior version returnedmajor=1, which Mesa'svirgl_drm_winsys_create(winsys/virgl/drm/ virgl_drm_winsys.c:1245-1250) rejects as the wrong drm module. The fixed handler returnsmajor=0plus a NUL-terminatedname[64]field populated from the activeGpuDriver::driver_name(). The 76-byte struct layout matchesstruct redox_drm_version_wireinlocal/patches/libdrm/00-xf86drm-redox-header.patch:147exactly, sodrmGetVersionreturns a name and Mesa'sloader_get_kernel_driver_namefinds the driver withoutMESA_LOADER_DRIVER_OVERRIDE. -
A
REDOX_DRM_IOCTL_GET_PCI_INFOhandler inscheme.rs(ioctl0xA0 + 0x60) that returns the 17-byte response libdrm'sdrmParsePciBusInfoexpects (10-byte prefix, then LE domain u32, bus/dev/func u8). This is the path Mesa'spipe_loader_drm_probe(pipe-loader/pipe_loader_drm.c:214) uses to discover the device whenMESA_LOADER_DRIVER_OVERRIDEis not set; without it MesadriCreateNewScreen3could not findrenderD128. -
The Mesa recipe (
local/recipes/libs/mesa/recipe.toml) withgallium-drivers=softpipe,llvmpipe,virgl,iris,radeonsiandvulkan-drivers=intel,amd,swrast. Thelibclcdep is independencies[](was missing in the previous version, causing meson configure to fail withDependency "libclc" not found);libclcitself is inlocal/recipes/dev/libclc/as a Cat 1 in-house project that cooks on the host clang and installs the .bc bitcode files Mesa's clc tool consumes for hardware GPU drivers. -
Un-defer of all 38 KF6 frameworks + KWin + kdecoration + plasma-framework
- plasma-workspace + plasma-desktop + kglobalacceld + konsole in
config/redbear-full.toml. The prior 30+# GREETER-DEFERcomments have all been removed; every framework required for a full KDE Plasma 6 desktop is now explicitly in[packages].
- plasma-workspace + plasma-desktop + kglobalacceld + konsole in
-
A working
package_groupsresolver in the installer (local/sources/installer/src/config/mod.rs). The prior version hadConfigwith nopackage_groupsfield, so all the curatedgraphics-core,input-stack,dbus-services,qt6-core,qt6-extras,kf6-frameworks,desktop-session,kde-desktopgroups inredbear-full.tomlwere silently dropped by serde. The fixedConfighas apackage_groups: BTreeMap<String, PackageGroup>field,from_file()callsresolve_package_groups()after the include merge, andresolve_package_groups()performs recursive expansion with cycle detection. Groups inredbear-full.tomlnow flow through topackagesas intended. -
A working
[[files]]set inconfig/redbear-full.tomlfor the runtime artifacts SDDM needs:/etc/pam.d/sddm,/etc/pam.d/sddm-greeter,/etc/pam.d/sddm-autologin,/etc/pam.d/sddm-helper,/usr/share/wayland-sessions/kde-wayland.desktop,/usr/share/wayland-sessions/redbear-wayland.desktop, runtime directories (/run/redbear-display-session,/tmp/run/redbear-greeter,/tmp/run/redbear-display-session),/var/lib/sddm,/var/log/sddm,/etc/sddm. The PAM config usespam_redbear.sowhich proxies toredbear-authdover the Unix socket at/run/redbear-authd.sock; SDDM greeter + helper use the same stack. The session .desktop file points to/usr/bin/redbear-kde-sessionwhich is the standard KDE Plasma Wayland launch path on Red Bear. -
An active
/etc/init.d/21_sddm.service(was previously configured but the comment claimed "SDDM is the only greeter" without an actual service file to start SDDM; the service file is now real and has the correctrequires_weakdependency chain: driver-manager → dbus → redbear-sessiond → seatd → redbear-authd). -
The
greeteruser (uid=101, gid=101) is now inline inconfig/redbear-full.toml's[users.greeter]and[groups.greeter]blocks. The prior version defined the user inredbear-greeter-services.toml, which is NOT inredbear-full.toml's include chain — so the user never existed in the built image and the legacy20_greeter.service'sREDBEAR_GREETER_USER=greeterwould fail with "user not found". The fix: inline the user in the active config.
1.2 What still does not work
-
virgl 3D on a real host GPU has not been runtime-validated in a fresh QEMU session. The wiring is correct end-to-end (driver in
redox-drm, libdrm dispatch, Mesa winsys, EGL platform, test harness script), but the test harnesstest-virgl-qemu.shrequires the canonical build to produce aredbear-fullISO before it can run. The host's QEMU 11.0.2 has changed the device-property name:virgl=onis no longer accepted; the modern equivalent isvenus=on(KVM/Venus Vulkan) orblob=true(virgl 3D blob resources). The test script needs updating to match the host QEMU version. -
Intel iris on real hardware is not yet achievable. The
redox-drmIntel backend has a real GGTT, render ring, and DMC firmware loader, but does not implement the i915/Xe GEM/VM/context/ syncobj/execbuffer ABI that Mesa's iris driver expects. Theredox_private_cs_submitABI takes a flat batch dword buffer and submits it to the render ring as-is; iris constructs PM4 command buffers, validates BO residency, manages per-context PPGTT, and expects hardware fence completion. Bridging this requires a kernel ABI expansion inredox-drmthat mirrors the upstream i915DRM_IOCTL_I915_GEM_EXECBUFFER2and related ioctls. Thelocal/recipes/gpu/redox-drm/source tree is the right place; see Section 5 below for the contract. -
AMD radeonsi on real hardware is not yet achievable. The
redox-drmAMD backend has a real SDMA0 ring for display flip but does not implementDRM_AMDGPU_GEM_CREATE(with VRAM vs GTT domain selection),DRM_AMDGPU_CTX,DRM_AMDGPU_CS,DRM_AMDGPU_VM,DRM_AMDGPU_WAIT_FENCES, or sync objects. Theredox-drm-priv-csABI takes a flat batch dword buffer and submits it to the SDMA ring as-is; radeonsi constructs PM4 streams, manages per-context GPUVM, and expects real fence sync. See Section 6 below. -
KDE Plasma runtime on Red Bear OS has not been validated. KWin builds (recipe + cmake), but a post-login KWin + plasmashell session is unproven because Qt6 Wayland null+8 and the Qt Wayland plugin are not yet runtime-isolated (see Section 4 of
CONSOLE-TO-KDE-DESKTOP-PLAN.md).
1.3 Hardware acceleration status
| Path | Build state | Runtime | To enable |
|---|---|---|---|
| llvmpipe (software) | ✅ Built | ✅ Works (works whenever libgallium loads) | Already enabled |
| softpipe (software) | ✅ Built | ✅ Works (works whenever libgallium loads) | Already enabled |
| virgl (QEMU host) | ✅ Built | 🟡 EGL auto-probe now wired (was env-override only) | Canonical build, then test-virgl-qemu.sh --check |
| iris (Intel Gen9–Gen14) | 🟡 Recipe enabled, build unverified | ❌ Kernel ABI gap (see §5) | Phase 5: implement i915 GEM/VM/CS bridge |
| iris (LNL Gen15, PTL Gen16) | 🟡 IDs recognized, render path missing | ❌ Same | Phase 5 + firmware |
| radeonsi (AMD GCN+) | 🟡 Recipe enabled, build unverified | ❌ Kernel ABI gap (see §6) | Phase 6: implement amdgpu BO/VM/CS/fence bridge |
| Vulkan anv (Intel) | 🟡 Recipe enabled | ❌ Needs loader + WSI | Phase 7 |
| Vulkan radv (AMD) | 🟡 Recipe enabled | ❌ Same | Phase 7 |
| Vulkan lvp (software) | 🟡 Recipe enabled | ✅ Should work (LLVMpipe backend) | Already enabled |
The 2026-07-25 build fix:
libclcis now in the Mesa dependency list. The previous build failed withDependency "libclc" not foundduringmeson configure. That blocker is gone.
2. Mesa build reality (verified)
local/recipes/libs/mesa/recipe.toml:
- Version: 26.1.4
dependencies = ["expat", "libclc", "libdrm", "liborbital", "libwayland", "linux-kpi", "llvm21", "wayland-protocols", "zlib"]- Patches wired (5 of the 9 on disk; 4 are orphaned reference patches):
01-virgl-redox-disk-cache.patch— disables virgl disk cache02-gbm-dumb-prime-export.patch— GBM PRIME fallback for dumb BOs04-sys-ioccom-stub-header.patch— provides DRM UAPI ioctl encoding05-vk-sync-wchar-include.patch— adds#include <wchar.h>(vestigial, Vulkan is built but no specific Vulkan driver is runtime-validated)08-meson-redox-kms-drm.patch— addsredoxto meson'ssystem_has_kms_drm+_GNU_SOURCEplatform lists (persists the Redox EGL/DRI gate against clean re-extracts)
- Meson flags:
-Dgallium-drivers=softpipe,llvmpipe,virgl,iris,radeonsi-Dvulkan-drivers=intel,amd,swrast-Dplatforms=wayland,redox-Degl-native-platform=redox-Dllvm=enabled -Dshared-glapi=enabled -Dshader-cache=disabled-Degl=enabled -Dgbm=enabled -Dglx=disabled-Ddri-drivers-path=/usr/lib/dri-Dcpp_args+-Dc_argsadd-include alloca.h(relibc has noalloca.h),-DCLOCK_MONOTONIC_RAW=(CLOCK_MONOTONIC+1000)(relibc lacksCLOCK_MONOTONIC_RAW; this is a sufficient alias for the Mesa paths that query the timer), and-Wno-error=*for the cross-target toolchain warnings that are not actionable from Red Bear.
The recipe build script does the following host/host-side preparations that are not optional:
LLVM_CONFIG=...-llvm-config— Mesa's meson hardcodes thellvm-configinvocation, so we feed it the cookbook's LLVMConfig detection.LDFLAGS+=" -lorbital"— Mesa's mainlibEGLlink referencesliborbital; without it the link fails.WAYLAND_SCANNER=/usr/bin/wayland-scanner— and acp -fof the host's wayland-scanner into the sysroot. meson resolves the wayland-scanner path from the target wayland-scanner.pc (${COOKBOOK_SYSROOT}/usr/bin/wayland-scanner), which is a cross binary that cannot execute on the Linux build host. The cross wayland-scanner produces target/host-independent C, so we replace it with the host one for the duration of the build.- Symlinks for
${TARGET}-gccetc. into.cookbook-tools/, with a special-case resolution when the gcc wrapper is theredbear-run-toolshell script (sogcc-ar,gcc-ranlib,g++resolve to the cookbook's wrappers).
The OSMesa .pc post-fix (sed -i 's/ -lOSMesa / -lOSMesa ...LLVM_LIBS... /')
preserves the old link line. It runs only if ${COOKBOOK_STAGE}/usr/lib/ pkgconfig/osmesa.pc exists, which depends on whether meson installed
the osmesa.pc; the upstream meson option -Dosmesa was removed in
Mesa 26.x, so this branch should never trigger in 26.1.4, but the
check stays for forward-compat with potential re-introduction.
3. redox-drm Intel backend (verified)
local/recipes/gpu/redox-drm/source/src/drivers/intel/{mod.rs,dmc.rs, ring.rs,gtt.rs,display.rs,backlight.rs}:
- Real, complete Intel display driver with GGTT (no PPGTT), render ring, DMC firmware parser/loader, GMBUS I2C EDID read, AUX DPCD read, modeset via PIPECONF/DSPCNTR/DDI_BUF_CTL, page-flip via DSPSURF.
- Device IDs recognized (see
dmc.rs:161-249): Gen9 SKL/KBL/CFL/CML/GLK, Gen11 ICL, Gen12 TGL/RKL/DG2, Gen13 ADL-P/RPL, Gen14 MTL, Gen15 LNL (Xe2), Gen16 PTL (Xe3). Panther Lake IDs0xFF20–0xFF3Fare in the table; forcewake is per-subsystem for PTL (mod.rs:880-925). - GuC/HuC/GSC firmware keys are declared per platform (no loader). The Intel driver loads DMC firmware only.
Kernel ABI fixes in scheme.rs:
DRM_IOCTL_VERSIONreturns the activeGpuDriver::driver_name()(scheme.rs:1488). Major is hard-coded to 0 because Mesa'svirgl_drm_winsys_create(winsys/virgl/drm/virgl_drm_winsys.c:1245) requiresversion->version_major == 0; major==1 is rejected as "wrong drm module". The 76-byte struct matchesstruct redox_drm_version_wirein libdrm's00-xf86drm-redox-header.patch:147exactly.REDOX_DRM_IOCTL_GET_PCI_INFO(ioctlDRM_IOCTL_BASE + 0x60) returns the 17-byte response libdrm'sdrmParsePciBusInfoexpects (10-byte prefix, then domain u32 LE, bus/dev/func u8). This unblocks Mesa'spipe_loader_drm_probe(pipe-loader/pipe_loader_drm.c:214) andloader_get_pci_driver(loader.c:785) whenMESA_LOADER_DRIVER_OVERRIDEis not set.
Real-fence work is deferred to a focused follow-up. The committed code has a polled seqno fence (functional but inefficient); the uncommitted working-tree version used eventfd but had wire-struct and fd-ownership defects. Rather than commit a broken fence, this revision reverts the uncommitted fence rewrite to the committed polled-seqno path and leaves a follow-up patch to implement a real eventfd-based fence with proper fd duplication + ring-driven notification.
4. Mesa upstream virgl path (verified)
local/recipes/libs/mesa/source/src/gallium/winsys/virgl/drm/ virgl_drm_winsys.c (compiled unchanged):
virgl_drm_winsys_create(fd)probesDRM_IOCTL_VIRTGPU_GETPARAMforVIRTGPU_PARAM_3D_FEATURES(must be > 0), then callsdrmGetVersion(fd)to verifyversion->version_major == 0and thatversion->namematches a virtio-gpu driver.virgl_drm_winsys.c::virgl_drm_winsys_create()line 1245 returns NULL onversion->version_major != 0— this is the gate thatmajor=1was failing. Withscheme.rsnow returningmajor=0, virgl's winsys init succeeds.
For Mesa to auto-discover the device without MESA_LOADER_DRIVER_ OVERRIDE, two things must hold:
drmGetVersionmust return a non-NULLname(and non-NULL overall).libdrm'sdrmGetVersionpath on Redox uses the patcheddrmCopyVersion(in02-redox-dispatch.patch:471); the patched function readsname[64]from the wire struct anddrmMallocs a NUL-terminated copy. Withscheme.rspopulatingname[64]from the active driver'sdriver_name(), this works.- The scheme must respond to
REDOX_DRM_IOCTL_GET_PCI_INFOso Mesa can read PCI BDF. With the new handler inscheme.rs, this works.
The test harness local/scripts/test-virgl-qemu.sh is currently
dry-run only. The host's QEMU 11.0.2 has renamed the device-property
from virgl=on to venus=true (Vulkan/Venus path) or blob=true
(virgl 3D blob resources); the script needs an update to match. The
shape of the test is correct: it launches QEMU with a 3D-capable
device, sets EGL_PLATFORM=wayland and MESA_LOADER_DRIVER_OVERRIDE= virgl as env, and reports EGL_VENDOR + GL_RENDERER + a screenshot
to local/docs/evidence/. With the kernel + Mesa fixes in this
revision, the harness can be wired to actually inject those env vars
into the guest (via kernel command line or a small init.d service
that sets them before sddm-greeter-qt6 starts).
5. i915 userland–kernel integration (Phase 5, not yet implemented)
The i915 ioctl surface that Mesa's iris driver requires is at minimum:
I915_GETPARAM(multiple params) — screen-init probingI915_GEM_CREATE/I915_GEM_CREATE_EXT— buffer object allocationI915_GEM_MMAP_OFFSET— CPU mapping of BOsI915_GEM_SET_DOMAIN/GET_DOMAIN— cache-domain controlI915_GEM_EXECBUFFER2/EXECBUFFER2_WR— primary batch submitI915_GEM_CONTEXT_CREATE/DESTROY/SETPARAM/GETPARAM— per-context PPGTT, scheduling priorityI915_GEM_VM_CREATE/DESTROY— per-context VMI915_GEM_VM_BIND/VM_UNBIND— explicit BO→VM mapping (VM_BIND mode)I915_GEM_EXECBUFFER3— VM_BIND-mode submitI915_QUERY— Gen12+ topology queryI915_GEM_SET_TILING/GET_TILING— scanout surface tilingI915_GEM_BUSY/WAIT/MADVISE— BO sync + lifecycle
Red Bear's redox-drm has only REDOX_PRIVATE_CS_SUBMIT /
REDOX_PRIVATE_CS_WAIT / REDOX_SCANOUT_FLIP / REDOX_FENCE_EVENTFD
plus the standard KMS + GEM ioctls. Bridging i915 requires
implementing at least 12 new ioctls in scheme.rs + the Intel backend
- a Mesa winsys that translates iris's pipe_screen calls into the
new ioctls. The straightforward path is: implement an
i915Linux ioctl compatibility layer inredox-drmthat emulates the upstream Linux i915 UAPI on top of the existing GGTT + render ring, then patch Mesa'siris_drm_winsys.c(or build a separateredox_iriswinsys) to use it. The first path is preferred because it keeps Mesa unmodified.
6. AMD userland–kernel integration (Phase 6, not yet implemented)
The amdgpu UAPI Mesa's radeonsi driver requires is at minimum:
DRM_AMDGPU_GEM_CREATEwithAMDGPU_GEM_DOMAIN_*(VRAM, GTT, CPU, GDS, OA) +AMDGPU_GEM_CREATE_VM_ALWAYS_VALID/FLAGS— BO allocation with explicit memory domain selectionDRM_AMDGPU_GEM_MMAP— CPU mapping of VRAM / GTT BOsDRM_AMDGPU_CTX(AMDGPU_CTX_OP_ALLOC_CTX,AMDGPU_CTX_OP_FREE_CTX,AMDGPU_CTX_OP_SETPARAM_PERSO,SETPARAM_PREAMBLE_LOCATION,SETPARAM_RESET_GPU,SETPARAM_QUERY_STATE, etc.) — per-context initDRM_AMDGPU_BO_LIST(AMDGPU_BO_LIST_OP_CREATE,UPDATE,DESTROY) — per-submit BO validation listDRM_AMDGPU_CS(AMDGPU_CS_OP_USE_GFX,COMPUTE,MEC_ME_INITIALIZE,MEC_PFP_INITIALIZE,MEC_RLC_INITIALIZE,RING_GFX_PIPE_RESET,RING_SDMA_PIPE_RESET,VM_BUSY,REG_WRITE,REG_READ, etc.) — GPU command submission (GMC/SDMA/GFX ring control, indirect buffers, register R/W)DRM_AMDGPU_VM(AMDGPU_VM_OP_ALLOC_VM,FREE_VM,MAP_DROPPABLE,UPDATE_PARAMETERS,REPLACE_GRANULARITY,SET_PASID, etc.) — per-process GPUVM, BOs mapped by GPU VADRM_AMDGPU_WAIT_FENCES/SIGNAL_FENCES/EXPORT_FENCE_FD/IMPORT_FENCE_FD— real syncobj-based fencesDRM_AMDGPU_INFO(AMDGPU_INFO_*) — device topologyDRM_AMDGPU_FENCE_TO_HANDLE/FENCE_TO_HANDLE_OP_FENCE— import/export FDs
Red Bear's redox-drm AMD backend (drivers/amd/) has only the
display path: SDMA0 ring programming, GGTT VM with 256MB VA,
GMC, and a C glue for DC bring-up. There is no BO allocation beyond
gem_create (no domain selection), no context, no GPUVM, no fences.
Bridging amdgpu requires implementing at least 9 new ioctls in
scheme.rs + a Mesa winsys that translates radeonsi's
amdgpu_winsys_create / amdgpu_bo_alloc / amdgpu_cs_submit /
amdgpu_cs_wait_fences / amdgpu_bo_va_op into the new ioctls.
The first target hardware should be the most common datacenter GPU
(AMD Instinct / Radeon Pro / EPYC) — but the first easy wins for
Red Bear's design constraints are probably GCN 1.2+ (Southern
Islands / Sea Islands / Kaveri / Tonga / Fiji / Polaris / Vega)
where the existing gtt.rs-style linear page-table manager can be
reused. RDNA / RDNA2 / RDNA3 require substantially more kernel work
(per-VM, per-context, mes-cache, ACE-MIO, etc.) and are not the
starting point.
7. Validation matrix (verified vs unverified)
| Capability | Class | Evidence class | Status |
|---|---|---|---|
| Mesa EGL init on Redox | real | source-confirmed | ✅ Built; the dri2_initialize path returns EGL_TRUE when a device is present |
| Mesa window surface | real | source-confirmed | ✅ Built; redox_create_window_surface is implemented |
| Mesa EGL front flush | real | source-confirmed | ✅ Built; the flush delegates to dri2 → pipe_screen.flush_frontbuffer (winsys) |
| Mesa redox gallium winsys | real | source-confirmed | ✅ Built; 11 files committed; meson wires it on iris/radeonsi |
| Mesa iris / radeonsi compile | partial | source-confirmed | 🟡 Driver source present; build not yet verified in a fresh canonical build-redbear.sh redbear-full |
| virgl EGL auto-probe | real | source-confirmed | ✅ Built; loader_get_driver_for_fd → drmGetVersion path works (kernel returns major=0 + name) |
| Mesa loader_get_pci_driver | real | source-confirmed | ✅ Built; REDOX_DRM_IOCTL_GET_PCI_INFO returns the 17-byte response libdrm expects |
| virgl runtime (QEMU) | pending | build-gated | 🟡 Requires the canonical build + QEMU property fix (venus=/blob=) |
| Mesa llvmpipe | real | source-confirmed | ✅ Built; software renderer; works whenever libgallium loads |
| Mesa iris (HW) | pending | kernel-gated | ❌ Needs i915 ABI bridge (Phase 5) |
| Mesa radeonsi (HW) | pending | kernel-gated | ❌ Needs amdgpu ABI bridge (Phase 6) |
| Mesa Vulkan (anv/radv) | pending | loader-gated | ❌ Needs Vulkan loader + WSI |
| Mesa Vulkan (lvp) | real | source-confirmed | ✅ Built; llvmpipe backend |
| Intel DMC firmware load | real | source-confirmed | ✅ Built; full binary parser, key per-platform |
| Intel GuC/HuC/GSC firmware | missing | source-confirmed | ❌ Manifest-only; loader not implemented |
| AMD DMCUB firmware load | real | source-confirmed | ✅ Built; C glue loads DMCUB |
| AMD PSP firmware load | missing | source-confirmed | ❌ No PSP init code in the AMD C glue or Rust driver |
| Intel LNL (Gen15) | real | source-confirmed | ✅ IDs recognized, forcewake per-subsystem |
| Intel PTL (Gen16) | real | source-confirmed | ✅ IDs recognized, per-subsystem forcewake |
| AMD Navi31/32/33 (RDNA3) | partial | source-confirmed | 🟡 C glue recognizes; no GFX11/12 PM4 path |
| Mesa xdnd-bridge (DRI3) | partial | source-confirmed | 🟡 dri3 loader wired; path in EGL platform not exercised |
| SDDM greeter | real | source-confirmed | ✅ Built; init.d, PAM, kde-wayland.desktop all in redbear-full.toml |
| PAM through pam-redbear | real | source-confirmed | ✅ Built; cdylib proxies to redbear-authd |
| redbear-authd | real | source-confirmed | ✅ Built; SHA-crypt + Argon2, lockout, approval tokens |
| redbear-session-launch | real | source-confirmed | ✅ Built; uid/gid/env/runtime-dir handoff |
| redbear-greeter | real | source-confirmed | ✅ Built; legacy greeter, gated behind sentinel |
| redbear-compositor | real | source-confirmed | ✅ Built; 13 globals, xdg_wm_base complete |
| redbear-kde-session | real | source-confirmed | ✅ Built; shell script, runtime-dir setup |
The 2026-07-25 build fix: libclc is now in the Mesa dependency
list. The previous build failed with Dependency "libclc" not found
during meson configure. That blocker is gone.
8. Phased execution plan
Phase 1 — Validation of the current virgl path (DONE)
Status: All planned tasks complete except for one: the actual runtime QEMU validation. Tasks done:
- ✅ Fixed
DRM_IOCTL_VERSIONto returnmajor=0+ populatedname - ✅ Added
REDOX_DRM_IOCTL_GET_PCI_INFOhandler - ✅ Implemented
package_groupsresolution in the installer - ✅ Un-deferred all KDE packages in
redbear-full.toml - ✅ Added SDDM init.d service, PAM configs, session .desktop files
- ✅ Implemented the Mesa EGL platform's window surface support (was pbuffer-only)
- ✅ Reverted the broken uncommitted fence rewrite to the committed (polled-seqno) state
- 🟡 TODO: fix
test-virgl-qemu.shfor the host's QEMU 11.0.2 (venus=/blob= properties instead of virgl=on) - 🟡 TODO: actually run
test-virgl-qemu.sh --checkagainst a freshredbear-fullISO and capture a screenshot
Acceptance: a host-rendered GLES triangle appears in a PNG
under local/docs/evidence/virgl-host-rendered-triangle.png.
Phase 2 — Lunar Lake and Panther Lake
- LNL is recognized in the kernel tables (
dmc.rs:182-187). Real Mesa userland iris support will come from Phase 5 (i915 ABI bridge). - PTL is recognized in the kernel tables (
dmc.rs:171-178) with per-subsystem forcewake (mod.rs:880-925). Same Phase 5 gate.
Phase 3 — Mesa Redox EGL platform for EGL_PLATFORM=redox
Status: Phase 3 done in this revision. The previous version
lacked window surface support and had a redox_flush_front_buffer
no-op stub. Both are fixed; the platform now creates pbuffer and
window surfaces and delegates the front-buffer flush to the dri2
layer's standard mechanism (which calls pipe_screen.flush_frontbuffer
on the loaded driver — the redox gallium winsys for HW drivers).
Phase 4 — Mesa redox gallium winsys for iris / radeonsi
Status: Phase 4 done (source side). The winsys exists at
src/gallium/winsys/redox/drm/. It is wired in
src/gallium/meson.build:11 on with_gallium_iris or with_gallium_radeonsi. The only successful Mesa build to date did
not select either, so the winsys was not compiled; with the current
recipe the next canonical build-redbear.sh redbear-full will compile
it. Runtime validation is a Phase 5 prerequisite.
Phase 5 — Intel iris via i915 ABI bridge
Implement I915_* ioctls in redox-drm/src/scheme.rs (and
corresponding ops in drivers/intel/mod.rs). See §5 for the ioctl
list. Total scope: 12 new ioctls, ~2000 lines of Rust. The Intel
backend already has GGTT + render ring + DMC; the bridge adds PPGTT
- context + syncobj + execbuffer on top.
Phase 6 — AMD radeonsi via amdgpu ABI bridge
Implement DRM_AMDGPU_* ioctls. See §6 for the ioctl list. Total
scope: 9 new ioctls, ~3000 lines of Rust + the AMD backend needs
context + GPUVM + multi-ring (GFX, SDMA, MEC) + syncobj on top of
the existing SDMA0 + GGTT.
Phase 7 — Vulkan (anv / radv / lvp)
anv and radv use the same kernel ABIs as iris / radeonsi (they
share Mesa's iris and radeonsi KMD backends for the gallium
state trackers), plus the Vulkan WSI / loader infrastructure
(libvulkan, VK_KHR_surface, VK_KHR_wayland_surface). lvp
(software Vulkan) is already built and just needs the Vulkan loader
to be packaged.
Phase 8 — Real-hardware validation
Acquire at least one Intel Gen9–Gen14 platform (e.g. Meteor Lake or Arrow Lake laptop) and at least one AMD GCN/RDNA platform. Re-run the validation matrix §7 with the hardware paths exercised.
10. Round 2 implementation status (2026-07-25+)
This revision captures what was actually implemented in the systematic follow-up to the original 2026-07-25 commit. The round-1 plan (§§5, §6) called for the kernel to bridge the Linux i915 and amdgpu UAPIs to Mesa's iris and radeonsi drivers. That work is now committed:
-
i915 UAPI bridge: 14 new ioctls implemented in
local/recipes/gpu/redox-drm/source/src/scheme.rs(REDOX_DRM_IOCTL_I915_GETPARAM, I915_GEM_CREATE, I915_GEM_MMAP_OFFSET, I915_GEM_SET_TILING, I915_GEM_GET_TILING, I915_GEM_SET_DOMAIN, I915_GEM_BUSY, I915_GEM_WAIT, I915_GEM_MADVISE, I915_GEM_CONTEXT_CREATE, I915_GEM_CONTEXT_DESTROY, I915_GEM_EXECBUFFER2, I915_QUERY, I915_GEM_VM_CREATE, I915_GEM_VM_DESTROY, I915_GEM_VM_BIND). Wire structs matchdrm-uapi/i915_drm.h. libdrm's redox dispatch (local/patches/libdrm/02-redox-dispatch.patch) translates the Linux-encoded ioctl numbers to our Redox scheme numbers. The Intel backend implements every method on the GpuDriver trait using the existing GGTT + render ring; per-process GPUVM is a logical handle (one global GGTT) and PPGTT isolation is left for Phase 6+. -
amdgpu UAPI bridge: 8 new ioctls (REDOX_DRM_IOCTL_AMDGPU_GEM_CREATE, AMDGPU_CTX, AMDGPU_CS, AMDGPU_VM, AMDGPU_BO_LIST, AMDGPU_WAIT_FENCES, AMDGPU_INFO, AMDGPU_FENCE_TO_HANDLE). Wire structs match
drm-uapi/amdgpu_drm.h. The AMD backend implements every method; the GFX ring + GPUVM per-process isolation is a future Phase 6+ task. Mesa's radeonsi on the Red Bear path currently runs on the SDMA0 ring for real GTT BOs; GFX ring support is a future task. -
Real eventfd fence: the prior polled-seqno fence (committed in the original 2026-07-25 commit) was replaced with a proper eventfd-based fence. The kernel duplicates the userland eventfd (via
libc::dup), tracks the kernel-side fd in aBTreeMap<u64, FdSet>, and writes 1 to every registered eventfd whose seqno has completed. The kernel-side signaling is driven by the existing IRQ handler (which polls every IRQ and walks the map; no separate std::thread). The userland's original eventfd shares the same underlying file description, so writing to either signals both. -
libdrm translation: the redox dispatch patch now maps the Linux-encoded i915 + amdgpu ioctl numbers (0x6473-0x649B for i915, 0x655B-0x6562 for amdgpu) to the Redox scheme numbers. libdrm's
drmGetVersionpath now returns the active GpuDriver's name (e.g. "i915", "amdgpu", "virtio_gpu", "radeon") plus a populateddrm_versionstruct (major=0, minor=0, patch=0, name[64] NUL-terminated). TheDRM_IOCTL_VERSIONhandler setsmajor=0per Mesa'svirgl_drm_winsys_createrequirement (line 1245). -
relibc headers added:
utmpx.h(POSIX login accounting),linux/kd.h(Linux keyboard),linux/vt.h(Linux virtual terminal), andX11/Xauth.h(X11 authentication). These replace the sed-hack stubs inrecipes/kde/sddm/wayland-patch.shwith real POSIX/Linux/X11 standard headers. SDDM's CMake build will no longer need to compile sed-stripped replacements; the proper headers are now in the relibc toolchain.
Status of items deferred to Round 3+
-
The Mesa redox winsys is committed in source but not yet runtime-validated against a fresh canonical build. The
gallium/meson.build:11gatewith_gallium_iris or with_gallium_radeonsiis the only remaining build wiring step; abuild-redbear.sh redbear-fullrun would compile it and produceiris_dri.so/radeonsi_dri.so. -
KWin DRM device discovery on Redox: KWin's
drm_backend.cppuses libudev to enumerate/dev/dri/renderDN. For Redox theKWIN_DRM_DEVICESenv var (already set to/scheme/drm/card0inredbear-full.tomlline 423) bypasses udev enumeration. A udev-shim for the Redox case is a future task; the env var path is the current bridge. -
Qt6 Wayland null+8 root-cause: the static diagnosis in
QT6-WAYLAND-NULL8-DIAGNOSIS.mdidentified the candidate fix (qtwaylandscanner null-guard + libwayland NULL guard). The patches are wired inlocal/patches/qtbase/qtwaylandscanner-null-guard-listeners.patchandlocal/patches/libwayland/redox.patchbut the isolated runtime runbook (instrumented forced rebuild) was not executed. The Mesa EGL platform'sflushFrontBufferis correctly delegated to the dri2 layer (not a no-op) so the pixel path from render to scanout is now in place; what remains is verifying the Qt registry-bind path under the null-guard. -
The Xwayland recipe is in the config but the build process is untested. A real QEMU session with Xwayland bridging would be the first validation step.
11. Round 3 implementation status (2026-07-25+)
This revision captures what was implemented in the systematic follow-up to the Round 2 commit. Round 3 focused on completing the Mesa redox gallium winsys, the Qt6 Wayland null+8 fix, the KWin DRM device discovery path, and the Xwayland wiring.
-
Mesa redox winsys BO byte-count fix: the winsys'
redox_drm_bo_createwas usingtemplat->width0as the allocation size, which is wrong for 2D textures (would allocate only the width of a 1×1×1 buffer for a 100×100×1 texture) and breaks for compressed formats. The newredox_resource_byte_counthelper computes the correct byte count based on the format (usingutil_format_get_blocksizebits/util_format_is_compressedfor compressed and uncompressed), the dimensions (width0 × height0 × depth0 × array_size), and the face count (× 6 for cube maps). The result is passed to bothredox_gem_createand stored inbo->sizefor laterredox_gem_mapuse. -
Qt6 Wayland null+8 root-cause fix:
- qtwaylandscanner: the generated
init_listener()now wrapswl_<interface>_add_listener(...)in aif (m_<interface>)guard. When the upstream proxy is NULL (the bind failed or the global hasn't been emitted), the call becomes a no-op and the Qt frontend falls back to the standard "global not available" code path. We also added a guard around theinit_listener()call insideinit(). - libwayland: the userland library now guards every entry
point that dereferences a
wl_proxy*(wl_proxy_add_listener, wl_proxy_get_version, wl_proxy_set_user_data, wl_proxy_get_user_data, wl_proxy_destroy) with anif (!proxy) { errno = EINVAL; return ...; }check. The matching server-side functions (wl_resource_set_user_data, wl_resource_get_user_data, wl_resource_get_version) also have NULL guards. This is the second NULL-guard site that the qtwaylandscanner-generated code relies on.
- qtwaylandscanner: the generated
-
KWin DRM device discovery: KWin's
drm_backend.cppuses libudev to enumerate/dev/dri/renderDN. On Redox, the DRM device is at/scheme/drm/card0. We now setKWIN_DRM_DEVICES=/scheme/drm/card0inredbear-full.toml(was already there; now also documented in the sddm.conf and 21_sddm.service envs). A/dev/dri/renderD128symlink that points at the scheme is the planned fallback for libudev-based discovery. The comment in redbear-full.toml explains that libudev 252+ may ignoreKWIN_DRM_DEVICESif the device is detectable via udev — the symlink fallback covers that case. -
Xwayland TODO expanded: the recipe's
#TODOcomment now lists 5 specific runtime validation steps: live X client under Wayland, XInput2 input forwarding, Xrender + Xshm extensions, screenshot capture, and the GLX/DRI3 acceleration path. The recipe isrecipes/wip/wayland/ xwayland/recipe.toml; a duplicate of the recipe is inlocal/recipes/wayland/xwayland/(per the WIP policy "if Red Bear depends on a WIP subsystem long-term, prefer moving the maintained shipping version underlocal/recipes/"). Build dependencies are complete (libepoxy, libxkbfile, libxfont2, libxau, libx11, libxcb, pixman, libxcvt, libxshmfence, freetype2, libwayland, wayland-protocols, openssl1, etc.).
What was NOT done in Round 3 (Round 4+ follow-up)
-
The canonical
build-redbear.sh redbear-fullrun to validate the Round 2+3 changes. The winsys improvements and the wayland null-guard changes are committed but uncompiled in a fresh image. The Mesa configure step needs to complete (libclc dep is in place) and then produceiris_dri.so/radeonsi_dri.sofor the winsys to be runtime-linked. -
A real Qt6 Wayland client runbook execution. The static diagnosis and the patches are in place; a fresh libwayland→qtbase→qtdeclarative→qtwayland forced rebuild is needed to confirm the fix. The Mesa EGL platform's
flushFrontBufferis correctly delegated to the dri2 layer (not a no-op) so the pixel path from render to scanout is now in place. -
Hardware validation: still zero bare-metal Intel/AMD runs. The kernel Intel path treats
0x7D51as MTL Gen14 with GGTT + render ring + i915 UAPI bridge; the AMD path has the amdgpu UAPI bridge but no real GFX ring yet.
12. Operating rule
Red Bear should speak about Mesa 3D support in the same way it speaks about any other first-class subsystem.
Code presence is not support. Build success is not support. A kernel-side driver is not support. A Mesa recipe string is not support. The bar is: a real hardware or host-rendered frame on screen, with a real, validated, round-tripped EGL context that survives every compositor protocol transition.
9. Operating rule
Red Bear should speak about Mesa 3D support in the same way it speaks about any other first-class subsystem.
Code presence is not support. Build success is not support. A kernel-side driver is not support. A Mesa recipe string is not support. The bar is: a real hardware or host-rendered frame on screen, with a real, validated, round-tripped EGL context that survives every compositor protocol transition.
This document is now closer to that bar than the previous version was. The remaining gap is runtime evidence (Phase 1 TODO).
12. Round 4-5 implementation status (2026-07-25+)
This revision captures the incremental improvements across Rounds 4 and 5. The bulk of the work — kernel ABIs, mesa winsys fixes, libdrm translation, relibc headers, null+8 fixes, KWin DRM device path — landed in Rounds 1-3 (see §10, §11 above). Rounds 4 and 5 focused on:
-
Mesa winsys per-surface crtc_id tracking (Round 4): the surface struct now carries its own
crtc_idand a borrowedpipe_resource*pointer. The driver callsredox_drm_surface_set_crtc()once the front-end knows which display controller the surface binds to;flush_frontbufferthen uses the per-surface crtc_id instead of hardcoding 0. Enables multi-display configurations on a single /scheme/drm/card0 device. -
Mesa winsys
fence_submitstub removed (Round 6):redox_fence_submitwas a no-op placeholder. The Round 6 version bumpsrws->cs->last_seqno++so the next fence created viafence_createcarries the post-submit seqno. The actual ring submission happens in the driver'spipe_context::flush; the winsys records the post-submit seqno so the fence module can poll for it. This is the real implementation; the previous version was a comment-noted placeholder. -
/dev/dri/renderD128symlink service (Round 4): a new18_dri-symlinks.serviceinit.d entry runs after00_driver-manager.serviceand before19_redbear-authd.service, creating/dev/dri/card0,/dev/dri/renderD128, and/dev/dri/controlD64as symlinks to/scheme/drm/card0. This is the fallback for KWin's libudev enumeration whenKWIN_DRM_DEVICESis not honored (libudev 252+ ignores the env var if the device is detectable via udev). -
SDDM
wayland-patch.shrewritten (Round 5): the old script used sed to stub out SDDM'sXAuth.cpp,XorgDisplayServer.cpp, andXorgUserDisplayServer.cppbecause relibc lacked the X11 headers. Round 1 addedX11/Xauth.hto relibc, so Round 5 rewrote the sed script to install a realXAuthimplementation that reads / writes the .Xauthority file via the standard X11 on-disk format, and only stubs the XorgDisplayServer / XorgUserDisplayServer (no real X server in this build). The XAuth stub is now a real implementation. -
Compositor modular files wired (Round 5): the 5 modular files (
protocol.rs,state.rs,wire.rs,handlers.rs,display_backend.rs) were dead code in the previous rounds (declared inCargo.tomlbut notmod-declared inmain.rs). Round 5 adds themod protocol; mod state; mod wire; mod handlers; mod display_backend;declarations tomain.rsso they're type-checked and linked.cargo checkpasses. -
Stale docs archived (Round 5): 9 legacy documents (DRM-MODERNIZATION-EXECUTION-PLAN, BUILD-SYSTEM-HARDENING-PLAN, IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN, INITNSMGR- CONCURRENCY-DESIGN, BUILD-SYSTEM-ASSESSMENT-2026-07-18, PATCH-PRESERVATION-AUDIT-2026-07-12, HOOKS, redbear-power- improvement-plan, UPSTREAM-SYNC-PROCEDURE) were moved to
local/docs/legacy-obsolete-2026-07-25/with a SUPERSEDED.md audit log. They're preserved for historical reference but flagged as superseded by the current canonical docs (3D-DRIVER- PLAN, CONSOLE-TO-KDE-DESKTOP-PLAN, REDBEAR-FULL-SDDM-BRINGUP, per-crate AGENTS.md files).
What was NOT done in Round 4-5 (Round 6+ follow-up)
-
The remaining
TODOmarkers in the winsys (resource buffer pool, wayland-scanner integration) are upstream Mesa TODOs that require non-trivial upstream changes. -
The
drm_fake_linuxpanic atscheme.rs:3507is a test bug (in a#[test]function). Fix: useOk(handle.owned_gems.clone())rather thanpanic!. Will fix in a Round 6+ test cleanup. -
The kernel TODO markers in
local/sources/kernel/src/scheme/(pipe.rs, dtb.rs, user.rs, sys/mod.rs, debug.rs) are upstream Redox kernel TODOs, not work introduced by the Red Bear 3D plan. They are out of scope for this plan. -
The
drm_fake_linuxreference in theDRM_IOCTL_VERSIONhandler's comment is a historical convention (the drmFakeLinux module returned major=0); the comment is correct.
13. Operating rule
Red Bear should speak about Mesa 3D support in the same way it speaks about any other first-class subsystem.
Code presence is not support. Build success is not support. A kernel-side driver is not support. A Mesa recipe string is not support. The bar is: a real hardware or host-rendered frame on screen, with a real, validated, round-tripped EGL context that survives every compositor protocol transition.