ADR-0006 — Raylib for Shell and Game UI

Date: Sprint 5
Status: Accepted
Deciders: PlayOS core team


Context

playos-shell, playos-overlay, and games need a rendering framework. Options: Raylib, SDL2+OpenGL, raw OpenGL ES, Qt, GTK, custom engine.

Decision

Use Raylib as the rendering framework for the shell, overlay, and recommended game development. Implement a custom Raylib PlayOS backend (rcore_playos.c) that integrates with the Wayland/EGL surface and the libplayos lifecycle API.

Rationale

  • Game-developer-friendly: Raylib is a beginner-to-intermediate game framework with a clean C API — matches the target game developer audience
  • Wayland support: Raylib already has Wayland/EGL support — the PlayOS backend extends this rather than starting from scratch
  • Minimal dependencies: Raylib has very few external dependencies; works well in a musl/Buildroot environment
  • Console-appropriate: Raylib is designed for fullscreen games — no window management, no decorations, no desktop assumptions
  • C ABI compatible: Raylib's C API is compatible with the libplayos C ABI philosophy
  • Active community: Regular upstream releases; ROG Ally and AMDGPU-based hardware known to work with Raylib/Wayland

Wayland Backend Approach

Rather than using Raylib's generic Wayland backend as-is, PlayOS implements rcore_playos.c which:

  • Creates a fullscreen xdg_toplevel with trusted role environment variables
  • Integrates playos_lifecycle_poll() into the Raylib frame loop
  • Keeps controller input shell-owned (direct evdev, src/input.c) — Raylib is rendering-only and its PollInputEvents() just resets internal input state
  • Disables desktop features (resize, decorations, clipboard, multi-window)

Alternatives Considered

OptionRejected because
SDL2Heavier; desktop-oriented features; PlayOS would need to strip a lot
Raw OpenGL ESNo windowing abstraction — more code to write for the shell UI
QtVery heavy; complex build; LGPL licensing concerns for static linking
GTKDesktop-oriented; heavy; Wayland support has desktop assumptions
GodotFull game engine is overkill for the shell; heavy binary size

Consequences

  • Games targeting PlayOS are recommended to use Raylib, but the libplayos C ABI is engine-agnostic — SDL2 or other frameworks can be adapted
  • Raylib version must be pinned in versions.lock
  • The rcore_playos.c backend must be maintained when Raylib updates change platform backend APIs
  • Multi-surface support (shell + overlay as one process) is limited by Raylib's single-surface design — the overlay is a separate process as a result (see [ADR for overlay architecture])

Follow-up (Sprint 5.5)

Raylib is now active for the shell. Sprint 5.5 vendored Raylib 6.0 into playos-shell/external/raylib and implemented external/raylib/src/platforms/rcore_playos.c as the PLATFORM_PLAYOS backend, replacing the shell's earlier direct EGL/GLES2 renderer. The shell links the vendored static library when PLAYOS_SHELL_USE_RAYLIB=ON; the raw-GLES2 path was retired. Raylib remains rendering-only — controller input is still read directly from evdev by src/input.c so SYSTEM/QUICK_MENU reserved buttons survive.