From b11baff09f78a4a383f817ec35208ae8966ab832 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 2 Jan 2017 16:42:08 +0200 Subject: py: Reorganize source directory Separate the Python bindings sources from the test scripts. While at it, remove the unneeded run.sh script. Signed-off-by: Laurent Pinchart --- py/CMakeLists.txt | 36 +----- py/alpha-test.py | 67 ---------- py/cam.py | 78 ------------ py/db.py | 72 ----------- py/functest.py | 19 --- py/gamma.py | 41 ------ py/helpers.py | 54 -------- py/iact.py | 43 ------- py/kmsmodeview.py | 317 --------------------------------------------- py/pykms.cpp | 53 -------- py/pykms/CMakeLists.txt | 26 ++++ py/pykms/pykms.cpp | 53 ++++++++ py/pykms/pykmsbase.cpp | 157 +++++++++++++++++++++++ py/pykms/pykmsomap.cpp | 21 +++ py/pykms/pykmsutil.cpp | 49 +++++++ py/pykms/pyvid.cpp | 38 ++++++ py/pykmsbase.cpp | 157 ----------------------- py/pykmsomap.cpp | 21 --- py/pykmsutil.cpp | 49 ------- py/pyvid.cpp | 38 ------ py/run.sh | 3 - py/test.py | 18 --- py/tests/CMakeLists.txt | 7 + py/tests/alpha-test.py | 67 ++++++++++ py/tests/cam.py | 78 ++++++++++++ py/tests/db.py | 72 +++++++++++ py/tests/functest.py | 19 +++ py/tests/gamma.py | 41 ++++++ py/tests/helpers.py | 54 ++++++++ py/tests/iact.py | 43 +++++++ py/tests/kmsmodeview.py | 317 +++++++++++++++++++++++++++++++++++++++++++++ py/tests/test.py | 18 +++ py/tests/trans-test.py | 332 ++++++++++++++++++++++++++++++++++++++++++++++++ py/trans-test.py | 332 ------------------------------------------------ 34 files changed, 1394 insertions(+), 1396 deletions(-) delete mode 100755 py/alpha-test.py delete mode 100755 py/cam.py delete mode 100755 py/db.py delete mode 100755 py/functest.py delete mode 100755 py/gamma.py delete mode 100644 py/helpers.py delete mode 100755 py/iact.py delete mode 100755 py/kmsmodeview.py delete mode 100644 py/pykms.cpp create mode 100644 py/pykms/CMakeLists.txt create mode 100644 py/pykms/pykms.cpp create mode 100644 py/pykms/pykmsbase.cpp create mode 100644 py/pykms/pykmsomap.cpp create mode 100644 py/pykms/pykmsutil.cpp create mode 100644 py/pykms/pyvid.cpp delete mode 100644 py/pykmsbase.cpp delete mode 100644 py/pykmsomap.cpp delete mode 100644 py/pykmsutil.cpp delete mode 100644 py/pyvid.cpp delete mode 100755 py/run.sh delete mode 100755 py/test.py create mode 100644 py/tests/CMakeLists.txt create mode 100755 py/tests/alpha-test.py create mode 100755 py/tests/cam.py create mode 100755 py/tests/db.py create mode 100755 py/tests/functest.py create mode 100755 py/tests/gamma.py create mode 100644 py/tests/helpers.py create mode 100755 py/tests/iact.py create mode 100755 py/tests/kmsmodeview.py create mode 100755 py/tests/test.py create mode 100755 py/tests/trans-test.py delete mode 100755 py/trans-test.py (limited to 'py') diff --git a/py/CMakeLists.txt b/py/CMakeLists.txt index 69bb845..77f19b4 100644 --- a/py/CMakeLists.txt +++ b/py/CMakeLists.txt @@ -1,34 +1,2 @@ -include_directories(${LIBDRM_INCLUDE_DIRS}) -link_directories(${LIBDRM_LIBRARY_DIRS}) - -pkg_check_modules(PYTHON python3 REQUIRED) -include_directories(${PYTHON_INCLUDE_DIRS}) - -if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") -endif() - -include_directories(${PROJECT_SOURCE_DIR}/ext/pybind11/include) - -set(SRCS pykms.cpp pykmsbase.cpp pykmsutil.cpp pyvid.cpp) - -if(LIBDRM_OMAP_FOUND) - set(SRCS ${SRCS} pykmsomap.cpp) -endif() - -add_library(pykms SHARED ${SRCS}) -target_link_libraries(pykms kms++ kms++util ${LIBDRM_LIBRARIES}) - -# 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}) - -add_test(NAME pytest COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/functest.py") -set_property(TEST pytest PROPERTY - ENVIRONMENT "PYTHONPATH=." "LD_LIBRARY_PATH=." -) - -# XXX Where should pykms.so be installed? -#install(TARGETS pykms DESTINATION lib) +add_subdirectory(pykms) +add_subdirectory(tests) diff --git a/py/alpha-test.py b/py/alpha-test.py deleted file mode 100755 index c6ec8ee..0000000 --- a/py/alpha-test.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/python3 - -import pykms -from helpers import * -import time - -# This hack makes drm initialize the fbcon, setting up the default connector -card = pykms.Card() -card = 0 - -card = pykms.Card() -res = pykms.ResourceManager(card) -conn = res.reserve_connector() -crtc = res.reserve_crtc(conn) -mode = conn.get_default_mode() - -planes = [] -for p in card.planes: - if p.supports_crtc(crtc) == False: - continue - planes.append(p) - -if len(planes) != 3: - print("Need 3 planes!") - exit(1) - -disable_planes(card) - -w = mode.hdisplay -h = mode.vdisplay - -fbs=[] - -for i in range(len(planes)): - fbs.append(pykms.DumbFramebuffer(card, w, h, "AR24")) - -pykms.draw_rect(fbs[0], 50, 50, 200, 200, pykms.RGB(128, 255, 0, 0)) -pykms.draw_rect(fbs[1], 150, 50, 200, 200, pykms.RGB(128, 0, 255, 0)) -pykms.draw_rect(fbs[2], 50, 150, 200, 200, pykms.RGB(128, 0, 0, 255)) - - -set_props(crtc, { - "trans-key-mode": 0, - "trans-key": 0, - "background": 0, - "alpha_blender": 1, -}) - -for i in range(len(planes)): - plane = planes[i] - fb = fbs[i] - - print("set crtc {}, plane {}, fb {}".format(crtc.id, p.id, fbs[i].id)) - - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_W": fb.width, - "CRTC_H": fb.height, - "zorder": i, - }) - - time.sleep(1) - -input("press enter to exit\n") diff --git a/py/cam.py b/py/cam.py deleted file mode 100755 index b44f8f9..0000000 --- a/py/cam.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/python3 - -import sys -import selectors -import pykms -from helpers import * - - -w = 640 -h = 480 -fmt = pykms.PixelFormat.YUYV - - -# This hack makes drm initialize the fbcon, setting up the default connector -card = pykms.Card() -card = 0 - -card = pykms.Card() -res = pykms.ResourceManager(card) -conn = res.reserve_connector() -crtc = res.reserve_crtc(conn) -plane = res.reserve_overlay_plane(crtc, fmt) - -mode = conn.get_default_mode() - -NUM_BUFS = 5 - -fbs = [] -for i in range(NUM_BUFS): - fb = pykms.DumbFramebuffer(card, w, h, fmt) - fbs.append(fb) - -vidpath = pykms.VideoDevice.get_capture_devices()[0] - -vid = pykms.VideoDevice(vidpath) -cap = vid.capture_streamer -cap.set_port(0) -cap.set_format(fmt, w, h) -cap.set_queue_size(NUM_BUFS) - -for fb in fbs: - cap.queue(fb) - -cap.stream_on() - - -def readvid(conn, mask): - fb = cap.dequeue() - - if card.has_atomic: - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_W": fb.width, - "CRTC_H": fb.height, - }) - else: - crtc.set_plane(plane, fb, 0, 0, fb.width, fb.height, - 0, 0, fb.width, fb.height) - - cap.queue(fb) - -def readkey(conn, mask): - #print("KEY EVENT"); - sys.stdin.readline() - exit(0) - -sel = selectors.DefaultSelector() -sel.register(cap.fd, selectors.EVENT_READ, readvid) -sel.register(sys.stdin, selectors.EVENT_READ, readkey) - -while True: - events = sel.select() - for key, mask in events: - callback = key.data - callback(key.fileobj, mask) diff --git a/py/db.py b/py/db.py deleted file mode 100755 index 3ffb716..0000000 --- a/py/db.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/python3 - -import sys -import pykms -import selectors -from helpers import * - -bar_width = 20 -bar_speed = 8 - -class FlipHandler(pykms.PageFlipHandlerBase): - def __init__(self): - super().__init__() - self.bar_xpos = 0 - self.front_buf = 0 - self.fb1 = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); - self.fb2 = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); - - def handle_page_flip(self, frame, time): - if self.front_buf == 0: - fb = self.fb2 - else: - fb = self.fb1 - - 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); - - self.bar_xpos = new_xpos - - pykms.draw_color_bar(fb, old_xpos, new_xpos, bar_width) - - if card.has_atomic: - ctx = pykms.AtomicReq(card) - ctx.add(crtc.primary_plane, "FB_ID", fb.id) - ctx.commit(self) - else: - crtc.page_flip(fb, self) - - -card = pykms.Card() -res = pykms.ResourceManager(card) -conn = res.reserve_connector() -crtc = res.reserve_crtc(conn) -mode = conn.get_default_mode() - -fliphandler = FlipHandler() - -crtc.set_mode(conn, fliphandler.fb1, mode) - -fliphandler.handle_page_flip(0, 0) - -def readdrm(conn, mask): - #print("EVENT"); - card.call_page_flip_handlers() - -def readkey(conn, mask): - #print("KEY EVENT"); - sys.stdin.readline() - exit(0) - -sel = selectors.DefaultSelector() -sel.register(card.fd, selectors.EVENT_READ, readdrm) -sel.register(sys.stdin, selectors.EVENT_READ, readkey) - -while True: - events = sel.select() - for key, mask in events: - callback = key.data - callback(key.fileobj, mask) diff --git a/py/functest.py b/py/functest.py deleted file mode 100755 index 44c29fb..0000000 --- a/py/functest.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/python3 - -import pykms -from helpers import * - -card = pykms.Card() -res = pykms.ResourceManager(card) -conn = res.reserve_connector() -crtc = res.reserve_crtc(conn) - -mode = conn.get_default_mode() - -fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); -pykms.draw_test_pattern(fb); - -crtc.set_mode(conn, fb, mode) - -print("OK") - diff --git a/py/gamma.py b/py/gamma.py deleted file mode 100755 index a6b68cc..0000000 --- a/py/gamma.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/python3 - -import pykms -from helpers import * - -# This hack makes drm initialize the fbcon, setting up the default connector -card = pykms.Card() -card = 0 - -card = pykms.Card() -res = pykms.ResourceManager(card) -conn = res.reserve_connector() -crtc = res.reserve_crtc(conn) -mode = conn.get_default_mode() - -fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); -pykms.draw_test_pattern(fb); - -crtc.set_mode(conn, fb, mode) - -len=256 -arr = bytearray(len*2*4) -view = memoryview(arr).cast("H") - -for i in range(len): - g = round(65535 * pow(i / float(len), 1 / 2.2)) - - view[i * 4 + 0] = g - view[i * 4 + 1] = g - view[i * 4 + 2] = g - view[i * 4 + 3] = 0 - -gamma = pykms.Blob(card, arr); - -set_prop(crtc, "GAMMA_LUT", gamma.id) - -input("press enter to remove gamma\n") - -set_prop(crtc, "GAMMA_LUT", 0) - -input("press enter to exit\n") diff --git a/py/helpers.py b/py/helpers.py deleted file mode 100644 index fd67d41..0000000 --- a/py/helpers.py +++ /dev/null @@ -1,54 +0,0 @@ -import pykms - -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.prop_map - for propid,propval in map.items(): - prop = o.card.get_prop(propid) - print("%-15s %d (%#x)" % (prop.name, propval, propval)) - -def set_prop(ob, prop, value): - if ob.card.has_atomic: - areq = pykms.AtomicReq(ob.card) - areq.add(ob, prop, value) - if areq.commit_sync() != 0: - print("commit failed") - else: - if ob.set_prop_value(prop, value) != 0: - print("setting property failed") - -def set_props(ob, map): - if ob.card.has_atomic: - areq = pykms.AtomicReq(ob.card) - - for key, value in map.items(): - areq.add(ob, key, value) - - if areq.commit_sync() != 0: - print("commit failed") - else: - for propid,propval in map.items(): - if ob.set_prop_value(propid, propval) != 0: - print("setting property failed") - -red = pykms.RGB(255, 0, 0) -green = pykms.RGB(0, 255, 0) -blue = pykms.RGB(0, 0, 255) -yellow = pykms.RGB(255, 255, 0) -purple = pykms.RGB(255, 0, 255) -white = pykms.RGB(255, 255, 255) -cyan = pykms.RGB(0, 255, 255) - -def disable_planes(card): - areq = pykms.AtomicReq(card) - - for p in card.planes: - areq.add(p, "FB_ID", 0) - areq.add(p, "CRTC_ID", 0) - - if areq.commit_sync() != 0: - print("disabling planes failed") diff --git a/py/iact.py b/py/iact.py deleted file mode 100755 index fecd899..0000000 --- a/py/iact.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/python3 -i - -# This is a base script for interactive kms++ python environment - -import pykms -from time import sleep -from math import sin -from math import cos -from helpers import * - -card = pykms.Card() -res = pykms.ResourceManager(card) -conn = res.reserve_connector() -crtc = res.reserve_crtc(conn) - -mode = conn.get_default_mode() - -fb = pykms.DumbFramebuffer(card, 200, 200, "XR24"); -pykms.draw_test_pattern(fb); - -#crtc.set_mode(conn, fb, mode) - -i = 0 -for p in card.planes: - globals()["plane"+str(i)] = p - i=i+1 - -i = 0 -for c in card.crtcs: - globals()["crtc"+str(i)] = c - i=i+1 - -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) - -set_plane(0, 0) - -# for x in range(0, crtc.width() - fb.width()): set_plane(x, int((sin(x/50) + 1) * 100)); sleep(0.01) diff --git a/py/kmsmodeview.py b/py/kmsmodeview.py deleted file mode 100755 index 355db02..0000000 --- a/py/kmsmodeview.py +++ /dev/null @@ -1,317 +0,0 @@ -#!/usr/bin/python3 - -import urwid -import pykms - -def exit_on_q(key): - if key in ('q', 'Q'): - raise urwid.ExitMainLoop() - elif key == 'a': - apply_mode() - -alarm_handle = None - -def recalc_info(l, d): - global alarm_handle - - alarm_handle = None - - for w in recalc_list: - w.recalc() - -def div_or_zero(n, d): - if d == 0: - return 0 - else: - return n / d - -class MyIntEdit(urwid.IntEdit): - _metaclass_ = urwid.signals.MetaSignals - signals = ['value_change'] - - def __init__(self, caption, calc=None): - self._myval = 0 - self._disable_change = False - self._calc = calc - self._updlist = None - - super().__init__(caption, 0) - - def set_edit_text(self, text): - global alarm_handle - - super().set_edit_text(text) - newtext = super().get_edit_text() - new_val = int(newtext) if newtext != "" else 0 - if new_val != self._myval: - self._myval = new_val - if not self._disable_change: - urwid.emit_signal(self, 'value_change', self, self._myval) - - if alarm_handle == None: - alarm_handle = loop.set_alarm_in(0, recalc_info) - - if self._updlist != None: - for w in self._updlist: - w.recalc() - - def recalc(self): - self._disable_change = True - self.set_val(self._calc()) - self._disable_change = False - - def set_val(self, val): - self.set_edit_text(str(int(val))) - - def get_val(self): - return self._myval - - def set_updlist(self, list): - self._updlist = list - - def keypress(self, size, key): - if key == '+': - self.set_edit_text(str(self.value() + 1)) - elif key == '-': - self.set_edit_text(str(self.value() - 1)) - else: - return super().keypress(size, key) - -class MyIntText(urwid.Text): - def __init__(self, fmt, calc=None): - super().__init__("") - self._fmt = fmt - self._calc = calc - - def recalc(self): - val = self._calc() - super().set_text(self._fmt.format(val)) - -def khz_to_ps(khz): - if khz == 0: - return 0 - else: - return 1.0 / khz * 1000 * 1000 * 1000 - -def khz_to_us(khz): - if khz == 0: - return 0 - else: - return 1.0 / khz * 1000 - -pclk_khz_widget = MyIntEdit(u"pclk (kHz) ") -pclk_ps_widget = MyIntText(fmt="pclk {:.2f} ps", calc = lambda: khz_to_ps(pclk_khz_widget.get_val())) - -pclk_widgets = [pclk_khz_widget, pclk_ps_widget] - -pclk_columns = urwid.LineBox(urwid.Columns(pclk_widgets), title = "Pixel clock") - -# Horizontal widgets - -hdisp_widget = MyIntEdit(u"hdisp ", calc = lambda: hdisp2_widget.get_val()) -hfp_widget = MyIntEdit(u"hfp ", calc = lambda: hss_widget.get_val() - hdisp_widget.get_val()) -hsw_widget = MyIntEdit(u"hsw ", calc = lambda: hse_widget.get_val() - hss_widget.get_val()) -hbp_widget = MyIntEdit(u"hbp ", calc = lambda: htot_widget.get_val() - hse_widget.get_val()) - -hdisp2_widget = MyIntEdit(u"hdisp ", calc = lambda: hdisp_widget.get_val()) -hss_widget = MyIntEdit(u"hss ", - calc = lambda: hdisp_widget.get_val() + hfp_widget.get_val()) -hse_widget = MyIntEdit(u"hse ", - calc = lambda: hdisp_widget.get_val() + hfp_widget.get_val() + hsw_widget.get_val()) -htot_widget = MyIntEdit(u"htot ", - calc = lambda: hdisp_widget.get_val() + hfp_widget.get_val() + hsw_widget.get_val() + hbp_widget.get_val()) - -hwidgets1 = [hdisp_widget, hfp_widget, hsw_widget, hbp_widget] -hwidgets2 = [hdisp2_widget, hss_widget, hse_widget, htot_widget] - -horiz_pile1 = urwid.Pile(hwidgets1) -horiz_pile2 = urwid.Pile(hwidgets2) - -h_columns = urwid.LineBox(urwid.Columns([(15, horiz_pile1), (15, horiz_pile2)]), title = "Horizontal") - -# Vertical columns - -vdisp_widget = MyIntEdit(u"vdisp ", calc = lambda: vdisp2_widget.get_val()) -vfp_widget = MyIntEdit(u"vfp ", calc = lambda: vss_widget.get_val() - vdisp_widget.get_val()) -vsw_widget = MyIntEdit(u"vsw ", calc = lambda: vse_widget.get_val() - vss_widget.get_val()) -vbp_widget = MyIntEdit(u"vbp ", calc = lambda: vtot_widget.get_val() - vse_widget.get_val()) - -vdisp2_widget = MyIntEdit(u"vdisp ", calc = lambda: vdisp_widget.get_val()) -vss_widget = MyIntEdit(u"vss ", - calc = lambda: vdisp_widget.get_val() + vfp_widget.get_val()) -vse_widget = MyIntEdit(u"vse ", - calc = lambda: vdisp_widget.get_val() + vfp_widget.get_val() + vsw_widget.get_val()) -vtot_widget = MyIntEdit(u"vtot ", - calc = lambda: vdisp_widget.get_val() + vfp_widget.get_val() + vsw_widget.get_val() + vbp_widget.get_val()) - -vwidgets1 = [vdisp_widget, vfp_widget, vsw_widget, vbp_widget] -vwidgets2 = [vdisp2_widget, vss_widget, vse_widget, vtot_widget] - -vert_pile1 = urwid.Pile(vwidgets1) -vert_pile2 = urwid.Pile(vwidgets2) - -v_columns = urwid.LineBox(urwid.Columns([(15, vert_pile1), (15, vert_pile2)]), title = "Vertical") - -# Info widgets - -line_us_widget = MyIntText(fmt="line {:.2f} us", - calc = lambda: khz_to_us(pclk_khz_widget.get_val()) * htot_widget.get_val()) -line_khz_widget = MyIntText(fmt="line {:.2f} kHz", - calc = lambda: div_or_zero(pclk_khz_widget.get_val(), htot_widget.get_val())) - -frame_tot_widget = MyIntText(fmt="tot {} pix", - calc = lambda: htot_widget.get_val() * vtot_widget.get_val()) -frame_us_widget = MyIntText(fmt="frame {:.2f} ms", - calc = lambda: khz_to_us(pclk_khz_widget.get_val()) * htot_widget.get_val() * vtot_widget.get_val() / 1000) -frame_khz_widget = MyIntText(fmt="frame {:.2f} Hz", - calc = lambda: div_or_zero(pclk_khz_widget.get_val() * 1000, htot_widget.get_val() * vtot_widget.get_val())) - -info_box = urwid.LineBox(urwid.Pile([line_us_widget, line_khz_widget, urwid.Divider(), frame_tot_widget, frame_us_widget, frame_khz_widget]), title = "Info") - -# Set update lists - -recalc_list = [ pclk_ps_widget, line_us_widget, line_khz_widget, frame_tot_widget, frame_us_widget, frame_khz_widget ] - -hdisp_widget.set_updlist([hdisp2_widget, hss_widget, hse_widget, htot_widget]) -hfp_widget.set_updlist([hss_widget, hse_widget, htot_widget]) -hsw_widget.set_updlist([hse_widget, htot_widget]) -hbp_widget.set_updlist([htot_widget]) -hdisp2_widget.set_updlist([hdisp_widget, hfp_widget]) -hss_widget.set_updlist([hfp_widget, hsw_widget]) -hse_widget.set_updlist([hsw_widget, hbp_widget]) -htot_widget.set_updlist([hbp_widget]) - -vdisp_widget.set_updlist([vdisp2_widget, vss_widget, vse_widget, vtot_widget]) -vfp_widget.set_updlist([vss_widget, vse_widget, vtot_widget]) -vsw_widget.set_updlist([vse_widget, vtot_widget]) -vbp_widget.set_updlist([vtot_widget]) -vdisp2_widget.set_updlist([vdisp_widget, vfp_widget]) -vss_widget.set_updlist([vfp_widget, vsw_widget]) -vse_widget.set_updlist([vsw_widget, vbp_widget]) -vtot_widget.set_updlist([vbp_widget]) - -# Flags - -fb = None - -DRM_MODE_FLAG_PHSYNC = (1<<0) -DRM_MODE_FLAG_NHSYNC = (1<<1) -DRM_MODE_FLAG_PVSYNC = (1<<2) -DRM_MODE_FLAG_NVSYNC = (1<<3) -DRM_MODE_FLAG_INTERLACE = (1<<4) -DRM_MODE_FLAG_DBLCLK = (1<<12) - -def mode_is_ilace(mode): - return (mode.flags & DRM_MODE_FLAG_INTERLACE) != 0 - -def apply_mode(): - global fb - - mode = pykms.Videomode() - mode.clock = pclk_khz_widget.get_val() - - mode.hdisplay = hdisp2_widget.get_val() - mode.hsync_start = hss_widget.get_val() - mode.hsync_end = hse_widget.get_val() - mode.htotal = htot_widget.get_val() - - mode.vdisplay = vdisp2_widget.get_val() - mode.vsync_start = vss_widget.get_val() - mode.vsync_end = vse_widget.get_val() - mode.vtotal = vtot_widget.get_val() - - if ilace_box.state: - mode.flags |= DRM_MODE_FLAG_INTERLACE - - if dblclk_box.state: - mode.flags |= DRM_MODE_FLAG_DBLCLK - - if hsync_pol.state == True: - mode.flags |= DRM_MODE_FLAG_PHSYNC - elif hsync_pol.state == False: - mode.flags |= DRM_MODE_FLAG_NHSYNC - - if vsync_pol.state == True: - mode.flags |= DRM_MODE_FLAG_PVSYNC - elif vsync_pol.state == False: - mode.flags |= DRM_MODE_FLAG_NVSYNC - - fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); - pykms.draw_test_pattern(fb); - - crtc.set_mode(conn, fb, mode) - -def read_mode(mode): - pclk_khz_widget.set_val(mode.clock) - hdisp2_widget.set_val(mode.hdisplay) - hss_widget.set_val(mode.hsync_start) - hse_widget.set_val(mode.hsync_end) - htot_widget.set_val(mode.htotal) - - vdisp2_widget.set_val(mode.vdisplay) - vss_widget.set_val(mode.vsync_start) - vse_widget.set_val(mode.vsync_end) - vtot_widget.set_val(mode.vtotal) - - ilace_box.set_state(mode_is_ilace(mode)) - dblclk_box.set_state((mode.flags & DRM_MODE_FLAG_DBLCLK) != 0) - - sync = 'mixed' - if (mode.flags & DRM_MODE_FLAG_PHSYNC) != 0: - sync = True - elif (mode.flags & DRM_MODE_FLAG_NHSYNC) != 0: - sync = False - hsync_pol.set_state(sync) - - sync = 'mixed' - if (mode.flags & DRM_MODE_FLAG_PVSYNC) != 0: - sync = True - elif (mode.flags & DRM_MODE_FLAG_NVSYNC) != 0: - sync = False - vsync_pol.set_state(sync) - -def apply_press(w): - apply_mode() - -ilace_box = urwid.CheckBox('interlace') -hsync_pol = urwid.CheckBox('hsync positive', has_mixed=True) -vsync_pol = urwid.CheckBox('vsync positive', has_mixed=True) -dblclk_box = urwid.CheckBox('double clock') - -flags_pile = urwid.LineBox(urwid.Pile([ilace_box, hsync_pol, vsync_pol, dblclk_box]), title = "Flags") - -apply_button = urwid.LineBox(urwid.Padding(urwid.Button('apply', on_press=apply_press))) - -# Main - -def mode_press(w, mode): - read_mode(mode) - -def mode_to_str(mode): - return "{}@{}{}".format(mode.name, mode.vrefresh, "i" if mode_is_ilace(mode) else "") - -mode_buttons = [] - -card = pykms.Card() -conn = card.get_first_connected_connector() -crtc = conn.get_current_crtc() -modes = conn.get_modes() -i = 0 -for m in modes: - mode_buttons.append(urwid.Button(mode_to_str(m), on_press=mode_press, user_data=m)) - i += 1 - -modes_pile = urwid.LineBox(urwid.Pile(mode_buttons), title = "Video modes") - -main_pile = urwid.Pile([modes_pile, pclk_columns, urwid.Columns([ h_columns, v_columns ]), info_box, flags_pile, apply_button]) - -main_columns = urwid.Filler(main_pile, valign='top') - -loop = urwid.MainLoop(main_columns, unhandled_input=exit_on_q, handle_mouse=False) - -# select the first mode -mode_press(None, modes[0]) - -loop.run() - -fb = None diff --git a/py/pykms.cpp b/py/pykms.cpp deleted file mode 100644 index 2199039..0000000 --- a/py/pykms.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include -#include - -namespace py = pybind11; - -using namespace kms; -using namespace std; - -void init_pykmstest(py::module &m); -void init_pykmsbase(py::module &m); -void init_pyvid(py::module &m); - -#if HAS_LIBDRM_OMAP -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_(m, "PageFlipHandlerBase") - .alias() - .def(py::init<>()) - .def("handle_page_flip", &PageFlipHandlerBase::handle_page_flip) - ; - - init_pykmstest(m); - - init_pyvid(m); - -#if HAS_LIBDRM_OMAP - init_pykmsomap(m); -#endif - return m.ptr(); -} diff --git a/py/pykms/CMakeLists.txt b/py/pykms/CMakeLists.txt new file mode 100644 index 0000000..3e6e0e1 --- /dev/null +++ b/py/pykms/CMakeLists.txt @@ -0,0 +1,26 @@ +include_directories(${LIBDRM_INCLUDE_DIRS}) +link_directories(${LIBDRM_LIBRARY_DIRS}) + +pkg_check_modules(PYTHON python3 REQUIRED) +include_directories(${PYTHON_INCLUDE_DIRS}) + +if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") +endif() + +include_directories(${PROJECT_SOURCE_DIR}/ext/pybind11/include) + +set(SRCS pykms.cpp pykmsbase.cpp pykmsutil.cpp pyvid.cpp) + +if(LIBDRM_OMAP_FOUND) + set(SRCS ${SRCS} pykmsomap.cpp) +endif() + +add_library(pykms SHARED ${SRCS}) +target_link_libraries(pykms kms++ kms++util ${LIBDRM_LIBRARIES}) + +# Don't add a 'lib' prefix to the shared library +set_target_properties(pykms PROPERTIES PREFIX "") + +# XXX Where should pykms.so be installed? +#install(TARGETS pykms DESTINATION lib) diff --git a/py/pykms/pykms.cpp b/py/pykms/pykms.cpp new file mode 100644 index 0000000..2199039 --- /dev/null +++ b/py/pykms/pykms.cpp @@ -0,0 +1,53 @@ +#include +#include +#include + +namespace py = pybind11; + +using namespace kms; +using namespace std; + +void init_pykmstest(py::module &m); +void init_pykmsbase(py::module &m); +void init_pyvid(py::module &m); + +#if HAS_LIBDRM_OMAP +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_(m, "PageFlipHandlerBase") + .alias() + .def(py::init<>()) + .def("handle_page_flip", &PageFlipHandlerBase::handle_page_flip) + ; + + init_pykmstest(m); + + init_pyvid(m); + +#if HAS_LIBDRM_OMAP + init_pykmsomap(m); +#endif + return m.ptr(); +} diff --git a/py/pykms/pykmsbase.cpp b/py/pykms/pykmsbase.cpp new file mode 100644 index 0000000..5247158 --- /dev/null +++ b/py/pykms/pykmsbase.cpp @@ -0,0 +1,157 @@ +#include +#include +#include + +namespace py = pybind11; + +using namespace kms; +using namespace std; + +void init_pykmsbase(py::module &m) +{ + 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) + ; + + py::class_(m, "DrmObject") + .def_property_readonly("id", &DrmObject::id) + .def_property_readonly("card", &DrmObject::card) + ; + + py::class_(m, "DrmPropObject", py::base()) + .def("refresh_props", &DrmPropObject::refresh_props) + .def_property_readonly("prop_map", &DrmPropObject::get_prop_map) + .def("get_prop_value", (uint64_t (DrmPropObject::*)(const string&) const)&DrmPropObject::get_prop_value) + .def("set_prop_value",(int (DrmPropObject::*)(const string&, uint64_t)) &DrmPropObject::set_prop_value) + .def("get_prop_value_as_blob", &DrmPropObject::get_prop_value_as_blob) + ; + + 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_possible_crtcs", &Connector::get_possible_crtcs) + .def("get_modes", &Connector::get_modes) + .def("get_mode", (Videomode (Connector::*)(const string& mode) const)&Connector::get_mode) + .def("get_mode", (Videomode (Connector::*)(unsigned xres, unsigned yres, float refresh, bool ilace) const)&Connector::get_mode) + .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_property_readonly("primary_plane", &Crtc::get_primary_plane) + .def_property_readonly("mode", &Crtc::mode) + .def_property_readonly("mode_valid", &Crtc::mode_valid) + .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, "Blob", py::base()) + .def("__init__", [](Blob& instance, Card& card, py::buffer buf) { + py::buffer_info info = buf.request(); + if (info.ndim != 1) + throw std::runtime_error("Incompatible buffer dimension!"); + + new (&instance) Blob(card, info.ptr, info.size * info.itemsize); + }) + .def_property_readonly("data", &Blob::data) + ; + + py::class_(m, "Framebuffer", py::base()) + ; + + py::class_(m, "MappedFramebuffer", py::base()) + .def_property_readonly("width", &MappedFramebuffer::width) + .def_property_readonly("height", &MappedFramebuffer::height) + ; + + py::class_(m, "DumbFramebuffer", py::base()) + .def(py::init(), + py::keep_alive<1, 2>()) // Keep Card alive until this is destructed + .def(py::init(), + py::keep_alive<1, 2>()) // Keep Card alive until this is destructed + ; + + py::enum_(m, "PixelFormat") + .value("Undefined", PixelFormat::Undefined) + + .value("NV12", PixelFormat::NV12) + .value("NV21", PixelFormat::NV21) + + .value("UYVY", PixelFormat::UYVY) + .value("YUYV", PixelFormat::YUYV) + .value("YVYU", PixelFormat::YVYU) + .value("VYUY", PixelFormat::VYUY) + + .value("XRGB8888", PixelFormat::XRGB8888) + .value("XBGR8888", PixelFormat::XBGR8888) + .value("ARGB8888", PixelFormat::ARGB8888) + .value("ABGR8888", PixelFormat::ABGR8888) + + .value("RGB888", PixelFormat::RGB888) + + .value("RGB565", PixelFormat::RGB565) + ; + + 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, "AtomicReq") + .def(py::init(), + py::keep_alive<1, 2>()) // Keep Card alive until this is destructed + .def("add", (void (AtomicReq::*)(DrmPropObject*, const 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_sync", &AtomicReq::commit_sync, py::arg("allow_modeset") = false) + ; +} diff --git a/py/pykms/pykmsomap.cpp b/py/pykms/pykmsomap.cpp new file mode 100644 index 0000000..525834b --- /dev/null +++ b/py/pykms/pykmsomap.cpp @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +namespace py = pybind11; + +using namespace kms; +using namespace std; + +void init_pykmsomap(py::module &m) +{ + py::class_(m, "OmapCard", py::base()) + .def(py::init<>()) + ; + + py::class_(m, "OmapFramebuffer", py::base()) + .def(py::init(), + py::keep_alive<1, 2>()) // Keep OmapCard alive until this is destructed + ; +} diff --git a/py/pykms/pykmsutil.cpp b/py/pykms/pykmsutil.cpp new file mode 100644 index 0000000..b3b7594 --- /dev/null +++ b/py/pykms/pykmsutil.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +namespace py = pybind11; + +using namespace kms; +using namespace std; + +void init_pykmstest(py::module &m) +{ + py::class_(m, "RGB") + .def(py::init<>()) + .def(py::init()) + .def(py::init()) + .def_property_readonly("rgb888", &RGB::rgb888) + .def_property_readonly("argb8888", &RGB::argb8888) + .def_property_readonly("abgr8888", &RGB::abgr8888) + .def_property_readonly("rgb565", &RGB::rgb565) + ; + + py::class_(m, "ResourceManager") + .def(py::init()) + .def("reset", &ResourceManager::reset) + .def("reserve_connector", &ResourceManager::reserve_connector, + py::arg("name") = string()) + .def("reserve_crtc", &ResourceManager::reserve_crtc) + .def("reserve_plane", &ResourceManager::reserve_plane, + py::arg("crtc"), + py::arg("type"), + py::arg("format") = PixelFormat::Undefined) + .def("reserve_primary_plane", &ResourceManager::reserve_primary_plane, + py::arg("crtc"), + py::arg("format") = PixelFormat::Undefined) + .def("reserve_overlay_plane", &ResourceManager::reserve_overlay_plane, + py::arg("crtc"), + py::arg("format") = PixelFormat::Undefined) + ; + + // Use lambdas to handle IMappedFramebuffer + m.def("draw_test_pattern", [](MappedFramebuffer& fb) { draw_test_pattern(fb); } ); + m.def("draw_color_bar", [](MappedFramebuffer& fb, int old_xpos, int xpos, int width) { + draw_color_bar(fb, old_xpos, xpos, width); + } ); + m.def("draw_rect", [](MappedFramebuffer& fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color) { + draw_rect(fb, x, y, w, h, color); + } ); +} diff --git a/py/pykms/pyvid.cpp b/py/pykms/pyvid.cpp new file mode 100644 index 0000000..01177d5 --- /dev/null +++ b/py/pykms/pyvid.cpp @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include + +namespace py = pybind11; + +using namespace kms; +using namespace std; + +void init_pyvid(py::module &m) +{ + py::class_(m, "VideoDevice") + .def(py::init()) + .def_property_readonly("fd", &VideoDevice::fd) + .def_property_readonly("has_capture", &VideoDevice::has_capture) + .def_property_readonly("has_output", &VideoDevice::has_output) + .def_property_readonly("has_m2m", &VideoDevice::has_m2m) + .def_property_readonly("capture_streamer", &VideoDevice::get_capture_streamer) + .def_property_readonly("output_streamer", &VideoDevice::get_output_streamer) + .def_property_readonly("discrete_frame_sizes", &VideoDevice::get_discrete_frame_sizes) + .def_property_readonly("frame_sizes", &VideoDevice::get_frame_sizes) + .def("get_capture_devices", &VideoDevice::get_capture_devices) + ; + + py::class_(m, "VideoStreamer") + .def_property_readonly("fd", &VideoStreamer::fd) + .def_property_readonly("ports", &VideoStreamer::get_ports) + .def("set_port", &VideoStreamer::set_port) + .def_property_readonly("formats", &VideoStreamer::get_formats) + .def("set_format", &VideoStreamer::set_format) + .def("set_queue_size", &VideoStreamer::set_queue_size) + .def("queue", &VideoStreamer::queue) + .def("dequeue", &VideoStreamer::dequeue) + .def("stream_on", &VideoStreamer::stream_on) + ; +} diff --git a/py/pykmsbase.cpp b/py/pykmsbase.cpp deleted file mode 100644 index 5247158..0000000 --- a/py/pykmsbase.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include -#include - -namespace py = pybind11; - -using namespace kms; -using namespace std; - -void init_pykmsbase(py::module &m) -{ - 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) - ; - - py::class_(m, "DrmObject") - .def_property_readonly("id", &DrmObject::id) - .def_property_readonly("card", &DrmObject::card) - ; - - py::class_(m, "DrmPropObject", py::base()) - .def("refresh_props", &DrmPropObject::refresh_props) - .def_property_readonly("prop_map", &DrmPropObject::get_prop_map) - .def("get_prop_value", (uint64_t (DrmPropObject::*)(const string&) const)&DrmPropObject::get_prop_value) - .def("set_prop_value",(int (DrmPropObject::*)(const string&, uint64_t)) &DrmPropObject::set_prop_value) - .def("get_prop_value_as_blob", &DrmPropObject::get_prop_value_as_blob) - ; - - 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_possible_crtcs", &Connector::get_possible_crtcs) - .def("get_modes", &Connector::get_modes) - .def("get_mode", (Videomode (Connector::*)(const string& mode) const)&Connector::get_mode) - .def("get_mode", (Videomode (Connector::*)(unsigned xres, unsigned yres, float refresh, bool ilace) const)&Connector::get_mode) - .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_property_readonly("primary_plane", &Crtc::get_primary_plane) - .def_property_readonly("mode", &Crtc::mode) - .def_property_readonly("mode_valid", &Crtc::mode_valid) - .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, "Blob", py::base()) - .def("__init__", [](Blob& instance, Card& card, py::buffer buf) { - py::buffer_info info = buf.request(); - if (info.ndim != 1) - throw std::runtime_error("Incompatible buffer dimension!"); - - new (&instance) Blob(card, info.ptr, info.size * info.itemsize); - }) - .def_property_readonly("data", &Blob::data) - ; - - py::class_(m, "Framebuffer", py::base()) - ; - - py::class_(m, "MappedFramebuffer", py::base()) - .def_property_readonly("width", &MappedFramebuffer::width) - .def_property_readonly("height", &MappedFramebuffer::height) - ; - - py::class_(m, "DumbFramebuffer", py::base()) - .def(py::init(), - py::keep_alive<1, 2>()) // Keep Card alive until this is destructed - .def(py::init(), - py::keep_alive<1, 2>()) // Keep Card alive until this is destructed - ; - - py::enum_(m, "PixelFormat") - .value("Undefined", PixelFormat::Undefined) - - .value("NV12", PixelFormat::NV12) - .value("NV21", PixelFormat::NV21) - - .value("UYVY", PixelFormat::UYVY) - .value("YUYV", PixelFormat::YUYV) - .value("YVYU", PixelFormat::YVYU) - .value("VYUY", PixelFormat::VYUY) - - .value("XRGB8888", PixelFormat::XRGB8888) - .value("XBGR8888", PixelFormat::XBGR8888) - .value("ARGB8888", PixelFormat::ARGB8888) - .value("ABGR8888", PixelFormat::ABGR8888) - - .value("RGB888", PixelFormat::RGB888) - - .value("RGB565", PixelFormat::RGB565) - ; - - 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, "AtomicReq") - .def(py::init(), - py::keep_alive<1, 2>()) // Keep Card alive until this is destructed - .def("add", (void (AtomicReq::*)(DrmPropObject*, const 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_sync", &AtomicReq::commit_sync, py::arg("allow_modeset") = false) - ; -} diff --git a/py/pykmsomap.cpp b/py/pykmsomap.cpp deleted file mode 100644 index 525834b..0000000 --- a/py/pykmsomap.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include -#include - -namespace py = pybind11; - -using namespace kms; -using namespace std; - -void init_pykmsomap(py::module &m) -{ - py::class_(m, "OmapCard", py::base()) - .def(py::init<>()) - ; - - py::class_(m, "OmapFramebuffer", py::base()) - .def(py::init(), - py::keep_alive<1, 2>()) // Keep OmapCard alive until this is destructed - ; -} diff --git a/py/pykmsutil.cpp b/py/pykmsutil.cpp deleted file mode 100644 index b3b7594..0000000 --- a/py/pykmsutil.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include -#include - -namespace py = pybind11; - -using namespace kms; -using namespace std; - -void init_pykmstest(py::module &m) -{ - py::class_(m, "RGB") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def_property_readonly("rgb888", &RGB::rgb888) - .def_property_readonly("argb8888", &RGB::argb8888) - .def_property_readonly("abgr8888", &RGB::abgr8888) - .def_property_readonly("rgb565", &RGB::rgb565) - ; - - py::class_(m, "ResourceManager") - .def(py::init()) - .def("reset", &ResourceManager::reset) - .def("reserve_connector", &ResourceManager::reserve_connector, - py::arg("name") = string()) - .def("reserve_crtc", &ResourceManager::reserve_crtc) - .def("reserve_plane", &ResourceManager::reserve_plane, - py::arg("crtc"), - py::arg("type"), - py::arg("format") = PixelFormat::Undefined) - .def("reserve_primary_plane", &ResourceManager::reserve_primary_plane, - py::arg("crtc"), - py::arg("format") = PixelFormat::Undefined) - .def("reserve_overlay_plane", &ResourceManager::reserve_overlay_plane, - py::arg("crtc"), - py::arg("format") = PixelFormat::Undefined) - ; - - // Use lambdas to handle IMappedFramebuffer - m.def("draw_test_pattern", [](MappedFramebuffer& fb) { draw_test_pattern(fb); } ); - m.def("draw_color_bar", [](MappedFramebuffer& fb, int old_xpos, int xpos, int width) { - draw_color_bar(fb, old_xpos, xpos, width); - } ); - m.def("draw_rect", [](MappedFramebuffer& fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color) { - draw_rect(fb, x, y, w, h, color); - } ); -} diff --git a/py/pyvid.cpp b/py/pyvid.cpp deleted file mode 100644 index 01177d5..0000000 --- a/py/pyvid.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include -#include -#include - -namespace py = pybind11; - -using namespace kms; -using namespace std; - -void init_pyvid(py::module &m) -{ - py::class_(m, "VideoDevice") - .def(py::init()) - .def_property_readonly("fd", &VideoDevice::fd) - .def_property_readonly("has_capture", &VideoDevice::has_capture) - .def_property_readonly("has_output", &VideoDevice::has_output) - .def_property_readonly("has_m2m", &VideoDevice::has_m2m) - .def_property_readonly("capture_streamer", &VideoDevice::get_capture_streamer) - .def_property_readonly("output_streamer", &VideoDevice::get_output_streamer) - .def_property_readonly("discrete_frame_sizes", &VideoDevice::get_discrete_frame_sizes) - .def_property_readonly("frame_sizes", &VideoDevice::get_frame_sizes) - .def("get_capture_devices", &VideoDevice::get_capture_devices) - ; - - py::class_(m, "VideoStreamer") - .def_property_readonly("fd", &VideoStreamer::fd) - .def_property_readonly("ports", &VideoStreamer::get_ports) - .def("set_port", &VideoStreamer::set_port) - .def_property_readonly("formats", &VideoStreamer::get_formats) - .def("set_format", &VideoStreamer::set_format) - .def("set_queue_size", &VideoStreamer::set_queue_size) - .def("queue", &VideoStreamer::queue) - .def("dequeue", &VideoStreamer::dequeue) - .def("stream_on", &VideoStreamer::stream_on) - ; -} diff --git a/py/run.sh b/py/run.sh deleted file mode 100755 index f0ead78..0000000 --- a/py/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -PYTHONPATH=build/py/ python3 $* - diff --git a/py/test.py b/py/test.py deleted file mode 100755 index 9c23b5b..0000000 --- a/py/test.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/python3 - -import pykms -from helpers import * - -card = pykms.Card() -res = pykms.ResourceManager(card) -conn = res.reserve_connector() -crtc = res.reserve_crtc(conn) - -mode = conn.get_default_mode() - -fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); -pykms.draw_test_pattern(fb); - -crtc.set_mode(conn, fb, mode) - -input("press enter to exit\n") diff --git a/py/tests/CMakeLists.txt b/py/tests/CMakeLists.txt new file mode 100644 index 0000000..a670ed9 --- /dev/null +++ b/py/tests/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB PY_SRCS "*.py") +add_custom_target(pyextras SOURCES ${PY_SRCS}) + +add_test(NAME pytest COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/functest.py") +set_property(TEST pytest PROPERTY + ENVIRONMENT "PYTHONPATH=." "LD_LIBRARY_PATH=." +) diff --git a/py/tests/alpha-test.py b/py/tests/alpha-test.py new file mode 100755 index 0000000..c6ec8ee --- /dev/null +++ b/py/tests/alpha-test.py @@ -0,0 +1,67 @@ +#!/usr/bin/python3 + +import pykms +from helpers import * +import time + +# This hack makes drm initialize the fbcon, setting up the default connector +card = pykms.Card() +card = 0 + +card = pykms.Card() +res = pykms.ResourceManager(card) +conn = res.reserve_connector() +crtc = res.reserve_crtc(conn) +mode = conn.get_default_mode() + +planes = [] +for p in card.planes: + if p.supports_crtc(crtc) == False: + continue + planes.append(p) + +if len(planes) != 3: + print("Need 3 planes!") + exit(1) + +disable_planes(card) + +w = mode.hdisplay +h = mode.vdisplay + +fbs=[] + +for i in range(len(planes)): + fbs.append(pykms.DumbFramebuffer(card, w, h, "AR24")) + +pykms.draw_rect(fbs[0], 50, 50, 200, 200, pykms.RGB(128, 255, 0, 0)) +pykms.draw_rect(fbs[1], 150, 50, 200, 200, pykms.RGB(128, 0, 255, 0)) +pykms.draw_rect(fbs[2], 50, 150, 200, 200, pykms.RGB(128, 0, 0, 255)) + + +set_props(crtc, { + "trans-key-mode": 0, + "trans-key": 0, + "background": 0, + "alpha_blender": 1, +}) + +for i in range(len(planes)): + plane = planes[i] + fb = fbs[i] + + print("set crtc {}, plane {}, fb {}".format(crtc.id, p.id, fbs[i].id)) + + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_W": fb.width, + "CRTC_H": fb.height, + "zorder": i, + }) + + time.sleep(1) + +input("press enter to exit\n") diff --git a/py/tests/cam.py b/py/tests/cam.py new file mode 100755 index 0000000..b44f8f9 --- /dev/null +++ b/py/tests/cam.py @@ -0,0 +1,78 @@ +#!/usr/bin/python3 + +import sys +import selectors +import pykms +from helpers import * + + +w = 640 +h = 480 +fmt = pykms.PixelFormat.YUYV + + +# This hack makes drm initialize the fbcon, setting up the default connector +card = pykms.Card() +card = 0 + +card = pykms.Card() +res = pykms.ResourceManager(card) +conn = res.reserve_connector() +crtc = res.reserve_crtc(conn) +plane = res.reserve_overlay_plane(crtc, fmt) + +mode = conn.get_default_mode() + +NUM_BUFS = 5 + +fbs = [] +for i in range(NUM_BUFS): + fb = pykms.DumbFramebuffer(card, w, h, fmt) + fbs.append(fb) + +vidpath = pykms.VideoDevice.get_capture_devices()[0] + +vid = pykms.VideoDevice(vidpath) +cap = vid.capture_streamer +cap.set_port(0) +cap.set_format(fmt, w, h) +cap.set_queue_size(NUM_BUFS) + +for fb in fbs: + cap.queue(fb) + +cap.stream_on() + + +def readvid(conn, mask): + fb = cap.dequeue() + + if card.has_atomic: + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_W": fb.width, + "CRTC_H": fb.height, + }) + else: + crtc.set_plane(plane, fb, 0, 0, fb.width, fb.height, + 0, 0, fb.width, fb.height) + + cap.queue(fb) + +def readkey(conn, mask): + #print("KEY EVENT"); + sys.stdin.readline() + exit(0) + +sel = selectors.DefaultSelector() +sel.register(cap.fd, selectors.EVENT_READ, readvid) +sel.register(sys.stdin, selectors.EVENT_READ, readkey) + +while True: + events = sel.select() + for key, mask in events: + callback = key.data + callback(key.fileobj, mask) diff --git a/py/tests/db.py b/py/tests/db.py new file mode 100755 index 0000000..3ffb716 --- /dev/null +++ b/py/tests/db.py @@ -0,0 +1,72 @@ +#!/usr/bin/python3 + +import sys +import pykms +import selectors +from helpers import * + +bar_width = 20 +bar_speed = 8 + +class FlipHandler(pykms.PageFlipHandlerBase): + def __init__(self): + super().__init__() + self.bar_xpos = 0 + self.front_buf = 0 + self.fb1 = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); + self.fb2 = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); + + def handle_page_flip(self, frame, time): + if self.front_buf == 0: + fb = self.fb2 + else: + fb = self.fb1 + + 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); + + self.bar_xpos = new_xpos + + pykms.draw_color_bar(fb, old_xpos, new_xpos, bar_width) + + if card.has_atomic: + ctx = pykms.AtomicReq(card) + ctx.add(crtc.primary_plane, "FB_ID", fb.id) + ctx.commit(self) + else: + crtc.page_flip(fb, self) + + +card = pykms.Card() +res = pykms.ResourceManager(card) +conn = res.reserve_connector() +crtc = res.reserve_crtc(conn) +mode = conn.get_default_mode() + +fliphandler = FlipHandler() + +crtc.set_mode(conn, fliphandler.fb1, mode) + +fliphandler.handle_page_flip(0, 0) + +def readdrm(conn, mask): + #print("EVENT"); + card.call_page_flip_handlers() + +def readkey(conn, mask): + #print("KEY EVENT"); + sys.stdin.readline() + exit(0) + +sel = selectors.DefaultSelector() +sel.register(card.fd, selectors.EVENT_READ, readdrm) +sel.register(sys.stdin, selectors.EVENT_READ, readkey) + +while True: + events = sel.select() + for key, mask in events: + callback = key.data + callback(key.fileobj, mask) diff --git a/py/tests/functest.py b/py/tests/functest.py new file mode 100755 index 0000000..44c29fb --- /dev/null +++ b/py/tests/functest.py @@ -0,0 +1,19 @@ +#!/usr/bin/python3 + +import pykms +from helpers import * + +card = pykms.Card() +res = pykms.ResourceManager(card) +conn = res.reserve_connector() +crtc = res.reserve_crtc(conn) + +mode = conn.get_default_mode() + +fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); +pykms.draw_test_pattern(fb); + +crtc.set_mode(conn, fb, mode) + +print("OK") + diff --git a/py/tests/gamma.py b/py/tests/gamma.py new file mode 100755 index 0000000..a6b68cc --- /dev/null +++ b/py/tests/gamma.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 + +import pykms +from helpers import * + +# This hack makes drm initialize the fbcon, setting up the default connector +card = pykms.Card() +card = 0 + +card = pykms.Card() +res = pykms.ResourceManager(card) +conn = res.reserve_connector() +crtc = res.reserve_crtc(conn) +mode = conn.get_default_mode() + +fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); +pykms.draw_test_pattern(fb); + +crtc.set_mode(conn, fb, mode) + +len=256 +arr = bytearray(len*2*4) +view = memoryview(arr).cast("H") + +for i in range(len): + g = round(65535 * pow(i / float(len), 1 / 2.2)) + + view[i * 4 + 0] = g + view[i * 4 + 1] = g + view[i * 4 + 2] = g + view[i * 4 + 3] = 0 + +gamma = pykms.Blob(card, arr); + +set_prop(crtc, "GAMMA_LUT", gamma.id) + +input("press enter to remove gamma\n") + +set_prop(crtc, "GAMMA_LUT", 0) + +input("press enter to exit\n") diff --git a/py/tests/helpers.py b/py/tests/helpers.py new file mode 100644 index 0000000..fd67d41 --- /dev/null +++ b/py/tests/helpers.py @@ -0,0 +1,54 @@ +import pykms + +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.prop_map + for propid,propval in map.items(): + prop = o.card.get_prop(propid) + print("%-15s %d (%#x)" % (prop.name, propval, propval)) + +def set_prop(ob, prop, value): + if ob.card.has_atomic: + areq = pykms.AtomicReq(ob.card) + areq.add(ob, prop, value) + if areq.commit_sync() != 0: + print("commit failed") + else: + if ob.set_prop_value(prop, value) != 0: + print("setting property failed") + +def set_props(ob, map): + if ob.card.has_atomic: + areq = pykms.AtomicReq(ob.card) + + for key, value in map.items(): + areq.add(ob, key, value) + + if areq.commit_sync() != 0: + print("commit failed") + else: + for propid,propval in map.items(): + if ob.set_prop_value(propid, propval) != 0: + print("setting property failed") + +red = pykms.RGB(255, 0, 0) +green = pykms.RGB(0, 255, 0) +blue = pykms.RGB(0, 0, 255) +yellow = pykms.RGB(255, 255, 0) +purple = pykms.RGB(255, 0, 255) +white = pykms.RGB(255, 255, 255) +cyan = pykms.RGB(0, 255, 255) + +def disable_planes(card): + areq = pykms.AtomicReq(card) + + for p in card.planes: + areq.add(p, "FB_ID", 0) + areq.add(p, "CRTC_ID", 0) + + if areq.commit_sync() != 0: + print("disabling planes failed") diff --git a/py/tests/iact.py b/py/tests/iact.py new file mode 100755 index 0000000..fecd899 --- /dev/null +++ b/py/tests/iact.py @@ -0,0 +1,43 @@ +#!/usr/bin/python3 -i + +# This is a base script for interactive kms++ python environment + +import pykms +from time import sleep +from math import sin +from math import cos +from helpers import * + +card = pykms.Card() +res = pykms.ResourceManager(card) +conn = res.reserve_connector() +crtc = res.reserve_crtc(conn) + +mode = conn.get_default_mode() + +fb = pykms.DumbFramebuffer(card, 200, 200, "XR24"); +pykms.draw_test_pattern(fb); + +#crtc.set_mode(conn, fb, mode) + +i = 0 +for p in card.planes: + globals()["plane"+str(i)] = p + i=i+1 + +i = 0 +for c in card.crtcs: + globals()["crtc"+str(i)] = c + i=i+1 + +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) + +set_plane(0, 0) + +# for x in range(0, crtc.width() - fb.width()): set_plane(x, int((sin(x/50) + 1) * 100)); sleep(0.01) diff --git a/py/tests/kmsmodeview.py b/py/tests/kmsmodeview.py new file mode 100755 index 0000000..355db02 --- /dev/null +++ b/py/tests/kmsmodeview.py @@ -0,0 +1,317 @@ +#!/usr/bin/python3 + +import urwid +import pykms + +def exit_on_q(key): + if key in ('q', 'Q'): + raise urwid.ExitMainLoop() + elif key == 'a': + apply_mode() + +alarm_handle = None + +def recalc_info(l, d): + global alarm_handle + + alarm_handle = None + + for w in recalc_list: + w.recalc() + +def div_or_zero(n, d): + if d == 0: + return 0 + else: + return n / d + +class MyIntEdit(urwid.IntEdit): + _metaclass_ = urwid.signals.MetaSignals + signals = ['value_change'] + + def __init__(self, caption, calc=None): + self._myval = 0 + self._disable_change = False + self._calc = calc + self._updlist = None + + super().__init__(caption, 0) + + def set_edit_text(self, text): + global alarm_handle + + super().set_edit_text(text) + newtext = super().get_edit_text() + new_val = int(newtext) if newtext != "" else 0 + if new_val != self._myval: + self._myval = new_val + if not self._disable_change: + urwid.emit_signal(self, 'value_change', self, self._myval) + + if alarm_handle == None: + alarm_handle = loop.set_alarm_in(0, recalc_info) + + if self._updlist != None: + for w in self._updlist: + w.recalc() + + def recalc(self): + self._disable_change = True + self.set_val(self._calc()) + self._disable_change = False + + def set_val(self, val): + self.set_edit_text(str(int(val))) + + def get_val(self): + return self._myval + + def set_updlist(self, list): + self._updlist = list + + def keypress(self, size, key): + if key == '+': + self.set_edit_text(str(self.value() + 1)) + elif key == '-': + self.set_edit_text(str(self.value() - 1)) + else: + return super().keypress(size, key) + +class MyIntText(urwid.Text): + def __init__(self, fmt, calc=None): + super().__init__("") + self._fmt = fmt + self._calc = calc + + def recalc(self): + val = self._calc() + super().set_text(self._fmt.format(val)) + +def khz_to_ps(khz): + if khz == 0: + return 0 + else: + return 1.0 / khz * 1000 * 1000 * 1000 + +def khz_to_us(khz): + if khz == 0: + return 0 + else: + return 1.0 / khz * 1000 + +pclk_khz_widget = MyIntEdit(u"pclk (kHz) ") +pclk_ps_widget = MyIntText(fmt="pclk {:.2f} ps", calc = lambda: khz_to_ps(pclk_khz_widget.get_val())) + +pclk_widgets = [pclk_khz_widget, pclk_ps_widget] + +pclk_columns = urwid.LineBox(urwid.Columns(pclk_widgets), title = "Pixel clock") + +# Horizontal widgets + +hdisp_widget = MyIntEdit(u"hdisp ", calc = lambda: hdisp2_widget.get_val()) +hfp_widget = MyIntEdit(u"hfp ", calc = lambda: hss_widget.get_val() - hdisp_widget.get_val()) +hsw_widget = MyIntEdit(u"hsw ", calc = lambda: hse_widget.get_val() - hss_widget.get_val()) +hbp_widget = MyIntEdit(u"hbp ", calc = lambda: htot_widget.get_val() - hse_widget.get_val()) + +hdisp2_widget = MyIntEdit(u"hdisp ", calc = lambda: hdisp_widget.get_val()) +hss_widget = MyIntEdit(u"hss ", + calc = lambda: hdisp_widget.get_val() + hfp_widget.get_val()) +hse_widget = MyIntEdit(u"hse ", + calc = lambda: hdisp_widget.get_val() + hfp_widget.get_val() + hsw_widget.get_val()) +htot_widget = MyIntEdit(u"htot ", + calc = lambda: hdisp_widget.get_val() + hfp_widget.get_val() + hsw_widget.get_val() + hbp_widget.get_val()) + +hwidgets1 = [hdisp_widget, hfp_widget, hsw_widget, hbp_widget] +hwidgets2 = [hdisp2_widget, hss_widget, hse_widget, htot_widget] + +horiz_pile1 = urwid.Pile(hwidgets1) +horiz_pile2 = urwid.Pile(hwidgets2) + +h_columns = urwid.LineBox(urwid.Columns([(15, horiz_pile1), (15, horiz_pile2)]), title = "Horizontal") + +# Vertical columns + +vdisp_widget = MyIntEdit(u"vdisp ", calc = lambda: vdisp2_widget.get_val()) +vfp_widget = MyIntEdit(u"vfp ", calc = lambda: vss_widget.get_val() - vdisp_widget.get_val()) +vsw_widget = MyIntEdit(u"vsw ", calc = lambda: vse_widget.get_val() - vss_widget.get_val()) +vbp_widget = MyIntEdit(u"vbp ", calc = lambda: vtot_widget.get_val() - vse_widget.get_val()) + +vdisp2_widget = MyIntEdit(u"vdisp ", calc = lambda: vdisp_widget.get_val()) +vss_widget = MyIntEdit(u"vss ", + calc = lambda: vdisp_widget.get_val() + vfp_widget.get_val()) +vse_widget = MyIntEdit(u"vse ", + calc = lambda: vdisp_widget.get_val() + vfp_widget.get_val() + vsw_widget.get_val()) +vtot_widget = MyIntEdit(u"vtot ", + calc = lambda: vdisp_widget.get_val() + vfp_widget.get_val() + vsw_widget.get_val() + vbp_widget.get_val()) + +vwidgets1 = [vdisp_widget, vfp_widget, vsw_widget, vbp_widget] +vwidgets2 = [vdisp2_widget, vss_widget, vse_widget, vtot_widget] + +vert_pile1 = urwid.Pile(vwidgets1) +vert_pile2 = urwid.Pile(vwidgets2) + +v_columns = urwid.LineBox(urwid.Columns([(15, vert_pile1), (15, vert_pile2)]), title = "Vertical") + +# Info widgets + +line_us_widget = MyIntText(fmt="line {:.2f} us", + calc = lambda: khz_to_us(pclk_khz_widget.get_val()) * htot_widget.get_val()) +line_khz_widget = MyIntText(fmt="line {:.2f} kHz", + calc = lambda: div_or_zero(pclk_khz_widget.get_val(), htot_widget.get_val())) + +frame_tot_widget = MyIntText(fmt="tot {} pix", + calc = lambda: htot_widget.get_val() * vtot_widget.get_val()) +frame_us_widget = MyIntText(fmt="frame {:.2f} ms", + calc = lambda: khz_to_us(pclk_khz_widget.get_val()) * htot_widget.get_val() * vtot_widget.get_val() / 1000) +frame_khz_widget = MyIntText(fmt="frame {:.2f} Hz", + calc = lambda: div_or_zero(pclk_khz_widget.get_val() * 1000, htot_widget.get_val() * vtot_widget.get_val())) + +info_box = urwid.LineBox(urwid.Pile([line_us_widget, line_khz_widget, urwid.Divider(), frame_tot_widget, frame_us_widget, frame_khz_widget]), title = "Info") + +# Set update lists + +recalc_list = [ pclk_ps_widget, line_us_widget, line_khz_widget, frame_tot_widget, frame_us_widget, frame_khz_widget ] + +hdisp_widget.set_updlist([hdisp2_widget, hss_widget, hse_widget, htot_widget]) +hfp_widget.set_updlist([hss_widget, hse_widget, htot_widget]) +hsw_widget.set_updlist([hse_widget, htot_widget]) +hbp_widget.set_updlist([htot_widget]) +hdisp2_widget.set_updlist([hdisp_widget, hfp_widget]) +hss_widget.set_updlist([hfp_widget, hsw_widget]) +hse_widget.set_updlist([hsw_widget, hbp_widget]) +htot_widget.set_updlist([hbp_widget]) + +vdisp_widget.set_updlist([vdisp2_widget, vss_widget, vse_widget, vtot_widget]) +vfp_widget.set_updlist([vss_widget, vse_widget, vtot_widget]) +vsw_widget.set_updlist([vse_widget, vtot_widget]) +vbp_widget.set_updlist([vtot_widget]) +vdisp2_widget.set_updlist([vdisp_widget, vfp_widget]) +vss_widget.set_updlist([vfp_widget, vsw_widget]) +vse_widget.set_updlist([vsw_widget, vbp_widget]) +vtot_widget.set_updlist([vbp_widget]) + +# Flags + +fb = None + +DRM_MODE_FLAG_PHSYNC = (1<<0) +DRM_MODE_FLAG_NHSYNC = (1<<1) +DRM_MODE_FLAG_PVSYNC = (1<<2) +DRM_MODE_FLAG_NVSYNC = (1<<3) +DRM_MODE_FLAG_INTERLACE = (1<<4) +DRM_MODE_FLAG_DBLCLK = (1<<12) + +def mode_is_ilace(mode): + return (mode.flags & DRM_MODE_FLAG_INTERLACE) != 0 + +def apply_mode(): + global fb + + mode = pykms.Videomode() + mode.clock = pclk_khz_widget.get_val() + + mode.hdisplay = hdisp2_widget.get_val() + mode.hsync_start = hss_widget.get_val() + mode.hsync_end = hse_widget.get_val() + mode.htotal = htot_widget.get_val() + + mode.vdisplay = vdisp2_widget.get_val() + mode.vsync_start = vss_widget.get_val() + mode.vsync_end = vse_widget.get_val() + mode.vtotal = vtot_widget.get_val() + + if ilace_box.state: + mode.flags |= DRM_MODE_FLAG_INTERLACE + + if dblclk_box.state: + mode.flags |= DRM_MODE_FLAG_DBLCLK + + if hsync_pol.state == True: + mode.flags |= DRM_MODE_FLAG_PHSYNC + elif hsync_pol.state == False: + mode.flags |= DRM_MODE_FLAG_NHSYNC + + if vsync_pol.state == True: + mode.flags |= DRM_MODE_FLAG_PVSYNC + elif vsync_pol.state == False: + mode.flags |= DRM_MODE_FLAG_NVSYNC + + fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); + pykms.draw_test_pattern(fb); + + crtc.set_mode(conn, fb, mode) + +def read_mode(mode): + pclk_khz_widget.set_val(mode.clock) + hdisp2_widget.set_val(mode.hdisplay) + hss_widget.set_val(mode.hsync_start) + hse_widget.set_val(mode.hsync_end) + htot_widget.set_val(mode.htotal) + + vdisp2_widget.set_val(mode.vdisplay) + vss_widget.set_val(mode.vsync_start) + vse_widget.set_val(mode.vsync_end) + vtot_widget.set_val(mode.vtotal) + + ilace_box.set_state(mode_is_ilace(mode)) + dblclk_box.set_state((mode.flags & DRM_MODE_FLAG_DBLCLK) != 0) + + sync = 'mixed' + if (mode.flags & DRM_MODE_FLAG_PHSYNC) != 0: + sync = True + elif (mode.flags & DRM_MODE_FLAG_NHSYNC) != 0: + sync = False + hsync_pol.set_state(sync) + + sync = 'mixed' + if (mode.flags & DRM_MODE_FLAG_PVSYNC) != 0: + sync = True + elif (mode.flags & DRM_MODE_FLAG_NVSYNC) != 0: + sync = False + vsync_pol.set_state(sync) + +def apply_press(w): + apply_mode() + +ilace_box = urwid.CheckBox('interlace') +hsync_pol = urwid.CheckBox('hsync positive', has_mixed=True) +vsync_pol = urwid.CheckBox('vsync positive', has_mixed=True) +dblclk_box = urwid.CheckBox('double clock') + +flags_pile = urwid.LineBox(urwid.Pile([ilace_box, hsync_pol, vsync_pol, dblclk_box]), title = "Flags") + +apply_button = urwid.LineBox(urwid.Padding(urwid.Button('apply', on_press=apply_press))) + +# Main + +def mode_press(w, mode): + read_mode(mode) + +def mode_to_str(mode): + return "{}@{}{}".format(mode.name, mode.vrefresh, "i" if mode_is_ilace(mode) else "") + +mode_buttons = [] + +card = pykms.Card() +conn = card.get_first_connected_connector() +crtc = conn.get_current_crtc() +modes = conn.get_modes() +i = 0 +for m in modes: + mode_buttons.append(urwid.Button(mode_to_str(m), on_press=mode_press, user_data=m)) + i += 1 + +modes_pile = urwid.LineBox(urwid.Pile(mode_buttons), title = "Video modes") + +main_pile = urwid.Pile([modes_pile, pclk_columns, urwid.Columns([ h_columns, v_columns ]), info_box, flags_pile, apply_button]) + +main_columns = urwid.Filler(main_pile, valign='top') + +loop = urwid.MainLoop(main_columns, unhandled_input=exit_on_q, handle_mouse=False) + +# select the first mode +mode_press(None, modes[0]) + +loop.run() + +fb = None diff --git a/py/tests/test.py b/py/tests/test.py new file mode 100755 index 0000000..9c23b5b --- /dev/null +++ b/py/tests/test.py @@ -0,0 +1,18 @@ +#!/usr/bin/python3 + +import pykms +from helpers import * + +card = pykms.Card() +res = pykms.ResourceManager(card) +conn = res.reserve_connector() +crtc = res.reserve_crtc(conn) + +mode = conn.get_default_mode() + +fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); +pykms.draw_test_pattern(fb); + +crtc.set_mode(conn, fb, mode) + +input("press enter to exit\n") diff --git a/py/tests/trans-test.py b/py/tests/trans-test.py new file mode 100755 index 0000000..8c1f964 --- /dev/null +++ b/py/tests/trans-test.py @@ -0,0 +1,332 @@ +#!/usr/bin/python3 + +import pykms +from helpers import * +import time + +# This hack makes drm initialize the fbcon, setting up the default connector +card = pykms.Card() +card = 0 + +card = pykms.Card() +res = pykms.ResourceManager(card) +conn = res.reserve_connector() +crtc = res.reserve_crtc(conn) +mode = conn.get_default_mode() + +planes = [] +for p in card.planes: + if p.supports_crtc(crtc) == False: + continue + planes.append(p) + +disable_planes(card) + +w = mode.hdisplay +h = mode.vdisplay + +fbs=[] + +def test_am5_trans_dest(): + fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) + fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) + + fb = fbs[0] + pykms.draw_rect(fb, 0, 0, fb.width, fb.height, purple) + pykms.draw_rect(fb, 100, 100, 100, 200, green) + pykms.draw_rect(fb, 300, 100, 100, 200, red) + pykms.draw_rect(fb, 500, 100, 100, 200, white) + + fb = fbs[1] + pykms.draw_rect(fb, 0, 0, fb.width, fb.height, cyan) + pykms.draw_rect(fb, 250, 100, 200, 200, yellow) + + set_props(crtc, { + "trans-key-mode": 1, + "trans-key": purple.rgb888, + "background": 0, + "alpha_blender": 0, + }) + + plane = 0 + + for i in range(0,2): + print("set crtc {}, plane {}, fb {}".format(crtc.id, planes[i].id, fbs[i].id)) + + plane = planes[i] + fb = fbs[i] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_W": fb.width, + "CRTC_H": fb.height, + "zorder": i, + }) + + time.sleep(1) + +def test_am5_trans_src(): + fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) + fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) + + fb = fbs[0] + pykms.draw_rect(fb, 0, 0, fb.width, fb.height, white) + pykms.draw_rect(fb, 200, 200, 100, 100, red) + pykms.draw_rect(fb, fb.width - 300, 200, 100, 100, green) + + fb = fbs[1] + pykms.draw_rect(fb, 0, 0, fb.width, fb.height, cyan) + pykms.draw_rect(fb, 100, 100, 500, 500, purple) + + set_props(crtc, { + "trans-key-mode": 2, + "trans-key": purple.rgb888, + "background": 0, + "alpha_blender": 0, + }) + + plane = 0 + + for i in range(0,2): + print("set crtc {}, plane {}, fb {}".format(crtc.id, planes[i].id, fbs[i].id)) + + plane = planes[i] + fb = fbs[i] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_W": fb.width, + "CRTC_H": fb.height, + "zorder": 3 if i == 1 else 0, + }) + + time.sleep(1) + +def test_am4_normal_trans_dst(): + fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) + fbs.append(pykms.DumbFramebuffer(card, w * 2 // 3, h, "XR24")) + fbs.append(pykms.DumbFramebuffer(card, w * 2 // 3, h, "XR24")) + + fb = fbs[0] + pykms.draw_rect(fb, 0, 0, w, h, purple) + pykms.draw_rect(fb, 100, 50, 50, 200, green) + pykms.draw_rect(fb, 200, 50, 50, 200, red) + pykms.draw_rect(fb, 300, 50, 50, 200, white) + + fb = fbs[1] + pykms.draw_rect(fb, 0, 0, fb.width, fb.height, blue) + + fb = fbs[2] + pykms.draw_rect(fb, 0, 0, fb.width, fb.height, cyan) + + set_props(crtc, { + "trans-key-mode": 1, + "trans-key": purple.rgb888, + "background": 0, + "alpha_blender": 0, + }) + + time.sleep(1) + + plane = planes[0] + fb = fbs[0] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_W": w, + "CRTC_H": h, + }) + + time.sleep(1) + + plane = planes[1] + fb = fbs[1] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_X": 0 << 16, + "SRC_Y": 0 << 16, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_X": 0, + "CRTC_Y": 0, + "CRTC_W": fb.width, + "CRTC_H": fb.height, + }) + + time.sleep(1) + + plane = planes[2] + fb = fbs[2] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_X": 0 << 16, + "SRC_Y": 0 << 16, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_X": w // 3, + "CRTC_Y": 0, + "CRTC_W": fb.width, + "CRTC_H": fb.height, + }) + +def test_am4_normal_trans_src(): + fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) + fbs.append(pykms.DumbFramebuffer(card, w // 2, h, "XR24")) + fbs.append(pykms.DumbFramebuffer(card, w // 2, h, "XR24")) + + fb = fbs[0] + pykms.draw_rect(fb, 0, 0, w, h, pykms.RGB(128, 255, 255)) + pykms.draw_rect(fb, 200, 100, 50, 200, red) + pykms.draw_rect(fb, w - 200 - 50, 100, 50, 200, green) + + fb = fbs[1] + pykms.draw_rect(fb, 0, 0, fb.width, fb.height, blue) + pykms.draw_rect(fb, 100, 100, fb.width - 200, fb.height - 200, purple) + + fb = fbs[2] + pykms.draw_rect(fb, 0, 0, fb.width, fb.height, cyan) + pykms.draw_rect(fb, 100, 100, fb.width - 200, fb.height - 200, purple) + + set_props(crtc, { + "trans-key-mode": 2, + "trans-key": purple.rgb888, + "background": 0, + "alpha_blender": 0, + }) + + time.sleep(1) + + plane = planes[0] + fb = fbs[0] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_W": w, + "CRTC_H": h, + }) + + time.sleep(1) + + plane = planes[1] + fb = fbs[1] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_X": 0 << 16, + "SRC_Y": 0 << 16, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_X": 0, + "CRTC_Y": 0, + "CRTC_W": fb.width, + "CRTC_H": fb.height, + }) + + time.sleep(1) + + plane = planes[2] + fb = fbs[2] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_X": 0 << 16, + "SRC_Y": 0 << 16, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_X": w - fb.width, + "CRTC_Y": 0, + "CRTC_W": fb.width, + "CRTC_H": fb.height, + }) + +def test_am4_alpha_trans_src(): + fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) + fbs.append(pykms.DumbFramebuffer(card, w // 2, h, "XR24")) + fbs.append(pykms.DumbFramebuffer(card, w // 2, h, "XR24")) + + fb = fbs[0] + pykms.draw_rect(fb, 0, 0, w, h, purple) + pykms.draw_rect(fb, 200, 100, 50, 200, red) + pykms.draw_rect(fb, w - 200 - 50, 100, 50, 200, green) + + fb = fbs[1] + pykms.draw_rect(fb, 0, 0, fb.width, fb.height, blue) + pykms.draw_rect(fb, 100, 100, fb.width - 200, fb.height - 200, purple) + + fb = fbs[2] + pykms.draw_rect(fb, 0, 0, fb.width, fb.height, cyan) + pykms.draw_rect(fb, 100, 100, fb.width - 200, fb.height - 200, purple) + + set_props(crtc, { + "trans-key-mode": 1, + "trans-key": purple.rgb888, + "background": 0, + "alpha_blender": 1, + }) + + time.sleep(1) + + plane = planes[0] + fb = fbs[0] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_W": w, + "CRTC_H": h, + }) + + time.sleep(1) + + plane = planes[1] + fb = fbs[1] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_X": 0 << 16, + "SRC_Y": 0 << 16, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_X": 0, + "CRTC_Y": 0, + "CRTC_W": fb.width, + "CRTC_H": fb.height, + }) + + time.sleep(1) + + plane = planes[2] + fb = fbs[2] + set_props(plane, { + "FB_ID": fb.id, + "CRTC_ID": crtc.id, + "SRC_X": 0 << 16, + "SRC_Y": 0 << 16, + "SRC_W": fb.width << 16, + "SRC_H": fb.height << 16, + "CRTC_X": w - fb.width, + "CRTC_Y": 0, + "CRTC_W": fb.width, + "CRTC_H": fb.height, + }) + + + +#test_am5_trans_dest() +test_am5_trans_src() +#test_am4_normal_trans_dst() +#test_am4_normal_trans_src() +#test_am4_alpha_trans_src() + +input("press enter to exit\n") diff --git a/py/trans-test.py b/py/trans-test.py deleted file mode 100755 index 8c1f964..0000000 --- a/py/trans-test.py +++ /dev/null @@ -1,332 +0,0 @@ -#!/usr/bin/python3 - -import pykms -from helpers import * -import time - -# This hack makes drm initialize the fbcon, setting up the default connector -card = pykms.Card() -card = 0 - -card = pykms.Card() -res = pykms.ResourceManager(card) -conn = res.reserve_connector() -crtc = res.reserve_crtc(conn) -mode = conn.get_default_mode() - -planes = [] -for p in card.planes: - if p.supports_crtc(crtc) == False: - continue - planes.append(p) - -disable_planes(card) - -w = mode.hdisplay -h = mode.vdisplay - -fbs=[] - -def test_am5_trans_dest(): - fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) - fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) - - fb = fbs[0] - pykms.draw_rect(fb, 0, 0, fb.width, fb.height, purple) - pykms.draw_rect(fb, 100, 100, 100, 200, green) - pykms.draw_rect(fb, 300, 100, 100, 200, red) - pykms.draw_rect(fb, 500, 100, 100, 200, white) - - fb = fbs[1] - pykms.draw_rect(fb, 0, 0, fb.width, fb.height, cyan) - pykms.draw_rect(fb, 250, 100, 200, 200, yellow) - - set_props(crtc, { - "trans-key-mode": 1, - "trans-key": purple.rgb888, - "background": 0, - "alpha_blender": 0, - }) - - plane = 0 - - for i in range(0,2): - print("set crtc {}, plane {}, fb {}".format(crtc.id, planes[i].id, fbs[i].id)) - - plane = planes[i] - fb = fbs[i] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_W": fb.width, - "CRTC_H": fb.height, - "zorder": i, - }) - - time.sleep(1) - -def test_am5_trans_src(): - fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) - fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) - - fb = fbs[0] - pykms.draw_rect(fb, 0, 0, fb.width, fb.height, white) - pykms.draw_rect(fb, 200, 200, 100, 100, red) - pykms.draw_rect(fb, fb.width - 300, 200, 100, 100, green) - - fb = fbs[1] - pykms.draw_rect(fb, 0, 0, fb.width, fb.height, cyan) - pykms.draw_rect(fb, 100, 100, 500, 500, purple) - - set_props(crtc, { - "trans-key-mode": 2, - "trans-key": purple.rgb888, - "background": 0, - "alpha_blender": 0, - }) - - plane = 0 - - for i in range(0,2): - print("set crtc {}, plane {}, fb {}".format(crtc.id, planes[i].id, fbs[i].id)) - - plane = planes[i] - fb = fbs[i] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_W": fb.width, - "CRTC_H": fb.height, - "zorder": 3 if i == 1 else 0, - }) - - time.sleep(1) - -def test_am4_normal_trans_dst(): - fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) - fbs.append(pykms.DumbFramebuffer(card, w * 2 // 3, h, "XR24")) - fbs.append(pykms.DumbFramebuffer(card, w * 2 // 3, h, "XR24")) - - fb = fbs[0] - pykms.draw_rect(fb, 0, 0, w, h, purple) - pykms.draw_rect(fb, 100, 50, 50, 200, green) - pykms.draw_rect(fb, 200, 50, 50, 200, red) - pykms.draw_rect(fb, 300, 50, 50, 200, white) - - fb = fbs[1] - pykms.draw_rect(fb, 0, 0, fb.width, fb.height, blue) - - fb = fbs[2] - pykms.draw_rect(fb, 0, 0, fb.width, fb.height, cyan) - - set_props(crtc, { - "trans-key-mode": 1, - "trans-key": purple.rgb888, - "background": 0, - "alpha_blender": 0, - }) - - time.sleep(1) - - plane = planes[0] - fb = fbs[0] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_W": w, - "CRTC_H": h, - }) - - time.sleep(1) - - plane = planes[1] - fb = fbs[1] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_X": 0 << 16, - "SRC_Y": 0 << 16, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_X": 0, - "CRTC_Y": 0, - "CRTC_W": fb.width, - "CRTC_H": fb.height, - }) - - time.sleep(1) - - plane = planes[2] - fb = fbs[2] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_X": 0 << 16, - "SRC_Y": 0 << 16, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_X": w // 3, - "CRTC_Y": 0, - "CRTC_W": fb.width, - "CRTC_H": fb.height, - }) - -def test_am4_normal_trans_src(): - fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) - fbs.append(pykms.DumbFramebuffer(card, w // 2, h, "XR24")) - fbs.append(pykms.DumbFramebuffer(card, w // 2, h, "XR24")) - - fb = fbs[0] - pykms.draw_rect(fb, 0, 0, w, h, pykms.RGB(128, 255, 255)) - pykms.draw_rect(fb, 200, 100, 50, 200, red) - pykms.draw_rect(fb, w - 200 - 50, 100, 50, 200, green) - - fb = fbs[1] - pykms.draw_rect(fb, 0, 0, fb.width, fb.height, blue) - pykms.draw_rect(fb, 100, 100, fb.width - 200, fb.height - 200, purple) - - fb = fbs[2] - pykms.draw_rect(fb, 0, 0, fb.width, fb.height, cyan) - pykms.draw_rect(fb, 100, 100, fb.width - 200, fb.height - 200, purple) - - set_props(crtc, { - "trans-key-mode": 2, - "trans-key": purple.rgb888, - "background": 0, - "alpha_blender": 0, - }) - - time.sleep(1) - - plane = planes[0] - fb = fbs[0] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_W": w, - "CRTC_H": h, - }) - - time.sleep(1) - - plane = planes[1] - fb = fbs[1] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_X": 0 << 16, - "SRC_Y": 0 << 16, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_X": 0, - "CRTC_Y": 0, - "CRTC_W": fb.width, - "CRTC_H": fb.height, - }) - - time.sleep(1) - - plane = planes[2] - fb = fbs[2] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_X": 0 << 16, - "SRC_Y": 0 << 16, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_X": w - fb.width, - "CRTC_Y": 0, - "CRTC_W": fb.width, - "CRTC_H": fb.height, - }) - -def test_am4_alpha_trans_src(): - fbs.append(pykms.DumbFramebuffer(card, w, h, "XR24")) - fbs.append(pykms.DumbFramebuffer(card, w // 2, h, "XR24")) - fbs.append(pykms.DumbFramebuffer(card, w // 2, h, "XR24")) - - fb = fbs[0] - pykms.draw_rect(fb, 0, 0, w, h, purple) - pykms.draw_rect(fb, 200, 100, 50, 200, red) - pykms.draw_rect(fb, w - 200 - 50, 100, 50, 200, green) - - fb = fbs[1] - pykms.draw_rect(fb, 0, 0, fb.width, fb.height, blue) - pykms.draw_rect(fb, 100, 100, fb.width - 200, fb.height - 200, purple) - - fb = fbs[2] - pykms.draw_rect(fb, 0, 0, fb.width, fb.height, cyan) - pykms.draw_rect(fb, 100, 100, fb.width - 200, fb.height - 200, purple) - - set_props(crtc, { - "trans-key-mode": 1, - "trans-key": purple.rgb888, - "background": 0, - "alpha_blender": 1, - }) - - time.sleep(1) - - plane = planes[0] - fb = fbs[0] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_W": w, - "CRTC_H": h, - }) - - time.sleep(1) - - plane = planes[1] - fb = fbs[1] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_X": 0 << 16, - "SRC_Y": 0 << 16, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_X": 0, - "CRTC_Y": 0, - "CRTC_W": fb.width, - "CRTC_H": fb.height, - }) - - time.sleep(1) - - plane = planes[2] - fb = fbs[2] - set_props(plane, { - "FB_ID": fb.id, - "CRTC_ID": crtc.id, - "SRC_X": 0 << 16, - "SRC_Y": 0 << 16, - "SRC_W": fb.width << 16, - "SRC_H": fb.height << 16, - "CRTC_X": w - fb.width, - "CRTC_Y": 0, - "CRTC_W": fb.width, - "CRTC_H": fb.height, - }) - - - -#test_am5_trans_dest() -test_am5_trans_src() -#test_am4_normal_trans_dst() -#test_am4_normal_trans_src() -#test_am4_alpha_trans_src() - -input("press enter to exit\n") -- cgit v1.2.3