py: drop the fancy event handling
[android/external-libkmsxx.git] / py / tests / big_fb.py
1 #!/usr/bin/python3
3 import pykms
4 import random
5 import time
6 import sys
7 import select
8 import argparse
9 import selectors
11 black = pykms.RGB(0, 0, 0)
13 parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
14 parser.add_argument('--flipmode', choices=['single', 'separate'], default='single', required=False,
15     help="""Page flip method to use:
16     single: Page flip on all displays with one request (default)
17     separate: Separate page flip on the displays""")
19 args = parser.parse_args()
21 card = pykms.Card()
23 if not card.has_atomic:
24     print('Atomic mode settings is not supported :(')
25     sys.exit()
27 if args.flipmode == 'single':
28     print('Page flip on all displays with one request')
29 elif args.flipmode == 'separate':
30     print('Page flip on all displays with separate requests')
32 res = pykms.ResourceManager(card)
34 conn_list = []
35 crtc_list = []
36 mode_list = []
37 plane_list = []
38 big_fb_list = []
40 for conn in card.connectors:
41     if conn.connected() == 1:
42         conn_list.append(conn)
44 print('Have {} connected connectors:'.format(len(conn_list)))
45 for conn in conn_list:
46     crtc = res.reserve_crtc(conn)
47     crtc_list.append(crtc)
49     mode = conn.get_default_mode()
50     mode_list.append(mode)
52     print(' {}: {} ({}x{})'.format(conn.idx, conn.fullname,
53         mode.hdisplay, mode.vdisplay))
55 fbX = sum(mode.hdisplay for mode in mode_list)
56 fbY = max(mode.vdisplay for mode in mode_list)
58 print('FB Resolution: {}x{}\n'.format(fbX, fbY))
60 # Create the (big)framebuffer(s)
61 for x in range(2):
62     fb_tmp = pykms.DumbFramebuffer(card, fbX, fbY, 'XR24');
63     big_fb_list.append(fb_tmp)
65 fb = big_fb_list[0]
66 screen_offset = 0
68 card.disable_planes()
69 for i in range(0, len(conn_list)):
70     conn = conn_list[i]
71     crtc = crtc_list[i]
72     mode = mode_list[i]
74     plane = res.reserve_generic_plane(crtc)
75     plane_list.append(plane)
77     modeb = mode.to_blob(card)
78     req = pykms.AtomicReq(card)
79     req.add(conn, 'CRTC_ID', crtc.id)
80     req.add(crtc, {'ACTIVE': 1,
81                     'MODE_ID': modeb.id})
82     req.add(plane, {'FB_ID': fb.id,
83                     'CRTC_ID': crtc.id,
84                     'SRC_X': screen_offset << 16,
85                     'SRC_Y': 0 << 16,
86                     'SRC_W': mode.hdisplay << 16,
87                     'SRC_H': mode.vdisplay << 16,
88                     'CRTC_X': 0,
89                     'CRTC_Y': 0,
90                     'CRTC_W': mode.hdisplay,
91                     'CRTC_H': mode.vdisplay,
92                     'zorder': 0})
94     req.commit_sync(allow_modeset = True)
96     screen_offset += mode.hdisplay
98 # Double buffering, page flipping
99 class bigFB_db:
100     def __init__(self, fb1, fb2):
101         self.speed_y = random.randrange(1, 10, 1)
102         self.dir_y = random.randrange(-1, 3, 2)
103         self.first_run = True
104         self.fbs = [fb1,fb2]
105         self.draw_buf = 0
106         self.fbX = fb1.width
107         self.fbY = fb1.height
108         self.pos_y = self.fbY // 2
109         self.old_pos_y = -1
110         # 5 + 10 + 15 + 10 + 5 = 45
111         self.bar_size = 45
112         self.flips = 0
113         self.frames = 0
114         self.time = 0
115         self.flip_count = 100
117     def new_color(self):
118         r = random.randrange(255)
119         g = random.randrange(255)
120         b = random.randrange(255)
121         self.color = pykms.RGB(r, g, b)
122         self.color2 = pykms.RGB(r // 2, g // 2, b // 2)
123         self.color3 = pykms.RGB(r // 3, g // 3, b // 3)
124     def move_stripe(self):
125         if self.first_run:
126             self.new_color()
127             self.first_run = False
129         fb = self.fbs[self.draw_buf]
131         old_box_y = self.old_pos_y
132         self.old_pos_y = self.pos_y
133         change_speed = 0
135         self.pos_y = int(self.pos_y + (self.dir_y * self.speed_y))
137         if self.pos_y < 0:
138             self.pos_y = 0
139             change_speed = 1
140             self.dir_y = 1
141         elif self.pos_y > (self.fbY - self.bar_size):
142             self.pos_y = self.fbY - self.bar_size
143             change_speed = 1
144             self.dir_y = -1
146         if change_speed == 1:
147             self.new_color()
148             self.speed_y = random.randrange(1, 10, 1)
150         # Erease the old box
151         if old_box_y >= 0:
152             pykms.draw_rect(fb, 0, old_box_y, self.fbX, self.bar_size, black)
154         pos_y = self.pos_y
155         pykms.draw_rect(fb, 0, pos_y, self.fbX, 5, self.color3)
156         pos_y += 5
157         pykms.draw_rect(fb, 0, pos_y, self.fbX, 10, self.color2)
158         pos_y += 10
159         pykms.draw_rect(fb, 0, pos_y, self.fbX, 15, self.color)
160         pos_y += 15
161         pykms.draw_rect(fb, 0, pos_y, self.fbX, 10, self.color2)
162         pos_y += 10
163         pykms.draw_rect(fb, 0, pos_y, self.fbX, 5, self.color3)
165     def handle_page_flip_single(self):
166         self.draw_buf ^= 1
167         self.move_stripe()
169         # one atomic request to flip on all displays/crtcs
170         fb = self.fbs[self.draw_buf]
171         screen_offset = 0
173         req = pykms.AtomicReq(card)
174         for i in range(0, len(conn_list)):
175             crtc = crtc_list[i]
176             mode = mode_list[i]
178             plane = plane_list[i]
180             req.add(plane, {'FB_ID': fb.id,
181                             'CRTC_ID': crtc.id,
182                             'SRC_X': screen_offset << 16,
183                             'SRC_Y': 0 << 16,
184                             'SRC_W': mode.hdisplay << 16,
185                             'SRC_H': mode.vdisplay << 16,
186                             'CRTC_X': 0,
187                             'CRTC_Y': 0,
188                             'CRTC_W': mode.hdisplay,
189                             'CRTC_H': mode.vdisplay,
190                             'zorder': 0})
192             screen_offset += mode.hdisplay
194         req.commit(0)
196     def handle_page_flip_separate(self):
197         self.draw_buf ^= 1
198         self.move_stripe()
200         # ask to flip the first screen
201         fb = self.fbs[self.draw_buf]
202         screen_offset = 0
204         # add separate atomic request for each display (crtc)
205         for i in range(0, len(conn_list)):
206             req = pykms.AtomicReq(card)
207             crtc = crtc_list[i]
208             mode = mode_list[i]
210             plane = plane_list[i]
212             req.add(plane, {'FB_ID': fb.id,
213                             'CRTC_ID': crtc.id,
214                             'SRC_X': screen_offset << 16,
215                             'SRC_Y': 0 << 16,
216                             'SRC_W': mode.hdisplay << 16,
217                             'SRC_H': mode.vdisplay << 16,
218                             'CRTC_X': 0,
219                             'CRTC_Y': 0,
220                             'CRTC_W': mode.hdisplay,
221                             'CRTC_H': mode.vdisplay,
222                             'zorder': 0})
224             screen_offset += mode.hdisplay
226             req.commit(0)
228     def handle_page_flip_main(self, frame, time):
229         self.flip_count += 1
231         if self.flip_count < len(conn_list):
232             return
234         self.flip_count = 0
236         # statistics
237         self.flips += 1
238         if self.time == 0:
239             self.frames = frame
240             self.time = time
242         time_delta = time - self.time
243         if time_delta >= 5:
244             frame_delta = frame - self.frames
245             print('Frame rate: %f (%u/%u frames in %f s)' %
246                   (frame_delta / time_delta, self.flips, frame_delta, time_delta))
248             self.flips = 0
249             self.frames = frame
250             self.time = time
252         if args.flipmode == 'single':
253             self.handle_page_flip_single()
254         elif args.flipmode == 'separate':
255             self.handle_page_flip_separate()
257 print('Press ENTER to exit\n')
259 box_db = bigFB_db(big_fb_list[0], big_fb_list[1])
260 box_db.handle_page_flip_main(0, 0)
262 def readdrm(fileobj, mask):
263     for ev in card.read_events():
264         if ev.type == pykms.DrmEventType.FLIP_COMPLETE:
265             box_db.handle_page_flip_main(ev.seq, ev.time)
267 def readkey(fileobj, mask):
268     sys.stdin.readline()
269     exit(0)
271 sel = selectors.DefaultSelector()
272 sel.register(card.fd, selectors.EVENT_READ, readdrm)
273 sel.register(sys.stdin, selectors.EVENT_READ, readkey)
275 while True:
276     events = sel.select()
277     for key, mask in events:
278         callback = key.data
279         callback(key.fileobj, mask)