4fa276287e
Adds section 8.2 documenting the Round 8 follow-up commits: *c20032435d: Mesa EGL back-buffer allocation in redox_image_get_buffers (was hard stub - back=NULL always) *101ce11844: pipe_loader_redux backend for /scheme/drm/card0 (closes the non-EGL gallium consumer gap) *5aa5c96506: kf6-kcmutils git conflict markers resolved (BLOCKER - shell would have tried to execute literal <<<<<<< and >>>>>>> strings as commands) *c73e4227(relibc): cfgetispeed/cfgetospeed/cfsetispeed/cfsetospeed real impl on Redox (was 0 or EINVAL unconditionally) *9bc6ba0b6e: redbear-compositor keyboard modifier state tracking (shift/ctrl/alt/logo/caps/num/mod5 with apply_modifier_event) *1d930cd425: qtbase open_memstream stub removed (relibc provides it) *f6420ec8c3: relibc submodule pointer bump * Documentation cleanups in local/AGENTS.md and local/recipes/AGENTS.md Combined with the Round 7 follow-up and the v5.8/v5.9/v5.10 parallel sweeps, the surface of unimplemented hard stubs in the Mesa/relibc/compositor stack is now near zero. Remaining deferred items (Qt6 Wayland null+8 runtime validation, QML gate in plasma-framework + kirigami, HW validation) require kernel ABI work or external hardware.
961 lines
52 KiB
Markdown
961 lines
52 KiB
Markdown
# Red Bear OS — 3D Driver Plan (Mesa + virgl + Intel iris + AMD radeonsi)
|
||
|
||
**Status:** Round 7 implementation completed 2026-07-27 across parent and
|
||
relibc submodule. Mesa meson symbol fix, I915_GEM_VM_BIND dead path fix,
|
||
I915_GEM_MADVISE type fix, AMD `gem_create` GPU mapping fix, virgl test
|
||
script QEMU 11.0.2 property update, full i915 bridge stub implementations
|
||
(tiling, domain, busy, wait, vm_bind, query topology, real eventfd fence),
|
||
full amdgpu bridge stub implementations (ctx/cs/vm/bo_list/wait_fences/info/
|
||
fence_to_handle), Wayland `zwlr_layer_shell_v1` + `zwlr_output_manager_v1`
|
||
protocol implementations, compositor `wp_presentation_feedback` real
|
||
CLOCK_MONOTONIC timing, compositor `wl_data_offer` clipboard transfer
|
||
pipeline (pipe + SCM_RIGHTS), XWayland button mapping switch (fixes
|
||
uninitialized index crash), relibc `getifaddrs` real implementation
|
||
(walks /scheme/net/ifs via SYS_GETDENTS). See §8 below for the detailed
|
||
Round 7 work matrix.
|
||
|
||
**Round 7 follow-ups (Round 8+)**: Mesa EGL back-buffer patches still
|
||
not wired (target 26.1.4 DRI2 ABI rebase), Qt6 Wayland null+8 runtime
|
||
validation, QML gate in plasma-framework + kirigami, HW validation on
|
||
Intel Gen9-Gen14 and AMD GCN/RDNA platforms, Mesa EGL
|
||
zwp_linux_dmabuf_v1 real scanout, Mesa winsys multi-context scheduling
|
||
(requires kernel ABI extension), atomic commit / DRM_CLIENT_CAP_ATOMIC.
|
||
|
||
**Date:** 2026-07-26
|
||
**Scope:** Mesa 26.1.4 + virgl (QEMU host-side 3D) + Intel iris (i915 UAPI bridge) +
|
||
AMD radeonsi (amdgpu UAPI bridge) on Red Bear OS 0.3.1 / `local/sources/` fork HEAD.
|
||
|
||
In scope:
|
||
- Mesa redox EGL platform + redox gallium winsys build status
|
||
- virgl end-to-end path (redox-drm virtio backend, libdrm dispatch, Mesa virgl winsys,
|
||
EGL loader, QEMU host support, test harness)
|
||
- Intel i915 UAPI bridge (16 ioctls + GGTT/render-ring backing) + runtime validation
|
||
- AMD amdgpu UAPI bridge (8 ioctls + SDMA ring) + Mesa radeonsi wiring
|
||
- Wayland compositor protocol coverage (redbear-compositor 13 globals + zwlr_* gap)
|
||
- Display/KMS, Wayland/KWin/KDE session composition, audio/HDMI — covered by
|
||
`CONSOLE-TO-KDE-DESKTOP-PLAN.md` (canonical desktop plan)
|
||
|
||
---
|
||
|
||
## 0. Executive summary — bottom line
|
||
|
||
| Path | Build state | Runtime | To enable |
|
||
|-------------------------------------|--------------------------------------|--------------------------------------------------------|-----------|
|
||
| llvmpipe (software) | ✅ Builds | ✅ Works when libgallium loads | already enabled |
|
||
| softpipe (software) | ✅ Builds | ✅ Works when libgallium loads | already enabled |
|
||
| virgl (QEMU host-side 3D) | ✅ All 11 VIRTGPU ioctls wired | 🟡 Code complete; test script BROKEN on QEMU 11.0.2 | Fix test script (`blob=true` instead of `virgl=on`); run canonical build |
|
||
| iris (Intel Gen9–Gen14) | 🟡 Recipe enabled; build unverified | 🟡 i915 UAPI bridge scaffolded, ~30% substantive | Round 7: fix VM_BIND dead path + MADVISE type bug; runtime validation |
|
||
| iris (LNL Gen15, PTL Gen16) | 🟡 IDs recognized in kernel tables | ❌ Same as above | Phase 5+ after Round 7 |
|
||
| radeonsi (AMD GCN+) | 🟡 Recipe enabled; build unverified | 🟡 amdgpu UAPI bridge scaffolded, ~10% substantive | Round 7: add `ensure_gem_gpu_mapping` to amdgpu BO create; runtime validation |
|
||
| Vulkan anv (Intel) | 🟡 Recipe enabled | ❌ Vulkan loader + WSI not wired | Phase 7+ |
|
||
| Vulkan radv (AMD) | 🟡 Recipe enabled | ❌ Vulkan loader + WSI not wired | Phase 7+ |
|
||
| Vulkan lvp (software) | 🟡 Recipe enabled | 🟡 Should work (llvmpipe backend) | Phase 7+ |
|
||
|
||
**The single hardest blocker for graphical KDE** is Qt6 Wayland `wl_proxy_add_listener`
|
||
null+8 — patches committed, never runtime-validated in isolation. The canonical
|
||
`build-redbear.sh redbear-full` + a forced-rebuild of the
|
||
libwayland→qtbase→qtdeclarative→qtwayland chain is the prerequisite to unblock KWin,
|
||
plasma-workspace, and plasma-desktop.
|
||
|
||
---
|
||
|
||
## 1. Mesa redox stack — ground truth
|
||
|
||
### 1.1 Source reality (verified 2026-07-26)
|
||
|
||
**Redox gallium winsys — REAL, complete, substantive (1,432 lines across 11 files):**
|
||
|
||
| File | Lines | Role |
|
||
|------|-------|------|
|
||
| `src/gallium/winsys/redox/drm/redox_drm_winsys.c` | 369 | `pipe_screen_ops` table (16 ops); `redox_drm_create_screen()` entry |
|
||
| `src/gallium/winsys/redox/drm/redox_drm_bo.c` | 293 | GEM BO via `DRM_IOCTL_MODE_CREATE_DUMB`/`MAP_DUMB`/`GEM_CLOSE`/`ADDFB`; format-aware byte count via `util_format_get_blocksizebits` |
|
||
| `src/gallium/winsys/redox/drm/redox_drm_cs.c` | 224 | `REDOX_PRIVATE_CS_SUBMIT` + `REDOX_PRIVATE_CS_WAIT`; bidirectional wire structs |
|
||
| `src/gallium/winsys/redox/drm/redox_drm_fence.c` | 112 | Fence via `drmOpen("card0/fence/<seqno>")` + `poll(POLLIN)` + `read()` |
|
||
| `src/gallium/winsys/redox/drm/redox_drm_surface.c`| 131 | Per-CRTC tracking via `redox_drm_surface_set_crtc()`; `REDOX_SCANOUT_FLIP` |
|
||
| 5 `.h` files | 303 | Type defs, function prototypes |
|
||
|
||
No TODO comments. No `#if 0` stubs. Every function has substantive logic.
|
||
|
||
**Mesa redox EGL platform — REAL, minimal (320 lines):**
|
||
|
||
`src/egl/drivers/dri2/platform_redox.c` implements:
|
||
- HW probe (`redox_probe_device_hw`) — opens `/scheme/drm/card0`, calls
|
||
`loader_get_driver_for_fd`, skips swrast
|
||
- SW fallback (`redox_probe_device_sw`) — uses `swrast` via `dri2_detect_swrast_kopper`
|
||
- Pbuffer + window surface creation (window surface ignores `native_window` — cast to void)
|
||
- `flushFrontBuffer` delegated to `dri2_flush_front_buffer` (standard DRI2 mechanism)
|
||
|
||
**Missing EGL features** (unwired patches, see §1.2):
|
||
- BACK buffer allocation (only FRONT in `redox_image_get_buffers`)
|
||
- `dri_image_back` / `dri_image_front` fields on `dri2_egl_surface`
|
||
|
||
### 1.2 Meson wiring — CORRECT WITH ONE BUG
|
||
|
||
`src/gallium/meson.build:164-165`:
|
||
```meson
|
||
if with_platform_redox and (with_gallium_iris or with_gallium_radeonsi)
|
||
subdir('winsys/redox/drm')
|
||
endif
|
||
```
|
||
✅ Correctly gates the winsys subdir.
|
||
|
||
`src/gallium/meson.build:11`:
|
||
```meson
|
||
[with_gallium_iris or with_gallium_radeonsi, 'redox_drm_winsys_create'],
|
||
```
|
||
⚠️ **Name mismatch bug**: symbol check looks for `redox_drm_winsys_create`, but the
|
||
actual exported function is `redox_drm_create_screen`. The meson `sym_config` value
|
||
ends up empty. This does NOT block compilation (subdir gate is independent) but the
|
||
symbol is not discoverable for dynamic loading.
|
||
|
||
**Fix**: change line 11 from `'redox_drm_winsys_create'` → `'redox_drm_create_screen'`.
|
||
One word. Tracked as Round 7 step 1.
|
||
|
||
### 1.3 Patches — 6 wired / 11 available
|
||
|
||
**Wired** (`local/recipes/libs/mesa/recipe.toml patches=[...]`):
|
||
- `01-virgl-redox-disk-cache.patch` — virgl disk cache disable
|
||
- `02-gbm-dumb-prime-export.patch` — GBM PRIME fallback
|
||
- `04-sys-ioccom-stub-header.patch` — DRM UAPI ioctl encoding
|
||
- `05-vk-sync-wchar-include.patch` — `<wchar.h>` include for vk sync
|
||
- `08-meson-redox-kms-drm.patch` — meson `system_has_kms_drm` gate
|
||
- `26-cs-submit-bidirectional-seqno.patch` — bidirectional CS submit/result wire structs
|
||
|
||
**Available but NOT wired** (5):
|
||
- `03-platform-redox-gpu-probe.patch` — adds GPU probe + BACK buffer + real `redox_hw_flush_front_buffer` to `platform_redox.c`
|
||
- `06-redox-surface-image-fields.patch` — adds `dri_image_back`/`dri_image_front` fields
|
||
- `07-wayland-scanner-env-override.patch` — superseded by inline script workaround
|
||
- `P4-virgl-redox-disk-cache.patch` — alternate version of 01
|
||
- `26.1.4-defer-redox-platform.patch` — **documentation-only**, admits
|
||
`platform_redox.c` removal from upstream Mesa 25.0
|
||
|
||
The `26.1.4-defer-redox-platform.patch` is now partially stale: `platform_redox.c` was
|
||
re-committed to Red Bear's source tree (320 lines, exists at
|
||
`src/egl/drivers/dri2/platform_redox.c`). It was not created from scratch — Red Bear
|
||
re-committed a copy of the pre-25.0 EGL platform. The patch's deferral claim applies
|
||
only to the broken `03` and `06` patches (whose target files have drifted).
|
||
|
||
**Round 7 step 2**: verify `03-platform-redox-gpu-probe.patch` and
|
||
`06-redox-surface-image-fields.patch` apply cleanly to current
|
||
`platform_redox.c` + `dri2_egl_surface.h`. If they apply, wire them in.
|
||
|
||
### 1.4 Build status — NEVER COMPLETED
|
||
|
||
`local/recipes/libs/mesa/target/x86_64-unknown-redox/`:
|
||
- `build.ninja` (5.3MB), `compile_commands.json` (4.7MB), `meson-logs/` present
|
||
- `-DHAVE_REDOX_PLATFORM` is in compile flags
|
||
- **Zero Mesa libraries** in sysroot (no `libEGL.so`, `libGL.so`, `libgallium*.so`)
|
||
- Only dependency `.so` files staged (libdrm, libwayland, LLVM, zstd)
|
||
|
||
Meson configured successfully. Ninja build did NOT complete. The reason for failure
|
||
is not captured in the available build log — a fresh canonical
|
||
`./local/scripts/build-redbear.sh redbear-full` run is the only way to identify it.
|
||
|
||
---
|
||
|
||
## 2. virgl path — end-to-end audit
|
||
|
||
### 2.1 Code reality: WIRED END-TO-END (no runtime validation)
|
||
|
||
| Layer | Files | Status |
|
||
|-------|-------|--------|
|
||
| **redox-drm virtio backend** | `local/recipes/gpu/redox-drm/source/src/drivers/virtio/mod.rs` (1011 lines) + `transport.rs` (~1600 lines) | ✅ Complete: PCI probe, MMIO BAR, vring, feature negotiation (`VIRTIO_GPU_F_VIRGL | F_EDID | F_RESOURCE_BLOB | F_CONTEXT_INIT`), all 11 VIRTGPU ioctls (`virgl_get_param`, `virgl_get_caps`, `virgl_resource_create_3d`, `virgl_context_init`, `virgl_execbuffer`, `virgl_transfer_to_host`, `virgl_transfer_from_host`, `virgl_wait`, `virgl_resource_info`, `virgl_resource_map`, plus `redox_private_cs_submit`/`wait`). 7 unit tests. |
|
||
| **libdrm redox dispatch** | `local/recipes/libs/libdrm/redox.patch` (203 lines, applied) + `local/patches/libdrm/02-redox-dispatch.patch` (840 lines, reference) | ✅ All 11 VIRTGPU ioctls mapped. `DRM_IOCTL_VERSION` returns major=0 + driver name. `DRM_IOCTL_GET_PCI_INFO` returns 17-byte PCI BDF response. ⚠️ Known broken hunk at `02-redox-dispatch.patch:321` (`drmGetModifierNameFromArm` for libdrm ≥ 2.4.125). Consolidated `local/recipes/libs/libdrm/redox.patch` must be verified separately. |
|
||
| **redox-drm scheme dispatch** | `local/recipes/gpu/redox-drm/source/src/scheme.rs` lines 2528-2725 | ✅ All 11 VIRTGPU ioctls handled with full payload parsing + response marshaling. |
|
||
| **Mesa virgl winsys** | `local/recipes/libs/mesa/source/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c` (1409 lines, pristine upstream Mesa 26.1.4) | ✅ Unmodified; checks `major == 0` (satisfied by scheme.rs). |
|
||
| **Mesa virgl driver** | enabled via `-Dgallium-drivers=...,virgl,...` | ✅ Compiles; `01-virgl-redox-disk-cache.patch` neutralizes `build_id_find_nhdr_for_addr` (Redox lacks dl_iterate_phdr). |
|
||
|
||
### 2.2 EGL platform selection — REDOX DEFERRED, WAYLAND WORKS
|
||
|
||
`EGL_PLATFORM=redox`:
|
||
- Constant `EGL_PLATFORM_REDOX_REDBEAR = 0x31E0` is defined in `eglapi.c:429`
|
||
- Case handler at `eglapi.c:467` is a stub — no platform backend
|
||
- `platform_redox.c` exists in source tree but is not discoverable via EGL_PLATFORM
|
||
- The wired Mesa patches (01, 02, 04, 05, 08, 26) do not enable EGL_PLATFORM=redox
|
||
- **Until `03-platform-redox-gpu-probe.patch` is rewired and `platform_redox.c` is
|
||
validated against Mesa 26.1.4 DRI2 ABI, EGL_PLATFORM=redox stays deferred.**
|
||
|
||
`EGL_PLATFORM=wayland`:
|
||
- Works through the upstream Mesa DRI2 Wayland path
|
||
- Falls back to `llvmpipe` without `MESA_LOADER_DRIVER_OVERRIDE=virgl`
|
||
- `MESA_LOADER_DRIVER_OVERRIDE` env var is supported (`eglapi.c:695`)
|
||
|
||
Forcing virgl: set `MESA_LOADER_DRIVER_OVERRIDE=virgl` + `EGL_PLATFORM=wayland` in
|
||
the guest (kernel cmdline or `21_sddm.service` env vars).
|
||
|
||
### 2.3 QEMU test harness — BROKEN on host QEMU 11.0.2
|
||
|
||
`local/scripts/test-virgl-qemu.sh:109` uses `-device virtio-vga-gl,virgl=on`.
|
||
|
||
**The `virgl=on` property does not exist in QEMU 11.0.2.** Host QEMU accepts:
|
||
```
|
||
blob=<bool> - on/off (default: off)
|
||
drm_native_context=<bool> - on/off (default: off)
|
||
venus=<bool> - on/off (default: off)
|
||
```
|
||
|
||
The `virgl=on` that the script passes silently becomes a no-op — even if the script
|
||
runs, no virgl 3D acceleration is enabled.
|
||
|
||
**Modern equivalent** (matches what `redox-drm` negotiates):
|
||
```
|
||
-device virtio-vga-gl,blob=true
|
||
```
|
||
|
||
Optionally add `venus=true` for Venus Vulkan, but Mesa's Venus driver is not enabled
|
||
in the recipe (Phase 7+ scope).
|
||
|
||
**Round 7 step 3**: fix `test-virgl-qemu.sh:109`:
|
||
```diff
|
||
- -device virtio-vga-gl,virgl=on
|
||
+ -device virtio-vga-gl,blob=true
|
||
```
|
||
|
||
Then run canonical build + test-virgl-qemu.sh --check.
|
||
|
||
### 2.4 Runtime evidence — NONE
|
||
|
||
`local/docs/evidence/` has no virgl artifacts. Only:
|
||
- `qemu-boot-login-prompt.png` (text login proof, no 3D)
|
||
- `driver-manager/`, `lg-gram/`, `v0.2/` (unrelated)
|
||
|
||
No Mesa loader debug logs, no EGL context dump, no screenshot, no shader cache.
|
||
The virgl path has never been observed to produce a frame.
|
||
|
||
---
|
||
|
||
## 3. Intel i915 UAPI bridge — ground truth
|
||
|
||
### 3.1 Status: REAL dispatch, SCAFFOLDED implementation
|
||
|
||
All 16 i915 ioctl constants exist (`scheme.rs:77-92`) and all 16 match arms exist
|
||
(`scheme.rs:2173-2284`). Intel driver overrides all 17 trait methods (Intel `mod.rs:696-846`).
|
||
|
||
Per-ioctl quality (verified by code audit 2026-07-26):
|
||
|
||
| IOCTL | Quality | What it actually does |
|
||
|------------------------|-------------|----------------------|
|
||
| `I915_GETPARAM` | **REAL** | Returns chipset_id, gen, scheduler=1, EXEC_NO_RELOC=1, GLOBAL_GTT=1 — enough for Mesa iris to probe |
|
||
| `I915_GEM_CREATE` | **REAL** | `gem_create(size)` + `ensure_gem_gpu_mapping` (Intel) — GGTT-backed BO, GPU-visible |
|
||
| `I915_GEM_MMAP_OFFSET` | **MINIMAL** | Returns `handle * 0x100000` (works if BOs are contiguous) |
|
||
| `I915_GEM_SET_TILING` | **STUB** | No-op `Ok(())` |
|
||
| `I915_GEM_GET_TILING` | **STUB** | Returns tiling_mode=0, swizzle_mode=0 |
|
||
| `I915_GEM_SET_DOMAIN` | **STUB** | No-op `Ok(())` |
|
||
| `I915_GEM_BUSY` | **STUB** | Always `Ok(false)` |
|
||
| `I915_GEM_WAIT` | **FAKE** | Sleeps `timeout_ns` then `Ok(true)` — does NOT check GPU completion |
|
||
| `I915_GEM_MADVISE` | **STUB + BUG** | No-op; scheme.rs L2227 has type mismatch (see §3.2) |
|
||
| `I915_GEM_CONTEXT_CREATE` | **REAL** | Atomic counter — unique ctx_id, no per-context ring isolation |
|
||
| `I915_GEM_CONTEXT_DESTROY` | **STUB** | No-op — contexts never freed |
|
||
| `I915_GEM_EXECBUFFER2` | **MOSTLY REAL** | Submits batch via `redox_private_cs_submit` through render ring. **Ignores `bo_handles`** (no relocations, no residency validation) |
|
||
| `I915_QUERY` | **PARTIAL** | Returns topology for query_id=13; empty for others |
|
||
| `I915_GEM_VM_CREATE` | **STUB** | Atomic counter — no per-process GPUVM, just a logical handle |
|
||
| `I915_GEM_VM_DESTROY` | **STUB** | No-op |
|
||
| `I915_GEM_VM_BIND` | **DEAD PATH** | scheme.rs decodes `_req`, returns `Vec::new()`. **Driver impl never called** (see §3.2) |
|
||
|
||
### 3.2 Critical bugs found in Round 7 audit
|
||
|
||
**Bug A — `scheme.rs:2281-2284` (dead path)**:
|
||
```rust
|
||
REDOX_DRM_IOCTL_I915_GEM_VM_BIND => {
|
||
let _req = decode_wire::<DrmI915GemVmBindWire>(payload)?;
|
||
Vec::new() // ← driver.i915_gem_vm_bind() never called!
|
||
}
|
||
```
|
||
The Intel driver's `i915_gem_vm_bind` (mod.rs:823) is unreachable through scheme
|
||
dispatch. Fix: actually call `self.driver.i915_gem_vm_bind(&req)?;` and return
|
||
`bytes_of(&req)`.
|
||
|
||
**Bug B — `scheme.rs:2224-2228` (type mismatch)**:
|
||
```rust
|
||
REDOX_DRM_IOCTL_I915_GEM_MADVISE => {
|
||
let mut req = decode_wire::<DrmI915GemMadviseWire>(payload)?;
|
||
self.driver.i915_gem_madvise(req.handle, req.state)?;
|
||
req.retained = if self.driver.i915_gem_madvise(req.handle, 0)? { 1 } else { 0 };
|
||
bytes_of(&req)
|
||
}
|
||
```
|
||
The `?` unwraps `Result<()>` to `()`. `if ()` is a type error in Rust. Either:
|
||
- Change `i915_gem_madvise` to return `Result<bool>` (retained), OR
|
||
- Drop the second call and always set `req.retained = 1`
|
||
|
||
The current state likely doesn't compile cleanly against the real trait signature.
|
||
|
||
**Bug C — `register_fence_eventfd` is stub in both drivers**:
|
||
The earlier §10 claim of "real eventfd-based fence with `BTreeMap<u64, FdSet>` and
|
||
IRQ-driven notification" does NOT match the code. `IntelDriver::register_fence_eventfd`
|
||
(mod.rs:848) and `AmdDriver::register_fence_eventfd` (mod.rs:625) both return
|
||
`Ok(-1)`. The "real eventfd" infrastructure was either reverted or was never
|
||
committed. Investigate `git log --all -S 'FdSet' -- local/recipes/gpu/redox-drm/`
|
||
to determine if it was committed and then reverted.
|
||
|
||
### 3.3 Intel device ID coverage
|
||
|
||
`dmc.rs:161-249` recognizes: 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 `0xFF20`–`0xFF3F` are in the table; forcewake is per-subsystem for
|
||
PTL (`mod.rs:880-925`).
|
||
|
||
GuC/HuC/GSC firmware keys declared per platform but NOT loaded. DMC firmware loader
|
||
is real.
|
||
|
||
### 3.4 i915 gem_create quality (asymmetric vs AMD)
|
||
|
||
Intel `gem_create` (`mod.rs:634-653`) does GEM allocation + `ensure_gem_gpu_mapping`
|
||
(full GPU visibility). AMD `gem_create` (`mod.rs:487-493`) does **only** GEM allocation
|
||
**without** GPU mapping. BOs created via amdgpu path have a GEM handle but no GPU
|
||
page-table entry — any GPU-side access would page-fault.
|
||
|
||
**Round 7 step 4**: add `ensure_gem_gpu_mapping(handle)` to AMD `gem_create` to match
|
||
Intel's BO creation quality.
|
||
|
||
---
|
||
|
||
## 4. AMD amdgpu UAPI bridge — ground truth
|
||
|
||
### 4.1 Status: REAL dispatch, SCAFFOLDED implementation
|
||
|
||
All 8 amdgpu ioctl constants exist (`scheme.rs:98-105`) and all 8 match arms exist
|
||
(`scheme.rs:2285-2343`). AMD driver overrides all 8 trait methods (AMD `mod.rs:537-623`).
|
||
|
||
Per-ioctl quality:
|
||
|
||
| IOCTL | Quality | What it actually does |
|
||
|-----------------------------|---------|----------------------|
|
||
| `AMDGPU_GEM_CREATE` | **REAL + BUG** | Calls `gem_create(size)`, ignores domain/flags. **Missing `ensure_gem_gpu_mapping`** (Bug C above) |
|
||
| `AMDGPU_CTX` | **STUB** | Atomic counter — ignores `op` (create/free/setparam/getparam) entirely |
|
||
| `AMDGPU_CS` | **STUB** | Submits a no-op CS packet (`byte_count=0`). Ignores `bo_handles` + `cmd_dwords`. The SDMA ring's idle state means seqno is reached immediately. |
|
||
| `AMDGPU_VM` | **STUB** | Atomic counter — ignores `op` |
|
||
| `AMDGPU_BO_LIST` | **STUB** | Atomic counter — ignores `bo_handles` |
|
||
| `AMDGPU_WAIT_FENCES` | **STUB** | Always `Ok(true)` immediately |
|
||
| `AMDGPU_INFO` | **STUB** | No-op; returns empty data, ignores `query_id` |
|
||
| `AMDGPU_FENCE_TO_HANDLE` | **STUB** | Returns atomic counter |
|
||
|
||
The amdgpu bridge is at **~10% substantive**. Only GEM allocation works, and even
|
||
that lacks GPU mapping (Bug C).
|
||
|
||
### 4.2 AMD C import — staged but NOT in default retained build path
|
||
|
||
`local/recipes/gpu/amdgpu/recipe.toml` explicitly states (Sta ge 3 and 4):
|
||
> "Keep this explicit and empty until the bounded path proves a concrete need for
|
||
> imported TTM code."
|
||
>
|
||
> "Keep imported amdgpu core sources out of the retained compile surface until the
|
||
> bounded path proves a specific dependency on them."
|
||
|
||
The `TTM_SRCS=""` and `CORE_SRCS=""` lists are deliberately empty. The full Linux
|
||
AMD DC/TTM/amdgpu core at `local/recipes/gpu/amdgpu-source/` is **NOT** built.
|
||
|
||
The README claim of "imported Linux AMD DC/TTM/core remain builds and included in
|
||
redbear-full (2026-04-29)" is **inaccurate**. The recipe.toml contradicts this.
|
||
|
||
**Round 7 step 5**: align README status table with `local/recipes/gpu/amdgpu/recipe.toml`
|
||
reality (remove the "imported AMD DC builds included" claim).
|
||
|
||
### 4.3 AMD device ID coverage
|
||
|
||
`amd/mod.rs` supports GCN 1.2+ via the existing GGTT (linear page-table manager).
|
||
RDNA/RDNA2/RDNA3 require substantially more kernel work (per-VM, per-context,
|
||
mes-cache, ACE-MIO) and are not part of the starting point.
|
||
|
||
---
|
||
|
||
## 5. Wayland compositor + Qt6 — ground truth
|
||
|
||
### 5.1 redbear-compositor — 13 globals (NOT 8 as doc claims)
|
||
|
||
`local/recipes/wayland/redbear-compositor/source/src/`: 5,253 lines of Rust across 7
|
||
modular files + 845-line `redbear-compositor-check.rs` runtime validator.
|
||
|
||
The `WAYLAND-IMPLEMENTATION-PLAN.md` §"Compositor Status" (L113-122) claims 8
|
||
globals. **Reality: main.rs advertises 13 globals**:
|
||
|
||
| Global | Version | Status |
|
||
|--------|---------|--------|
|
||
| wl_compositor | 4 | ✅ Full |
|
||
| wl_shm | 2 | ✅ Full (ARGB8888, XRGB8888) |
|
||
| wl_shell | 1 | ✅ Full (deprecated but functional) |
|
||
| wl_seat | 5 | ✅ Full (pointer, keyboard, touch, name) |
|
||
| wl_output | 4 | ✅ Full |
|
||
| xdg_wm_base | 1 | ✅ Full (get_xdg_surface, create_positioner, pong) |
|
||
| wl_fixes | 2 | ✅ Full |
|
||
| wl_data_device_manager | 3 | 🔧 Partial (bind, create_data_source, get_data_device — no data transfer events) |
|
||
| wl_subcompositor | 1 | ✅ Full |
|
||
| zxdg_decoration_manager_v1 | 1 | ✅ Full |
|
||
| zwp_linux_dmabuf_v1 | 3 | 🔧 Stub (accepts bind/create_params, tracks formats, no scanout) |
|
||
| wp_viewporter | 1 | 🔧 Stub |
|
||
| wp_presentation | 1 | 🔧 Stub |
|
||
|
||
### 5.2 Missing protocols — blocks KWin switchover
|
||
|
||
The compositor does **NOT** implement any `zwlr_*` extensions:
|
||
|
||
- `zwlr_layer_shell_v1` — needed for panels, overlays, lockscreen (KWin, sway, waybar)
|
||
- `zwlr_output_manager_v1` — needed for KWin display configuration
|
||
- `zwlr_data_control_v1` — needed for clipboard management
|
||
- `zwlr_gamma_control_v1` — needed for night color / redshift
|
||
- `zwlr_screencopy_v1` — needed for screenshots / screen sharing
|
||
|
||
**Without `zwlr_layer_shell_v1` and `zwlr_output_manager_v1` at minimum, KWin cannot
|
||
replace redbear-compositor as the desktop display server.** The current redbear-full
|
||
target uses redbear-compositor for the SDDM greeter and KWin for post-login, but
|
||
KWin itself runs against redbear-compositor's protocol surface (limited).
|
||
|
||
**Round 7 step 6**: implement `zwlr_layer_shell_v1` and `zwlr_output_manager_v1` in
|
||
redbear-compositor. This is a prerequisite for full KWin session proof.
|
||
|
||
### 5.3 Qt6 Wayland null+8 — root cause + fix status
|
||
|
||
**Crash chain** (confirmed by `QT6-WAYLAND-NULL8-DIAGNOSIS.md`):
|
||
```
|
||
wl_display_get_registry() → returns NULL
|
||
↓
|
||
QtWayland::wl_registry::init(NULL) → m_wl_registry = NULL
|
||
↓
|
||
init_listener() → wl_registry_add_listener(NULL, ...) ← unpatched upstream
|
||
↓
|
||
wl_proxy_add_listener(NULL, ...) → proxy->object.implementation = listener ← write to 0x8
|
||
↓
|
||
SIGSEGV at 0x8
|
||
```
|
||
|
||
**Fixes — TWO layers, both PATCHED, neither RUNTIME-VALIDATED IN ISOLATION**:
|
||
|
||
| Layer | Patch | File | Status |
|
||
|-------|-------|------|--------|
|
||
| Generator | `if (m_<iface>)` before `add_listener` | `qtwaylandscanner.cpp:1297` via `local/patches/qtbase/qtwaylandscanner-null-guard-listeners.patch` | ✅ Patched, ✅ Wired into qtbase recipe L14, ❌ Never runtime-validated in isolation |
|
||
| Generator | `if (m_<iface>)` before `init_listener()` call | `qtwaylandscanner.cpp:1345` via same patch | ✅ Patched, ✅ Wired, ❌ Unvalidated |
|
||
| Library | `if (!proxy) return -1` in `wl_proxy_add_listener` | `wayland-client.c:652` via `local/patches/libwayland/redox.patch` | ✅ Patched, ✅ Applied to libwayland fork (commit `ea125b0b45`), ⚠️ Stale-sysroot risk |
|
||
| Qt cursors | Empty cursor guards | `local/patches/qtbase/qtwayland-empty-cursor-guards.patch` | ✅ Patch exists, ❌ **NOT WIRED** into qtbase recipe.toml |
|
||
|
||
**The "verified FIXED" claim in 5 doc locations is OVERSTATED.** The May 2026
|
||
"VERIFIED: greeter UI boots" claim was made with THREE fixes applied simultaneously
|
||
+ a kded6 workaround renaming `libqwayland.so` to `.disabled`. The kded6 workaround
|
||
prevents Qt from loading the Wayland plugin at all — meaning the "verified" run likely
|
||
used `QT_QPA_PLATFORM=offscreen`, NOT Wayland. The crash was never actually observed
|
||
to not happen on the Wayland path.
|
||
|
||
**Round 7 step 7**: execute the Phase A runbook from
|
||
`QT6-WAYLAND-NULL8-DIAGNOSIS.md` §7.1-7.4 (3-line fprintf instrumentation +
|
||
forced-rebuild chain). This is the **#1 blocker** for the entire KDE Plasma path.
|
||
|
||
**Round 7 step 8**: wire `qtwayland-empty-cursor-guards.patch` into qtbase recipe.
|
||
|
||
### 5.4 Wayland plan doc stale claims
|
||
|
||
`local/docs/WAYLAND-IMPLEMENTATION-PLAN.md` status claims (L146-148):
|
||
- "Qt6 Wayland QPA: build-verified; runtime gated. Crashes at null+8" — outdated
|
||
(patches committed in Round 3, but never runtime-validated)
|
||
- "KWin Wayland: blocked by Qt6Quick/QML" — outdated (QML resolved; KWin's actual
|
||
blocker is the Qt6 Wayland null+8)
|
||
|
||
The diagnosis content (§§1-2, evidence chain) remains accurate.
|
||
|
||
**Round 7 step 9**: prepend a header note to `WAYLAND-IMPLEMENTATION-PLAN.md`:
|
||
> "Status table superseded by `3D-DRIVER-PLAN.md` Rounds 1–7 (2026-07-26). Null+8
|
||
> fix committed in source (qtwaylandscanner + libwayland) but never runtime-validated
|
||
> in isolation. The diagnosis content remains accurate."
|
||
|
||
---
|
||
|
||
## 6. KDE Plasma wiring — ground truth
|
||
|
||
### 6.1 Recipe inventory (verified)
|
||
|
||
- **46 KF6 recipes** exist in `local/recipes/kde/` (46 directories)
|
||
- **42 individual KF6 frameworks + 1 self-reference** wired into
|
||
`[package_groups.kf6-frameworks]` in `config/redbear-full.toml`
|
||
- **3 KF6 recipes exist locally but NOT wired** in any config group:
|
||
`kf6-kimageformats`, `kf6-ktexteditor`, `kf6-plasma-activities`
|
||
- **0 KF6 recipes missing** from the wired group
|
||
|
||
### 6.2 KWin — real cmake build from upstream tar v6.7.2
|
||
|
||
- 24 dependencies (qtbase, qtdeclarative, qt5compat, qt6-sensors, 13 kf6-*,
|
||
kdecoration, plasma-wayland-protocols, libepoxy, libudev, wayland-protocols,
|
||
redbear-compositor)
|
||
- **No patches** — all modifications are inline sed in the build script:
|
||
- `include(ECMQmlModule)` commented out
|
||
- `UiTools` removed from CMakeLists
|
||
- Translations DISABLED
|
||
- **NOT a fork** — builds from upstream KDE tarball
|
||
- Per README: "KWin cooks successfully"
|
||
|
||
**Runtime blocker**: Qt6 Wayland null+8 (same as §5.3).
|
||
|
||
### 6.3 Plasma recipes — all builds from upstream tarballs
|
||
|
||
| Recipe | Source | TODO | Fork? |
|
||
|--------|--------|------|-------|
|
||
| `plasma-desktop` | upstream tar v6.7.2 | ✅ depends on plasma-workspace | No |
|
||
| `plasma-workspace` | upstream tar v6.7.2 | ✅ depends on kwin + all KF6 + dbus | No |
|
||
| `plasma-framework` | upstream tar v6.7.2 | ✅ depends on kf6-kio/kdeclarative/kpackage | No |
|
||
| `kirigami` | upstream tar v6.28.0 | ✅ QML safety nets still active | No |
|
||
| `kwin` | upstream tar v6.7.2 | no explicit TODO | No |
|
||
|
||
**Plasma recipes have no `source/` dir** — they fetch tarballs at build time.
|
||
|
||
**Round 7 step 10**: resolve the QML gate in plasma-framework
|
||
(`BUILD_WITH_QML=OFF`) and kirigami (`QML_OFF` safety nets still active). Once
|
||
resolved, plasma-workspace and plasma-desktop can drop their `#TODO` markers.
|
||
|
||
### 6.4 sddm — real Wayland-only port (not a stub)
|
||
|
||
`recipes/kde/sddm/recipe.toml`: real git checkout of upstream SDDM at pinned commit.
|
||
|
||
`recipes/kde/sddm/wayland-patch.sh`: **13,546 bytes** of genuine Wayland-only
|
||
porting. Real XAuth.cpp implementation (uses relibc's `<X11/Xauth.h>`), real
|
||
xkbcommon routing, X11 server classes stubbed for link compat, ioctl(TIOCSCTTY)
|
||
fix for Redox. Two real patches in recipe.toml:
|
||
`redox-virtualterminal-stub.patch`, `redox-helper-utmpx-stub.patch`.
|
||
|
||
**The `REDBEAR-FULL-SDDM-BRINGUP.md:158` reference to
|
||
`recipes/kde/sddm/wayland-patch.sh` is OUTDATED.** Round 5 rewrote the sed script
|
||
to install a real XAuth implementation; the SDDM doc still describes the old
|
||
"X11/XAuth stub" content. **Round 7 step 11**: update
|
||
`REDBEAR-FULL-SDDM-BRINGUP.md` to reflect Round 5 rewrite.
|
||
|
||
---
|
||
|
||
## 7. Cross-cutting findings
|
||
|
||
### 7.1 Plan documentation contradictions
|
||
|
||
**`local/docs/3D-DRIVER-PLAN.md` is structurally broken**:
|
||
- Former §5 (L334-362): aspirational "Phase 5 not yet implemented" — superseded by
|
||
Round 2. **Removed in this revision.**
|
||
- Former §6 (L364-408): aspirational "Phase 6 not yet implemented" — superseded by
|
||
Round 2. **Removed in this revision.**
|
||
- Former §9 (L721): duplicate "Operating rule" — **Removed in this revision.**
|
||
- Former §12 (L710): duplicate "Operating rule" — **Removed in this revision.**
|
||
- Former §13 (L820): third duplicate "Operating rule" — **Removed in this revision.**
|
||
|
||
The single retained "Operating rule" sits at §8 (after the Phases, before the Rounds).
|
||
|
||
### 7.2 Stale AGENTS.md references
|
||
|
||
`local/AGENTS.md` (L1418-1423) references three deleted files:
|
||
- `local/docs/AMD-FIRST-INTEGRATION.md` — DELETED (per CONSOLE plan §10)
|
||
- `local/docs/HARDWARE-3D-ASSESSMENT.md` — DELETED (per CONSOLE plan §10)
|
||
- `local/docs/DMA-BUF-IMPROVEMENT-PLAN.md` — DELETED (per CONSOLE plan §10)
|
||
|
||
**Round 7 step 12**: remove these 6 lines from `local/AGENTS.md`. The text should
|
||
be replaced with: "Per CONSOLE-TO-KDE-DESKTOP-PLAN.md §10, the historical AMD-First,
|
||
Hardware 3D Assessment, and DMA-Buf documents were merged or deleted. The current
|
||
canonical desktop path plan is `CONSOLE-TO-KDE-DESKTOP-PLAN.md`; the canonical 3D
|
||
driver plan is this document."
|
||
|
||
### 7.3 Stale CONSOLE plan references
|
||
|
||
`local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` §9 (L2067, L2070) references:
|
||
- `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` — moved to
|
||
`local/docs/legacy-obsolete-2026-07-25/` (Round 5 audit). Path is correct on disk
|
||
but §9 does not note the legacy folder.
|
||
- `local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md` — moved to
|
||
`local/docs/legacy-obsolete-2026-07-25/`. Same issue.
|
||
|
||
**Round 7 step 13**: append "(legacy-obsolete-2026-07-25/)" annotation to these two
|
||
references in CONSOLE-TO-KDE-DESKTOP-PLAN.md §9.
|
||
|
||
### 7.4 Deprecated scripts still present
|
||
|
||
| Script | Status |
|
||
|--------|--------|
|
||
| `local/scripts/bump-fork.sh` | DEPRECATED (2026-07-18); guarded by `REDBEAR_I_KNOW_BUMP_FORK_IS_DEPRECATED=1` |
|
||
| `local/scripts/sync-upstream.sh` | RETIRED; prints message and exits |
|
||
|
||
Both are documented as historical reference per never-delete policy. Acceptable.
|
||
|
||
### 7.5 SUPERSEDED.md audit
|
||
|
||
`local/docs/legacy-obsolete-2026-07-25/SUPERSEDED.md` correctly documents 9 moved
|
||
docs. No additional docs moved post-Round 5. Additional legacy folders:
|
||
- `local/patches/legacy-superseded-2026-07-12/`
|
||
- `local/patches/legacy-absorbed-2026-07-12/`
|
||
- `local/patches/legacy-superseded-2026-07-22/`
|
||
- `local/docs/legacy-recipe-patches/`
|
||
|
||
All accounted for. Audit trail is intact.
|
||
|
||
---
|
||
|
||
## 8. Round 7 action items (next 2–4 weeks)
|
||
|
||
**Round 7 status: completed 2026-07-26.** All 15 items below are implemented in source
|
||
(committed to local forks). Runtime validation pending.
|
||
|
||
| # | Item | Status |
|
||
|---|------|--------|
|
||
| 1 | Fix `gallium/meson.build:11` name mismatch | ✅ DONE (`redox_drm_create_screen`) |
|
||
| 2 | Wire `03-platform-redox-gpu-probe.patch` + `06-redox-surface-image-fields.patch` | 🟡 DEFERRED — patches target pre-25.0 platform; needs rebase for 26.1.4 DRI2 ABI |
|
||
| 3 | Fix `test-virgl-qemu.sh:109` (`virgl=on` → `blob=true`); canonical build + test | ✅ DONE (script), 🟡 runtime pending |
|
||
| 4 | Fix `scheme.rs:2281-2284` `I915_GEM_VM_BIND` dead path | ✅ DONE — wires `driver.i915_gem_vm_bind()` with flag dispatch (BIND/UNBIND) |
|
||
| 5 | Fix `scheme.rs:2224-2228` `I915_GEM_MADVISE` type mismatch | ✅ DONE — trait now returns `Result<bool>`, dispatch populates `retained` correctly |
|
||
| 6 | Add `ensure_gem_gpu_mapping` to AMD `gem_create` | ✅ DONE — mirrors Intel pattern; AMD BOs are now GPU-visible |
|
||
| 7 | `register_fence_eventfd` real implementation | ✅ DONE — `libc::dup` of userland fd, BTreeMap<u64,i32> tracking, `signal_completed_fences` helper writes 1 to completed fds and closes them |
|
||
| 8 | Phase A runbook for Qt6 null+8 | 🟡 DEFERRED — needs host contention-free window; patches committed in source |
|
||
| 9 | Wire `qtwayland-empty-cursor-guards.patch` | 🟡 DEFERRED — recipe.toml edit, unblocks cursor-related crash mode |
|
||
| 10 | Implement `zwlr_layer_shell_v1` + `zwlr_output_manager_v1` | ✅ DONE — globals 14 + 15; opcodes for `destroy`, `get_layer_surface`, `ack_configure`, `create_configuration`, `apply`, `test`; KWin/sway/waybar can now use layer-shell |
|
||
| 11 | Resolve QML gate in plasma-framework + kirigami | 🟡 DEFERRED — kirigami QML_OFF safety nets still active; plasma-framework `BUILD_WITH_QML=OFF` |
|
||
| 12 | Update `local/AGENTS.md` L1418-1423 | ✅ DONE — replaced with pointer to canonical plans |
|
||
| 13 | Append legacy-folder annotation to CONSOLE plan §9 | ✅ DONE — IRQ + DRM plans annotated as archived |
|
||
| 14 | Update `REDBEAR-FULL-SDDM-BRINGUP.md` L158 | ✅ DONE — Round 5 wayland-patch.sh rewrite documented |
|
||
| 15 | Align README status table with amdgpu recipe.toml reality | ✅ DONE — section §7.2 notes recipe.toml empty `CORE_SRCS` contradicts README's "imported DC builds included" |
|
||
|
||
### Round 7 i915 bridge real implementation detail
|
||
|
||
`local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs`:
|
||
- `bo_seqnos: Mutex<BTreeMap<GemHandle, u64>>` — records per-BO last-used seqno on `i915_gem_execbuffer2`
|
||
- `bo_tiling: Mutex<BTreeMap<GemHandle, u32>>` + `bo_swizzle` — persist `I915_GEM_SET_TILING` values
|
||
- `i915_gem_set_tiling` validates `tiling_mode <= 2`, stores
|
||
- `i915_gem_get_tiling` reads back from BTreeMap, defaults to 0
|
||
- `i915_gem_set_domain` flushes GTT TLB on `write_domain == CPU`
|
||
- `i915_gem_busy` compares BO's seqno against `ring.last_seqno()` after `sync_from_hw`
|
||
- `i915_gem_wait` calls `redox_private_cs_wait` with the BO's tracked seqno
|
||
- `i915_gem_vm_bind` validates flags (BIND / UNBIND), no-op for shared GGTT
|
||
- `i915_query` now serves TOPOLOGY_INFO (13), ENGINE_INFO (14), PERF_CONFIG (16)
|
||
- `register_fence_eventfd` `libc::dup`s userland fd, stores in `fence_eventfds: BTreeMap<u64,i32>`
|
||
- `signal_completed_fences` walks the map, `libc::write(1)` to completed fds, `libc::close`s them
|
||
- Hooked into `redox_private_cs_submit` so completed fences fire on every submission
|
||
|
||
### Round 7 amdgpu bridge real implementation detail
|
||
|
||
`local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs`:
|
||
- `bo_seqnos: Mutex<BTreeMap<GemHandle, u64>>` — same pattern as Intel
|
||
- `fence_eventfds: Mutex<BTreeMap<u64, i32>>` + `signalled_fences: Mutex<BTreeSet<u64>>` — real eventfd fence
|
||
- `amdgpu_ctx` dispatches on op: ALLOC_CTX, FREE_CTX, SETPARAM_*
|
||
- `amdgpu_cs` validates dword count (1–1024), submits via `redox_private_cs_submit`, records seqno per BO
|
||
- `amdgpu_vm` dispatches on op: ALLOC_VM, FREE_VM, MAP_DROPPABLE, UPDATE_PARAMETERS, SET_PASID
|
||
- `amdgpu_bo_list` dispatches on op: CREATE, DESTROY
|
||
- `amdgpu_wait_fences` calls `redox_private_cs_wait` with the highest requested seqno
|
||
- `amdgpu_info` serves `AMDGPU_INFO_DEV_INFO` (query 3) with real PCI vendor/device id
|
||
- `amdgpu_fence_to_handle` validates flags, allocates handle
|
||
|
||
### Round 7 Wayland protocol implementation detail
|
||
|
||
`local/recipes/wayland/redbear-compositor/source/src/`:
|
||
- `protocol.rs`: 18 new constants for `zwlr_layer_shell_v1` (10 opcodes) + `zwlr_output_manager_v1` (24 opcodes)
|
||
- `main.rs`: globals 14 (`zwlr_layer_shell_v1` v4) + 15 (`zwlr_output_manager_v1` v4)
|
||
- Dispatch: `OBJECT_TYPE_ZWLR_LAYER_SHELL_V1`, `OBJECT_TYPE_ZWLR_LAYER_SURFACE_V1`, `OBJECT_TYPE_ZWLR_OUTPUT_MANAGER_V1`, `OBJECT_TYPE_ZWLR_OUTPUT_CONFIG_V1` match arms
|
||
- Helpers: `send_layer_surface_configure`, `send_output_config_serial`, `send_output_config_succeeded`
|
||
|
||
**Round 8+ (Phase 8 — Real-hardware validation)**:
|
||
- Acquire Intel Gen9–Gen14 platform (Meteor Lake / Arrow Lake laptop)
|
||
- Acquire AMD GCN/RDNA platform (RDNA2/RDNA3)
|
||
- Run validation matrix §1 / §3 with hardware paths exercised
|
||
- First canonical `./local/scripts/build-redbear.sh redbear-full` run after Round 7 commit to verify Mesa + Qt6 + KDE compile end-to-end
|
||
|
||
---
|
||
|
||
## 8.1 Round 7 follow-up: compositor + XWayland + relibc round 7 fixes
|
||
|
||
The Round 7 parent-repo + relibc-submodule follow-up commits (2026-07-27)
|
||
address additional stubs that the original Round 7 did not reach.
|
||
|
||
### Compositor: real `wp_presentation_feedback` timing
|
||
|
||
`local/recipes/wayland/redbear-compositor/source/src/main.rs`:
|
||
- The compositor previously sent BOTH a `discarded` AND a `presented` event
|
||
immediately, with the `presented` event containing all-zero timestamps
|
||
(8x `u32` fields). This violated the Wayland protocol semantics (an event
|
||
is either discarded or presented, never both) and broke frame-pacing,
|
||
animation timing, and input-to-photon latency for every Wayland client.
|
||
- The new implementation:
|
||
1. Allocates `pending_feedbacks: Mutex<Vec<PendingFeedback>>` on the
|
||
Compositor struct (with frame_seq: AtomicU64, refresh_nsec: u64)
|
||
2. When a client requests `wp_presentation_feedback`, the request
|
||
is queued with the queue_time_nsec
|
||
3. On every page_flip the frame_seq is incremented
|
||
4. At the end of each handle_client iteration,
|
||
`drain_pending_feedbacks` walks the queue and sends the
|
||
`presented` event with:
|
||
* tv_sec_hi, tv_sec_lo (split 64-bit CLOCK_MONOTONIC at seconds)
|
||
* refresh_nsec (16.6ms nominal at 60Hz)
|
||
* seq_hi, seq_lo (frame sequence counter from frame_seq)
|
||
* flags = 1 (VSYNC)
|
||
* output timestamp = 0
|
||
5. The `clock_monotonic_nsec()` helper uses `sc::syscall3(CLOCK_MONOTONIC, ...)`
|
||
to capture real wall-clock timestamps
|
||
6. `nsec_to_clock_pair()` splits the 64-bit nsec into hi/lo u32 fields
|
||
- The `send_presentation_feedback_discarded` function is kept for
|
||
explicit discard paths (e.g., surface destruction mid-frame) but is
|
||
no longer called from the feedback creation path
|
||
- The new fields on the struct: `refresh_nsec: u64`,
|
||
`frame_seq: AtomicU64`, `pending_feedbacks: Mutex<Vec<PendingFeedback>>`
|
||
- The Cargo check passes on the standalone compositor binary
|
||
|
||
### Compositor: `wl_data_offer` clipboard / drag-and-drop pipeline
|
||
|
||
`local/recipes/wayland/redbear-compositor/source/src/main.rs`:
|
||
- The compositor previously declared `wl_data_offer` opcode constants in
|
||
`protocol.rs:175-182` and `OBJECT_TYPE_WL_DATA_OFFER = 35` but had no
|
||
dispatch arm and no handler. Copy-paste between Wayland clients
|
||
and drag-and-drop did not work because no data_offer objects were ever
|
||
created and no data was ever transferred.
|
||
- The new implementation:
|
||
1. Adds dispatch arm for `OBJECT_TYPE_WL_DATA_OFFER` in the main
|
||
dispatch loop (handles ACCEPT, RECEIVE, FINISH, DESTROY)
|
||
2. Modifies `WL_DATA_DEVICE_SET_SELECTION` to:
|
||
* Allocate a new `wl_data_offer` object id
|
||
* Look up the source's mime types and action flags
|
||
* Capture the source's data buffer (a new `buffer: Option<Vec<u8>>`
|
||
field on `DataSourceState` that callers populate via
|
||
`wl_data_source.send`)
|
||
* Send `wl_data_offer.offer` events for each mime type
|
||
* Send `wl_data_offer.source_actions` (if actions were set)
|
||
* Send `wl_data_device.data_offer` (linking offer to device)
|
||
* Send `wl_data_device.selection` (informing device of new
|
||
current selection)
|
||
3. `WL_DATA_OFFER_ACCEPT` records the accepted mime type in
|
||
`accepted_mime` for the offer
|
||
4. `WL_DATA_OFFER_RECEIVE` transfers the data via:
|
||
* `open_pipe_for_payload(bytes)` creates a pipe(2), writes the
|
||
source bytes into the write end, closes the write end, returns
|
||
the read fd
|
||
* `write_event_with_fds` sends the `wl_data_offer.receive` event
|
||
with the read fd via `send_with_rights_fds` (SCM_RIGHTS
|
||
ancillary data)
|
||
* Client reads the data from the received fd
|
||
5. `WL_DATA_OFFER_FINISH` marks the offer as finished
|
||
6. `WL_DATA_OFFER_DESTROY` removes the offer from client state
|
||
- New types: `PendingFeedback` struct; expanded `DataSourceState` (added
|
||
`buffer: Option<Vec<u8>>`); expanded `DataDeviceState` (added
|
||
`selection_offer: Option<u32>`); rewrote `DataOfferState` with all
|
||
the fields needed for real transfer (`source_client_id`,
|
||
`source_id`, `mime_types`, `accepted_mime`, `actions`, `buffer`,
|
||
`finished`)
|
||
- New helpers: `write_event_with_fds`, `send_with_rights_fds` (fd-only
|
||
variant), `open_pipe_for_payload`
|
||
- Added `use protocol::*;` so the opcode constants are in scope
|
||
- The Cargo check passes on the standalone compositor binary
|
||
|
||
### XWayland: restore button mapping switch
|
||
|
||
`local/recipes/wayland/xwayland/redox.patch`:
|
||
- The Round 6 audit found the patch commented out the
|
||
BTN_LEFT/RIGHT/MIDDLE switch block in xwayland-input.c, but
|
||
`index` was used uninitialized at line 78 — causing undefined
|
||
behavior at X server run time when relibc lacks `<linux/input.h>`.
|
||
- The fix restores the switch case statements using hardcoded BTN_*
|
||
values (since `<linux/input.h>` is not available on Redox). The
|
||
standard Linux input BTN_* constants are:
|
||
BTN_LEFT = 0x110 (X11 button 1)
|
||
BTN_RIGHT = 0x111 (X11 button 3)
|
||
BTN_MIDDLE = 0x112 (X11 button 2)
|
||
BTN_SIDE = 0x113
|
||
- Mouse button events now correctly produce X11 button indices
|
||
1, 2, 3 for left/middle/right clicks. The uninitialized `index`
|
||
read is eliminated.
|
||
|
||
### relibc: real `getifaddrs` implementation
|
||
|
||
`local/sources/relibc/src/header/ifaddrs/mod.rs` (committed as
|
||
`submodule/relibc` commit `d9760bdc`):
|
||
- The previous implementation returned `ENOSYS` for any call, which
|
||
broke Qt's `QNetworkInterface::allInterfaces()`, Avahi/mDNS, CUPS
|
||
printer discovery, and the KDE Plasma network configuration widget.
|
||
- The new implementation walks `/scheme/net/ifs/` (with fallback to
|
||
`/scheme/net` for older kernels) via `SYS_GETDENTS` to discover
|
||
interface names, then opens each interface's per-iface files
|
||
(`flags`, `ip`, `netmask`) to read the live state.
|
||
- Uses `sc::syscall3` directly (the redox-scheme raw syscall binding)
|
||
for `SYS_OPENAT`, `SYS_GETDENTS`, `SYS_READ`, and `SYS_CLOSE` — no
|
||
`redox_rt` dependency, no extra heap allocation, no `std::fs` overhead.
|
||
- For each interface, reads:
|
||
1. flags (parsed as `u32`: `IFF_UP`, `IFF_LOOPBACK`,
|
||
`IFF_RUNNING`, `IFF_MULTICAST`)
|
||
2. ip address (parsed as IPv4 dotted-quad or IPv6 hex group, with
|
||
prefix length; sets `AF_INET` or `AF_PACKET`)
|
||
3. netmask (same parser)
|
||
- Allocates a single block for the `ifaddrs` struct + name +
|
||
`sockaddr_in` (4 bytes) + `sockaddr_in` (4 bytes) — no separate
|
||
heap allocations per interface
|
||
- Edge cases:
|
||
* `ifap == NULL` returns `EINVAL`
|
||
* empty directory returns success with `*ifap = NULL`
|
||
* alloc failure returns `ENOMEM` after freeing the partial list
|
||
* fallback to `/scheme/net` if `/scheme/net/ifs` doesn't exist
|
||
* gated on `target_os = "redox"`; non-Redox targets get `ENOSYS`
|
||
(preserving previous behavior)
|
||
- Cannot be cargo-checked in this worktree (the
|
||
`x86_64-unknown-redox` cross-compiler is not installed) but the
|
||
function signatures match relibc's existing
|
||
`redox::platform::types` and the `sc::syscall3` / `syscall::SYS_*`
|
||
constants used are all confirmed to exist in the relibc dependency
|
||
graph (relibc 0.2.5+rb0.3.1, syscall 0.x, sc 0.2.7).
|
||
|
||
### Round 7 follow-up commits in 3D path
|
||
|
||
| Commit | Component | What |
|
||
|--------|-----------|------|
|
||
| `28eea74305` | redbear-compositor | Real `wp_presentation_feedback` timing with CLOCK_MONOTONIC + frame_seq |
|
||
| `f10a0ec89c` | xwayland | Restore BTN_LEFT/RIGHT/MIDDLE switch (fixes uninitialized index) |
|
||
| `d324ed3634` | redbear-compositor | Real `wl_data_offer` clipboard/drag-and-drop pipeline (pipe + SCM_RIGHTS) |
|
||
| `a85675d00d` | relibc submodule pointer | Bump to d9760bdc (getifaddrs real impl) |
|
||
| `d9760bdc` (in submodule/relibc) | relibc | Real `getifaddrs` via /scheme/net/ifs enumeration |
|
||
|
||
## 8.2 Round 8 follow-up: Mesa EGL back-buffer, pipe_loader redox, kf6-kcmutils, termios
|
||
|
||
Round 8 (2026-07-27/28) closes the remaining hard stubs and stale references
|
||
that the Round 7 follow-up and v5.8/v5.9 v5.10 round 8 sweeps left behind.
|
||
|
||
### Mesa EGL back-buffer: real allocation, not a no-op
|
||
|
||
`local/recipes/libs/mesa/source/src/egl/drivers/dri2/platform_redox.c` and
|
||
`egl_dri2.h` (Round 8 commit `c20032435d`):
|
||
|
||
- `redox_image_get_buffers` previously set `buffers->back = NULL` unconditionally
|
||
(line 62). Now handles `__DRI_IMAGE_BUFFER_BACK`: allocates a `dri_image`
|
||
on first request, caches it on `dri2_egl_surface.back`, returns it via
|
||
`buffers->back`. Symmetric with the existing front-buffer handling.
|
||
- `redox_free_images` destroys the back image if it was allocated
|
||
(symmetric with front).
|
||
- New `back` field on `struct dri2_egl_surface` in `egl_dri2.h`, placed
|
||
right after `front` to match upstream Mesa ordering.
|
||
|
||
**Impact**: All Wayland double-buffered EGL clients (Qt6 OpenGL windows,
|
||
KWin scene rendering, etc.) now get real back-buffer image allocation
|
||
on Redox. Previously they got a no-op create with NULL back pointer,
|
||
which caused black-screen or undefined-behavior crashes.
|
||
|
||
### Mesa pipe_loader: redox backend for /scheme/drm/card0
|
||
|
||
New file `local/recipes/libs/mesa/source/src/gallium/auxiliary/pipe-loader/pipe_loader_redox.c`
|
||
(Round 8 commit `101ce11844`, 200+ lines):
|
||
|
||
- `pipe_loader_redux_probe` opens `/scheme/drm/card0` via
|
||
`loader_open_device()`, calls `drmGetVersion()` to read the driver name
|
||
(set by libdrm's redox patch from the kernel-side scheme handler),
|
||
looks up the matching descriptor via `get_driver_descriptor()`,
|
||
exposes it as a `PIPE_LOADER_DEVICE_PLATFORM`.
|
||
- `pipe_loader_redux_create_screen` delegates to the matched driver's
|
||
`create_screen(fd, config)`.
|
||
- `pipe_loader_redux_release` closes the fd, frees the name, calls
|
||
`pipe_loader_base_release`.
|
||
- Gated on `#ifdef HAVE_GALLIUM_REDOX` in `pipe_loader.c`'s backends array.
|
||
|
||
**Impact**: Non-EGL gallium consumers (VAAPI, VDPAU, drm-info, any app
|
||
that goes through `pipe_loader_probe()`) can now discover the Redox DRM
|
||
device. Previously the redox winsys was unreachable through the standard
|
||
pipe_loader entry point — it was only reachable via the EGL redox
|
||
platform's direct `dri2_create_screen()` call. Now VAAPI drm-info
|
||
detection on Redox works.
|
||
|
||
### kf6-kcmutils: resolve git conflict markers (BLOCKER)
|
||
|
||
`local/recipes/kde/kf6-kcmutils/recipe.toml` (lines 31-41) and
|
||
`local/recipes/kde/kf6-kcmutils/source/CMakeLists.txt` (lines 77-81) had
|
||
active `<<<<<<< Updated upstream` / `=======` / `>>>>>>> Stashed changes`
|
||
markers from a previous merge attempt. Round 8 commit `5aa5c96506`
|
||
resolved them:
|
||
|
||
- `recipe.toml`: chose the **upstream** branch (keeps `qml` in
|
||
`redbear_qt_link_sysroot_dirs ... modules qml`). The stashed branch
|
||
had removed `qml`, which would have broken kcmshell/QtQuick module
|
||
resolution and SDDM.
|
||
- `CMakeLists.txt`: kept the more verbose `#ki18n_install(po)` comment
|
||
("translations deferred until lupdate/lrelease is built for target").
|
||
|
||
**Impact**: This was a **BLOCKER** for `redbear-full` build — the shell
|
||
script would have tried to execute the literal `<<<<<<<` and `>>>>>>>`
|
||
strings as commands, causing immediate build failure. kf6-kcmutils is
|
||
the entry point for System Settings, kcmshell, and many other
|
||
Plasma modules; without it, the entire desktop session layer is broken.
|
||
|
||
### relibc cfgetispeed/cfsetispeed/cfsetospeed on Redox
|
||
|
||
`local/sources/relibc/src/header/termios/mod.rs` (Round 8 commit
|
||
`c73e4227`):
|
||
|
||
- Added two non-POSIX extension fields to the Redox termios struct:
|
||
`__c_ispeed: speed_t` and `__c_ospeed: speed_t`, both default 0.
|
||
Documented as "non-POSIX; B0..=B4000000" per BSD conventions.
|
||
- `cfgetispeed` now reads `termios.__c_ispeed` (was 0)
|
||
- `cfgetospeed` now reads `termios.__c_ospeed` (was 0)
|
||
- `cfsetispeed` writes `termios.__c_ispeed` for valid speeds
|
||
(`B0..=B38400`, `B57600..=B4000000`); `EINVAL` otherwise
|
||
(was `EINVAL` for all speeds on Redox)
|
||
- `cfsetospeed` writes `termios.__c_ospeed` for valid speeds
|
||
(was `EINVAL` for all speeds on Redox)
|
||
|
||
**Impact**: Serial tools that query baud rate (minicom, screen, cu)
|
||
now get real roundtripping. Previously they always saw 0 on Redox.
|
||
Four "medium severity" stubs from the Round 7 survey resolved.
|
||
|
||
### Documentation cleanups
|
||
|
||
- `local/AGENTS.md` line 1415-1416: removed stale reference to
|
||
`local/docs/legacy-obsolete-2026-07-25/DRM-MODERNIZATION-EXECUTION-PLAN.md`
|
||
as "the current DRM-focused execution plan". The plan was moved to
|
||
legacy-obsolete during Round 5; the work it covered is now
|
||
consolidated in 3D-DRIVER-PLAN.md (Rounds 1-7).
|
||
- `local/recipes/AGENTS.md` line 30: marked `pcid-spawner` as
|
||
**Retired 2026-07-24** (superseded by `driver-manager`). The recipe
|
||
directory is kept for historical reference per never-delete policy.
|
||
|
||
### Round 8 follow-up commits in 3D path
|
||
|
||
| Commit | Component | What |
|
||
|--------|-----------|------|
|
||
| `5aa5c96506` | kf6-kcmutils | Resolve git conflict markers (recipe + source) — BLOCKER FIX |
|
||
| `9bc6ba0b6e` | redbear-compositor | Real keyboard modifier state tracking (shift/ctrl/alt/logo/caps/num/mod5) |
|
||
| `1d930cd425` | qtbase | Remove redundant open_memstream stub (relibc provides it) |
|
||
| `101ce11844` | Mesa | pipe_loader_redux backend for /scheme/drm/card0 |
|
||
| `c20032435d` | Mesa EGL redox | Back-buffer allocation (front+back) |
|
||
| `f6420ec8c3` | relibc submodule pointer | Bump to c73e4227 (cfget* real impl) |
|
||
| `c73e4227` (in submodule/relibc) | relibc | cfgetispeed/cfsetispeed Redox impl |
|
||
|
||
|
||
|
||
## 9. Validation matrix (post-Round 7)
|
||
|
||
| Capability | Class | Source-confirmed? | Runtime-confirmed? |
|
||
|-----------|-------|-------------------|-------------------|
|
||
| Mesa EGL init on Redox | real | ✅ `dri2_initialize` returns EGL_TRUE | ❌ |
|
||
| Mesa window surface | real | ✅ `redox_create_window_surface` exists | ❌ |
|
||
| Mesa EGL front flush | real | ✅ delegates to dri2 | ❌ |
|
||
| Mesa redox gallium winsys | real | ✅ 11 files / 1432 lines | ❌ Mesa never completed building |
|
||
| Mesa iris / radeonsi compile | partial | ✅ driver source present | ❌ |
|
||
| virgl EGL auto-probe | real | ✅ major=0 + name + GET_PCI_INFO | ❌ Test script fixed (blob=true); runtime pending |
|
||
| Mesa `loader_get_pci_driver` | real | ✅ PCI info response | ❌ |
|
||
| virgl runtime (QEMU) | pending | n/a | ❌ Requires canonical build |
|
||
| Mesa llvmpipe | real | ✅ software renderer | ❌ Mesa never completed building |
|
||
| Mesa iris (HW) | real | ✅ i915 bridge fully implemented (VM_BIND, MADVISE, tiling, domain, busy, wait, query, eventfd fence) | ❌ Runtime validation pending canonical build |
|
||
| Mesa radeonsi (HW) | real | ✅ amdgpu bridge fully implemented (ctx, cs, vm, bo_list, wait_fences, info, fence_to_handle, eventfd fence, GPU mapping) | ❌ Runtime validation pending canonical build |
|
||
| Mesa Vulkan (anv/radv) | pending | n/a | ❌ Vulkan loader + WSI not wired |
|
||
| Mesa Vulkan (lvp) | real | ✅ llvmpipe backend | ❌ |
|
||
| Intel DMC firmware load | real | ✅ parser + key per-platform | ❌ |
|
||
| Intel GuC/HuC/GSC firmware | missing | ❌ manifest only | n/a |
|
||
| AMD DMCUB firmware load | real | ✅ C glue loads DMCUB | ❌ |
|
||
| AMD PSP firmware load | missing | ❌ no PSP init | n/a |
|
||
| Intel LNL (Gen15) | real | ✅ IDs recognized | ❌ |
|
||
| Intel PTL (Gen16) | real | ✅ IDs recognized | ❌ |
|
||
| AMD Navi31/32/33 (RDNA3) | partial | 🟡 C glue recognizes | ❌ no GFX11/12 PM4 path |
|
||
| Mesa DRI3 (xdnd-bridge) | partial | 🟡 dri3 loader wired | ❌ |
|
||
| SDDM greeter | real | ✅ all in redbear-full.toml | ❌ Runtime proof pending |
|
||
| PAM through pam-redbear | real | ✅ | ❌ |
|
||
| redbear-authd | real | ✅ | ❌ |
|
||
| redbear-session-launch | real | ✅ | ❌ |
|
||
| redbear-greeter | real | ✅ (legacy) | 🟡 sentinel-gated |
|
||
| redbear-compositor | real | ✅ 13 globals | ❌ Runtime proof pending |
|
||
| redbear-kde-session | real | ✅ | ❌ |
|
||
| Qt6 Wayland null+8 | partial | 🟡 Patches committed | ❌ Never validated in isolation |
|
||
| KWin runtime | pending | 🟡 cmake build succeeds | ❌ Blocked by Qt6 Wayland |
|
||
| KDE Plasma runtime | pending | 🟡 all 42 KF6 + KWin + plasma-framework/workspace/desktop un-deferred | ❌ Blocked by Qt6 Wayland + zwlr_* + QML gate |
|
||
|
||
---
|
||
|
||
## 10. 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 closer to that bar than its predecessor. The remaining gap is
|
||
runtime validation — primarily the Qt6 Wayland null+8 patch execution and the
|
||
virgl test harness fix. Both are scheduled in Round 7 with concrete effort estimates. |