From 6d13ebbb8b9854713a5597df71a12f8dd9a36c34 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 20 May 2016 22:09:35 +0300 Subject: Use pybind11 instead of SWIG --- py/CMakeLists.txt | 23 +++----- py/alpha-test.py | 2 +- py/db.py | 10 ++-- py/helpers.py | 11 ++-- py/iact.py | 18 +++---- py/pykms.cpp | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ py/pykms.i | 41 --------------- py/run.sh | 3 ++ py/trans-test.py | 2 +- 9 files changed, 184 insertions(+), 81 deletions(-) create mode 100644 py/pykms.cpp delete mode 100644 py/pykms.i create mode 100755 py/run.sh (limited to 'py') diff --git a/py/CMakeLists.txt b/py/CMakeLists.txt index c6341d8..ff68939 100644 --- a/py/CMakeLists.txt +++ b/py/CMakeLists.txt @@ -1,27 +1,20 @@ -set(SWIG_EXECUTABLE "swig3.0") -find_package(SWIG 3.0 REQUIRED) -include(${SWIG_USE_FILE}) - include_directories(${LIBDRM_INCLUDE_DIRS}) link_directories(${LIBDRM_LIBRARY_DIRS}) pkg_check_modules(PYTHON python3 REQUIRED) include_directories(${PYTHON_INCLUDE_DIRS}) -# XXX how to add these inc dirs in a proper way? -include_directories(../libkms++ ../libkmstest) - -#set(CMAKE_SWIG_FLAGS "-I../../libkms") -set(CMAKE_SWIG_FLAGS "-builtin") +if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") +endif() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-field-initializers") +include_directories(${PROJECT_SOURCE_DIR}/ext/pybind11/include) -set_source_files_properties(pykms.i PROPERTIES CPLUSPLUS ON) -swig_add_module(pykms python pykms.i) -swig_link_libraries(pykms kms++ kmstest ${LIBDRM_LIBRARIES} ${PYTHON_LIBRARIES}) +add_library(pykms SHARED pykms.cpp) +target_link_libraries(pykms kms++ kmstest ${LIBDRM_LIBRARIES}) -# We get some "maybe-uninitialized" warnings from the generated code. I hope they are harmless. -set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-Wno-maybe-uninitialized") +# Don't add a 'lib' prefix to the shared library +set_target_properties(pykms PROPERTIES PREFIX "") file(GLOB PY_SRCS "*.py") add_custom_target(pyextras SOURCES ${PY_SRCS}) diff --git a/py/alpha-test.py b/py/alpha-test.py index 695cd1b..99c84fb 100755 --- a/py/alpha-test.py +++ b/py/alpha-test.py @@ -15,7 +15,7 @@ mode = conn.get_default_mode() crtc = conn.get_current_crtc() planes = [] -for p in card.get_planes(): +for p in card.planes: if p.supports_crtc(crtc) == False: continue planes.append(p) diff --git a/py/db.py b/py/db.py index ce1a54e..c51ca70 100755 --- a/py/db.py +++ b/py/db.py @@ -24,16 +24,16 @@ class FlipHandler(pykms.PageFlipHandlerBase): self.front_buf = self.front_buf ^ 1 current_xpos = self.bar_xpos; - old_xpos = (current_xpos + (fb.width() - bar_width - bar_speed)) % (fb.width() - bar_width); - new_xpos = (current_xpos + bar_speed) % (fb.width() - bar_width); + old_xpos = (current_xpos + (fb.width - bar_width - bar_speed)) % (fb.width - bar_width); + new_xpos = (current_xpos + bar_speed) % (fb.width - bar_width); self.bar_xpos = new_xpos pykms.draw_color_bar(fb, old_xpos, new_xpos, bar_width) - if card.has_atomic(): + if card.has_atomic: ctx = pykms.AtomicReq(card) - ctx.add(crtc, "FB_ID", fb.id()) + ctx.add(crtc, "FB_ID", fb.id) ctx.commit(self) else: crtc.page_flip(fb, self) @@ -61,7 +61,7 @@ def readkey(conn, mask): exit(0) sel = selectors.DefaultSelector() -sel.register(card.fd(), selectors.EVENT_READ, readdrm) +sel.register(card.fd, selectors.EVENT_READ, readdrm) sel.register(sys.stdin, selectors.EVENT_READ, readkey) while True: diff --git a/py/helpers.py b/py/helpers.py index 15f6cfa..acb9098 100644 --- a/py/helpers.py +++ b/py/helpers.py @@ -4,13 +4,12 @@ def add_props(areq, ob, map): for key, value in map.items(): areq.add(ob, key, value) - def props(o): o.refresh_props() - map = o.get_prop_map() - for propid in map: - prop = o.card().get_prop(propid) - print("%-15s %d (%#x)" % (prop.name(), map[propid], map[propid])) + map = o.prop_map + for propid,propval in map.items(): + prop = o.card.get_prop(propid) + print("%-15s %d (%#x)" % (prop.name, propval, propval)) def set_props(ob, map): areq = pykms.AtomicReq(ob.card()) @@ -32,7 +31,7 @@ cyan = pykms.RGB(0, 255, 255) def disable_planes(card): areq = pykms.AtomicReq(card) - for p in card.get_planes(): + for p in card.planes: areq.add(p, "FB_ID", 0) areq.add(p, "CRTC_ID", 0) diff --git a/py/iact.py b/py/iact.py index 073e4ca..82511c3 100755 --- a/py/iact.py +++ b/py/iact.py @@ -6,6 +6,7 @@ import pykms from time import sleep from math import sin from math import cos +from helpers import * card = pykms.Card() @@ -21,29 +22,22 @@ crtc = conn.get_current_crtc() #crtc.set_mode(conn, fb, mode) i = 0 -for p in card.get_planes(): +for p in card.planes: globals()["plane"+str(i)] = p i=i+1 i = 0 -for c in card.get_crtcs(): +for c in card.crtcs: globals()["crtc"+str(i)] = c i=i+1 -for p in crtc.get_possible_planes(): - if p.plane_type() == 0: +for p in crtc.possible_planes: + if p.plane_type == pykms.PlaneType.Overlay: plane = p break def set_plane(x, y): - crtc.set_plane(plane, fb, x, y, fb.width(), fb.height(), 0, 0, fb.width(), fb.height()) - -def props(o): - o.refresh_props() - map = o.get_prop_map() - for propid in map: - prop = card.get_prop(propid) - print("%-15s %d (%#x)" % (prop.name(), map[propid], map[propid])) + crtc.set_plane(plane, fb, x, y, fb.width, fb.height, 0, 0, fb.width, fb.height) set_plane(0, 0) diff --git a/py/pykms.cpp b/py/pykms.cpp new file mode 100644 index 0000000..7e42e4f --- /dev/null +++ b/py/pykms.cpp @@ -0,0 +1,155 @@ +#include +#include +#include +#include "kmstest.h" + +namespace py = pybind11; + +using namespace kms; +using namespace std; + +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"); + + py::class_(m, "Card") + .def(py::init<>()) + .def_property_readonly("fd", &Card::fd) + .def("get_first_connected_connector", &Card::get_first_connected_connector) + .def_property_readonly("connectors", &Card::get_connectors) + .def_property_readonly("crtcs", &Card::get_crtcs) + .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) + .def("get_prop", (Property* (Card::*)(const string&) const)&Card::get_prop) + ; + + py::class_(m, "DrmObject") + .def_property_readonly("id", &DrmObject::id) + .def("refresh_props", &DrmObject::refresh_props) + .def_property_readonly("prop_map", &DrmObject::get_prop_map) + .def_property_readonly("card", &DrmObject::card) + ; + + py::class_(m, "Connector", py::base()) + .def_property_readonly("fullname", &Connector::fullname) + .def("get_default_mode", &Connector::get_default_mode) + .def("get_current_crtc", &Connector::get_current_crtc) + .def("get_modes", &Connector::get_modes) + .def("__repr__", [](const Connector& o) { return ""; }) + ; + + py::class_(m, "Crtc", py::base()) + .def("set_mode", &Crtc::set_mode) + .def("page_flip", &Crtc::page_flip) + .def("set_plane", &Crtc::set_plane) + .def_property_readonly("possible_planes", &Crtc::get_possible_planes) + .def("__repr__", [](const Crtc& o) { return ""; }) + ; + + py::class_(m, "Encoder", py::base()) + ; + + py::class_(m, "Plane", py::base()) + .def("supports_crtc", &Plane::supports_crtc) + .def_property_readonly("plane_type", &Plane::plane_type) + .def("__repr__", [](const Plane& o) { return ""; }) + ; + + py::enum_(m, "PlaneType") + .value("Overlay", PlaneType::Overlay) + .value("Primary", PlaneType::Primary) + .value("Cursor", PlaneType::Cursor) + ; + + py::class_(m, "Property", py::base()) + .def_property_readonly("name", &Property::name) + ; + + py::class_(m, "Framebuffer", py::base()) + ; + + py::class_(m, "DumbFramebuffer", py::base()) + .def(py::init(), + py::keep_alive<1, 2>()) // Keep Card alive until this is destructed + .def_property_readonly("width", &DumbFramebuffer::width) + .def_property_readonly("height", &DumbFramebuffer::height) + ; + + py::class_(m, "Videomode") + .def(py::init<>()) + + .def_readwrite("name", &Videomode::name) + + .def_readwrite("clock", &Videomode::clock) + + .def_readwrite("hdisplay", &Videomode::hdisplay) + .def_readwrite("hsync_start", &Videomode::hsync_start) + .def_readwrite("hsync_end", &Videomode::hsync_end) + .def_readwrite("htotal", &Videomode::htotal) + + .def_readwrite("vdisplay", &Videomode::vdisplay) + .def_readwrite("vsync_start", &Videomode::vsync_start) + .def_readwrite("vsync_end", &Videomode::vsync_end) + .def_readwrite("vtotal", &Videomode::vtotal) + + .def_readwrite("vrefresh", &Videomode::vrefresh) + + .def_readwrite("flags", &Videomode::flags) + .def_readwrite("type", &Videomode::type) + ; + + py::class_(m, "PageFlipHandlerBase") + .alias() + .def(py::init<>()) + .def("handle_page_flip", &PageFlipHandlerBase::handle_page_flip) + ; + + py::class_(m, "AtomicReq") + .def(py::init(), + py::keep_alive<1, 2>()) // Keep Card alive until this is destructed + .def("add", (void (AtomicReq::*)(DrmObject*, const string&, uint64_t)) &AtomicReq::add) + .def("test", &AtomicReq::test) + .def("commit", (int (AtomicReq::*)()) &AtomicReq::commit) + .def("commit", (int (AtomicReq::*)(void*)) &AtomicReq::commit) + .def("commit_sync", &AtomicReq::commit_sync) + ; + + + + /* libkmstest */ + + py::class_(m, "RGB") + .def(py::init<>()) + .def(py::init()) + .def(py::init()) + ; + + // Use lambdas to handle IMappedFramebuffer + m.def("draw_test_pattern", [](DumbFramebuffer& fb) { draw_test_pattern(fb); } ); + m.def("draw_color_bar", [](DumbFramebuffer& fb, int old_xpos, int xpos, int width) { + draw_color_bar(fb, old_xpos, xpos, width); + } ); + m.def("draw_rect", [](DumbFramebuffer& fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color) { + draw_rect(fb, x, y, w, h, color); + } ); + + return m.ptr(); +} diff --git a/py/pykms.i b/py/pykms.i deleted file mode 100644 index cefdce7..0000000 --- a/py/pykms.i +++ /dev/null @@ -1,41 +0,0 @@ -%module(directors="1") pykms -%{ -#include "kms++.h" - -#include "kmstest.h" - -using namespace kms; -%} - -%include "std_string.i" -%include "stdint.i" -%include "std_vector.i" -%include "std_map.i" - -%feature("director") PageFlipHandlerBase; - -%include "decls.h" -%include "drmobject.h" -%include "atomicreq.h" -%include "crtc.h" -%include "card.h" -%include "property.h" -%include "framebuffer.h" -%include "dumbframebuffer.h" -%include "plane.h" -%include "connector.h" -%include "encoder.h" -%include "pagefliphandler.h" -%include "videomode.h" - -%include "color.h" -%include "kmstest.h" - -%template(ConnectorVector) std::vector; -%template(CrtcVector) std::vector; -%template(EncoderVector) std::vector; -%template(PlaneVector) std::vector; -%template(VideoModeVector) std::vector; -/* for some reason uint64_t doesn't compile on 64 bit pc */ -/* %template(map_u32_u64) std::map; */ -%template(map_u32_u64) std::map; diff --git a/py/run.sh b/py/run.sh new file mode 100755 index 0000000..f0ead78 --- /dev/null +++ b/py/run.sh @@ -0,0 +1,3 @@ +#!/bin/sh +PYTHONPATH=build/py/ python3 $* + diff --git a/py/trans-test.py b/py/trans-test.py index d2e6050..57855ff 100755 --- a/py/trans-test.py +++ b/py/trans-test.py @@ -15,7 +15,7 @@ mode = conn.get_default_mode() crtc = conn.get_current_crtc() planes = [] -for p in card.get_planes(): +for p in card.planes: if p.supports_crtc(crtc) == False: continue planes.append(p) -- cgit v1.2.3