Path: blob/21.2-virgl/src/vulkan/overlay-layer/mesa-overlay-control.py
7204 views
#!/usr/bin/env python31import os2import socket3import sys4import select5from select import EPOLLIN, EPOLLPRI, EPOLLERR6import time7from collections import namedtuple8import argparse910TIMEOUT = 1.0 # seconds1112VERSION_HEADER = bytearray('MesaOverlayControlVersion', 'utf-8')13DEVICE_NAME_HEADER = bytearray('DeviceName', 'utf-8')14MESA_VERSION_HEADER = bytearray('MesaVersion', 'utf-8')1516DEFAULT_SERVER_ADDRESS = "\0mesa_overlay"1718class Connection:19def __init__(self, path):20# Create a Unix Domain socket and connect21sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)22try:23sock.connect(path)24except socket.error as msg:25print(msg)26sys.exit(1)2728self.sock = sock2930# initialize poll interface and register socket31epoll = select.epoll()32epoll.register(sock, EPOLLIN | EPOLLPRI | EPOLLERR)33self.epoll = epoll3435def recv(self, timeout):36'''37timeout as float in seconds38returns:39- None on error or disconnection40- bytes() (empty) on timeout41'''4243events = self.epoll.poll(timeout)44for ev in events:45(fd, event) = ev46if fd != self.sock.fileno():47continue4849# check for socket error50if event & EPOLLERR:51return None5253# EPOLLIN or EPOLLPRI, just read the message54msg = self.sock.recv(4096)5556# socket disconnected57if len(msg) == 0:58return None5960return msg6162return bytes()6364def send(self, msg):65self.sock.send(msg)6667class MsgParser:68MSGBEGIN = bytes(':', 'utf-8')[0]69MSGEND = bytes(';', 'utf-8')[0]70MSGSEP = bytes('=', 'utf-8')[0]7172def __init__(self, conn):73self.cmdpos = 074self.parampos = 075self.bufferpos = 076self.reading_cmd = False77self.reading_param = False78self.buffer = None79self.cmd = bytearray(4096)80self.param = bytearray(4096)8182self.conn = conn8384def readCmd(self, ncmds, timeout=TIMEOUT):85'''86returns:87- None on error or disconnection88- bytes() (empty) on timeout89'''9091parsed = []9293remaining = timeout9495while remaining > 0 and ncmds > 0:96now = time.monotonic()9798if self.buffer == None:99self.buffer = self.conn.recv(remaining)100self.bufferpos = 0101102# disconnected or error103if self.buffer == None:104return None105106for i in range(self.bufferpos, len(self.buffer)):107c = self.buffer[i]108self.bufferpos += 1109if c == self.MSGBEGIN:110self.cmdpos = 0111self.parampos = 0112self.reading_cmd = True113self.reading_param = False114elif c == self.MSGEND:115if not self.reading_cmd:116continue117self.reading_cmd = False118self.reading_param = False119120cmd = self.cmd[0:self.cmdpos]121param = self.param[0:self.parampos]122self.reading_cmd = False123self.reading_param = False124125parsed.append((cmd, param))126ncmds -= 1127if ncmds == 0:128break129elif c == self.MSGSEP:130if self.reading_cmd:131self.reading_param = True132else:133if self.reading_param:134self.param[self.parampos] = c135self.parampos += 1136elif self.reading_cmd:137self.cmd[self.cmdpos] = c138self.cmdpos += 1139140# if we read the entire buffer and didn't finish the command,141# throw it away142self.buffer = None143144# check if we have time for another iteration145elapsed = time.monotonic() - now146remaining = max(0, remaining - elapsed)147148# timeout149return parsed150151def control(args):152if args.socket:153address = '\0' + args.socket154else:155address = DEFAULT_SERVER_ADDRESS156157conn = Connection(address)158msgparser = MsgParser(conn)159160version = None161name = None162mesa_version = None163164msgs = msgparser.readCmd(3)165166for m in msgs:167cmd, param = m168if cmd == VERSION_HEADER:169version = int(param)170elif cmd == DEVICE_NAME_HEADER:171name = param.decode('utf-8')172elif cmd == MESA_VERSION_HEADER:173mesa_version = param.decode('utf-8')174175if version != 1 or name == None or mesa_version == None:176print('ERROR: invalid protocol')177sys.exit(1)178179180if args.info:181info = "Protocol Version: {}\n"182info += "Device Name: {}\n"183info += "Mesa Version: {}"184print(info.format(version, name, mesa_version))185186if args.cmd == 'start-capture':187conn.send(bytearray(':capture=1;', 'utf-8'))188elif args.cmd == 'stop-capture':189conn.send(bytearray(':capture=0;', 'utf-8'))190191if __name__ == '__main__':192parser = argparse.ArgumentParser(description='MESA_overlay control client')193parser.add_argument('--info', action='store_true', help='Print info from socket')194parser.add_argument('--socket', '-s', type=str, help='Path to socket')195196commands = parser.add_subparsers(help='commands to run', dest='cmd')197commands.add_parser('start-capture')198commands.add_parser('stop-capture')199200args = parser.parse_args()201202control(args)203204205