about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/programs/steam.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/programs/steam.nix')
-rw-r--r--nixpkgs/nixos/modules/programs/steam.nix108
1 files changed, 100 insertions, 8 deletions
diff --git a/nixpkgs/nixos/modules/programs/steam.nix b/nixpkgs/nixos/modules/programs/steam.nix
index d80718e792af..c63b31bde11f 100644
--- a/nixpkgs/nixos/modules/programs/steam.nix
+++ b/nixpkgs/nixos/modules/programs/steam.nix
@@ -4,16 +4,67 @@ with lib;
 
 let
   cfg = config.programs.steam;
+  gamescopeCfg = config.programs.gamescope;
 
-  steam = pkgs.steam.override {
-    extraLibraries = pkgs: with config.hardware.opengl;
-      if pkgs.hostPlatform.is64bit
-      then [ package ] ++ extraPackages
-      else [ package32 ] ++ extraPackages32;
-  };
+  steam-gamescope = let
+    exports = builtins.attrValues (builtins.mapAttrs (n: v: "export ${n}=${v}") cfg.gamescopeSession.env);
+  in
+    pkgs.writeShellScriptBin "steam-gamescope" ''
+      ${builtins.concatStringsSep "\n" exports}
+      gamescope --steam ${toString cfg.gamescopeSession.args} -- steam -tenfoot -pipewire-dmabuf
+    '';
+
+  gamescopeSessionFile =
+    (pkgs.writeTextDir "share/wayland-sessions/steam.desktop" ''
+      [Desktop Entry]
+      Name=Steam
+      Comment=A digital distribution platform
+      Exec=${steam-gamescope}/bin/steam-gamescope
+      Type=Application
+    '').overrideAttrs (_: { passthru.providedSessions = [ "steam" ]; });
 in {
   options.programs.steam = {
-    enable = mkEnableOption "steam";
+    enable = mkEnableOption (lib.mdDoc "steam");
+
+    package = mkOption {
+      type = types.package;
+      default = pkgs.steam;
+      defaultText = literalExpression "pkgs.steam";
+      example = literalExpression ''
+        pkgs.steam-small.override {
+          extraEnv = {
+            MANGOHUD = true;
+            OBS_VKCAPTURE = true;
+            RADV_TEX_ANISO = 16;
+          };
+          extraLibraries = p: with p; [
+            atk
+          ];
+        }
+      '';
+      apply = steam: steam.override (prev: {
+        extraLibraries = pkgs: let
+          prevLibs = if prev ? extraLibraries then prev.extraLibraries pkgs else [ ];
+          additionalLibs = with config.hardware.opengl;
+            if pkgs.stdenv.hostPlatform.is64bit
+            then [ package ] ++ extraPackages
+            else [ package32 ] ++ extraPackages32;
+        in prevLibs ++ additionalLibs;
+      } // optionalAttrs (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice)
+      {
+        buildFHSEnv = pkgs.buildFHSEnv.override {
+          # use the setuid wrapped bubblewrap
+          bubblewrap = "${config.security.wrapperDir}/..";
+        };
+      });
+      description = lib.mdDoc ''
+        The Steam package to use. Additional libraries are added from the system
+        configuration to ensure graphics work properly.
+
+        Use this option to customise the Steam package rather than adding your
+        custom Steam to {option}`environment.systemPackages` yourself.
+      '';
+    };
 
     remotePlay.openFirewall = mkOption {
       type = types.bool;
@@ -30,6 +81,31 @@ in {
         Open ports in the firewall for Source Dedicated Server.
       '';
     };
+
+    gamescopeSession = mkOption {
+      description = mdDoc "Run a GameScope driven Steam session from your display-manager";
+      default = {};
+      type = types.submodule {
+        options = {
+          enable = mkEnableOption (mdDoc "GameScope Session");
+          args = mkOption {
+            type = types.listOf types.string;
+            default = [ ];
+            description = mdDoc ''
+              Arguments to be passed to GameScope for the session.
+            '';
+          };
+
+          env = mkOption {
+            type = types.attrsOf types.string;
+            default = { };
+            description = mdDoc ''
+              Environmental variables to be passed to GameScope for the session.
+            '';
+          };
+        };
+      };
+    };
   };
 
   config = mkIf cfg.enable {
@@ -39,12 +115,28 @@ in {
       driSupport32Bit = true;
     };
 
+    security.wrappers = mkIf (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) {
+      # needed or steam fails
+      bwrap = {
+        owner = "root";
+        group = "root";
+        source = "${pkgs.bubblewrap}/bin/bwrap";
+        setuid = true;
+      };
+    };
+
+    programs.gamescope.enable = mkDefault cfg.gamescopeSession.enable;
+    services.xserver.displayManager.sessionPackages = mkIf cfg.gamescopeSession.enable [ gamescopeSessionFile ];
+
     # optionally enable 32bit pulseaudio support if pulseaudio is enabled
     hardware.pulseaudio.support32Bit = config.hardware.pulseaudio.enable;
 
     hardware.steam-hardware.enable = true;
 
-    environment.systemPackages = [ steam steam.run ];
+    environment.systemPackages = [
+      cfg.package
+      cfg.package.run
+    ] ++ lib.optional cfg.gamescopeSession.enable steam-gamescope;
 
     networking.firewall = lib.mkMerge [
       (mkIf cfg.remotePlay.openFirewall {