summaryrefslogtreecommitdiff
path: root/py/tests
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2017-01-02 16:42:08 +0200
committerTomi Valkeinen <tomi.valkeinen@ti.com>2017-01-03 10:46:42 +0200
commitb11baff09f78a4a383f817ec35208ae8966ab832 (patch)
tree610e89719c4a3d9714a472cdc6681e36df419a1b /py/tests
parentc6f964425cdec25e3d0ecd0054d398d3420fdfeb (diff)
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 <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'py/tests')
-rw-r--r--py/tests/CMakeLists.txt7
-rwxr-xr-xpy/tests/alpha-test.py67
-rwxr-xr-xpy/tests/cam.py78
-rwxr-xr-xpy/tests/db.py72
-rwxr-xr-xpy/tests/functest.py19
-rwxr-xr-xpy/tests/gamma.py41
-rw-r--r--py/tests/helpers.py54
-rwxr-xr-xpy/tests/iact.py43
-rwxr-xr-xpy/tests/kmsmodeview.py317
-rwxr-xr-xpy/tests/test.py18
-rwxr-xr-xpy/tests/trans-test.py332
11 files changed, 1048 insertions, 0 deletions
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")