summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--py/pykms/__init__.py65
-rw-r--r--py/pykms/pykms.cpp25
-rw-r--r--py/pykms/pykmsbase.cpp19
-rwxr-xr-xpy/tests/db.py8
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");