-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0697226
commit 9e79e57
Showing
4 changed files
with
398 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,273 @@ | ||
{ | ||
config, | ||
lib, | ||
pkgs, | ||
... | ||
}: | ||
|
||
let | ||
cfg = config.programs.opengamepadui; | ||
gamescopeCfg = config.programs.gamescope; | ||
|
||
opengamepadui-gamescope = | ||
let | ||
exports = builtins.attrValues ( | ||
builtins.mapAttrs (n: v: "export ${n}=${v}") cfg.gamescopeSession.env | ||
); | ||
in | ||
# Based on gamescope-session-plus from ChimeraOS | ||
pkgs.writeShellScriptBin "opengamepadui-gamescope" '' | ||
${builtins.concatStringsSep "\n" exports} | ||
# Enable Mangoapp | ||
export MANGOHUD_CONFIGFILE=$(mktemp /tmp/mangohud.XXXXXXXX) | ||
export RADV_FORCE_VRS_CONFIG_FILE=$(mktemp /tmp/radv_vrs.XXXXXXXX) | ||
# Plop GAMESCOPE_MODE_SAVE_FILE into $XDG_CONFIG_HOME (defaults to ~/.config). | ||
export GAMESCOPE_MODE_SAVE_FILE="''${XDG_CONFIG_HOME:-$HOME/.config}/gamescope/modes.cfg" | ||
export GAMESCOPE_PATCHED_EDID_FILE="''${XDG_CONFIG_HOME:-$HOME/.config}/gamescope/edid.bin" | ||
# Make path to gamescope mode save file. | ||
mkdir -p "$(dirname "$GAMESCOPE_MODE_SAVE_FILE")" | ||
touch "$GAMESCOPE_MODE_SAVE_FILE" | ||
# Make path to Gamescope edid patched file. | ||
mkdir -p "$(dirname "$GAMESCOPE_PATCHED_EDID_FILE")" | ||
touch "$GAMESCOPE_PATCHED_EDID_FILE" | ||
# Initially write no_display to our config file | ||
# so we don't get mangoapp showing up before OpenGamepadUI initializes | ||
# on OOBE and stuff. | ||
mkdir -p "$(dirname "$MANGOHUD_CONFIGFILE")" | ||
echo "no_display" >"$MANGOHUD_CONFIGFILE" | ||
# Prepare our initial VRS config file | ||
# for dynamic VRS in Mesa. | ||
mkdir -p "$(dirname "$RADV_FORCE_VRS_CONFIG_FILE")" | ||
echo "1x1" >"$RADV_FORCE_VRS_CONFIG_FILE" | ||
# To play nice with the short term callback-based limiter for now | ||
export GAMESCOPE_LIMITER_FILE=$(mktemp /tmp/gamescope-limiter.XXXXXXXX) | ||
ulimit -n 524288 | ||
# Setup socket for gamescope | ||
# Create run directory file for startup and stats sockets | ||
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 | ||
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 | ||
export GAMESCOPE_STATS="$stats" | ||
mkfifo -- "$stats" | ||
mkfifo -- "$socket" | ||
# Start gamescope compositor, log it's output and background it | ||
echo gamescope ${lib.escapeShellArgs cfg.gamescopeSession.args} -R $socket -T $stats >"$HOME"/.gamescope-cmd.log | ||
gamescope ${lib.escapeShellArgs cfg.gamescopeSession.args} -R $socket -T $stats >"$HOME"/.gamescope-stdout.log 2>&1 & | ||
gamescope_pid="$!" | ||
if read -r -t 3 response_x_display response_wl_display <>"$socket"; then | ||
export DISPLAY="$response_x_display" | ||
export GAMESCOPE_WAYLAND_DISPLAY="$response_wl_display" | ||
# We're done! | ||
else | ||
echo "gamescope failed" | ||
kill -9 "$gamescope_pid" | ||
wait -n "$gamescope_pid" | ||
exit 1 | ||
# Systemd or Session manager will have to restart session | ||
fi | ||
# If we have mangoapp binary start it | ||
if command -v mangoapp >/dev/null; then | ||
(while true; do | ||
sleep 1 | ||
mangoapp >"$HOME"/.mangoapp-stdout.log 2>&1 | ||
done) & | ||
fi | ||
# Start OpenGamepadUI | ||
opengamepadui ${lib.escapeShellArgs cfg.args} | ||
# When the client exits, kill gamescope nicely | ||
kill $gamescope_pid | ||
''; | ||
|
||
gamescopeSessionFile = | ||
(pkgs.writeTextDir "share/wayland-sessions/opengamepadui.desktop" '' | ||
[Desktop Entry] | ||
Name=opengamepadui | ||
Comment=OpenGamepadUI Session | ||
Exec=${opengamepadui-gamescope}/bin/opengamepadui-gamescope | ||
Type=Application | ||
'').overrideAttrs | ||
(_: { | ||
passthru.providedSessions = [ "opengamepadui" ]; | ||
}); | ||
in | ||
{ | ||
options.programs.opengamepadui = { | ||
enable = lib.mkEnableOption "opengamepadui"; | ||
|
||
args = lib.mkOption { | ||
type = lib.types.listOf lib.types.str; | ||
default = [ ]; | ||
description = '' | ||
Arguments to be passed to OpenGamepadUI | ||
''; | ||
}; | ||
|
||
package = lib.mkPackageOption pkgs "OpenGamepadUI" { | ||
default = [ "opengamepadui" ]; | ||
}; | ||
|
||
extraPackages = lib.mkOption { | ||
type = lib.types.listOf lib.types.package; | ||
default = [ ]; | ||
example = lib.literalExpression '' | ||
with pkgs; [ | ||
gamescope | ||
] | ||
''; | ||
description = '' | ||
Additional packages to add to the OpenGamepadUI environment. | ||
''; | ||
}; | ||
|
||
fontPackages = lib.mkOption { | ||
type = lib.types.listOf lib.types.package; | ||
# `fonts.packages` is a list of paths now, filter out which are not packages | ||
default = builtins.filter lib.types.package.check config.fonts.packages; | ||
defaultText = lib.literalExpression "builtins.filter lib.types.package.check config.fonts.packages"; | ||
example = lib.literalExpression "with pkgs; [ source-han-sans ]"; | ||
description = '' | ||
Font packages to use in OpenGamepadUI. | ||
Defaults to system fonts, but could be overridden to use other fonts — useful for users who would like to customize CJK fonts used in opengamepadui. According to the [upstream issue](https://github.com/ValveSoftware/opengamepadui-for-linux/issues/10422#issuecomment-1944396010), opengamepadui only follows the per-user fontconfig configuration. | ||
''; | ||
}; | ||
|
||
gamescopeSession = lib.mkOption { | ||
description = "Run a GameScope driven OpenGamepadUI session from your display-manager"; | ||
default = { }; | ||
type = lib.types.submodule { | ||
options = { | ||
enable = lib.mkEnableOption "GameScope Session"; | ||
args = lib.mkOption { | ||
type = lib.types.listOf lib.types.str; | ||
default = [ | ||
"--prefer-output" | ||
"*,eDP-1" | ||
"--xwayland-count" | ||
"2" | ||
"--default-touch-mode" | ||
"4" | ||
"--hide-cursor-delay" | ||
"3000" | ||
"--fade-out-duration" | ||
"200" | ||
"--steam" | ||
]; | ||
description = '' | ||
Arguments to be passed to GameScope for the session. | ||
''; | ||
}; | ||
|
||
env = lib.mkOption { | ||
type = lib.types.attrsOf lib.types.str; | ||
default = { | ||
# Fix intel color corruption | ||
# might come with some performance degradation but is better than a corrupted | ||
# color image | ||
INTEL_DEBUG = "norbc"; | ||
mesa_glthread = "true"; | ||
# This should be used by default by gamescope. Cannot hurt to force it anyway. | ||
# Reported better framelimiting with this enabled | ||
ENABLE_GAMESCOPE_WSI = "1"; | ||
# Force Qt applications to run under xwayland | ||
QT_QPA_PLATFORM = "xcb"; | ||
# Some environment variables by default (taken from Deck session) | ||
SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS = "0"; | ||
# There is no way to set a color space for an NV12 | ||
# buffer in Wayland. And the color management protocol that is | ||
# meant to let this happen is missing the color range... | ||
# So just workaround this with an ENV var that Remote Play Together | ||
# and Gamescope will use for now. | ||
GAMESCOPE_NV12_COLORSPACE = "k_EStreamColorspace_BT601"; | ||
# Workaround older versions of vkd3d-proton setting this | ||
# too low (desc.BufferCount), resulting in symptoms that are potentially like | ||
# swapchain starvation. | ||
VKD3D_SWAPCHAIN_LATENCY_FRAMES = "3"; | ||
# To expose vram info from radv | ||
WINEDLLOVERRIDES = "dxgi=n"; | ||
# Don't wait for buffers to idle on the client side before sending them to gamescope | ||
vk_xwayland_wait_ready = "false"; | ||
# Temporary crutch until dummy plane interactions / etc are figured out | ||
GAMESCOPE_DISABLE_ASYNC_FLIPS = "1"; | ||
}; | ||
description = '' | ||
Environmental variables to be passed to GameScope for the session. | ||
''; | ||
}; | ||
}; | ||
}; | ||
}; | ||
|
||
inputplumber.enable = lib.mkEnableOption '' | ||
Run InputPlumber service for input management and gamepad configuration. | ||
''; | ||
|
||
powerstation.enable = lib.mkEnableOption '' | ||
Run PowerStation service for TDP and performance control. | ||
''; | ||
}; | ||
|
||
config = lib.mkIf cfg.enable { | ||
hardware.graphics = { | ||
# this fixes the "glXChooseVisual failed" bug, context: https://github.com/NixOS/nixpkgs/issues/47932 | ||
enable = true; | ||
enable32Bit = true; | ||
}; | ||
|
||
security.wrappers = lib.mkIf (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) { | ||
# needed or steam plugin fails | ||
bwrap = { | ||
owner = "root"; | ||
group = "root"; | ||
source = lib.getExe pkgs.bubblewrap; | ||
setuid = true; | ||
}; | ||
}; | ||
|
||
programs.opengamepadui.extraPackages = cfg.fontPackages; | ||
|
||
programs.gamescope.enable = lib.mkForce cfg.gamescopeSession.enable; | ||
services.displayManager.sessionPackages = lib.mkIf cfg.gamescopeSession.enable [ | ||
gamescopeSessionFile | ||
]; | ||
|
||
# optionally enable 32bit pulseaudio support if pulseaudio is enabled | ||
hardware.pulseaudio.support32Bit = config.hardware.pulseaudio.enable; | ||
services.pipewire.alsa.support32Bit = config.services.pipewire.alsa.enable; | ||
|
||
hardware.steam-hardware.enable = true; | ||
|
||
services.inputplumber.enable = lib.mkDefault cfg.inputplumber.enable; | ||
services.powerstation.enable = lib.mkDefault cfg.powerstation.enable; | ||
|
||
environment.pathsToLink = [ "/share" ]; | ||
|
||
environment.systemPackages = [ | ||
cfg.package | ||
cfg.package.run | ||
] ++ lib.optional cfg.gamescopeSession.enable opengamepadui-gamescope; | ||
}; | ||
|
||
meta.maintainers = with lib.maintainers; [ shadowapex ]; | ||
} |
Oops, something went wrong.