Files
dotfiles/config/scripts/.local/snippets/set_display
2025-12-07 02:52:32 +01:00

83 lines
2.7 KiB
Bash

#!/usr/bin/env bash
# Description:
# Select which GPU to use for rendering for Hyprland and Niri.
#
# envs exported:
# HYPR_AQ_DRM_DEVICES - Colon-separated list of DRM device paths for Hyprland's aq_drm
# BRIGHTNESSCTL_DEVICE - Device identifier for brightnessctl
# Constants
niri_config_file="$HOME/.config/niri/config/misc.kdl"
prefer_order=(amd nvidia intel) # AMD -> Nvidia -> Intel
# Get vendor and path of each GPU
default_dri_path="$(find /dev/dri/card* 2>/dev/null | head -n 1)"
[[ -z "$default_dri_path" ]] && default_dri_path="/dev/dri/card0"
intel_path=""
nvidia_path=""
amd_path=""
for link in /dev/dri/by-path/*-card; do
[[ -e "$link" ]] || continue
card="$(readlink -f "$link")"
vfile="/sys/class/drm/$(basename "$card")/device/vendor"
[[ -r "$vfile" ]] || continue
vendor="$(cat "$vfile")"
case "$vendor" in
0x10de) nvidia_path="$card" ;;
0x8086) intel_path="$card" ;;
0x1002) amd_path="$card" ;;
esac
done
# Specify device for brightnessctl
# Only tested on my laptop with Intel iGPU & Nvidia dGPU
BRIGHTNESSCTL_DEVICE="auto"
if [[ -n "$intel_path" ]]; then
BRIGHTNESSCTL_DEVICE="intel_backlight"
elif [[ -n "$nvidia_path" ]]; then
BRIGHTNESSCTL_DEVICE="nvidia_0"
fi
export BRIGHTNESSCTL_DEVICE
# AQ_DRM_DEVICES allows multiple entries separated by colon
devices=""
for who in "${prefer_order[@]}"; do
case "$who" in
nvidia) [[ -n "$nvidia_path" ]] && devices="${devices:+$devices:}$nvidia_path" ;;
intel) [[ -n "$intel_path" ]] && devices="${devices:+$devices:}$intel_path" ;;
amd) [[ -n "$amd_path" ]] && devices="${devices:+$devices:}$amd_path" ;;
esac
done
HYPR_AQ_DRM_DEVICES="${devices:-$default_dri_path}"
export HYPR_AQ_DRM_DEVICES
# But niri only supports choosing one preferred render device
primary_device="$default_dri_path"
for who in "${prefer_order[@]}"; do
case "$who" in
nvidia) [[ -n "$nvidia_path" ]] && { primary_device="$nvidia_path"; break; } ;;
intel) [[ -n "$intel_path" ]] && { primary_device="$intel_path"; break; } ;;
amd) [[ -n "$amd_path" ]] && { primary_device="$amd_path"; break; } ;;
esac
done
# Update niri config
function update_niri_config() {
local config_file="$1"
local device_path="$2"
[[ -f "$config_file" ]] || return
if grep -qE '^\s*render-drm-device\s+"[^"]+"' "$config_file"; then
local current
current="$(grep -E '^\s*render-drm-device\s+"[^"]+"' "$config_file" | sed -E 's/^\s*render-drm-device\s+"([^"]+)".*/\1/')"
[[ "$current" == "$device_path" ]] && return
sed -i -E "s|^(\s*render-drm-device\s+)\"[^\"]+\"|\1\"$device_path\"|" "$config_file"
else
printf '\ndebug {\nrender-drm-device "%s"\n}\n' "$device_path" >> "$config_file"
fi
}
update_niri_config "$niri_config_file" "$primary_device"