150 lines
5.3 KiB
Bash
150 lines
5.3 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
set -euo pipefail
|
||
|
|
LOG_FILE="$HOME/.local/logs/session.log"
|
||
|
|
|
||
|
|
log() { echo "[$(date --iso-8601=seconds)] $*" | tee -a "$LOG_FILE"; }
|
||
|
|
|
||
|
|
CONF_FILE="$HOME/.config/gamescope/gamescope.conf"
|
||
|
|
[ -f "$CONF_FILE" ] && source "$CONF_FILE"
|
||
|
|
|
||
|
|
FRAMERATE=${FRAMERATE:-60}
|
||
|
|
RESOLUTION=${RESOLUTION:-1920x1080}
|
||
|
|
WIDTH="${RESOLUTION%x*}"
|
||
|
|
HEIGHT="${RESOLUTION#*x}"
|
||
|
|
|
||
|
|
export __GL_GSYNC_ALLOWED=1
|
||
|
|
export __GL_VRR_ALLOWED=1
|
||
|
|
export __GL_SHADER_DISK_CACHE=1
|
||
|
|
export __GL_SYNC_TO_VBLANK=0
|
||
|
|
export LIBVA_DRIVER_NAME=nvidia
|
||
|
|
export __GLX_VENDOR_LIBRARY_NAME=nvidia
|
||
|
|
export NVD_BACKEND=direct
|
||
|
|
# export __GL_THREADED_OPTIMIZATIONS=1
|
||
|
|
|
||
|
|
GAMESCOPE_BIN="$(command -v gamescope || true)"
|
||
|
|
if [ -z "$GAMESCOPE_BIN" ]; then
|
||
|
|
log "ERROR: gamescope not found in PATH"
|
||
|
|
exit 127
|
||
|
|
fi
|
||
|
|
|
||
|
|
HDR_FLAG=""
|
||
|
|
if [[ "$HDR_ENABLED" == "1" || "$HDR_ENABLED" == "true" || "$HDR_ENABLED" == "yes" ]]; then
|
||
|
|
HDR_FLAG="--hdr-enabled"
|
||
|
|
log "HDR flag added: --hdr-enabled"
|
||
|
|
else
|
||
|
|
log "HDR disabled, no HDR flag added"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Create run directory file for startup and stats sockets
|
||
|
|
# shellcheck disable=SC2030 # (broken warning)
|
||
|
|
tmpdir="$([[ -n ${XDG_RUNTIME_DIR+x} ]] && mktemp -p "$XDG_RUNTIME_DIR" -d -t gamescope.XXXXXXX)"
|
||
|
|
socket="${tmpdir:+$tmpdir/startup.socket}"
|
||
|
|
stats="${tmpdir:+$tmpdir/stats.pipe}"
|
||
|
|
# Fail early if we don't have a proper runtime directory setup
|
||
|
|
# shellcheck disable=SC2031 # (broken warning)
|
||
|
|
if [[ -z $tmpdir || -z ${XDG_RUNTIME_DIR+x} ]]; then
|
||
|
|
echo >&2 "!! Failed to find run directory in which to create stats session sockets (is \$XDG_RUNTIME_DIR set?)"
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Chromium (and therefore Steam) ignore XCursor and use on the GTK config
|
||
|
|
kwriteconfig6 --file gtk-3.0/settings.ini --group Settings --key gtk-cursor-theme-name steam
|
||
|
|
|
||
|
|
# Workaround for Steam login issue while Steam client change propagates out of Beta
|
||
|
|
touch ~/.steam/root/config/SteamAppData.vdf || true
|
||
|
|
|
||
|
|
# Increase open file limit for gamescope session
|
||
|
|
ulimit -n 524288
|
||
|
|
|
||
|
|
# 1048576 = 1M - passing it like that omits the 'M' suffix - xargs removes whitespace
|
||
|
|
free_disk_space_megs=$(df ~/ --output=avail -B1048576 | sed -n '2 p' | xargs)
|
||
|
|
minimum_free_disk_space_needed_megs=500
|
||
|
|
|
||
|
|
if [[ "$free_disk_space_megs" -lt "$minimum_free_disk_space_needed_megs" ]]; then
|
||
|
|
echo >&2 "gamescope-session: not enough disk space to proceed, trying to find game to delete"
|
||
|
|
|
||
|
|
find ~/.local/share/Steam/steamapps/common/ -mindepth 1 -maxdepth 1 -type d -printf "%T@ %p\0" | sort -n -z | while IFS= read -r -d $'\0' line; do
|
||
|
|
timestamp=${line%% *}
|
||
|
|
game_folder=${line#* }
|
||
|
|
|
||
|
|
[[ -d $game_folder ]] || continue
|
||
|
|
|
||
|
|
acf=$(grep -F -- "$(basename -- "$game_folder")" ~/.local/share/Steam/steamapps/*.acf | grep \"installdir\" | cut -d: -f1)
|
||
|
|
[[ -e "$acf" ]] || continue
|
||
|
|
|
||
|
|
echo >&2 "gamescope-session: deleting $(basename "$game_folder")"
|
||
|
|
appid=$(basename "$acf" | cut -d_ -f2 | cut -d. -f1)
|
||
|
|
|
||
|
|
# TODO leave a note for Steam to display UI to explain what happened, if this logic stays
|
||
|
|
# intentionally leave compatdata; could be unclouded save files there
|
||
|
|
rm -rf --one-file-system -- "$game_folder" "$acf" ~/.local/share/Steam/steamapps/shadercache/"$appid"
|
||
|
|
|
||
|
|
free_disk_space_megs=$(df ~/ --output=avail -B1048576 | sed -n '2 p' | xargs)
|
||
|
|
[[ "$free_disk_space_megs" -lt "$minimum_free_disk_space_needed_megs" ]] || break
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
|
||
|
|
export GAMESCOPE_STATS="$stats"
|
||
|
|
mkfifo -- "$stats"
|
||
|
|
mkfifo -- "$socket"
|
||
|
|
|
||
|
|
# Attempt to claim global session if we're the first one running (e.g. /run/1000/gamescope)
|
||
|
|
linkname="gamescope-stats"
|
||
|
|
# shellcheck disable=SC2031 # (broken warning)
|
||
|
|
sessionlink="${XDG_RUNTIME_DIR:+$XDG_RUNTIME_DIR/}${linkname}" # Account for XDG_RUNTIME_DIR="" (notfragileatall)
|
||
|
|
lockfile="$sessionlink".lck
|
||
|
|
exec 9>"$lockfile" # Keep as an fd such that the lock lasts as long as the session if it is taken
|
||
|
|
if flock -n 9 && rm -f "$sessionlink" && ln -sf "$tmpdir" "$sessionlink"; then
|
||
|
|
# Took the lock. Don't blow up if those commands fail, though.
|
||
|
|
echo >&2 "Claimed global gamescope stats session at \"$sessionlink\""
|
||
|
|
else
|
||
|
|
echo >&2 "!! Failed to claim global gamescope stats session"
|
||
|
|
fi
|
||
|
|
|
||
|
|
read_gamescope_env() {
|
||
|
|
log "Waiting for gamescope to provide DISPLAY and GAMESCOPE_WAYLAND_DISPLAY via socket..."
|
||
|
|
if read -r -t 3 response_x_display response_wl_display <> "$socket"; then
|
||
|
|
log "Received gamescope environment:"
|
||
|
|
log " DISPLAY=$response_x_display"
|
||
|
|
log " GAMESCOPE_WAYLAND_DISPLAY=$response_wl_display"
|
||
|
|
export DISPLAY="$response_x_display"
|
||
|
|
export GAMESCOPE_WAYLAND_DISPLAY="$response_wl_display"
|
||
|
|
|
||
|
|
# Sync environment variables to systemd, then notify we are ready to launch subsequent services
|
||
|
|
log "Storing gamescope environment for systemd..."
|
||
|
|
env > $XDG_RUNTIME_DIR/gamescope-environment
|
||
|
|
systemd-notify --ready
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Spawned in parallel to read values from gamescope
|
||
|
|
(read_gamescope_env &)
|
||
|
|
|
||
|
|
log "Starting Gamescope session..."
|
||
|
|
|
||
|
|
# Build gamescope argument array for safe quoting and readability
|
||
|
|
GAMESCOPE_ARGS=(
|
||
|
|
--generate-drm-mode fixed
|
||
|
|
--fade-out-duration 200
|
||
|
|
--cursor-scale-height 720
|
||
|
|
-f
|
||
|
|
-W "$WIDTH" -H "$HEIGHT"
|
||
|
|
-w "$WIDTH" -h "$HEIGHT"
|
||
|
|
--rt --mangoapp -e -R "$socket" -T "$stats"
|
||
|
|
)
|
||
|
|
|
||
|
|
# Append HDR flag if enabled
|
||
|
|
if [ -n "${HDR_FLAG:-}" ]; then
|
||
|
|
GAMESCOPE_ARGS+=("$HDR_FLAG")
|
||
|
|
fi
|
||
|
|
|
||
|
|
export XDG_CURRENT_DESKTOP=gamescope
|
||
|
|
export XDG_SESSION_TYPE=wayland
|
||
|
|
export DESKTOP_SESSION=gamescope
|
||
|
|
|
||
|
|
log "Launching Gamescope: $GAMESCOPE_BIN ${GAMESCOPE_ARGS[*]} -- $*"
|
||
|
|
sudo setcap 'CAP_SYS_NICE=eip' "$GAMESCOPE_BIN"
|
||
|
|
|
||
|
|
exec "$GAMESCOPE_BIN" "${GAMESCOPE_ARGS[@]}" >>"$LOG_FILE" 2>&1
|
||
|
|
|