|
|
|
|
|
|
|
|
|
|
|
import subprocess |
|
|
import shlex |
|
|
import re |
|
|
import platform |
|
|
import tempfile |
|
|
import os |
|
|
import sys |
|
|
|
|
|
def pci_records(): |
|
|
records = [] |
|
|
command = shlex.split('lspci -vmm') |
|
|
output = subprocess.check_output(command).decode() |
|
|
|
|
|
for devices in output.strip().split("\n\n"): |
|
|
record = {} |
|
|
records.append(record) |
|
|
for row in devices.split("\n"): |
|
|
key, value = row.split("\t") |
|
|
record[key.split(':')[0]] = value |
|
|
|
|
|
return records |
|
|
|
|
|
def generate_xorg_conf(devices): |
|
|
xorg_conf = [] |
|
|
|
|
|
device_section = """ |
|
|
Section "Device" |
|
|
Identifier "Device{device_id}" |
|
|
Driver "nvidia" |
|
|
VendorName "NVIDIA Corporation" |
|
|
BusID "{bus_id}" |
|
|
EndSection |
|
|
""" |
|
|
server_layout_section = """ |
|
|
Section "ServerLayout" |
|
|
Identifier "Layout0" |
|
|
{screen_records} |
|
|
EndSection |
|
|
""" |
|
|
screen_section = """ |
|
|
Section "Screen" |
|
|
Identifier "Screen{screen_id}" |
|
|
Device "Device{device_id}" |
|
|
DefaultDepth 24 |
|
|
Option "AllowEmptyInitialConfiguration" "True" |
|
|
SubSection "Display" |
|
|
Depth 24 |
|
|
Virtual 1024 768 |
|
|
EndSubSection |
|
|
EndSection |
|
|
""" |
|
|
screen_records = [] |
|
|
for i, bus_id in enumerate(devices): |
|
|
xorg_conf.append(device_section.format(device_id=i, bus_id=bus_id)) |
|
|
xorg_conf.append(screen_section.format(device_id=i, screen_id=i)) |
|
|
screen_records.append('Screen {screen_id} "Screen{screen_id}" 0 0'.format(screen_id=i)) |
|
|
|
|
|
xorg_conf.append(server_layout_section.format(screen_records="\n ".join(screen_records))) |
|
|
|
|
|
output = "\n".join(xorg_conf) |
|
|
print(output) |
|
|
return output |
|
|
|
|
|
def startx(display): |
|
|
if platform.system() != 'Linux': |
|
|
raise Exception("Can only run startx on linux") |
|
|
|
|
|
devices = [] |
|
|
for r in pci_records(): |
|
|
if r.get('Vendor', '') == 'NVIDIA Corporation' \ |
|
|
and r['Class'] in ['VGA compatible controller', '3D controller']: |
|
|
bus_id = 'PCI:' + ':'.join(map(lambda x: str(int(x, 16)), re.split(r'[:\.]', r['Slot']))) |
|
|
devices.append(bus_id) |
|
|
|
|
|
if not devices: |
|
|
raise Exception("no nvidia cards found") |
|
|
|
|
|
try: |
|
|
fd, path = tempfile.mkstemp() |
|
|
with open(path, "w") as f: |
|
|
f.write(generate_xorg_conf(devices)) |
|
|
command = shlex.split("Xorg -noreset +extension GLX +extension RANDR +extension RENDER -config %s :%s" % (path, display)) |
|
|
subprocess.call(command) |
|
|
finally: |
|
|
os.close(fd) |
|
|
os.unlink(path) |
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
display = 1 |
|
|
if len(sys.argv) > 1: |
|
|
display = int(sys.argv[1]) |
|
|
print("Starting X on DISPLAY=:%s" % display) |
|
|
startx(display) |
|
|
|