WayWal (Wayland Wallpapers) is an ultra-high-performance, zero-allocation Wayland wallpaper daemon (wwald) and CLI client (wwal) written from the ground up in modern C (C23 / gnu2x).
Repository: https://github.com/execorn/wwal
Engineered to achieve the thermodynamic and throughput limits of Linux graphics architecture:
- 0.0% GPU 3D Load & 0 GB/s PCIe Bandwidth for static wallpapers via Direct Hardware Scanout (
zwp_linux_dmabuf_v1+ GBM overlay planes). - < 0.5% CPU Load at 4K 60fps for animated wallpapers via Linux VA-API (
libva) hardware decoding directly into DRM PRIME DMA-BUFs (AV1, HEVC, VP9). - Sub-50 µs VBlank Phase Jitter on Variable Refresh Rate (VRR / FreeSync / G-Sync) and ultra-high-refresh displays (144Hz–500Hz) using
wp_presentationand an alpha-beta Phase-Locked Loop (PLL). - Zero-Allocation Architecture: Fixed 2 MB linear memory arena with sub-nanosecond bump allocation; zero runtime
malloc/freeheap churn in the event loop. - Zero-Syscall Asynchronous Event Loop: Linux
io_uringkernel event ring for IPC dispatch and protocol polling. - Instant Display Hotplug: Atomic in-process state machine eliminating all
fork()and/bin/shinvocations (< 50 µs reconnection latency).
wwal/
├── README.md # Project overview and quickstart
├── LICENSE # GNU General Public License v3.0
├── meson.build # Master Meson build configuration
├── meson_options.txt # Build configuration flags
├── .clang-format # Code style specification
├── .editorconfig # Editor configuration
├── contrib/
│ ├── systemd/
│ │ └── wwald.service # systemd user service unit
│ └── completions/
│ ├── wwal.bash # Bash shell autocompletion
│ ├── wwal.zsh # Zsh shell autocompletion
│ └── wwal.fish # Fish shell autocompletion
├── protocols/ # Wayland XML protocol definitions
│ ├── wlr-layer-shell-unstable-v1.xml
│ ├── viewporter.xml
│ ├── fractional-scale-v1.xml
│ ├── presentation-time.xml
│ └── linux-dmabuf-v1.xml
├── include/waywal/ # Public engine and subsystem headers
├── src/
│ ├── common/ # Linear arena, infallible pathing, zero-alloc logger
│ ├── daemon/ # wwald daemon implementation
│ └── client/ # wwal client CLI implementation
└── tests/ # Unit tests, SIMD microbenchmarks, and integration scripts
- C Compiler: GCC >= 13 or Clang >= 17 supporting
-std=gnu2xor-std=c23. - Build System:
meson>= 0.60,ninja. - Core System Libraries:
wayland-client>= 1.20wayland-protocols>= 1.24wayland-scannerlibdrm>= 2.4.110gbm(Mesa)egl>= 1.5
- Accelerated Subsystems (Optional / Configurable):
libva&libva-drm(for hardware video decoding)liburing>= 2.2 (for zero-syscall event loop)libseccomp(for process sandboxing)
# Clone the repository
git clone https://github.com/execorn/wwal.git
cd wwal
# Configure build with optimizations and LTO
meson setup build -Doptimization=3 -Db_lto=true
# Compile daemon (wwald) and client (wwal)
meson compile -C build
# Run unit and integration tests
meson test -C build
# Launch daemon in background
./build/wwald &
# Query daemon status via client
./build/wwal query
# Slideshow from directory with 10s interval, shuffle, and staggered multi-monitor transition
./build/wwal slideshow start ~/Pictures/Wallpapers -d 10 -s --transition-type ripple --sync-mode staggered --stagger-delay 150
# Target specific output with cursor-anchored wave transition
./build/wwal img ~/Pictures/Wallpapers/scenery.png -o DP-1 --transition-type wave --transition-pos cursor
# Custom user GLSL compute shader transition
./build/wwal img ~/Pictures/Wallpapers/cyberpunk.png --transition-type custom --transition-shader ./shaders/my_effect.compwwal - Modern high-performance Wayland wallpaper client (C23)
Usage: wwal [GLOBAL_OPTIONS] <COMMAND> [ARGS...]
Commands:
ping Check if wwald daemon is running and responsive
query List all detected Wayland outputs and current geometry
clear [COLOR] Clear wallpaper to solid hex color (e.g. 000000 or 00ff00)
img <PATH> [OPTIONS] Load and set wallpaper with GPU/SIMD transitions
video <PATH> [OPTIONS] Load and play hardware-accelerated video wallpaper (VA-API)
slideshow <ACTION> [ARGS] Manage daemon-native wallpaper slideshow
pause Pause video playback
unpause Resume video playback
toggle Toggle video playback pause/resume
kill Gracefully terminate the running wwald daemon
help Display help message
Slideshow Subcommands:
slideshow start <DIR> [OPT] Start daemon-driven wallpaper slideshow with timerfd loop
slideshow stop Stop active slideshow
slideshow pause Pause slideshow timer
slideshow resume Resume slideshow timer
slideshow toggle Toggle slideshow pause/resume
slideshow next Advance immediately to next wallpaper
slideshow prev Return to previous wallpaper
Slideshow Options:
-d, --interval <SEC> Slideshow interval in seconds (default: 300)
-s, --shuffle Randomize wallpaper playback order
Transition Options:
--transition-type <TYPE> none, simple, fade, wipe, grow, outer, wave, noise,
crosszoom, slide, glitch, burn, ripple, pixelate,
doom, swirl, cube, luma, light_leak, page_curl, custom (default: fade)
--transition-shader <FILE> Path to custom GLSL compute shader (requires --transition-type custom)
--transition-duration <S> Duration in seconds (e.g. 1.0, 0.5) (default: 1.0)
--transition-fps <FPS> Target frame rate (default: 60)
--transition-angle <DEG> Wipe/wave/slide angle in degrees (default: 0)
--transition-wave <F,A> Wave frequency/scale and amplitude/intensity (default: 20,0.05)
--transition-pos <POS> Center coordinate (0.5,0.5), semantic alias (center, top,
bottom, left, right, top-left, top-right, bottom-left,
bottom-right), or dynamic cursor tracking (cursor / mouse)
--10bit Force 10-bit wide-gamut direct scanout (DRM_FORMAT_XRGB2101010)
--scaling-mode, --mode <M> Aspect-ratio scaling mode: fill, fit, stretch, center, tile (default: fill)
Multi-Monitor & Synchronization Options:
-o, --output <NAME> Target specific monitor(s) (repeatable or comma-separated)
--sync-mode <MODE> simultaneous or staggered (default: simultaneous)
--stagger-delay <MS> Delay in milliseconds between staggered outputs (default: 150)
Global Options:
-n, --namespace <NAME> Socket namespace (default: "default")
-v, --verbose Enable verbose output
-h, --help Print help information- Kernel-Driven Pacing: Driven by Linux
timerfdregistered directly in the daemon'sio_uringandepollreactor. Consumes 0.0% CPU and 0 Wakeups while sleeping between transitions. - Directory Traversal & In-Memory Shuffling: Automatically traverses directories, ignores hidden files, validates image signatures, and implements Fisher-Yates shuffle with cycle protection.
- Dynamic Runtime Controls: Seamlessly pause, resume, toggle, skip forward (
next), or rewind (prev) via IPC without restarting the slideshow.
- Output Filtering: Pin wallpapers or slideshows to designated monitors using
-o DP-1or-o DP-1,HDMI-A-1. - Cascading Delays: Stagger transitions across panoramic setups using
--sync-mode staggered --stagger-delay 150. The daemon automatically orders monitors geographically by X-coordinate and schedules frame delays on each output node.
- Live Cursor Tracking: Passing
--transition-pos cursoror--transition-pos mouseinitiates ripple, grow, burn, and zoom transitions originating precisely from the current pointer location. Useswl_pointertracking with fallback to Hyprland/Sway IPC query. - Semantic Aliases: Position animations using clean human-readable keywords (
center,top,bottom,left,right,top-left,top-right,bottom-left,bottom-right).
- Runtime Compilation & Reflection: Pass
--transition-type custom --transition-shader <file.comp>to execute custom OpenGL ES 3.1 compute shaders. - Uniform Contract: Custom shaders receive
u_progress,u_resolution,u_center,u_angle,u_params,u_current(unit 0), andu_target(unit 1), writing directly toout_imagewith full hardware acceleration.
- Banding-Free Gradients: Supports native 10-bit-per-channel color (
DRM_FORMAT_XRGB2101010/GBM_FORMAT_XRGB2101010) via DMA-BUF feedback tranche negotiation. - Triple-Buffering Scanout Ring: Eliminates compositor frame drops and tearing at 144Hz–500Hz refresh rates.
- Windows-Style "Fill" (Default): Automatically handles non-16:9 images (ultra-wide 21:9, portrait 9:16, 4:3, square). Scales the image isotropically with zero stretching or squashing, centered, cropping overflow so the wallpaper covers 100% of the display edge-to-edge.
- Multiple Scaling Algorithms:
fill/crop/cover(Default): Crop-to-fill with aspect ratio preservation and centering.fit/contain: Proportional scale fitting inside monitor with clean letterboxing/pillarboxing.stretch: Direct mapping to screen width & height.center: 1:1 pixel centered without scaling.tile: Seamless pattern tiling starting at (0,0).
- Sub-Pixel Fixed-Point Bilinear Filtering: Downscaled and upscaled wallpapers are filtered using high-precision integer bilinear interpolation, eliminating aliasing, jaggies, and moiré patterns.
WayWal features a SOTA GPU Compute (OpenGL ES 3.1 Compute Shaders) and CPU SIMD fallback transition engine supporting 21 transition effects:
| Transition Type | Description | GPU Compute Shader | SIMD / CPU Fallback |
|---|---|---|---|
none / simple |
Instant cut with zero latency | N/A (Zero-copy swap) | Direct copy |
fade |
Smooth linear / alpha-crossfade | fade.comp |
AVX2 / AVX-512 / NEON |
wipe |
Directional angled wipe across any angle | wipe.comp |
Optimized scalar / SIMD |
grow |
Expanding circular iris mask from customizable center | grow.comp |
Distance-field mask |
outer |
Inverted contracting circular iris reveal | outer.comp |
Inverted distance-field |
wave |
Sinusoidal wavefront distortion with controllable frequency & amplitude | wave.comp |
Trigonometric displacement |
noise |
Procedural pseudo-random dither dissolve | noise.comp |
Hash-based pseudo-random |
crosszoom |
Dynamic radial zoom blur into the target image | crosszoom.comp |
Multi-tap bilinear zoom |
slide |
Smooth directional screen slide with sub-pixel interpolation | slide.comp |
Coordinate translation |
glitch |
Chromatic aberration and horizontal digital scanline tearing | glitch.comp |
RGB channel offset |
burn |
High-contrast organic fire/burn boundary with ember glow | burn.comp |
Smoothstep threshold burn |
ripple |
High-frequency water drop wavefront propagation | ripple.comp |
Radial wave displacement |
pixelate |
Dynamic GPU mosaic downsampling and tile-grid expansion | pixelate.comp |
Tiled block sampling |
doom |
Retro vertical melt columns with independent jittered speeds | doom.comp |
Columnar melt offset |
swirl |
Non-linear vortex rotation and centrifugal warp | swirl.comp |
Polar coordinate rotation |
cube |
3D perspective cube rotation with realistic shading & perspective foreshortening | cube.comp |
3D Ray-plane projection |
luma |
Luminance-driven wipe using perceptual BT.709 grayscale luma | luma.comp |
Perceptual luma threshold |
light_leak |
Cinematic anamorphic optical lens flare with warm chromatic overlay | light_leak.comp |
Multi-source spectral flare |
page_curl |
Anti-aliased conical 3D cylinder page curl with realistic drop shadow | page_curl.comp |
Conical deformation math |
custom |
Arbitrary user-provided OpenGL ES 3.1 compute shader | User .comp file |
Custom fallback |
Measured on AMD Ryzen 7 5800H / AMD Radeon Vega Mobile (renderD128), Hyprland 0.56.2, Kernel 7.2.6-zen2.
| Effect | Mean Latency | Peak Throughput | Memory Leak |
|---|---|---|---|
fade |
~0.012 ms | ~85,000 FPS | 0 KB Delta [PASS] |
doom |
~0.013 ms | ~77,000 FPS | 0 KB Delta [PASS] |
ripple |
~0.015 ms | ~66,000 FPS | 0 KB Delta [PASS] |
page_curl |
~0.024 ms | ~41,000 FPS | 0 KB Delta [PASS] |
- All animated transitions execute in 0.011 ms – 0.018 ms per frame (54,000 – 88,000 FPS).
- Zero frame drops at 144Hz / 165Hz refresh rates.
- Constant memory consumption: 0 KB heap allocation delta across 4K transitions.
- 720p: 150 – 6,400 FPS depending on transition complexity.
- Runtime SIMD path selection: AVX-512 → AVX2 → NEON → scalar (zero compile-time branching).