PlayOS Architecture Reference

Version: 2.5
Device: ROG Ally (AMD/AMDGPU primary)
Source of truth: ideas.md — this document is the distilled reference.


Table of Contents

  1. Defining Principle
  2. System Diagram
  3. Repository Map
  4. Process Model
  5. Boot Sequence
  6. Component Responsibilities
  7. Console Lifecycle State Machine
  8. Game Launch Flow
  9. Input Routing
  10. Graphics Stack
  11. Audio Stack
  12. Storage Layout
  13. Security Boundaries
  14. Architectural Constraints (Non-Goals)

1. Defining Principle

PlayOS is a console operating environment built on a minimal Linux hardware layer. playos-init owns processes, playos-compositor owns display and focus, playos-shell owns the user experience, playos-platform-api owns the public libplayos C ABI, playos-runtime owns internal lifecycle transport and control IPC, and one isolated game process runs at a time. The system remains immutable, the data partition remains writable, and the player never interacts with Linux as a desktop operating system.

Key axioms:

  • Linux is the hardware layer, not the product.
  • The system image is immutable; only the data partition is writable.
  • The compositor permanently owns DRM/KMS — no handoffs to games.
  • One game runs at a time; playos-shell always stays alive.
  • Games target playos-platform-api; they never touch compositor or kernel internals.

2. System Diagram

UEFI Firmware
    │
    ▼
Linux EFI-stub kernel  ◄── embedded initramfs
    │
    ▼
Linux Kernel
    ├── EFI / ACPI / PCIe / IOMMU
    ├── AMDGPU / DRM/KMS
    ├── USB / HID / evdev
    ├── ALSA
    ├── NVMe / ext4 / FAT
    └── battery / thermal / power
    │
    ▼
PlayOS Runtime (all in initramfs)
    ├── playos-init              PID 1, process supervisor
    ├── playos-compositor        wlroots compositor, DRM/KMS owner
    │       ├── playos-shell     persistent Raylib UI (Wayland client)
    │       ├── playos-overlay   trusted system overlay (Wayland client)
    │       └── active-game      one isolated Wayland game process
    ├── libplayos                public C ABI (from playos-platform-api)
    ├── playos-runtime           internal IPC and lifecycle transport
    └── Mesa / Wayland / ALSA   platform libraries
    │
    ▼
Persistent Data Partition (/data)
    games / saves / cache / log / updates / config

3. Repository Map

RepositoryOwns
playos-specArchitecture, public contracts, ADRs, schemas, roadmap
playos-initPID 1 process supervisor, boot lifecycle, storage mount, game launch/supervision
playos-platform-apiPublic libplayos C ABI, C++ wrappers, engine adapters
playos-runtimeInternal IPC, lifecycle transport, private Wayland protocols, OS integration
playos-compositorwlroots compositor, DRM/KMS, surface/focus/input policy
playos-shellController-first Raylib shell and PlayOS Raylib backend
playos-refdistroBuildroot integration, kernel config, image assembly, installer
playos-samplesSample games and reference applications
playos-toolsHost-side developer and OTA staging tools
playos-foundationShared foundation libraries and utilities
playos-reference-devicesReference device configurations and images
playos-cloudCloud services — cloud saves and accounts (post-MVP)
playos-marketplaceGame store and marketplace (post-MVP)

Dependency direction:

playos-spec
    └── defines contracts for all implementation repos

playos-runtime  ◄────────────────────────────  playos-compositor
    ▲                                                 ▲
    │                                                 │ (private control IPC)
playos-platform-api                          playos-shell (trusted client)
    ▲
    │
games / playos-shell (public API consumers)

playos-refdistro  ──  pins and assembles all runtime components

Rules:

  • Public application ABI lives only in playos-platform-api.
  • Private IPC/protocol definitions live only in playos-runtime.
  • DRM/KMS and compositor implementation lives only in playos-compositor.
  • playos-refdistro packages and pins; it does not redefine contracts.

4. Process Model

playos-init  (PID 1)
    │
    ├── playos-compositor        (DRM/KMS owner, Wayland display)
    │       ├── playos-shell      (trusted Wayland client, always alive)
    │       └── playos-overlay    (trusted Wayland client, shown on demand)
    │
    └── active-game               (isolated Wayland client, one at a time)
  • playos-init spawns and supervises playos-compositor, playos-shell, playos-overlay, and active-game.
  • The compositor owns the Wayland display and surface presentation for its trusted clients; it does not spawn processes.

5. Boot Sequence

StepActorAction
1UEFILoads /EFI/BOOT/BOOTX64.EFI
2EFI stubTransfers control to the Linux kernel
3KernelInitializes hardware: ACPI, PCIe, GPU, USB, ALSA, NVMe
4KernelUnpacks embedded initramfs into RAM
5KernelStarts /initplayos-init as PID 1
6playos-initMounts /dev, /proc, /sys, /run
7playos-initDiscovers and mounts the PlayOS data partition
8playos-initStarts playos-compositor
9playos-compositorInitializes wlroots backend, DRM/KMS, renderer, Wayland socket
10playos-initLaunches playos-shell and playos-overlay with trusted identity
11playos-shellMaps fullscreen surface; shows game library
UserSelects a game
12playos-shellSends LaunchGame(game_id) over control IPC
13playos-initValidates manifest; spawns game process
14playos-compositorWaits for game's first valid committed frame
15playos-compositorSwitches foreground from shell → game

First-frame rule: The compositor never switches to the game surface until it receives a real committed buffer. This prevents a black-screen transition during game initialization.


6. Component Responsibilities

playos-init

Owns: Boot lifecycle, process supervision, storage mount, game launch/kill, reboot/shutdown/recovery.
Does NOT own: Surfaces, focus, rendering, network, game-specific logic.

playos-compositor

Owns: DRM/KMS, Wayland socket and display, surface z-order and focus, trusted client identity, reserved system input, overlay stacking, lifecycle state transitions, crash recovery.
Does NOT own: Game installation, save management, process spawning.

playos-shell

Owns: Persistent console UI, controller-first navigation, game discovery, launch requests via control IPC, settings, Raylib rendering.
Behavior while game is running: Remains alive; stops or throttles rendering; available to show system UI.

playos-overlay

Owns: Quick menu, volume/brightness HUD, power menu, notifications, virtual keyboard.
May later merge into a multi-surface playos-shell backend.

playos-platform-api / libplayos

Owns: Public, engine-agnostic C ABI. Stable across versions. Exposes lifecycle events, storage paths, device info, logical input, audio/display/power queries, structured logging.
Does NOT expose: Compositor internals, privileged IPC, or DRM handles.

playos-runtime

Owns: Internal IPC protocol definitions, lifecycle event transport, private Wayland protocol XML, restricted client libraries for trusted components, OS integration helpers.
Does NOT own: DRM/KMS policy or the compositor implementation.

Active game process

Owns: Its address space, Wayland surface, audio streams, input stream, save/cache directories.
Prohibited from: Becoming DRM master, reconfiguring displays, mounting filesystems, modifying the system image, synthesizing reserved input, connecting to privileged IPC endpoints.


7. Console Lifecycle State Machine

SHELL_FOREGROUND
    │
    │  launch accepted by playos-init
    ▼
GAME_STARTING
    │
    │  first valid game frame committed
    ▼
GAME_FOREGROUND ◄─────────────────────────────────┐
    │                                              │
    │  PLAYOS_BUTTON_SYSTEM pressed                │ Resume
    ▼                                              │
PLAYOS_UI_FOREGROUND_WITH_GAME_BACKGROUND ─────────┘
    │
    │  Quit selected
    ▼
TERMINATING_GAME
    │
    ▼
SHELL_FOREGROUND ◄── game exits cleanly or crashes (any state)

This state machine is a core PlayOS contract and must be explicitly tested.

State transition triggers:

FromEventTo
SHELL_FOREGROUNDplayos-init accepts launchGAME_STARTING
GAME_STARTINGFirst valid game frameGAME_FOREGROUND
GAME_FOREGROUNDPLAYOS_BUTTON_SYSTEMPLAYOS_UI_FOREGROUND_WITH_GAME_BACKGROUND
PLAYOS_UI_...ResumeGAME_FOREGROUND
PLAYOS_UI_...QuitTERMINATING_GAMESHELL_FOREGROUND
GAME_FOREGROUNDExit or crashSHELL_FOREGROUND

8. Game Launch Flow

playos-shell      →  LaunchGame(game_id)  →  playos-init control IPC
playos-init       →  validates manifest, permissions, one-game rule
playos-init       →  prepares save/cache paths, process group, lifecycle channel, launch identity
playos-init       →  spawns game with WAYLAND_DISPLAY + PlayOS env vars
playos-compositor →  matches client to expected launch identity
playos-compositor →  waits for first committed buffer
playos-compositor →  switches foreground from shell → game
playos-shell      →  remains alive, rendering throttled

Launch responsibility split:

ComponentRole in launch
playos-shellChooses and requests via restricted control IPC
playos-initValidates, spawns, supervises, terminates
playos-compositorIdentifies surface; controls presentation
playos-runtimeTransports lifecycle and control messages
playos-platform-apiExposes lifecycle events and safe services to the game

9. Input Routing

Controller / keyboard / touch
    │
    ▼
Linux HID / evdev / libinput
    │
    ▼
playos-compositor
    ├── PLAYOS_BUTTON_SYSTEM  →  PlayOS only (never delivered to games)
    ├── overlay visible        →  playos-overlay
    ├── game foreground        →  active game
    └── otherwise              →  playos-shell

Logical input constants (defined in playos-platform-api):

PLAYOS_BUTTON_SOUTH / EAST / WEST / NORTH
PLAYOS_BUTTON_START / SELECT
PLAYOS_BUTTON_SYSTEM          // reserved — not delivered to games
PLAYOS_BUTTON_QUICK_MENU      // reserved
PLAYOS_AXIS_LEFT_X / LEFT_Y
PLAYOS_AXIS_RIGHT_X / RIGHT_Y
PLAYOS_AXIS_LEFT_TRIGGER / RIGHT_TRIGGER

10. Graphics Stack

Raylib shell or game
    │  Wayland / PlayOS Raylib backend (rcore_playos.c)
    ▼
Wayland protocol
    │
    ▼
playos-compositor + wlroots
    │  GBM / EGL / OpenGL ES renderer
    ▼
DRM/KMS + AMDGPU
    │
    ▼
Display

AMD (primary): amdgpu kernel driver → Mesa RadeonSI → libdrm / GBM / EGL
Intel (later): i915 / xe → Mesa Iris → libdrm / GBM / EGL
Vulkan: Deferred (RADV / ANV added after AMD baseline is stable)

Direct scanout: When a game's fullscreen buffer is compatible with the DRM output plane, the compositor attempts to assign it directly, skipping composition. Falls back automatically when an overlay is visible or format/scaling prevents it.

Recovery graphics: SimpleDRM or firmware framebuffer fallback for recovery mode without accelerated graphics.


11. Audio Stack

Raylib audio
    │  PlayOS audio backend
    ▼
ALSA PCM
    │
    ▼
Kernel ALSA driver (HDA / SoC / ACP)
    │
    ▼
Built-in speakers / headphones

MVP policy:

  • Stereo PCM only; no PulseAudio or PipeWire.
  • One foreground audio owner: game while foreground, shell otherwise.
  • Shell mutes/stops audio when game becomes foreground; resumes when game exits.

12. Storage Layout

Partition model (production A/B):

GPT disk
├── Partition 1: EFI System Partition   FAT32     512 MiB  BOOTX64.EFI
├── Partition 2: PlayOS system A        immutable 4 GiB    read-only root slot
├── Partition 3: PlayOS system B        immutable 4 GiB    reserved for A/B (Sprint 11)
├── Partition 4: PlayOS misc            ext4      64 MiB   A/B slot metadata
└── Partition 5: PlayOS data            ext4      remainder writable

Data partition (/data):

/data/
    games/<game-id>/          manifest.json, bin/, assets/, shaders/, licenses/
    saves/<game-id>/          profiles/, autosaves/, settings/
    cache/<game-id>/          shaders/, compiled-assets/, temporary/
    resources/
    downloads/
    log/
    updates/
    screenshots/
    config/
    profiles/

Rules:

  • PlayOS must never silently format an unknown disk.
  • Factory reset operates on /data only; the immutable system slots are untouched.
  • First-boot provisioning requires explicit confirmation before creating filesystems.

13. Security Boundaries

┌────────────────────────────────────────────────────────┐
│  Trusted system components                             │
│  playos-init (root)                                    │
│  playos-compositor (display/input caps)                │
│  playos-shell / playos-overlay (service user)          │
│                                                        │
│  ← communicate via restricted playos-runtime IPC →    │
└────────────────────────────────────────────────────────┘
                          │
              public libplayos C ABI
                          │
┌────────────────────────────────────────────────────────┐
│  Untrusted                                             │
│  active-game (unprivileged game identity)              │
│  per-title save and cache directories only             │
│  no DRM primary nodes                                  │
│  no mount, format, or kernel-module access             │
│  no reserved input synthesis                           │
│  no direct compositor or privileged IPC access         │
└────────────────────────────────────────────────────────┘

Hardening roadmap: capabilities → seccomp → Landlock → namespaces → signed manifests → Secure Boot (signed EFI + kernel + initramfs + A/B metadata).


14. Architectural Constraints (Non-Goals)

The following are explicitly excluded from PlayOS v1:

ExcludedReason
Desktop environmentConsole OS; Linux is the hardware layer only
X11 / XwaylandWayland-only
systemdCustom playos-init owns lifecycle
Display / login managerDirect boot to shell
ContainersNot needed for single-game model
Conventional package managerImmutable system image
Custom Linux kernelUpstream LTS with ROG Ally config
Custom GPU driver / OpenGLMesa / AMDGPU
Multiple simultaneous gamesOne-game process model
Multi-GPU / hybrid graphicsROG Ally is single AMD GPU
Wi-Fi, Bluetooth, SSH, cloud savesPost-MVP
Full suspend/resumePost-MVP
HDR, VRR, recording, streamingPost-MVP
libc other than muslmusl only

For sprint-by-sprint implementation detail, see roadmap.md and the individual Sprint-N.md files.
For the public API contract, see platform-api.md.
For internal IPC definitions, see runtime-ipc.md.