# DisplayLink Artifact Fix ## Problem Description When using the USB-C dock with two external DisplayLink monitors (Shenzhen KTC Q3212RUC, 2560x1440@60Hz), visual artifacts appeared in applications: - Rendering glitches in foot terminal emulator - Visual artifacts in Firefox browser - High CPU usage by DisplayLinkManager (22.8%) - Kernel warnings about buffer sharing between evdi and AMD GPU drivers ## Root Cause DisplayLink uses the EVDI (Extensible Virtual Display Interface) kernel driver, which creates virtual displays and copies framebuffers from the main GPU. The artifacts were caused by: 1. **Compositor conflicts**: Hyprland settings incompatible with DisplayLink's rendering pipeline 2. **VRR (Variable Refresh Rate)**: DisplayLink doesn't support VRR, causing timing conflicts 3. **GPU-intensive effects**: Blur and complex animations increased frame copy overhead 4. **Direct scanout**: Hyprland's optimization bypassed DisplayLink's buffer management 5. **Monitor positioning bug**: Incorrect calculations in monitor setup script ## Solution Applied ### 1. Hyprland Configuration Optimizations **File**: `/home/alexander/.config/hypr/hyprland.conf` #### Changes Made: **Disabled VRR globally:** ``` misc { vrr = 0 vfr = true mouse_move_enables_dpms = true key_press_enables_dpms = true } ``` - DisplayLink doesn't support variable refresh rate - Enabled VFR (variable frame rate) for power savings instead **Disabled GPU-intensive effects:** ``` decoration { rounding = 8 blur { enabled = false size = 3 passes = 1 } } ``` - Blur effects require extra GPU work and framebuffer copies - Significantly reduces load on DisplayLink pipeline **Disabled tearing mode:** ``` general { allow_tearing = false } ``` - Tearing causes visual artifacts on DisplayLink monitors **Simplified animations:** ``` animations { enabled = yes # Faster, simpler animations animation = windows, 1, 3, myBezier, popin 80% animation = windowsOut, 1, 3, default, popin 80% animation = border, 1, 5, default animation = fade, 1, 4, default animation = workspaces, 1, 4, default, slide } ``` - Reduced animation duration and complexity - Less framebuffer updates = smoother DisplayLink rendering **Disabled direct scanout:** ``` render { explicit_sync = 2 direct_scanout = false } ``` - Direct scanout bypasses compositor, conflicts with DisplayLink buffer management - Explicit sync ensures proper frame ordering **Hardware cursors:** ``` cursor { no_hardware_cursors = false no_warps = false } ``` - Hardware cursors work better than software cursors on this setup - Software cursors caused severe stuttering and trails **Optimized damage tracking:** ``` debug { disable_logs = false damage_tracking = 2 } ``` - Level 2 damage tracking balances performance and correctness ### 2. Monitor Setup Script Fix **File**: `/home/alexander/.config/hypr/scripts/monitor-setup.sh` **Bug Fixed** (line 77-82): - **Before**: Used 1920px for monitor positioning (wrong resolution) - **After**: Correctly uses 2560px per monitor - **Before**: Loop bug prevented XPOS from incrementing - **After**: Fixed loop to properly accumulate monitor positions **Improved 3-monitor layout** (line 92): - Laptop screen now positioned centered below external monitors - Position: `1280x1440` (centered under two 2560px wide monitors) ### 3. Kernel Module Configuration **File**: `/etc/modprobe.d/displaylink.conf` ``` # DisplayLink/EVDI kernel module optimization options evdi initial_device_count=2 options evdi initial_loglevel=3 ``` **Why this helps:** - Pre-allocates 2 evdi devices at module load (reduces initialization overhead) - Reduces kernel log verbosity (minor performance improvement) **To apply**: Module parameters take effect after reboot or manual reload: ```bash modprobe -r evdi modprobe evdi initial_device_count=2 initial_loglevel=3 ``` ## How to Verify It's Working ### Check for artifacts: 1. Open foot terminal on external monitor 2. Scroll through text rapidly 3. Open Firefox and browse websites 4. No visual glitches or tearing should appear ### Check DisplayLinkManager CPU usage: ```bash ps aux | grep DisplayLinkManager ``` Should show lower CPU usage (ideally < 10% when idle) ### Check kernel messages: ```bash dmesg | grep evdi | tail -20 ``` Should not show repeated warnings or errors ### Monitor configuration: ```bash hyprctl monitors ``` Should show: - `eDP-1`: 2880x1800@120Hz (laptop) - `DVI-I-1`: 2560x1440@60Hz (external left) - `DVI-I-2`: 2560x1440@60Hz (external right) ## Trade-offs **What we gave up:** - VRR on laptop display (not critical for development work) - Blur effects (aesthetic preference) - Slightly faster animations **What we gained:** - Stable, artifact-free external displays - Lower GPU load and better performance - Lower DisplayLinkManager CPU usage - More reliable dock connection/disconnection ## Future Improvements If artifacts return or performance degrades: 1. **Try different rendering backend:** - Set `WLR_RENDERER=vulkan` or `WLR_RENDERER=gles2` in environment 2. **Adjust refresh rate:** - Try 50Hz or 75Hz instead of 60Hz - Some USB-C docks work better at non-standard rates 3. **Update DisplayLink driver:** - Check for newer evdi kernel module versions - Monitor DisplayLink driver releases 4. **Consider alternative:** - USB-C docks with native DP-Alt mode (no DisplayLink) perform better - But lose flexibility of DisplayLink's multi-monitor support ## References - Hyprland Wiki: https://wiki.hyprland.org/ - DisplayLink Driver: https://github.com/DisplayLink/evdi - Monitor configuration was based on: `Monitor-Dock-via-DisplayLink.md`