#!/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()