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

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