summaryrefslogtreecommitdiff
path: root/tests/kms-test-crc.py
blob: 8876c88506c1624cceea7e5b12e667376c0d46bb (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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0-or-later
# SPDX-FileCopyrightText: 2017-2019 Renesas Electronics Corporation

import copy
import kmstest
import pykms


class Composer(object):
    # Manage the composition of planes on the screen by computing the source
    # and destination rectangles of each plane.
    #
    # Stack the plane, starting at START_POINT, with a fixed INCREMENT.
    #

    START_POINT = kmstest.Point(0, 0)
    INCREMENT = kmstest.Dist(50, 50)

    def __init__(self, crtc, planes, fb):
        self.__fb_size = kmstest.Size(fb.width, fb.height)
        self.__planes_positions = {}

        position = copy.copy(Composer.START_POINT)
        for plane in planes:
            self.__planes_positions[plane] = copy.copy(position)
            position.move(Composer.INCREMENT)

    def source(self, plane):
        pos = self.__planes_positions[plane]
        return kmstest.Rect(0, 0,
                            max(0, self.__fb_size.width - pos.x),
                            max(0, self.__fb_size.height - pos.y))

    def destination(self, plane):
        pos = self.__planes_positions[plane]
        return kmstest.Rect(pos.x, pos.y,
                            max(0, self.__fb_size.width - pos.x),
                            max(0, self.__fb_size.height - pos.y))


class CRCTest(kmstest.KMSTest):
    """Test CRC calculation on pipeline output."""

    def handle_page_flip(self, frame, time):
        self.logger.log("Page flip complete")

    def main(self):
        # Create the connectors to CRTCs map
        connectors = {}
        for connector in self.output_connectors():
            # Skip disconnected connectors
            if not connector.connected():
                continue

            # Add the connector to the map
            for crtc in connector.get_possible_crtcs():
                if crtc not in connectors:
                    connectors[crtc] = connector

        for crtc in self.card.crtcs:
            self.start("CRC calculation on CRTC %u" % crtc.id)

            # Get the connector and default mode
            try:
                connector = connectors[crtc];
                mode = connector.get_default_mode()
            except KeyError:
                self.skip("no connector or mode available")
                continue

            # List planes available for the CRTC
            planes = []
            for plane in self.card.planes:
                if plane.supports_crtc(crtc):
                    planes.append(plane)

            if len(planes) == 0:
                self.skip("no plane available for CRTC")
                continue

            self.logger.log("Testing connector %s, CRTC %u, mode %s with %u planes" % \
                  (connector.fullname, crtc.id, mode.name, len(planes)))

            # Create a frame buffer and draw a test pattern.
            fb = pykms.DumbFramebuffer(self.card, mode.hdisplay, mode.vdisplay, "XR24")
            pykms.draw_test_pattern(fb)

            # Create a composer.
            composer = Composer(crtc, planes, fb)

            # Set the mode and add all planes
            ret = self.atomic_crtc_mode_set(crtc, connector, mode, sync=True)
            if ret < 0:
                self.fail("atomic mode set failed with %d" % ret)
                continue

            req = kmstest.AtomicRequest(self)

            for plane in planes:
                source = composer.source(plane)
                destination = composer.destination(plane)
                req.add(plane, {
                        'FB_ID': fb.id,
                        'CRTC_ID': crtc.id,
                        'SRC_X': int(source.left * 65536),
                        'SRC_Y': int(source.top * 65536),
                        'SRC_W': int(source.width * 65536),
                        'SRC_H': int(source.height * 65536),
                        'CRTC_X': destination.left,
                        'CRTC_Y': destination.top,
                        'CRTC_W': destination.width,
                        'CRTC_H': destination.height,
                })

            ret = req.commit(0)
            if ret < 0:
                self.fail("atomic plane set failed with %d" % ret)
                continue

            # Wait for one second and make sure the page flip has completed.
            self.run(1)
            if self.flips == 0:
                self.fail("No page flip registered")
                continue

            sources = ["auto"] + ["plane%u" % plane.id for plane in planes]
            for src in sources:
                self.logger.log("Computing CRC in source %s" % src)

                crc_reader = kmstest.CRCReader(crtc)
                crc_reader.start(src)
                crcs = crc_reader.read(10)
                crc_reader.stop()

                crcs = [c.crcs[0] for c in crcs]
                if len(set(crcs)) != 1:
                    self.fail("CRC values not constant on source %s" % src)
                    break

                self.logger.log("CRC value 0x%08x" % crcs[0])
            else:
                self.success()

            self.atomic_crtc_disable(crtc)

CRCTest().execute()