You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
4.5 KiB
198 lines
4.5 KiB
from .pykms import *
|
|
from enum import Enum
|
|
import os
|
|
import struct
|
|
|
|
#
|
|
# Common RGB colours
|
|
#
|
|
|
|
red = RGB(255, 0, 0)
|
|
green = RGB(0, 255, 0)
|
|
blue = RGB(0, 0, 255)
|
|
yellow = RGB(255, 255, 0)
|
|
purple = RGB(255, 0, 255)
|
|
white = RGB(255, 255, 255)
|
|
cyan = RGB(0, 255, 255)
|
|
|
|
#
|
|
# Rotation enum
|
|
#
|
|
|
|
class Rotation(int, Enum):
|
|
ROTATE_0 = 1 << 0
|
|
ROTATE_90 = 1 << 1
|
|
ROTATE_180 = 1 << 2
|
|
ROTATE_270 = 1 << 3
|
|
ROTATE_MASK = ROTATE_0 | ROTATE_90 | ROTATE_180 | ROTATE_270
|
|
REFLECT_X = 1 << 4
|
|
REFLECT_Y = 1 << 5
|
|
REFLECT_MASK = REFLECT_X | REFLECT_Y
|
|
|
|
#
|
|
# DrmObject API extensions
|
|
#
|
|
|
|
def __obj_set_prop(self, prop, value):
|
|
if self.card.has_atomic:
|
|
areq = AtomicReq(self.card)
|
|
areq.add(self, prop, value)
|
|
if areq.commit_sync() != 0:
|
|
print("commit failed")
|
|
else:
|
|
if self.set_prop_value(prop, value) != 0:
|
|
print("setting property failed")
|
|
|
|
def __obj_set_props(self, map):
|
|
if self.card.has_atomic:
|
|
areq = AtomicReq(self.card)
|
|
|
|
for key, value in map.items():
|
|
areq.add(self, key, value)
|
|
|
|
if areq.commit_sync() != 0:
|
|
print("commit failed")
|
|
else:
|
|
for propid,propval in map.items():
|
|
if self.set_prop_value(propid, propval) != 0:
|
|
print("setting property failed")
|
|
|
|
DrmObject.set_prop = __obj_set_prop
|
|
DrmObject.set_props = __obj_set_props
|
|
|
|
#
|
|
# Card API extensions
|
|
#
|
|
|
|
def __card_disable_planes(self):
|
|
areq = AtomicReq(self)
|
|
|
|
for p in self.planes:
|
|
areq.add(p, "FB_ID", 0)
|
|
areq.add(p, "CRTC_ID", 0)
|
|
|
|
if areq.commit_sync() != 0:
|
|
print("disabling planes failed")
|
|
|
|
Card.disable_planes = __card_disable_planes
|
|
|
|
class DrmEventType(Enum):
|
|
VBLANK = 0x01
|
|
FLIP_COMPLETE = 0x02
|
|
|
|
#
|
|
# AtomicReq API extensions
|
|
#
|
|
|
|
def __atomic_req_add_connector(req, conn, crtc):
|
|
req.add(conn, "CRTC_ID", crtc.id if crtc else 0)
|
|
|
|
def __atomic_req_add_crtc(req, crtc, mode_blob):
|
|
if mode_blob:
|
|
req.add(crtc, {"ACTIVE": 1, "MODE_ID": mode_blob.id})
|
|
else:
|
|
req.add(crtc, {"ACTIVE": 0, "MODE_ID": 0})
|
|
|
|
def __atomic_req_add_plane(req, plane, fb, crtc,
|
|
src=None, dst=None, zpos=None,
|
|
params={}):
|
|
if not src and fb:
|
|
src = (0, 0, fb.width, fb.height)
|
|
|
|
if not dst:
|
|
dst = src
|
|
|
|
m = {"FB_ID": fb.id if fb else 0,
|
|
"CRTC_ID": crtc.id if crtc else 0}
|
|
|
|
if src is not None:
|
|
src_x = int(round(src[0] * 65536))
|
|
src_y = int(round(src[1] * 65536))
|
|
src_w = int(round(src[2] * 65536))
|
|
src_h = int(round(src[3] * 65536))
|
|
|
|
m["SRC_X"] = src_x
|
|
m["SRC_Y"] = src_y
|
|
m["SRC_W"] = src_w
|
|
m["SRC_H"] = src_h
|
|
|
|
if dst is not None:
|
|
crtc_x = int(round(dst[0]))
|
|
crtc_y = int(round(dst[1]))
|
|
crtc_w = int(round(dst[2]))
|
|
crtc_h = int(round(dst[3]))
|
|
|
|
m["CRTC_X"] = crtc_x
|
|
m["CRTC_Y"] = crtc_y
|
|
m["CRTC_W"] = crtc_w
|
|
m["CRTC_H"] = crtc_h
|
|
|
|
if zpos is not None:
|
|
m["zpos"] = zpos
|
|
|
|
m.update(params)
|
|
|
|
req.add(plane, m)
|
|
|
|
pykms.AtomicReq.add_connector = __atomic_req_add_connector
|
|
pykms.AtomicReq.add_crtc = __atomic_req_add_crtc
|
|
pykms.AtomicReq.add_plane = __atomic_req_add_plane
|
|
|
|
# struct drm_event {
|
|
# __u32 type;
|
|
# __u32 length;
|
|
#};
|
|
#
|
|
|
|
_drm_ev = struct.Struct("II")
|
|
|
|
#struct drm_event_vblank {
|
|
# struct drm_event base;
|
|
# __u64 user_data;
|
|
# __u32 tv_sec;
|
|
# __u32 tv_usec;
|
|
# __u32 sequence;
|
|
# __u32 reserved;
|
|
#};
|
|
|
|
_drm_ev_vbl = struct.Struct("QIIII") # Note: doesn't contain drm_event
|
|
|
|
class DrmEvent:
|
|
def __init__(self, type, seq, time, data):
|
|
self.type = type
|
|
self.seq = seq
|
|
self.time = time
|
|
self.data = data
|
|
|
|
# Return DrmEvents. Note: blocks if there's nothing to read
|
|
def __card_read_events(self):
|
|
buf = os.read(self.fd, _drm_ev_vbl.size * 20)
|
|
|
|
if len(buf) == 0:
|
|
return
|
|
|
|
if len(buf) < _drm_ev.size:
|
|
raise RuntimeError("Partial DRM event")
|
|
|
|
idx = 0
|
|
|
|
while idx < len(buf):
|
|
ev_tuple = _drm_ev.unpack_from(buf, idx)
|
|
|
|
type = DrmEventType(ev_tuple[0])
|
|
|
|
if type != DrmEventType.VBLANK and type != DrmEventType.FLIP_COMPLETE:
|
|
raise RuntimeError("Illegal DRM event type")
|
|
|
|
vbl_tuple = _drm_ev_vbl.unpack_from(buf, idx + _drm_ev.size)
|
|
|
|
seq = vbl_tuple[3]
|
|
time = vbl_tuple[1] + vbl_tuple[2] / 1000000.0;
|
|
udata = vbl_tuple[0]
|
|
|
|
yield DrmEvent(type, seq, time, udata)
|
|
|
|
idx += ev_tuple[1]
|
|
|
|
Card.read_events = __card_read_events
|