SemaDraw is a prototype semantic graphics foundation for FreeBSD.
It defines graphics as a deterministic, resolution independent system based on meaning rather than pixels, GPU APIs, or display servers.
SemaDraw sits above kernel graphics subsystems and below toolkits and environments. It provides a stable semantic contract that remains valid even as hardware, drivers, and rendering backends evolve.
SemaDraw is not a window system. SemaDraw is not a toolkit. SemaDraw is a foundation.
- Graphics are semantic operations, not pixel pipelines
- Resolution independence is mandatory, not optional
- Rendering must be deterministic and inspectable
- Meaning is separated from acceleration
- The same command stream can be replayed locally, remotely, or headless
-
libsemadraw
Zig module used by applications and toolkits to construct semantic command streams -
SDCS
SemaDraw Command Stream, the canonical binary representation of graphics intent -
semadrawd
Userland service responsible for surface ownership, composition, and presentation -
Backends
Software, Vulkan, DRM KMS, and host bridges -
Tooling Command recording, dumping, replay, and golden image testing
-
Applications Terminal emulator (semadraw-term), graphics demo (semadraw-demo)
Requires Zig 0.15 or newer.
zig build
zig build testTools and libraries produced:
- libsemadraw_client.a - Client library for connecting to semadrawd
- semadrawd - Compositor daemon
- sdcs_dump - SDCS file inspector
- sdcs_replay - Software renderer
- sdcs_make_demo - Demo showcase generator
- sdcs_make_* - Various test generators
- semadraw-term - VT100 terminal emulator
- semadraw-demo - Animated graphics demo
Rendering options supported by the encoder and replay tool:
- StrokeJoin: 0 = Miter, 1 = Bevel, 2 = Round
- StrokeCap: 0 = Butt, 1 = Square, 2 = Round
Required:
- Zig 0.15 or newer
- POSIX-compatible OS (FreeBSD, Linux)
- C library (libc)
Optional (for specific backends):
- X11: libX11, libXext (for X11 backend)
- Vulkan: Vulkan SDK, libvulkan (for GPU-accelerated rendering)
- Wayland: libwayland-client (for Wayland backend)
- DRM/KMS: Linux kernel with DRM support (for console output)
- FreeBSD Vulkan Console: libinput, libudev (for keyboard/mouse input in graphics mode)
# Clone the repository
git clone https://github.com/pgsdf/semadraw.git
cd semadraw
# Build all components
zig build
# Run tests
zig build test# Install to /usr/local (default)
sudo zig build install --prefix /usr/local
# Or install to custom location
zig build install --prefix ~/.localThis installs:
/usr/local/bin/semadrawd- Compositor daemon/usr/local/bin/semadraw-term- Terminal emulator/usr/local/bin/semadraw-demo- Animated graphics demo/usr/local/bin/sdcs_dump- SDCS file inspector/usr/local/bin/sdcs_replay- Software renderer/usr/local/lib/libsemadraw_client.a- Client library
Create socket directory (if using default socket path):
sudo mkdir -p /var/run/semadraw
sudo chmod 755 /var/run/semadrawGenerate and view a 1280x1080 showcase of SemaDraw capabilities:
sdcs_make_demo /tmp/demo.sdcs
sdcs_replay /tmp/demo.sdcs /tmp/demo.ppm 1280 1080
feh /tmp/demo.ppmThe demo showcases:
- Anti-aliased Bezier curves (cubic and quadratic)
- Stroked paths with round and miter joins
- Overlapping rectangles with alpha transparency
- Additive blend mode for glow effects
- Diagonal lines with smooth edges
- AA vs non-AA comparison
bash tests/run.shThis runs unit tests, malformed input validation, golden image tests, and determinism verification.
Active development.
The SDCS format is executable and replayable. The software backend provides deterministic reference behavior.
The semadrawd compositor daemon is functional with:
- Unix socket IPC with binary protocol
- Client session management with resource limits
- Surface registry with z-ordering
- Damage tracking and frame scheduling
- Backend abstraction with process isolation
- DRM/KMS backend for direct display output
For running SemaDraw directly on the Linux console without X11 or Wayland (CPU rendering):
# Switch to a virtual console (Ctrl+Alt+F2) or boot without display manager
# Start semadrawd with KMS backend (requires root or video group membership)
sudo semadrawd --backend kms
# In another terminal/session, run the terminal emulator
semadraw-termRequirements:
- Linux kernel with DRM support
- Access to
/dev/dri/card0(usually requires root orvideogroup) - Access to
/dev/input/event*for keyboard and mouse (root orinputgroup) - No active X11/Wayland session on the target display
Input Support:
- Keyboard and mouse input via evdev (
/dev/input/event*) - Mouse chording and text selection work the same as X11/Wayland
- Automatic detection of keyboard and mouse devices
Notes:
- The KMS backend takes exclusive control of the display
- Use Ctrl+Alt+F1 to return to your previous console
- For multi-monitor setups, the first available display is used
- If input doesn't work, ensure user is in the
inputgroup:sudo usermod -aG input $USER
For GPU-accelerated console rendering without X11 or Wayland:
# Switch to a virtual console (Ctrl+Alt+F2) or boot without display manager
# Start semadrawd with Vulkan console backend
sudo semadrawd --backend vulkan_console
# In another terminal/session, run the terminal emulator
semadraw-termRequirements:
- Vulkan-capable GPU with VK_KHR_display extension support
- Vulkan SDK and drivers installed
- No active X11/Wayland session on the target display
- Root privileges or appropriate device permissions
Linux Input:
- Keyboard and mouse via evdev (
/dev/input/event*) - Requires root or
inputgroup membership
FreeBSD Input:
- Mouse via sysmouse (
/dev/sysmouse) - requiresmouseddaemon - Keyboard input (tried in order of preference):
- libinput - preferred for graphics mode, works reliably with KMS/DRM
- evdev (
/dev/input/event*) - good option, works from any VT - Direct keyboard (
/dev/kbdmux0,/dev/ukbd0) - raw scancode access - VT raw mode (
/dev/ttyv0) - raw termios on VT device - TTY fallback (
/dev/tty) - controlling terminal only
FreeBSD Setup (Recommended):
# Install required packages
sudo pkg install libinput libudev-devd
# Ensure moused is running for mouse input
sudo service moused start
# Build semadraw
zig build
# Start semadrawd (libinput is used automatically)
sudo ./zig-out/bin/semadrawd --backend vulkan_console
# In another terminal (or switch VT with Alt+F2), run the terminal emulator
./zig-out/bin/semadraw-termAlternative: Using evdev (if libinput fails):
# Load evdev kernel modules
sudo kldload evdev
sudo kldload kbdmux
# Enable evdev for keyboard
sudo sysctl kern.evdev.rcpt_mask=12
# Start semadrawd
sudo semadrawd --backend vulkan_consoleMake evdev persistent (add to /boot/loader.conf):
evdev_load="YES"
kbdmux_load="YES"
kern.evdev.rcpt_mask=12
Make moused persistent (add to /etc/rc.conf):
moused_enable="YES"
Verifying input on FreeBSD:
# Check if libinput can see devices
sudo libinput list-devices
# Or check evdev devices
ls -la /dev/input/event*
# Test with evtest (install from ports: sysutils/evtest)
sudo evtest
# You should see devices like:
# /dev/input/event0: System keyboard multiplexer
# /dev/input/event1: System mouseTroubleshooting Keyboard Input:
- If logs show "keyboard: using libinput", input should work in graphics mode
- If logs show "libinput: failed to create context", check libinput is installed
- If logs show "EVIOCGNAME failed", evdev is not enabled - load the modules above
- If logs show "keyboard: using /dev/ttyv0", using VT raw mode (may not work in graphics mode)
- If logs show "keyboard: using /dev/tty", only the daemon's terminal receives input
- For best results, ensure libinput is installed on FreeBSD
Notes:
- Uses VK_KHR_display for direct display output (no windowing system)
- GPU-accelerated rendering with CPU-based SDCS execution
- libinput provides reliable input even when VT is in graphics mode
- With evdev/libinput enabled, keyboard input works regardless of which VT you're on
- Without libinput/evdev, keyboard may not work when VT is in graphics mode
- Input is optional - backend works without input devices for testing
For running SemaDraw as a window inside an X11 session:
# Start semadrawd with X11 backend
semadrawd --backend x11
# Run the terminal emulator (in another terminal)
semadraw-termFor GPU-accelerated rendering with Vulkan:
# Start with Vulkan backend (requires Vulkan-capable GPU)
semadrawd --backend vulkan
# Run the terminal emulator
semadraw-termRequirements:
- Running X11 session
- DISPLAY environment variable set
- For Vulkan: Vulkan SDK and compatible GPU drivers
For running SemaDraw as a window inside a Wayland session:
# Start semadrawd with Wayland backend
semadrawd --backend wayland
# Run the terminal emulator (in another terminal)
semadraw-termRequirements:
- Running Wayland compositor (Sway, GNOME Wayland, KDE Wayland, etc.)
- WAYLAND_DISPLAY environment variable set
- libwayland-client
Example 1: Terminal on X11
# Terminal 1: Start daemon
semadrawd --backend x11
# Terminal 2: Run terminal emulator with custom size
semadraw-term --cols 120 --rows 40 --shell /bin/bashExample 2: Terminal on Wayland
# Terminal 1: Start daemon
semadrawd --backend wayland
# Terminal 2: Run terminal
semadraw-termExample 3: Graphics demo on X11
# Terminal 1: Start daemon
semadrawd --backend x11
# Terminal 2: Run animated graphics demo
semadraw-demoExample 4: GPU-accelerated on X11 (Vulkan)
# Terminal 1: Start daemon with Vulkan acceleration
semadrawd --backend vulkan
# Terminal 2: Run terminal
semadraw-termExample 5: GPU-accelerated console (no X11/Wayland)
# From a virtual console (Ctrl+Alt+F2)
# Requires: no display server running, Vulkan drivers
# Start daemon (auto-selects best display mode)
sudo semadrawd --backend vulkan_console
# Or specify a display mode if needed
sudo semadrawd --backend vulkan_console -r 1280x720
# In another session, run terminal
semadraw-termExample 6: FreeBSD console
# Ensure moused is running
sudo service moused start
# Enable evdev for keyboard input (recommended)
sudo kldload evdev
sudo sysctl kern.evdev.rcpt_mask=12
# Start with Vulkan console (auto-selects display mode)
sudo semadrawd --backend vulkan_console
# Run terminal from any VT (keyboard works with evdev)
semadraw-term --scale 2Example 7: Headless testing
# Start headless (no display output)
semadrawd --backend headless
# Connect terminal for testing
semadraw-termStart the compositor daemon:
semadrawd [OPTIONS]Options:
| Option | Description |
|---|---|
-b, --backend TYPE |
Backend: software, headless, kms, x11, vulkan, vulkan_console, wayland |
-r, --resolution WxH |
Output display mode (default: 1920x1080) |
-s, --socket PATH |
Unix socket path (default: /var/run/semadraw/semadraw.sock) |
-t, --tcp PORT |
Enable TCP server on PORT for remote connections |
--tcp-addr ADDR |
Bind TCP to specific address (default: 0.0.0.0) |
-h, --help |
Show help |
Display Mode (-r):
The -r option sets the output display mode, not the content resolution. SemaDraw content is resolution-independent - the SDCS command stream uses semantic coordinates that render correctly at any output size.
| Backend | What -r does |
|---|---|
| vulkan_console, kms | Selects hardware display mode |
| x11, vulkan, wayland | Sets initial window size |
| headless | Sets framebuffer size for testing |
For console backends, -r tells the hardware what mode to use. For windowed backends, it's optional since windows can resize. Content automatically scales to fit the output.
Backend Comparison:
| Backend | Acceleration | Display | Platform | Use Case |
|---|---|---|---|---|
| software | CPU | Varies | Any | Reference, debugging |
| headless | CPU | None | Any | Testing, CI/CD |
| kms | CPU | Console | Linux | Framebuffer, embedded |
| x11 | CPU | X11 Window | Linux, FreeBSD | Desktop development |
| vulkan | GPU | X11 Window | Linux, FreeBSD | High performance (X11) |
| vulkan_console | GPU | Console | Linux, FreeBSD | High performance (no X11) |
| wayland | CPU | Wayland Window | Linux | Wayland desktops |
semadrawd supports TCP connections for remote SDCS streaming:
# Enable TCP on port 7234
semadrawd --backend x11 --tcp 7234
# Bind to specific address
semadrawd --tcp 7234 --tcp-addr 192.168.1.100Remote clients use inline buffer transfer instead of shared memory.
Terminal emulator for running shell sessions:
semadraw-term [OPTIONS]Options:
| Option | Description |
|---|---|
-c, --cols N |
Terminal columns (default: 80) |
-r, --rows N |
Terminal rows (default: 24) |
-z, --scale N |
Font scale multiplier 1-4 (default: 1) |
-e, --shell PATH |
Shell to execute (default: $SHELL or /bin/sh) |
-s, --socket PATH |
Daemon socket path |
-h, --help |
Show help |
Font Scaling:
The -z/--scale option multiplies all font and cell dimensions for larger text without changing the terminal's logical dimensions:
# Normal size (8x16 pixel cells)
semadraw-term
# 2x scale (16x32 pixel cells) - good for HiDPI or accessibility
semadraw-term --scale 2
# 3x scale (24x48 pixel cells)
semadraw-term -z 3
# Combine with fewer columns for very large text
semadraw-term --cols 40 --rows 12 --scale 2This respects SemaDraw's resolution-independent design - the SDCS command stream uses semantic coordinates that scale with the font.
Features:
- VT100/ANSI escape sequence support
- Full UTF-8 with wide character handling (CJK double-width)
- 256-color palette with RGB extensions (OSC 4/10/11)
- Mouse tracking (X10, VT200, SGR, URXVT modes)
- Alternative screen buffer (vim, htop, less, nano)
- Scrollback buffer with Shift+PageUp/PageDown navigation
- Cursor styles (block, underline, bar) with blink support
- Box drawing characters (U+2500-U+257F)
- Text decorations (bold, italic, underline, strikethrough)
- Text selection with mouse (click and drag)
Keyboard shortcuts:
- Ctrl+Shift+C: Copy selection to system clipboard
- Ctrl+Shift+V: Paste from system clipboard
- Shift+PageUp: Scroll up in history
- Shift+PageDown: Scroll down in history
Mouse:
- Left click and drag: Select text (highlighted with inverted colors)
- Left release: Copies selection to PRIMARY clipboard
- Middle click: Paste from PRIMARY clipboard
Plan 9-style mouse chording with menus:
- Hold left button, then press middle or right to show a chord menu
- Move mouse to highlight an option, release left to execute
- Text selection is preserved when initiating a chord (small movements ignored)
Left + Middle chord (Edit menu):
- Copy: Copy selection to system clipboard
- Clear: Clear the current selection
Left + Right chord (Paste menu):
- Paste: Paste from system clipboard
- Paste Primary: Paste from X11 PRIMARY selection
Chord workflow example:
- Select text by dragging with left button
- Release left button (selection stays highlighted)
- Press and hold left button again
- Press middle button to show Edit menu
- Move to highlight "Copy", release left to copy
The menu stays open while left button is held, allowing easy selection.
Animated graphics demonstration:
semadraw-demo [OPTIONS]Options:
| Option | Description |
|---|---|
-s, --socket PATH |
Daemon socket path |
-h, --help |
Show help |
Features:
- Real-time animated graphics using SemaDraw API
- Rotating bezier curves with rainbow colors
- Orbiting shapes with alpha blending
- Pulsing center with additive blend mode
- Anti-aliased rendering
Controls:
- ESC or Q: Quit the demo
- Close window: Quit the demo
This demo showcases SemaDraw's immediate-mode graphics API including:
- Quadratic bezier curves
- Alpha blending and additive blending
- Anti-aliased rendering
- Real-time animation at ~30 FPS
- Resolution-independent graphics
BSD 2-Clause License
Copyright (c) 2025, Pacific Grove Software Distribution Foundation
Vester "Vic" Thacker, Principal Scientist, Pacific Grove Software Distribution Foundation