summaryrefslogtreecommitdiff
path: root/tests/kms-test-pageflip.py
blob: 1bb1214080ffc7b3c7bd221a0e91c778617a86b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0-or-later
# SPDX-FileCopyrightText: 2017-2019 Renesas Electronics Corporation

import kmstest
import pykms

class PageFlipTest(kmstest.KMSTest):
    """Test page flipping on all connectors in sequence with the default mode."""

    BAR_WIDTH = 20
    BAR_SPEED = 8

    def handle_page_flip(self, frame, time):
        if self.flips == 1:
            self.logger.log(f'first page flip frame {frame} time {time}')
            self.frame_start = frame
            self.time_start = time

        if self.stop_requested:
            self.logger.log(f'last page flip frame {frame} time {time}')
            self.frame_end = frame
            self.time_end = time
            self.loop.stop()
            self.stop_requested = False
            return

        fb = self.fbs[self.front_buf]
        self.front_buf = self.front_buf ^ 1

        old_xpos = (self.bar_xpos - self.BAR_SPEED) % (fb.width - self.BAR_WIDTH);
        new_xpos = (self.bar_xpos + self.BAR_SPEED) % (fb.width - self.BAR_WIDTH);
        self.bar_xpos = new_xpos

        pykms.draw_color_bar(fb, old_xpos, new_xpos, self.BAR_WIDTH)

        source = kmstest.Rect(0, 0, fb.width, fb.height)
        destination = kmstest.Rect(0, 0, fb.width, fb.height)
        self.atomic_plane_set(self.plane, self.crtc, source, destination, fb)

    def stop_page_flip(self):
        self.stop_requested = True

    def main(self):
        for connector in self.output_connectors():
            self.start(f'page flip on connector {connector.fullname}')

            # Skip disconnected connectors
            if not connector.connected():
                self.skip('unconnected connector')
                continue

            # Find a CRTC suitable for the connector
            crtc = connector.get_current_crtc()
            if not crtc:
                crtcs = connector.get_possible_crtcs()
                if len(crtcs) == 0:
                    pass

                crtc = crtcs[0]

            self.crtc = crtc

            # Find a plane suitable for the CRTC
            for plane in self.card.planes:
                if plane.supports_crtc(crtc):
                    self.plane = plane
                    break
            else:
                self.skip(f'no plane available for CRTC {crtc.id}')
                continue

            # Get the default mode for the connector
            try:
                mode = connector.get_default_mode()
            except ValueError:
                self.skip('no mode available')
                continue

            self.logger.log(f'Testing connector {connector.fullname}, CRTC {crtc.id}, '
                            f'plane {self.plane.id}, mode {mode.name}')

            # Create two frame buffers
            self.fbs = []
            for i in range(2):
                self.fbs.append(pykms.DumbFramebuffer(self.card, mode.hdisplay, mode.vdisplay, 'XR24'))

            # Set the mode and perform the initial page flip
            ret = self.atomic_crtc_mode_set(crtc, connector, mode, self.fbs[0])
            if ret < 0:
                self.fail(f'atomic mode set failed with {ret}')
                continue

            # Flip pages for 10s
            self.bar_xpos = 0
            self.front_buf = 0
            self.frame_start = 0
            self.frame_end = 0
            self.time_start = 0
            self.time_end = 0
            self.stop_requested = False

            self.loop.add_timer(10, self.stop_page_flip)
            self.run(11)
            self.atomic_crtc_disable(crtc)

            if not self.flips:
                self.fail('No page flip registered')
                continue

            if self.stop_requested:
                self.fail('Last page flip not registered')
                continue

            frames = self.frame_end - self.frame_start + 1
            interval = self.time_end - self.time_start
            self.logger.log(f'Frame rate: {frames / interval} '
                            f'({self.flips}/{frames} frames in {interval} s)')
            self.success()


if __name__ == '__main__':
    PageFlipTest().execute()