From 29ddfda5cf91e880b01d9cd3ed99bfea483cf8c2 Mon Sep 17 00:00:00 2001 From: cronyakatsuki Date: Thu, 7 Apr 2022 18:03:37 +0200 Subject: [PATCH 1/4] Using amdgpu for amd igpu's. --- envycontrol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/envycontrol.py b/envycontrol.py index 5886330..b5b8b37 100644 --- a/envycontrol.py +++ b/envycontrol.py @@ -117,7 +117,7 @@ Section "Device" Identifier "amdgpu" - Driver "modesetting" + Driver "amdgpu" EndSection Section "Screen" From 049183304f223929ba99f793027f5e6e17bda60a Mon Sep 17 00:00:00 2001 From: cronyakatsuki Date: Thu, 7 Apr 2022 18:53:40 +0200 Subject: [PATCH 2/4] Reimplemented display managment setup. --- envycontrol.py | 88 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 7 deletions(-) diff --git a/envycontrol.py b/envycontrol.py index b5b8b37..ec857c0 100644 --- a/envycontrol.py +++ b/envycontrol.py @@ -5,7 +5,7 @@ import re import subprocess -VERSION = '2.0' +VERSION = '2.1' BLACKLIST_PATH = '/etc/modprobe.d/blacklist-nvidia.conf' @@ -153,14 +153,31 @@ options nvidia "NVreg_DynamicPowerManagement=0x02" ''' -XSETUP_PATH = '/usr/share/sddm/scripts/Xsetup' +SDDM_XSETUP_PATH = '/usr/share/sddm/scripts/Xsetup' -XSETUP_CONTENT = '''#!/bin/sh +SDDM_XSETUP_CONTENT = '''#!/bin/sh # Xsetup - run as root before the login dialog appears ''' -def _switcher(mode): +LIGHTDM_SCRIPT_PATH = '/etc/lightdm/nvidia.sh' + +LIGHTDM_CONFIG_PATH = '/etc/lightdm/lightdm.conf.d/20-nvidia.conf' + +LIGHTDM_CONFIG_CONTENT = '''# Automatically generated by EnvyControl + +[Seat:*] +display-setup-script=/etc/lightdm/nvidia.sh +''' + +NVIDIA_XRANDR_SCRIPT = '''#!/bin/sh +# Automatically generated by EnvyControl + +xrandr --setprovideroutputsource "{}" NVIDIA-0 +xrandr --auto +''' + +def _switcher(mode, display_manager = ''): _check_root() yes = ('yes', 'y', 'ye') if mode == 'integrated': @@ -190,12 +207,17 @@ def _switcher(mode): igpu_vendor = _get_igpu_vendor() # get the Nvidia dGPU PCI bus pci_bus = _get_pci_bus() + # get display manager + if display_manager == '': + display_manager = _check_display_manager() try: # Create X.org config if igpu_vendor == 'intel': _create_file(XORG_PATH, XORG_INTEL.format(pci_bus)) + _setup_display_manager(display_manager) elif igpu_vendor == 'amd': _create_file(XORG_PATH, XORG_AMD.format(pci_bus)) + _setup_display_manager(display_manager) # Enable modeset for Nvidia driver _create_file(MODESET_PATH, MODESET_CONTENT) choice = input('Enable ForceCompositionPipeline? (y/N): ').lower() @@ -226,7 +248,7 @@ def _switcher(mode): def _cleanup(): # Remove all files created by EnvyControl - to_remove = (BLACKLIST_PATH,UDEV_INTEGRATED_PATH, UDEV_PM_PATH, XORG_PATH, EXTRA_PATH, '/etc/X11/xorg.conf.d/90-nvidia.conf', MODESET_PATH, '/etc/lightdm/nvidia.sh', '/etc/lightdm/lightdm.conf.d/20-nvidia.conf') + to_remove = (BLACKLIST_PATH,UDEV_INTEGRATED_PATH, UDEV_PM_PATH, XORG_PATH, EXTRA_PATH, '/etc/X11/xorg.conf.d/90-nvidia.conf', MODESET_PATH, LIGHTDM_SCRIPT_PATH, LIGHTDM_CONFIG_PATH, SDDM_XSETUP_PATH) for file in to_remove: try: os.remove(file) @@ -247,6 +269,16 @@ def _get_igpu_vendor(): print('Error: could not find Intel or AMD iGPU') sys.exit(1) +def _get_amd_igpu_name(): + pattern = re.compile(r'(name:).*(ATI*|AMD*|AMD\/ATI)*') + xrandr = subprocess.run(['xrandr', '--listproviders'], capture_output=True, text=True).stdout + + if pattern.findall(xrandr): + name = re.search(pattern, xrandr).group(0)[5:] + else: + name = "Error: could not find AMD iGPU" + return name + def _get_pci_bus(): pattern = re.compile( r'([0-9]{2}:[0-9a-z]{2}.[0-9]).*(VGA compatible controller: NVIDIA|3D controller: NVIDIA)') @@ -258,6 +290,46 @@ def _get_pci_bus(): print(f'Error: switching directly from integrated to Nvidia mode is not supported\nTry switching to hybrid mode first!') sys.exit(1) +def _check_display_manager(): + # automatically detect the current Display Manager + # this depends on systemd + pattern = re.compile(r'(\/usr\/bin\/|\/usr\/sbin\/)(.*)') + try: + with open('/etc/systemd/system/display-manager.service',mode='r', encoding='utf-8') as f: + display_manager = pattern.findall(f.read())[0][1] + except Exception: + display_manager = '' + print('Warning: automatic Display Manager detection is not available') + finally: + return display_manager + +def _setup_display_manager(display_manager): + # setup the Xrandr script if necessary + # get igpu vendor to use if needed + igpu_vendor = _get_igpu_vendor() + + if display_manager == 'sddm': + if igpu_vendor == "intel": + _create_file(SDDM_XSETUP_PATH, NVIDIA_XRANDR_SCRIPT.format("modesetting")) + else: + amd_name = _get_amd_igpu_name() + _create_file(SDDM_XSETUP_PATH, NVIDIA_XRANDR_SCRIPT.format(amd_name)) + subprocess.run(['chmod','+x',SDDM_XSETUP_PATH], stdout=subprocess.DEVNULL) + elif display_manager == 'lightdm': + if igpu_vendor == "amd": + amd_name = _get_amd_igpu_name() + _create_file(SDDM_XSETUP_PATH, NVIDIA_XRANDR_SCRIPT.format(amd_name)) + else: + _create_file(SDDM_XSETUP_PATH, NVIDIA_XRANDR_SCRIPT.format("modesetting")) + subprocess.run(['chmod','+x',LIGHTDM_SCRIPT_PATH], stdout=subprocess.DEVNULL) + # create config + if not os.path.exists(os.path.dirname(LIGHTDM_CONFIG_PATH)): + _create_file(LIGHTDM_CONFIG_PATH, LIGHTDM_CONFIG_CONTENT) + elif display_manager not in ['', 'gdm', 'gdm3']: + print('Error: provided Display Manager is not valid') + print('Supported Display Managers: gdm, sddm, lightdm') + sys.exit(1) + def _rebuild_initramfs(): is_debian = os.path.exists('/etc/debian_version') is_rhel = os.path.exists('/etc/redhat-release') @@ -300,8 +372,8 @@ def _query_mode(): def _reset_sddm(): _check_root() try: - _create_file(XSETUP_PATH, XSETUP_CONTENT) - subprocess.run(['chmod', '+x', XSETUP_PATH], stdout=subprocess.DEVNULL) + _create_file(SDDM_XSETUP_PATH, SDDM_XSETUP_CONTENT) + subprocess.run(['chmod', '+x', SDDM_XSETUP_PATH], stdout=subprocess.DEVNULL) except Exception as e: print(f'Error: {e}') sys.exit(1) @@ -316,6 +388,8 @@ def main(): parser.add_argument('-v', '--version', action='store_true', help='show this program\'s version number and exit') parser.add_argument('-s', '--switch', type=str, metavar='MODE', action='store', help='switch the graphics mode, supported modes: integrated, hybrid, nvidia') parser.add_argument('-q', '--query', action='store_true', help='query the current graphics mode set by EnvyControl') + parser.add_argument('--dm', type=str, metavar='DISPLAY_MANAGER', action='store', + help='Manually specify your Display Manager. This is required only for systems without systemd. Supported DMs: gdm, sddm, lightdm') parser.add_argument('--reset_sddm', action='store_true', help='restore original SDDM Xsetup file') # print help if no arg is provided if len(sys.argv) == 1: From 1c54efe8233e43fbd87cd58f9d9e6a1bb6f2a4c0 Mon Sep 17 00:00:00 2001 From: cronyakatsuki Date: Thu, 7 Apr 2022 18:56:56 +0200 Subject: [PATCH 3/4] Restore version. --- envycontrol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/envycontrol.py b/envycontrol.py index ec857c0..9a6d26c 100644 --- a/envycontrol.py +++ b/envycontrol.py @@ -5,7 +5,7 @@ import re import subprocess -VERSION = '2.1' +VERSION = '2.0' BLACKLIST_PATH = '/etc/modprobe.d/blacklist-nvidia.conf' From 9709d379707c77dd1cc56fd5cf79a478ed0d868b Mon Sep 17 00:00:00 2001 From: cronyakatsuki Date: Thu, 7 Apr 2022 19:12:51 +0200 Subject: [PATCH 4/4] Use the --dm option. --- envycontrol.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/envycontrol.py b/envycontrol.py index 9a6d26c..ff27d57 100644 --- a/envycontrol.py +++ b/envycontrol.py @@ -403,7 +403,14 @@ def main(): elif args.reset_sddm: _reset_sddm() elif args.switch: - _switcher(args.switch) + if args.dm and args.switch == 'nvidia': + _switcher(args.switch, args.dm) + else: + _switcher(args.switch) + elif args.dm and not args.switch: + print('Error: this option is intended to be used with --switch nvidia') + print('Example: sudo envycontrol --switch nvidia --dm sddm') + sys.exit(1) if __name__ == '__main__': main()