1*f0687c8aSRaman Tennetifrom .pykms import * 2*f0687c8aSRaman Tennetifrom enum import Enum 3*f0687c8aSRaman Tennetiimport os 4*f0687c8aSRaman Tennetiimport struct 5*f0687c8aSRaman Tenneti 6*f0687c8aSRaman Tenneti# 7*f0687c8aSRaman Tenneti# Common RGB colours 8*f0687c8aSRaman Tenneti# 9*f0687c8aSRaman Tenneti 10*f0687c8aSRaman Tennetired = RGB(255, 0, 0) 11*f0687c8aSRaman Tennetigreen = RGB(0, 255, 0) 12*f0687c8aSRaman Tennetiblue = RGB(0, 0, 255) 13*f0687c8aSRaman Tennetiyellow = RGB(255, 255, 0) 14*f0687c8aSRaman Tennetipurple = RGB(255, 0, 255) 15*f0687c8aSRaman Tennetiwhite = RGB(255, 255, 255) 16*f0687c8aSRaman Tenneticyan = RGB(0, 255, 255) 17*f0687c8aSRaman Tenneti 18*f0687c8aSRaman Tenneti# 19*f0687c8aSRaman Tenneti# Rotation enum 20*f0687c8aSRaman Tenneti# 21*f0687c8aSRaman Tenneti 22*f0687c8aSRaman Tenneticlass Rotation(int, Enum): 23*f0687c8aSRaman Tenneti ROTATE_0 = 1 << 0 24*f0687c8aSRaman Tenneti ROTATE_90 = 1 << 1 25*f0687c8aSRaman Tenneti ROTATE_180 = 1 << 2 26*f0687c8aSRaman Tenneti ROTATE_270 = 1 << 3 27*f0687c8aSRaman Tenneti ROTATE_MASK = ROTATE_0 | ROTATE_90 | ROTATE_180 | ROTATE_270 28*f0687c8aSRaman Tenneti REFLECT_X = 1 << 4 29*f0687c8aSRaman Tenneti REFLECT_Y = 1 << 5 30*f0687c8aSRaman Tenneti REFLECT_MASK = REFLECT_X | REFLECT_Y 31*f0687c8aSRaman Tenneti 32*f0687c8aSRaman Tenneti# 33*f0687c8aSRaman Tenneti# DrmObject API extensions 34*f0687c8aSRaman Tenneti# 35*f0687c8aSRaman Tenneti 36*f0687c8aSRaman Tennetidef __obj_set_prop(self, prop, value): 37*f0687c8aSRaman Tenneti if self.card.has_atomic: 38*f0687c8aSRaman Tenneti areq = AtomicReq(self.card) 39*f0687c8aSRaman Tenneti areq.add(self, prop, value) 40*f0687c8aSRaman Tenneti if areq.commit_sync() != 0: 41*f0687c8aSRaman Tenneti print("commit failed") 42*f0687c8aSRaman Tenneti else: 43*f0687c8aSRaman Tenneti if self.set_prop_value(prop, value) != 0: 44*f0687c8aSRaman Tenneti print("setting property failed") 45*f0687c8aSRaman Tenneti 46*f0687c8aSRaman Tennetidef __obj_set_props(self, map): 47*f0687c8aSRaman Tenneti if self.card.has_atomic: 48*f0687c8aSRaman Tenneti areq = AtomicReq(self.card) 49*f0687c8aSRaman Tenneti 50*f0687c8aSRaman Tenneti for key, value in map.items(): 51*f0687c8aSRaman Tenneti areq.add(self, key, value) 52*f0687c8aSRaman Tenneti 53*f0687c8aSRaman Tenneti if areq.commit_sync() != 0: 54*f0687c8aSRaman Tenneti print("commit failed") 55*f0687c8aSRaman Tenneti else: 56*f0687c8aSRaman Tenneti for propid,propval in map.items(): 57*f0687c8aSRaman Tenneti if self.set_prop_value(propid, propval) != 0: 58*f0687c8aSRaman Tenneti print("setting property failed") 59*f0687c8aSRaman Tenneti 60*f0687c8aSRaman TennetiDrmObject.set_prop = __obj_set_prop 61*f0687c8aSRaman TennetiDrmObject.set_props = __obj_set_props 62*f0687c8aSRaman Tenneti 63*f0687c8aSRaman Tenneti# 64*f0687c8aSRaman Tenneti# Card API extensions 65*f0687c8aSRaman Tenneti# 66*f0687c8aSRaman Tenneti 67*f0687c8aSRaman Tennetidef __card_disable_planes(self): 68*f0687c8aSRaman Tenneti areq = AtomicReq(self) 69*f0687c8aSRaman Tenneti 70*f0687c8aSRaman Tenneti for p in self.planes: 71*f0687c8aSRaman Tenneti areq.add(p, "FB_ID", 0) 72*f0687c8aSRaman Tenneti areq.add(p, "CRTC_ID", 0) 73*f0687c8aSRaman Tenneti 74*f0687c8aSRaman Tenneti if areq.commit_sync() != 0: 75*f0687c8aSRaman Tenneti print("disabling planes failed") 76*f0687c8aSRaman Tenneti 77*f0687c8aSRaman TennetiCard.disable_planes = __card_disable_planes 78*f0687c8aSRaman Tenneti 79*f0687c8aSRaman Tenneticlass DrmEventType(Enum): 80*f0687c8aSRaman Tenneti VBLANK = 0x01 81*f0687c8aSRaman Tenneti FLIP_COMPLETE = 0x02 82*f0687c8aSRaman Tenneti 83*f0687c8aSRaman Tenneti# 84*f0687c8aSRaman Tenneti# AtomicReq API extensions 85*f0687c8aSRaman Tenneti# 86*f0687c8aSRaman Tenneti 87*f0687c8aSRaman Tennetidef __atomic_req_add_connector(req, conn, crtc): 88*f0687c8aSRaman Tenneti req.add(conn, "CRTC_ID", crtc.id if crtc else 0) 89*f0687c8aSRaman Tenneti 90*f0687c8aSRaman Tennetidef __atomic_req_add_crtc(req, crtc, mode_blob): 91*f0687c8aSRaman Tenneti if mode_blob: 92*f0687c8aSRaman Tenneti req.add(crtc, {"ACTIVE": 1, "MODE_ID": mode_blob.id}) 93*f0687c8aSRaman Tenneti else: 94*f0687c8aSRaman Tenneti req.add(crtc, {"ACTIVE": 0, "MODE_ID": 0}) 95*f0687c8aSRaman Tenneti 96*f0687c8aSRaman Tennetidef __atomic_req_add_plane(req, plane, fb, crtc, 97*f0687c8aSRaman Tenneti src=None, dst=None, zpos=None, 98*f0687c8aSRaman Tenneti params={}): 99*f0687c8aSRaman Tenneti if not src and fb: 100*f0687c8aSRaman Tenneti src = (0, 0, fb.width, fb.height) 101*f0687c8aSRaman Tenneti 102*f0687c8aSRaman Tenneti if not dst: 103*f0687c8aSRaman Tenneti dst = src 104*f0687c8aSRaman Tenneti 105*f0687c8aSRaman Tenneti m = {"FB_ID": fb.id if fb else 0, 106*f0687c8aSRaman Tenneti "CRTC_ID": crtc.id if crtc else 0} 107*f0687c8aSRaman Tenneti 108*f0687c8aSRaman Tenneti if src is not None: 109*f0687c8aSRaman Tenneti src_x = int(round(src[0] * 65536)) 110*f0687c8aSRaman Tenneti src_y = int(round(src[1] * 65536)) 111*f0687c8aSRaman Tenneti src_w = int(round(src[2] * 65536)) 112*f0687c8aSRaman Tenneti src_h = int(round(src[3] * 65536)) 113*f0687c8aSRaman Tenneti 114*f0687c8aSRaman Tenneti m["SRC_X"] = src_x 115*f0687c8aSRaman Tenneti m["SRC_Y"] = src_y 116*f0687c8aSRaman Tenneti m["SRC_W"] = src_w 117*f0687c8aSRaman Tenneti m["SRC_H"] = src_h 118*f0687c8aSRaman Tenneti 119*f0687c8aSRaman Tenneti if dst is not None: 120*f0687c8aSRaman Tenneti crtc_x = int(round(dst[0])) 121*f0687c8aSRaman Tenneti crtc_y = int(round(dst[1])) 122*f0687c8aSRaman Tenneti crtc_w = int(round(dst[2])) 123*f0687c8aSRaman Tenneti crtc_h = int(round(dst[3])) 124*f0687c8aSRaman Tenneti 125*f0687c8aSRaman Tenneti m["CRTC_X"] = crtc_x 126*f0687c8aSRaman Tenneti m["CRTC_Y"] = crtc_y 127*f0687c8aSRaman Tenneti m["CRTC_W"] = crtc_w 128*f0687c8aSRaman Tenneti m["CRTC_H"] = crtc_h 129*f0687c8aSRaman Tenneti 130*f0687c8aSRaman Tenneti if zpos is not None: 131*f0687c8aSRaman Tenneti m["zpos"] = zpos 132*f0687c8aSRaman Tenneti 133*f0687c8aSRaman Tenneti m.update(params) 134*f0687c8aSRaman Tenneti 135*f0687c8aSRaman Tenneti req.add(plane, m) 136*f0687c8aSRaman Tenneti 137*f0687c8aSRaman Tennetipykms.AtomicReq.add_connector = __atomic_req_add_connector 138*f0687c8aSRaman Tennetipykms.AtomicReq.add_crtc = __atomic_req_add_crtc 139*f0687c8aSRaman Tennetipykms.AtomicReq.add_plane = __atomic_req_add_plane 140*f0687c8aSRaman Tenneti 141*f0687c8aSRaman Tenneti# struct drm_event { 142*f0687c8aSRaman Tenneti# __u32 type; 143*f0687c8aSRaman Tenneti# __u32 length; 144*f0687c8aSRaman Tenneti#}; 145*f0687c8aSRaman Tenneti# 146*f0687c8aSRaman Tenneti 147*f0687c8aSRaman Tenneti_drm_ev = struct.Struct("II") 148*f0687c8aSRaman Tenneti 149*f0687c8aSRaman Tenneti#struct drm_event_vblank { 150*f0687c8aSRaman Tenneti# struct drm_event base; 151*f0687c8aSRaman Tenneti# __u64 user_data; 152*f0687c8aSRaman Tenneti# __u32 tv_sec; 153*f0687c8aSRaman Tenneti# __u32 tv_usec; 154*f0687c8aSRaman Tenneti# __u32 sequence; 155*f0687c8aSRaman Tenneti# __u32 reserved; 156*f0687c8aSRaman Tenneti#}; 157*f0687c8aSRaman Tenneti 158*f0687c8aSRaman Tenneti_drm_ev_vbl = struct.Struct("QIIII") # Note: doesn't contain drm_event 159*f0687c8aSRaman Tenneti 160*f0687c8aSRaman Tenneticlass DrmEvent: 161*f0687c8aSRaman Tenneti def __init__(self, type, seq, time, data): 162*f0687c8aSRaman Tenneti self.type = type 163*f0687c8aSRaman Tenneti self.seq = seq 164*f0687c8aSRaman Tenneti self.time = time 165*f0687c8aSRaman Tenneti self.data = data 166*f0687c8aSRaman Tenneti 167*f0687c8aSRaman Tenneti# Return DrmEvents. Note: blocks if there's nothing to read 168*f0687c8aSRaman Tennetidef __card_read_events(self): 169*f0687c8aSRaman Tenneti buf = os.read(self.fd, _drm_ev_vbl.size * 20) 170*f0687c8aSRaman Tenneti 171*f0687c8aSRaman Tenneti if len(buf) == 0: 172*f0687c8aSRaman Tenneti return 173*f0687c8aSRaman Tenneti 174*f0687c8aSRaman Tenneti if len(buf) < _drm_ev.size: 175*f0687c8aSRaman Tenneti raise RuntimeError("Partial DRM event") 176*f0687c8aSRaman Tenneti 177*f0687c8aSRaman Tenneti idx = 0 178*f0687c8aSRaman Tenneti 179*f0687c8aSRaman Tenneti while idx < len(buf): 180*f0687c8aSRaman Tenneti ev_tuple = _drm_ev.unpack_from(buf, idx) 181*f0687c8aSRaman Tenneti 182*f0687c8aSRaman Tenneti type = DrmEventType(ev_tuple[0]) 183*f0687c8aSRaman Tenneti 184*f0687c8aSRaman Tenneti if type != DrmEventType.VBLANK and type != DrmEventType.FLIP_COMPLETE: 185*f0687c8aSRaman Tenneti raise RuntimeError("Illegal DRM event type") 186*f0687c8aSRaman Tenneti 187*f0687c8aSRaman Tenneti vbl_tuple = _drm_ev_vbl.unpack_from(buf, idx + _drm_ev.size) 188*f0687c8aSRaman Tenneti 189*f0687c8aSRaman Tenneti seq = vbl_tuple[3] 190*f0687c8aSRaman Tenneti time = vbl_tuple[1] + vbl_tuple[2] / 1000000.0; 191*f0687c8aSRaman Tenneti udata = vbl_tuple[0] 192*f0687c8aSRaman Tenneti 193*f0687c8aSRaman Tenneti yield DrmEvent(type, seq, time, udata) 194*f0687c8aSRaman Tenneti 195*f0687c8aSRaman Tenneti idx += ev_tuple[1] 196*f0687c8aSRaman Tenneti 197*f0687c8aSRaman TennetiCard.read_events = __card_read_events 198