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