diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix index b2c97f0bfad..2d5643d4d94 100644 --- a/nixos/modules/hardware/opengl.nix +++ b/nixos/modules/hardware/opengl.nix @@ -10,6 +10,15 @@ let videoDrivers = config.services.xserver.videoDrivers; + makePackage = p: p.buildEnv { + name = "mesa-drivers+txc-${p.mesa_drivers.version}"; + paths = + [ p.mesa_drivers + p.mesa_noglu # mainly for libGL + (if cfg.s3tcSupport then p.libtxc_dxtn else p.libtxc_dxtn_s2tc) + ]; + }; + in { @@ -52,73 +61,64 @@ in ''; }; + hardware.opengl.package = mkOption { + type = types.package; + internal = true; + description = '' + The package that provides the OpenGL implementation. + ''; + }; + + hardware.opengl.package32 = mkOption { + type = types.package; + internal = true; + description = '' + The package that provides the 32-bit OpenGL implementation on + 64-bit systems. Used when is + set. + ''; + }; + }; config = mkIf cfg.enable { + assertions = pkgs.lib.singleton { assertion = cfg.driSupport32Bit -> pkgs.stdenv.isx86_64; - message = "Option driSupport32Bit only makes sens on a 64-bit system."; + message = "Option driSupport32Bit only makes sense on a 64-bit system."; }; - system.activationScripts.setup-opengl.deps = []; - system.activationScripts.setup-opengl.text = '' - rm -f /run/opengl-driver{,-32} - ${optionalString (pkgs.stdenv.isi686) "ln -sf opengl-driver /run/opengl-driver-32"} - '' - #TODO: The OpenGL driver should depend on what's detected at runtime. - +( if elem "nvidia" videoDrivers then - '' - ln -sf ${kernelPackages.nvidia_x11} /run/opengl-driver - ${optionalString cfg.driSupport32Bit - "ln -sf ${pkgs_i686.linuxPackages.nvidia_x11.override { libsOnly = true; kernel = null; } } /run/opengl-driver-32"} - '' - else if elem "nvidiaLegacy173" videoDrivers then - "ln -sf ${kernelPackages.nvidia_x11_legacy173} /run/opengl-driver" - else if elem "nvidiaLegacy304" videoDrivers then - '' - ln -sf ${kernelPackages.nvidia_x11_legacy304} /run/opengl-driver - ${optionalString cfg.driSupport32Bit - "ln -sf ${pkgs_i686.linuxPackages.nvidia_x11_legacy304.override { libsOnly = true; kernel = null; } } /run/opengl-driver-32"} - '' - else if elem "ati_unfree" videoDrivers then - "ln -sf ${kernelPackages.ati_drivers_x11} /run/opengl-driver" - else - let - lib_fun = p: p.buildEnv { - name = "mesa-drivers+txc-${p.mesa_drivers.version}"; - paths = [ - p.mesa_drivers - p.mesa_noglu # mainly for libGL - (if cfg.s3tcSupport then p.libtxc_dxtn else p.libtxc_dxtn_s2tc) - ]; - }; - in - '' - ${optionalString cfg.driSupport "ln -sf ${lib_fun pkgs} /run/opengl-driver"} - ${optionalString cfg.driSupport32Bit - "ln -sf ${lib_fun pkgs_i686} /run/opengl-driver-32"} - '' - ); + system.activationScripts.setup-opengl = + '' + ln -sfn ${cfg.package} /run/opengl-driver + ${if pkgs.stdenv.isi686 then '' + ln -sfn opengl-driver /run/opengl-driver-32 + '' else if cfg.driSupport32Bit then '' + ln -sfn ${cfg.package32} /run/opengl-driver-32 + '' else '' + rm -f /run/opengl-driver-32 + ''} + ''; environment.variables.LD_LIBRARY_PATH = [ "/run/opengl-driver/lib" "/run/opengl-driver-32/lib" ]; + # FIXME: move this into card-specific modules. + hardware.opengl.package = mkDefault + (if elem "ati_unfree" videoDrivers then + kernelPackages.ati_drivers_x11 + else + makePackage pkgs); + + hardware.opengl.package32 = mkDefault (makePackage pkgs_i686); + boot.extraModulePackages = - optional (elem "nvidia" videoDrivers) kernelPackages.nvidia_x11 ++ - optional (elem "nvidiaLegacy173" videoDrivers) kernelPackages.nvidia_x11_legacy173 ++ - optional (elem "nvidiaLegacy304" videoDrivers) kernelPackages.nvidia_x11_legacy304 ++ optional (elem "virtualbox" videoDrivers) kernelPackages.virtualboxGuestAdditions ++ optional (elem "ati_unfree" videoDrivers) kernelPackages.ati_drivers_x11; - boot.blacklistedKernelModules = - optionals (elem "nvidia" videoDrivers) [ "nouveau" "nvidiafb" ]; - environment.etc = - (optionalAttrs (elem "ati_unfree" videoDrivers) { + optionalAttrs (elem "ati_unfree" videoDrivers) { "ati".source = "${kernelPackages.ati_drivers_x11}/etc/ati"; - }) - // (optionalAttrs (elem "nvidia" videoDrivers) { - "OpenCL/vendors/nvidia.icd".source = "${kernelPackages.nvidia_x11}/lib/vendors/nvidia.icd"; - }); + }; }; } diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix new file mode 100644 index 00000000000..0ca5558ee10 --- /dev/null +++ b/nixos/modules/hardware/video/nvidia.nix @@ -0,0 +1,54 @@ +# This module provides the proprietary NVIDIA X11 / OpenGL drivers. + +{ config, lib, pkgs, pkgs_i686, ... }: + +with lib; + +let + + drivers = config.services.xserver.videoDrivers; + + # FIXME: should introduce an option like + # ‘hardware.video.nvidia.package’ for overriding the default NVIDIA + # driver. + enabled = elem "nvidia" drivers || elem "nvidiaLegacy173" drivers || elem "nvidiaLegacy304" drivers; + + nvidia_x11 = + if elem "nvidia" drivers then + config.boot.kernelPackages.nvidia_x11 + else if elem "nvidiaLegacy173" drivers then + config.boot.kernelPackages.nvidia_x11_legacy173 + else if elem "nvidiaLegacy304" videoDrivers then + config.boot.kernelPackages.nvidia_x11_legacy304 + else throw "impossible"; + +in + +{ + + config = mkIf enabled { + + services.xserver.drivers = singleton + { name = "nvidia"; modules = [ nvidia_x11 ]; libPath = [ nvidia_x11 ]; }; + + services.xserver.screenSection = + '' + Option "RandRRotation" "on" + ''; + + hardware.opengl.package = nvidia_x11; + hardware.opengl.package32 = pkgs_i686.linuxPackages.nvidia_x11.override { libsOnly = true; kernel = null; }; + + environment.systemPackages = [ nvidia_x11 ]; + + boot.extraModulePackages = [ nvidia_x11 ]; + + boot.blacklistedKernelModules = [ "nouveau" "nvidiafb" ]; + + services.acpid.enable = true; + + environment.etc."OpenCL/vendors/nvidia.icd".source = "${nvidia_x11}/lib/vendors/nvidia.icd"; + + }; + +} diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index a769914499d..b95f30b7916 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -32,6 +32,7 @@ ./hardware/opengl.nix ./hardware/pcmcia.nix ./hardware/video/bumblebee.nix + ./hardware/video/nvidia.nix ./installer/tools/nixos-checkout.nix ./installer/tools/tools.nix ./misc/assertions.nix diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index 941d08c4641..dc3aa9d15cc 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -11,30 +11,16 @@ let xorg = pkgs.xorg; - # Map video driver names to driver packages. + # Map video driver names to driver packages. FIXME: move into card-specific modules. knownVideoDrivers = { ati_unfree = { modules = [ kernelPackages.ati_drivers_x11 ]; driverName = "fglrx"; }; nouveau = { modules = [ pkgs.xf86_video_nouveau ]; }; - nvidia = { modules = [ kernelPackages.nvidia_x11 ]; }; - nvidiaLegacy173 = { modules = [ kernelPackages.nvidia_x11_legacy173 ]; driverName = "nvidia"; }; - nvidiaLegacy304 = { modules = [ kernelPackages.nvidia_x11_legacy304 ]; driverName = "nvidia"; }; unichrome = { modules = [ pkgs.xorgVideoUnichrome ]; }; virtualbox = { modules = [ kernelPackages.virtualboxGuestAdditions ]; driverName = "vboxvideo"; }; ati = { modules = [ pkgs.xorg.xf86videoati pkgs.xorg.glamoregl ]; }; intel-testing = { modules = with pkgs.xorg; [ xf86videointel-testing glamoregl ]; driverName = "intel"; }; }; - driverNames = cfg.videoDrivers; - - needsAcpid = - (elem "nvidia" driverNames) || - (elem "nvidiaLegacy173" driverNames) || - (elem "nvidiaLegacy304" driverNames); - - drivers = flip map driverNames - (name: { inherit name; driverName = name; } // - attrByPath [name] (if (hasAttr ("xf86video" + name) xorg) then { modules = [(getAttr ("xf86video" + name) xorg) ]; } else throw "unknown video driver `${name}'") knownVideoDrivers); - fontsForXServer = config.fonts.fonts ++ # We don't want these fonts in fonts.conf, because then modern, @@ -79,7 +65,6 @@ let monitors = foldl mkMonitor [] xrandrHeads; in concatMapStrings (getAttr "value") monitors; - configFile = pkgs.stdenv.mkDerivation { name = "xserver.conf"; @@ -204,6 +189,15 @@ in ''; }; + drivers = mkOption { + type = types.listOf types.attrs; + internal = true; + description = '' + A list of attribute sets specifying drivers to be loaded by + the X11 server. + ''; + }; + vaapiDrivers = mkOption { type = types.listOf types.path; default = [ ]; @@ -397,9 +391,21 @@ in ###### implementation config = mkIf cfg.enable { - hardware.opengl.enable = true; + + hardware.opengl.enable = mkDefault true; + services.xserver.videoDrivers = mkIf (cfg.videoDriver != null) [ cfg.videoDriver ]; + # FIXME: somehow check for unknown driver names. + services.xserver.drivers = flip concatMap cfg.videoDrivers (name: + let driver = + attrByPath [name] + (if (hasAttr ("xf86video" + name) xorg) + then { modules = [(getAttr ("xf86video" + name) xorg) ]; } + else null) + knownVideoDrivers; + in optional (driver != null) ({ inherit name; driverName = name; } // driver)); + assertions = [ { assertion = !(config.programs.ssh.startAgent && cfg.startGnuPGAgent); message = @@ -438,24 +444,18 @@ in pkgs.xterm pkgs.xdg_utils ] - ++ optional (elem "nvidia" driverNames) kernelPackages.nvidia_x11 - ++ optional (elem "nvidiaLegacy173" driverNames) kernelPackages.nvidia_x11_legacy173 - ++ optional (elem "nvidiaLegacy304" driverNames) kernelPackages.nvidia_x11_legacy304 - ++ optional (elem "virtualbox" driverNames) xorg.xrefresh - ++ optional (elem "ati_unfree" driverNames) kernelPackages.ati_drivers_x11; - - services.acpid.enable = mkIf needsAcpid true; + ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh + ++ optional (elem "ati_unfree" cfg.videoDrivers) kernelPackages.ati_drivers_x11; environment.pathsToLink = [ "/etc/xdg" "/share/xdg" "/share/applications" "/share/icons" "/share/pixmaps" ]; systemd.defaultUnit = mkIf cfg.autorun "graphical.target"; - systemd.services."display-manager" = + systemd.services.display-manager = { description = "X11 Server"; - after = [ "systemd-udev-settle.service" "local-fs.target" ] - ++ optional needsAcpid "acpid.service"; + after = [ "systemd-udev-settle.service" "local-fs.target" "acpid.service" ]; restartIfChanged = false; @@ -463,15 +463,11 @@ in { FONTCONFIG_FILE = "/etc/fonts/fonts.conf"; # !!! cleanup XKB_BINDIR = "${xorg.xkbcomp}/bin"; # Needed for the Xkb extension. XORG_DRI_DRIVER_PATH = "/run/opengl-driver/lib/dri"; # !!! Depends on the driver selected at runtime. - } // optionalAttrs (elem "nvidia" driverNames) { - LD_LIBRARY_PATH = "${xorg.libX11}/lib:${xorg.libXext}/lib:${kernelPackages.nvidia_x11}/lib"; - } // optionalAttrs (elem "nvidiaLegacy173" driverNames) { - LD_LIBRARY_PATH = "${xorg.libX11}/lib:${xorg.libXext}/lib:${kernelPackages.nvidia_x11_legacy173}/lib"; - } // optionalAttrs (elem "nvidiaLegacy304" driverNames) { - LD_LIBRARY_PATH = "${xorg.libX11}/lib:${xorg.libXext}/lib:${kernelPackages.nvidia_x11_legacy304}/lib"; - } // optionalAttrs (elem "ati_unfree" driverNames) { - LD_LIBRARY_PATH = "${xorg.libX11}/lib:${xorg.libXext}/lib:${kernelPackages.ati_drivers_x11}/lib:${kernelPackages.ati_drivers_x11}/X11R6/lib64/modules/linux"; - #XORG_DRI_DRIVER_PATH = "${kernelPackages.ati_drivers_x11}/lib/dri"; # is ignored because ati drivers ship their own unpatched libglx.so ! + LD_LIBRARY_PATH = concatStringsSep ":" ( + [ "${xorg.libX11}/lib" "${xorg.libXext}/lib" ] + ++ optionals (elem "ati_unfree" cfg.videoDrivers) + [ "${kernelPackages.ati_drivers_x11}/lib" "${kernelPackages.ati_drivers_x11}/X11R6/lib64/modules/linux" ] + ++ concatLists (catAttrs "libPath" cfg.drivers)); } // cfg.displayManager.job.environment; preStart = @@ -501,7 +497,7 @@ in ] ++ optional (!cfg.enableTCP) "-nolisten tcp"; services.xserver.modules = - concatLists (catAttrs "modules" drivers) ++ + concatLists (catAttrs "modules" cfg.drivers) ++ [ xorg.xorgserver xorg.xf86inputevdev ]; @@ -537,7 +533,7 @@ in ${cfg.serverLayoutSection} # Reference the Screen sections for each driver. This will # cause the X server to try each in turn. - ${flip concatMapStrings drivers (d: '' + ${flip concatMapStrings cfg.drivers (d: '' Screen "Screen-${d.name}[0]" '')} EndSection @@ -551,11 +547,11 @@ in # For each supported driver, add a "Device" and "Screen" # section. - ${flip concatMapStrings drivers (driver: '' + ${flip concatMapStrings cfg.drivers (driver: '' Section "Device" Identifier "Device-${driver.name}[0]" - Driver "${driver.driverName}" + Driver "${driver.driverName or driver.name}" ${if cfg.useGlamor then ''Option "AccelMethod" "glamor"'' else ""} ${cfg.deviceSection} ${xrandrDeviceSection} @@ -574,10 +570,6 @@ in DefaultDepth ${toString cfg.defaultDepth} ''} - ${optionalString (driver.name == "nvidia") '' - Option "RandRRotation" "on" - ''} - ${optionalString (driver.name != "virtualbox" && (cfg.resolutions != [] ||