xref: /aosp_15_r20/external/libkmsxx/py/pykms/__init__.py (revision f0687c8a10b3e371dbe09214db6664e37c283cca)
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