CopperlineOS Vulkan/KMS compositor.
compositord owns the display pipeline. It imports client buffers (DMABUFs), manages on-screen layers, and composites them on a vsync-paced timeline. It exposes a small register model (layer[n].x/y/alpha/z/visible, etc.) so timed programs (from copperd) and apps can move and blend things with rock‑solid latency.
TL;DR: a lean compositor that feels like hardware. Layers and registers you can poke at frame time—no bloated stack in the way.
Typical desktops put many layers between apps and pixels, which is great for features but not for determinism. CopperlineOS splits responsibilities: compositord makes pixels fast and predictable, copperd tells when to change them. Together they deliver Amiga‑style immediacy on modern GPUs.
- Deterministic frame loop: runs at the display’s vsync cadence.
- Tiny, explicit API: layers with numeric registers you can set.
- Zero‑copy: DMABUF import from apps; blits via Vulkan transfer/compute.
- Scriptable: controlled via a message port (JSON in Phase‑0).
- Phase‑0 JSON protocol: stable‑ish (v0)
- Backends: DRM/KMS (preferred), experimental Wayland/X11 host mode
- Language: Rust
- License: MIT OR Apache‑2.0
flowchart LR
comp["compositord (Vulkan + KMS)"];
subgraph Apps
a1["Vulkan apps"];
a2["Tools / CLI"];
a3["ARexx-Next"];
end
subgraph Services
cop["copperd (timeline)"];
blt["blitterd (2D ops)"];
end
subgraph Kernel_and_Drivers
drm["DRM / KMS"];
alsa["ALSA (optional)"];
end
a1 --> comp;
a2 --> comp;
a3 --> comp;
cop --> comp;
blt --> comp;
drm --> comp;
alsa -.-> comp;
comp --> cop;
comp --> a1;
comp --> a2;
comp --> a3;
Text-only fallback (if Mermaid fails)
Apps (Vulkan, Tools, ARexx) -> compositord
Services (copperd, blitterd) -> compositord
Kernel/Drivers (DRM/KMS, ALSA optional) -> compositord
compositord -> copperd (vsync ticks)
compositord -> Apps (events)
Text-only fallback (if Mermaid fails)
Apps (Vulkan, Tools, ARexx) -> compositord
Services (copperd, blitterd) -> compositord
Kernel/Drivers (DRM/KMS, ALSA optional) -> compositord
compositord -> copperd (vsync ticks)
compositord -> Apps (events)
- DMABUF import for client buffers (apps, blitterd).
- Layer register model the rest of the system writes to.
- Vsync feed published to
copperdand subscribers.
- Layer: a composited surface with registers:
x,y,alpha,z,visible,scale_x,scale_y,rotation(deg),blend(normal,add,mul,screen). - Register writes: atomic per-frame; late writes apply to the next frame.
- Outputs: connectors / CRTCs / modes from DRM (hotplug aware).
- Clock: vsync‑driven; falls back to high‑res timer if needed.
Backed by double‑buffered state; updates are latched on vsync.
| Register | Type | Range | Notes |
|---|---|---|---|
layer[n].x |
int | pixels | Left position |
layer[n].y |
int | pixels | Top position |
layer[n].alpha |
float | 0.0–1.0 | Per‑layer opacity |
layer[n].z |
int | any | Draw order (higher = in front) |
layer[n].visible |
bool | true/false | Visibility toggle |
layer[n].scale_x |
float | >0 | Default 1.0 |
layer[n].scale_y |
float | >0 | Default 1.0 |
layer[n].rotation |
float | degrees | Pivot is layer center |
layer[n].blend |
enum | normal/add/mul/screen | Compositing mode |
Socket (default): /run/copperline/compositord.sock
Configurable via COMPOSITORD_SOCKET.
{"cmd":"ping"}→{"ok":true,"name":"compositord","version":"0.1.0"}{"cmd":"output_list"}→{"ok":true,"outputs":[{"id":0,"name":"HDMI-A-1","modes":[...],"current_mode":{...}}]}{"cmd":"output_set_mode","id":0,"mode":{"w":1920,"h":1080,"hz":60}}{"cmd":"create_layer"}→{"ok":true,"id":1}(IDs are auto-assigned){"cmd":"destroy_layer","id":1}{"cmd":"bind_dmabuf","id":1,"fd":<int>,"w":128,"h":128,"format":"RGBA8","stride":512,"modifier":"LINEAR"}{"cmd":"bind_image","id":1,"path":"/tmp/sprite.rgba","w":128,"h":128,"format":"RGBA8"}(debug/testing){"cmd":"unbind","id":1}{"cmd":"set","id":1,"x":100,"y":360,"alpha":1.0,"z":10,"visible":true}{"cmd":"set_regs","regs":{"layer[1].x":100,"layer[1].y":360}}(batch){"cmd":"commit"}(optional barrier; otherwise commits at vsync){"cmd":"subscribe","events":["vsync","pageflip","hotplug","error"]}
{"event":"vsync","usec":12345678,"frame":424242}{"event":"pageflip","frame":424242}{"event":"hotplug","outputs":[ ... ]}{"event":"error","message":"..."}"
# Prereqs: Vulkan loader/driver, DRM/KMS access (seatd/logind recommended)
git clone https://github.com/CopperlineOS/compositord
cd compositord
cargo build --release
RUST_LOG=info ./target/release/compositordEnvironment variables:
COMPOSITORD_SOCKET=/run/copperline/compositord.sockCOMPOSITORD_BACKEND=kms|wayland|x11(default:kms)COMPOSITORD_OUTPUT=auto|HDMI-A-1(choose connector)COMPOSITORD_MODE=1920x1080@60(preferred mode override)
Using portctl (from CopperlineOS/tools):
# Create layer id 1
portctl /run/copperline/compositord.sock '{"cmd":"create_layer"}'
# Bind a test RGBA image (raw 128x128)
portctl /run/copperline/compositord.sock '{"cmd":"bind_image","id":1,"path":"/tmp/sprite.rgba","w":128,"h":128,"format":"RGBA8"}'
# Place it at (100,360) on top
portctl /run/copperline/compositord.sock '{"cmd":"set","id":1,"x":100,"y":360,"alpha":1.0,"z":10,"visible":true}'Now run the Copper demo to animate it:
# load & start the infinite rightward move (see copperd README for /tmp/demo.json)
portctl /run/copperline/copperd.sock "$(jq -c '{cmd:"load",program:.}' /tmp/demo.json)"
portctl /run/copperline/copperd.sock '{"cmd":"start","id":1}'# Toolchain
rustup default stable
rustup component add rustfmt clippy
# Optional system libraries (names vary by distro):
# - Vulkan loader/headers, libdrm, wayland-client (if using host mode)
# Build & test
cargo fmt --all
cargo clippy --all-targets -- -D warnings
cargo testMinimum Rust: 1.78+.
- Crates:
compositord-core(graph/layers),compositord-backend(KMS/host),compositord-ipc(protocol),compositord-bin(daemon). - Frame loop: gather register writes → latch → composite → pageflip, once per vsync.
- DMABUF: imported via
DMA_HEAP/primeFDs; validated size/format/modifier; lifetime tracked. - Shaders: minimal set for blend modes; sRGB‑aware sampling.
- Planes: Phase‑0 composites in GPU; Phase‑1 maps simple cases to HW planes.
- Timing: publishes
vsyncevents and frame counters to copperd (and subscribers). - Safety: checks for invalid IDs, stale FDs, size/format mismatches; clamps out‑of‑range registers.
- v0.1: KMS backend, DMABUF import, layers/regs, basic blend, vsync events.
- v0.2: Hardware plane mapping, partial damage, fences (Vulkan timeline) to/from
copperd. - v0.3: Color management (HDR metadata, ICC), screenshots/recording via zero‑copy taps.
- v0.4: Multi‑output spanning, hotplug robustness, low‑latency capture for streaming.
- v0.5: Security caps per client (layer quotas, z‑range, rate limits).
RFCs will live in CopperlineOS/rfcs.
We welcome issues and PRs!
- Read
CONTRIBUTING.md. - Check good first issue / help wanted labels.
- Protocol or register changes → open an RFC and link it in your PR.
Code of Conduct: CODE_OF_CONDUCT.md.
compositord may require DRM/KMS privileges. Prefer running under seatd/logind rather than root.
Report vulnerabilities privately to security@copperline.os (placeholder) or via GitHub advisories. See SECURITY.md.
Dual-licensed under Apache‑2.0 OR MIT.
copperd: timeline engine (writes registers at vsync)blitterd: 2D copy/fill/convert serviceports: message‑port protocol & client libsexamples/vulkan-scene: sample app exporting DMABUF