diff options
-rw-r--r-- | py/pykms/__init__.py | 65 | ||||
-rw-r--r-- | py/pykms/pykms.cpp | 25 | ||||
-rw-r--r-- | py/pykms/pykmsbase.cpp | 19 | ||||
-rwxr-xr-x | py/tests/db.py | 8 |
4 files changed, 91 insertions, 26 deletions
diff --git a/py/pykms/__init__.py b/py/pykms/__init__.py index d4cdc43..41c1219 100644 --- a/py/pykms/__init__.py +++ b/py/pykms/__init__.py @@ -1,4 +1,7 @@ from .pykms import * +from enum import Enum +import os +import struct # # Common RGB colours @@ -58,3 +61,65 @@ def __card_disable_planes(self): print("disabling planes failed") Card.disable_planes = __card_disable_planes + +class DrmEventType(Enum): + VBLANK = 0x01 + FLIP_COMPLETE = 0x02 + +# 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 = pykms.__ob_unpack_helper(vbl_tuple[0]) + + yield DrmEvent(type, seq, time, udata) + + idx += ev_tuple[1] + +Card.read_events = __card_read_events diff --git a/py/pykms/pykms.cpp b/py/pykms/pykms.cpp index 2199039..7752f19 100644 --- a/py/pykms/pykms.cpp +++ b/py/pykms/pykms.cpp @@ -15,32 +15,15 @@ void init_pyvid(py::module &m); void init_pykmsomap(py::module &m); #endif -class PyPageFlipHandlerBase : PageFlipHandlerBase -{ -public: - using PageFlipHandlerBase::PageFlipHandlerBase; - - virtual void handle_page_flip(uint32_t frame, double time) - { - PYBIND11_OVERLOAD_PURE( - void, /* Return type */ - PageFlipHandlerBase, /* Parent class */ - handle_page_flip, /* Name of function */ - frame, time - ); - } -}; - PYBIND11_PLUGIN(pykms) { py::module m("pykms", "kms bindings"); init_pykmsbase(m); - py::class_<PyPageFlipHandlerBase>(m, "PageFlipHandlerBase") - .alias<PageFlipHandlerBase>() - .def(py::init<>()) - .def("handle_page_flip", &PageFlipHandlerBase::handle_page_flip) - ; + m.def("__ob_unpack_helper", [](uint64_t v) { + // AtomicReq::commit or Crtc::page_flip added a ref, so we can use borrowed = false + return py::object((PyObject*)v, false); + }); init_pykmstest(m); diff --git a/py/pykms/pykmsbase.cpp b/py/pykms/pykmsbase.cpp index 0d5bb86..1cc91d8 100644 --- a/py/pykms/pykmsbase.cpp +++ b/py/pykms/pykmsbase.cpp @@ -18,7 +18,6 @@ void init_pykmsbase(py::module &m) .def_property_readonly("encoders", &Card::get_encoders) .def_property_readonly("planes", &Card::get_planes) .def_property_readonly("has_atomic", &Card::has_atomic) - .def("call_page_flip_handlers", &Card::call_page_flip_handlers) .def("get_prop", (Property* (Card::*)(uint32_t) const)&Card::get_prop) ; @@ -49,7 +48,14 @@ void init_pykmsbase(py::module &m) py::class_<Crtc, Crtc*>(m, "Crtc", py::base<DrmPropObject>()) .def("set_mode", &Crtc::set_mode) - .def("page_flip", &Crtc::page_flip) + .def("page_flip", + [](Crtc* self, Framebuffer& fb, py::object ob) + { + // This adds a ref to the object, and must be unpacked with __ob_unpack_helper() + PyObject* pob = ob.ptr(); + Py_XINCREF(pob); + self->page_flip(fb, pob); + }) .def("set_plane", &Crtc::set_plane) .def_property_readonly("possible_planes", &Crtc::get_possible_planes) .def_property_readonly("primary_plane", &Crtc::get_primary_plane) @@ -167,7 +173,14 @@ void init_pykmsbase(py::module &m) .def("add", (void (AtomicReq::*)(DrmPropObject*, const string&, uint64_t)) &AtomicReq::add) .def("add", (void (AtomicReq::*)(DrmPropObject*, const map<string, uint64_t>&)) &AtomicReq::add) .def("test", &AtomicReq::test, py::arg("allow_modeset") = false) - .def("commit", &AtomicReq::commit, py::arg("data"), py::arg("allow_modeset") = false) + .def("commit", + [](AtomicReq* self, py::object ob, bool allow) + { + // This adds a ref to the object, and must be unpacked with __ob_unpack_helper() + PyObject* pob = ob.ptr(); + Py_XINCREF(pob); + self->commit(pob, allow); + }, py::arg("data"), py::arg("allow_modeset") = false) .def("commit_sync", &AtomicReq::commit_sync, py::arg("allow_modeset") = false) ; } diff --git a/py/tests/db.py b/py/tests/db.py index eb31669..d51820c 100755 --- a/py/tests/db.py +++ b/py/tests/db.py @@ -7,7 +7,7 @@ import selectors bar_width = 20 bar_speed = 8 -class FlipHandler(pykms.PageFlipHandlerBase): +class FlipHandler(): def __init__(self): super().__init__() self.bar_xpos = 0 @@ -75,7 +75,11 @@ fliphandler.handle_page_flip(0, 0) def readdrm(fileobj, mask): #print("EVENT"); - card.call_page_flip_handlers() + #card.call_page_flip_handlers() + for ev in card.read_events(): + if ev.type == pykms.DrmEventType.FLIP_COMPLETE: + ev.data.handle_page_flip(ev.seq, ev.time) + def readkey(fileobj, mask): #print("KEY EVENT"); |