py: drop the fancy event handling
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Tue, 5 Sep 2017 08:01:17 +0000 (11:01 +0300)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Tue, 5 Sep 2017 08:15:28 +0000 (11:15 +0300)
Unfortunately the nice event handler added previously doesn't work: we
may get multiple page-flip events, which would lead to unref'ing the
passed python object multiple times, leading to memory corruption.

I guess it's only possible to pass a plain int as user data to commit()
and page_flip().

py/pykms/__init__.py
py/pykms/pykms.cpp
py/pykms/pykmsbase.cpp
py/tests/big_fb.py
py/tests/db.py
py/tests/modeset_event.py
py/tests/sync.py

index 3b5f743aa43a4d4c3d5f92ee35237b8421641bd9..746c9172383401134e29a318f10928d46a6ea2f4 100644 (file)
@@ -130,7 +130,7 @@ def __card_read_events(self):
 
         seq = vbl_tuple[3]
         time = vbl_tuple[1] + vbl_tuple[2] / 1000000.0;
-        udata = pykms.__ob_unpack_helper(vbl_tuple[0])
+        udata = vbl_tuple[0]
 
         yield DrmEvent(type, seq, time, udata)
 
index 7752f19142815c402436f38f0f75b9c72db90c1f..1e54c9bb4501d4732d37092bcf4f12fc2448d62d 100644 (file)
@@ -20,11 +20,6 @@ PYBIND11_PLUGIN(pykms) {
 
        init_pykmsbase(m);
 
-       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);
 
        init_pyvid(m);
index 604e07c84da603946d0c30eca13bc36898a977e9..e53fe54f18ee4c60fe7d051babdc110e3679d588 100644 (file)
@@ -53,13 +53,10 @@ void init_pykmsbase(py::module &m)
                        .def("set_mode", &Crtc::set_mode)
                        .def("disable_mode", &Crtc::disable_mode)
                        .def("page_flip",
-                            [](Crtc* self, Framebuffer& fb, py::object ob)
+                            [](Crtc* self, Framebuffer& fb, uint32_t data)
                                {
-                                       // 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);
-                               })
+                                       self->page_flip(fb, (void*)(intptr_t)data);
+                               }, py::arg("fb"), py::arg("data") = 0)
                        .def("set_plane", &Crtc::set_plane)
                        .def_property_readonly("possible_planes", &Crtc::get_possible_planes)
                        .def_property_readonly("primary_plane", &Crtc::get_primary_plane)
@@ -196,13 +193,10 @@ void init_pykmsbase(py::module &m)
                        .def("add", (void (AtomicReq::*)(DrmPropObject*, const map<string, uint64_t>&)) &AtomicReq::add)
                        .def("test", &AtomicReq::test, py::arg("allow_modeset") = false)
                        .def("commit",
-                            [](AtomicReq* self, py::object ob, bool allow)
+                            [](AtomicReq* self, uint32_t data, bool allow)
                                {
-                                       // This adds a ref to the object, and must be unpacked with __ob_unpack_helper()
-                                       PyObject* pob = ob.ptr();
-                                       Py_XINCREF(pob);
-                                       return self->commit(pob, allow);
-                               }, py::arg("data"), py::arg("allow_modeset") = false)
+                                       return self->commit((void*)(intptr_t)data, allow);
+                               }, py::arg("data") = 0, py::arg("allow_modeset") = false)
                        .def("commit_sync", &AtomicReq::commit_sync, py::arg("allow_modeset") = false)
                        ;
 }
index 16423768f2873243d59928f1cd06247d654ef493..54de6858a5ca7448416943e5b8494aaf6da2b045 100755 (executable)
@@ -112,6 +112,7 @@ class bigFB_db:
         self.flips = 0
         self.frames = 0
         self.time = 0
+        self.flip_count = 100
 
     def new_color(self):
         r = random.randrange(255)
@@ -190,7 +191,7 @@ class bigFB_db:
 
             screen_offset += mode.hdisplay
 
-        req.commit(self)
+        req.commit(0)
 
     def handle_page_flip_separate(self):
         self.draw_buf ^= 1
@@ -222,9 +223,16 @@ class bigFB_db:
 
             screen_offset += mode.hdisplay
 
-            req.commit(self)
+            req.commit(0)
 
     def handle_page_flip_main(self, frame, time):
+        self.flip_count += 1
+
+        if self.flip_count < len(conn_list):
+            return
+
+        self.flip_count = 0
+
         # statistics
         self.flips += 1
         if self.time == 0:
@@ -254,31 +262,14 @@ box_db.handle_page_flip_main(0, 0)
 def readdrm(fileobj, mask):
     for ev in card.read_events():
         if ev.type == pykms.DrmEventType.FLIP_COMPLETE:
-            ev.data.handle_page_flip_main(ev.seq, ev.time)
-
-event_counter = len(conn_list)
-def readdrm_counted(fileobj, mask):
-    global event_counter
-
-    for ev in card.read_events():
-        if ev.type == pykms.DrmEventType.FLIP_COMPLETE:
-            # we expect events for each display (crtc), but only execute the
-            # next drawing and flip when we have received the last event.
-            event_counter -= 1
-            if event_counter == 0:
-                event_counter = len(conn_list)
-                ev.data.handle_page_flip_main(ev.seq, ev.time)
+            box_db.handle_page_flip_main(ev.seq, ev.time)
 
 def readkey(fileobj, mask):
     sys.stdin.readline()
     exit(0)
 
 sel = selectors.DefaultSelector()
-if args.flipmode == 'single':
-    sel.register(card.fd, selectors.EVENT_READ, readdrm)
-else:
-    sel.register(card.fd, selectors.EVENT_READ, readdrm_counted)
-
+sel.register(card.fd, selectors.EVENT_READ, readdrm)
 sel.register(sys.stdin, selectors.EVENT_READ, readkey)
 
 while True:
index 660364de0975ec2877a14a29e2314c79ddb9e77a..f7b13eb82d523c39cfcc5dc49541bf7737084d85 100755 (executable)
@@ -52,9 +52,9 @@ class FlipHandler():
         if card.has_atomic:
             ctx = pykms.AtomicReq(card)
             ctx.add(crtc.primary_plane, "FB_ID", fb.id)
-            ctx.commit(self)
+            ctx.commit()
         else:
-            crtc.page_flip(fb, self)
+            crtc.page_flip(fb)
 
 if len(sys.argv) > 1:
     conn_name = sys.argv[1]
@@ -77,7 +77,7 @@ def readdrm(fileobj, mask):
     #print("EVENT");
     for ev in card.read_events():
         if ev.type == pykms.DrmEventType.FLIP_COMPLETE:
-            ev.data.handle_page_flip(ev.seq, ev.time)
+            fliphandler.handle_page_flip(ev.seq, ev.time)
 
 
 def readkey(fileobj, mask):
index 0957e5122b62b01075c0ec8d0c426846719dd521..11cfd58c62c896c55b4f690931b2d0aa4d8f7b11 100755 (executable)
@@ -6,7 +6,7 @@ import sys
 
 def readdrm(fileobj, mask):
     for ev in card.read_events():
-        ev.data(ev)
+        eventhandler(ev)
 
 def waitevent(sel):
     events = sel.select(1)
@@ -67,7 +67,7 @@ if ret != 0:
     print("Atomic test failed: %d" % ret)
     sys.exit()
 
-req.commit(eventhandler, allow_modeset = True)
+req.commit(0, allow_modeset = True)
 waitevent(sel)
 
 input("press enter to exit\n")
index 4616ee85a977a7c5e3a709214ccc489b160a23c1..e394c8d3d7664347aac76f48597d0ea3450659b1 100755 (executable)
@@ -148,7 +148,7 @@ class FlipHandler():
         fence = self.timeline.create_fence(2 * self.flips - 1)
         req = pykms.AtomicReq(self.crtc.card)
         req.add(self.crtc.primary_plane, { 'FB_ID': fb.id, 'IN_FENCE_FD': fence.fd })
-        req.commit(self)
+        req.commit()
         del fence
 
         # Arm a timer to signal the fence in 0.5s.
@@ -207,7 +207,7 @@ def main(argv):
     def readdrm(fileobj, mask):
         for ev in card.read_events():
             if ev.type == pykms.DrmEventType.FLIP_COMPLETE:
-                ev.data.handle_page_flip(ev.seq, ev.time)
+                flip_handler.handle_page_flip(ev.seq, ev.time)
 
     def readkey(fileobj, mask):
         sys.stdin.readline()