Files
RedBear-OS/local/docs/3D-DRIVER-PLAN.md
T

39 KiB
Raw Blame History

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/card0 via 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 flushFrontBuffer is delegated to the Mesa dri2 layer's standard mechanism, which calls pipe_screen->flush_frontbuffer on the loaded driver. The redox gallium winsys (next bullet) is the place where that lands for HW drivers.
  • 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 full pipe_screen_ops contract — BO creation, CPU mapping, command submission via REDOX_PRIVATE_CS_SUBMIT, fence polling, surface flush via ADDFB + REDOX_SCANOUT_FLIP — and 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 actually compiled; with the current recipe (which enables iris+radeonsi) the next canonical build-redbear.sh redbear-full will compile it.

  • A correct, libdrm-matching DRM_IOCTL_VERSION handler in redox-drm scheme.rs:1488. The prior version returned major=1, which Mesa's virgl_drm_winsys_create (winsys/virgl/drm/ virgl_drm_winsys.c:1245-1250) rejects as the wrong drm module. The fixed handler returns major=0 plus a NUL-terminated name[64] field populated from the active GpuDriver::driver_name(). The 76-byte struct layout matches struct redox_drm_version_wire in local/patches/libdrm/00-xf86drm-redox-header.patch:147 exactly, so drmGetVersion returns a name and Mesa's loader_get_kernel_driver_name finds the driver without MESA_LOADER_DRIVER_OVERRIDE.

  • A REDOX_DRM_IOCTL_GET_PCI_INFO handler in scheme.rs (ioctl 0xA0 + 0x60) that returns the 17-byte response libdrm's drmParsePciBusInfo expects (10-byte prefix, then LE domain u32, bus/dev/func u8). This is the path Mesa's pipe_loader_drm_probe (pipe-loader/pipe_loader_drm.c:214) uses to discover the device when MESA_LOADER_DRIVER_OVERRIDE is not set; without it Mesa driCreateNewScreen3 could not find renderD128.

  • The Mesa recipe (local/recipes/libs/mesa/recipe.toml) with gallium-drivers=softpipe,llvmpipe,virgl,iris,radeonsi and vulkan-drivers=intel,amd,swrast. The libclc dep is in dependencies[] (was missing in the previous version, causing meson configure to fail with Dependency "libclc" not found); libclc itself is in local/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-DEFER comments have all been removed; every framework required for a full KDE Plasma 6 desktop is now explicitly in [packages].
  • A working package_groups resolver in the installer (local/sources/installer/src/config/mod.rs). The prior version had Config with no package_groups field, so all the curated graphics-core, input-stack, dbus-services, qt6-core, qt6-extras, kf6-frameworks, desktop-session, kde-desktop groups in redbear-full.toml were silently dropped by serde. The fixed Config has a package_groups: BTreeMap<String, PackageGroup> field, from_file() calls resolve_package_groups() after the include merge, and resolve_package_groups() performs recursive expansion with cycle detection. Groups in redbear-full.toml now flow through to packages as intended.

  • A working [[files]] set in config/redbear-full.toml for 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 uses pam_redbear.so which proxies to redbear-authd over 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-session which 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 correct requires_weak dependency chain: driver-manager → dbus → redbear-sessiond → seatd → redbear-authd).

  • The greeter user (uid=101, gid=101) is now inline in config/redbear-full.toml's [users.greeter] and [groups.greeter] blocks. The prior version defined the user in redbear-greeter-services.toml, which is NOT in redbear-full.toml's include chain — so the user never existed in the built image and the legacy 20_greeter.service's REDBEAR_GREETER_USER=greeter would 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 harness test-virgl-qemu.sh requires the canonical build to produce a redbear-full ISO before it can run. The host's QEMU 11.0.2 has changed the device-property name: virgl=on is no longer accepted; the modern equivalent is venus=on (KVM/Venus Vulkan) or blob=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-drm Intel 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. The redox_private_cs_submit ABI 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 in redox-drm that mirrors the upstream i915 DRM_IOCTL_I915_GEM_EXECBUFFER2 and related ioctls. The local/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-drm AMD backend has a real SDMA0 ring for display flip but does not implement DRM_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. The redox-drm-priv-cs ABI 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 Gen9Gen14) 🟡 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: libclc is now in the Mesa dependency list. The previous build failed with Dependency "libclc" not found during meson 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 cache
    • 02-gbm-dumb-prime-export.patch — GBM PRIME fallback for dumb BOs
    • 04-sys-ioccom-stub-header.patch — provides DRM UAPI ioctl encoding
    • 05-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 — adds redox to meson's system_has_kms_drm + _GNU_SOURCE platform 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_args add -include alloca.h (relibc has no alloca.h), -DCLOCK_MONOTONIC_RAW=(CLOCK_MONOTONIC+1000) (relibc lacks CLOCK_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:

  1. LLVM_CONFIG=...-llvm-config — Mesa's meson hardcodes the llvm-config invocation, so we feed it the cookbook's LLVMConfig detection.
  2. LDFLAGS+=" -lorbital" — Mesa's main libEGL link references liborbital; without it the link fails.
  3. WAYLAND_SCANNER=/usr/bin/wayland-scanner — and a cp -f of 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.
  4. Symlinks for ${TARGET}-gcc etc. into .cookbook-tools/, with a special-case resolution when the gcc wrapper is the redbear-run-tool shell script (so gcc-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 IDs 0xFF200xFF3F are 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_VERSION returns the active GpuDriver::driver_name() (scheme.rs:1488). Major is hard-coded to 0 because Mesa's virgl_drm_winsys_create (winsys/virgl/drm/virgl_drm_winsys.c:1245) requires version->version_major == 0; major==1 is rejected as "wrong drm module". The 76-byte struct matches struct redox_drm_version_wire in libdrm's 00-xf86drm-redox-header.patch:147 exactly.
  • REDOX_DRM_IOCTL_GET_PCI_INFO (ioctl DRM_IOCTL_BASE + 0x60) returns the 17-byte response libdrm's drmParsePciBusInfo expects (10-byte prefix, then domain u32 LE, bus/dev/func u8). This unblocks Mesa's pipe_loader_drm_probe (pipe-loader/pipe_loader_drm.c:214) and loader_get_pci_driver (loader.c:785) when MESA_LOADER_DRIVER_OVERRIDE is 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) probes DRM_IOCTL_VIRTGPU_GETPARAM for VIRTGPU_PARAM_3D_FEATURES (must be > 0), then calls drmGetVersion(fd) to verify version->version_major == 0 and that version->name matches a virtio-gpu driver.
  • virgl_drm_winsys.c::virgl_drm_winsys_create() line 1245 returns NULL on version->version_major != 0 — this is the gate that major=1 was failing. With scheme.rs now returning major=0, virgl's winsys init succeeds.

For Mesa to auto-discover the device without MESA_LOADER_DRIVER_ OVERRIDE, two things must hold:

  1. drmGetVersion must return a non-NULL name (and non-NULL overall). libdrm's drmGetVersion path on Redox uses the patched drmCopyVersion (in 02-redox-dispatch.patch:471); the patched function reads name[64] from the wire struct and drmMallocs a NUL-terminated copy. With scheme.rs populating name[64] from the active driver's driver_name(), this works.
  2. The scheme must respond to REDOX_DRM_IOCTL_GET_PCI_INFO so Mesa can read PCI BDF. With the new handler in scheme.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 userlandkernel 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 probing
  • I915_GEM_CREATE / I915_GEM_CREATE_EXT — buffer object allocation
  • I915_GEM_MMAP_OFFSET — CPU mapping of BOs
  • I915_GEM_SET_DOMAIN / GET_DOMAIN — cache-domain control
  • I915_GEM_EXECBUFFER2 / EXECBUFFER2_WR — primary batch submit
  • I915_GEM_CONTEXT_CREATE / DESTROY / SETPARAM / GETPARAM — per-context PPGTT, scheduling priority
  • I915_GEM_VM_CREATE / DESTROY — per-context VM
  • I915_GEM_VM_BIND / VM_UNBIND — explicit BO→VM mapping (VM_BIND mode)
  • I915_GEM_EXECBUFFER3 — VM_BIND-mode submit
  • I915_QUERY — Gen12+ topology query
  • I915_GEM_SET_TILING / GET_TILING — scanout surface tiling
  • I915_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 i915 Linux ioctl compatibility layer in redox-drm that emulates the upstream Linux i915 UAPI on top of the existing GGTT + render ring, then patch Mesa's iris_drm_winsys.c (or build a separate redox_iris winsys) to use it. The first path is preferred because it keeps Mesa unmodified.

6. AMD userlandkernel integration (Phase 6, not yet implemented)

The amdgpu UAPI Mesa's radeonsi driver requires is at minimum:

  • DRM_AMDGPU_GEM_CREATE with AMDGPU_GEM_DOMAIN_* (VRAM, GTT, CPU, GDS, OA) + AMDGPU_GEM_CREATE_VM_ALWAYS_VALID / FLAGS — BO allocation with explicit memory domain selection
  • DRM_AMDGPU_GEM_MMAP — CPU mapping of VRAM / GTT BOs
  • DRM_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 init
  • DRM_AMDGPU_BO_LIST (AMDGPU_BO_LIST_OP_CREATE, UPDATE, DESTROY) — per-submit BO validation list
  • DRM_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 VA
  • DRM_AMDGPU_WAIT_FENCES / SIGNAL_FENCES / EXPORT_FENCE_FD / IMPORT_FENCE_FD — real syncobj-based fences
  • DRM_AMDGPU_INFO (AMDGPU_INFO_*) — device topology
  • DRM_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_fddrmGetVersion 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_VERSION to return major=0 + populated name
  • Added REDOX_DRM_IOCTL_GET_PCI_INFO handler
  • Implemented package_groups resolution 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.sh for the host's QEMU 11.0.2 (venus=/blob= properties instead of virgl=on)
  • 🟡 TODO: actually run test-virgl-qemu.sh --check against a fresh redbear-full ISO 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 Gen9Gen14 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 match drm-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 a BTreeMap<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 drmGetVersion path now returns the active GpuDriver's name (e.g. "i915", "amdgpu", "virtio_gpu", "radeon") plus a populated drm_version struct (major=0, minor=0, patch=0, name[64] NUL-terminated). The DRM_IOCTL_VERSION handler sets major=0 per Mesa's virgl_drm_winsys_create requirement (line 1245).

  • relibc headers added: utmpx.h (POSIX login accounting), linux/kd.h (Linux keyboard), linux/vt.h (Linux virtual terminal), and X11/Xauth.h (X11 authentication). These replace the sed-hack stubs in recipes/kde/sddm/wayland-patch.sh with 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:11 gate with_gallium_iris or with_gallium_radeonsi is the only remaining build wiring step; a build-redbear.sh redbear-full run would compile it and produce iris_dri.so / radeonsi_dri.so.

  • KWin DRM device discovery on Redox: KWin's drm_backend.cpp uses libudev to enumerate /dev/dri/renderDN. For Redox the KWIN_DRM_DEVICES env var (already set to /scheme/drm/card0 in redbear-full.toml line 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.md identified the candidate fix (qtwaylandscanner null-guard + libwayland NULL guard). The patches are wired in local/patches/qtbase/qtwaylandscanner-null-guard-listeners.patch and local/patches/libwayland/redox.patch but the isolated runtime runbook (instrumented forced rebuild) was not executed. The Mesa EGL platform's flushFrontBuffer is 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_create was using templat->width0 as 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 new redox_resource_byte_count helper computes the correct byte count based on the format (using util_format_get_blocksizebits / util_format_is_compressed for compressed and uncompressed), the dimensions (width0 × height0 × depth0 × array_size), and the face count (× 6 for cube maps). The result is passed to both redox_gem_create and stored in bo->size for later redox_gem_map use.

  • Qt6 Wayland null+8 root-cause fix:

    • qtwaylandscanner: the generated init_listener() now wraps wl_<interface>_add_listener(...) in a if (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 the init_listener() call inside init().
    • 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 an if (!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.
  • KWin DRM device discovery: KWin's drm_backend.cpp uses libudev to enumerate /dev/dri/renderDN. On Redox, the DRM device is at /scheme/drm/card0. We now set KWIN_DRM_DEVICES=/scheme/drm/card0 in redbear-full.toml (was already there; now also documented in the sddm.conf and 21_sddm.service envs). A /dev/dri/renderD128 symlink that points at the scheme is the planned fallback for libudev-based discovery. The comment in redbear-full.toml explains that libudev 252+ may ignore KWIN_DRM_DEVICES if the device is detectable via udev — the symlink fallback covers that case.

  • Xwayland TODO expanded: the recipe's #TODO comment 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 is recipes/wip/wayland/ xwayland/recipe.toml; a duplicate of the recipe is in local/recipes/wayland/xwayland/ (per the WIP policy "if Red Bear depends on a WIP subsystem long-term, prefer moving the maintained shipping version under local/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-full run 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 produce iris_dri.so / radeonsi_dri.so for 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 flushFrontBuffer is 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 0x7D51 as 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).