[igt-dev] [PATCH i-g-t] [RFC] add a kms_fb_stride test

Martin Peres martin.peres at free.fr
Sun Feb 4 13:10:38 UTC 2018


From: Martin Peres <martin.peres at linux.intel.com>

This test checks what strides are actually supported by each plane of
each pipe. The tested strides are 4K, 8K, 16K and 32K.

To verify that the display controler is OK with the stride, the test
uses the pipe crc and verifies that a test image blitted to a
hdisplay x vdisplay framebuffer appears the same when blitted to a
stride x vdisplay framebuffer (with stride varying from 4K to 32K).

Current limitations that will be addressed in a later revision:
 - When a stride is not supported by the kernel, we get a fail rather
   than a skip.
 - If the stride is smaller than the current width of the current mode,
   the test will fail because the image will be truncated. Instead,
   we should skip or modeset to a resolution lower than the stride
   we want to test.

Any thoughts?
---
 tests/Makefile.sources |   1 +
 tests/kms_fb_stride.c  | 189 +++++++++++++++++++++++++++++++++++++++++++++++++
 tests/meson.build      |   1 +
 3 files changed, 191 insertions(+)
 create mode 100644 tests/kms_fb_stride.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index e4e06d01..4c533497 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -181,6 +181,7 @@ TESTS_progs = \
 	kms_cursor_legacy \
 	kms_draw_crc \
 	kms_fbcon_fbt \
+	kms_fb_stride \
 	kms_fence_pin_leak \
 	kms_flip \
 	kms_flip_event_leak \
diff --git a/tests/kms_fb_stride.c b/tests/kms_fb_stride.c
new file mode 100644
index 00000000..8fa66bb7
--- /dev/null
+++ b/tests/kms_fb_stride.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright © 2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Martin Peres <martin.peres at linux.intel.com>
+ */
+
+#include "igt.h"
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+typedef struct {
+	int drm_fd;
+	igt_display_t display;
+	igt_pipe_crc_t *pipe_crc;
+} data_t;
+
+typedef enum {
+	TEST_STRIDE_4K = 4,
+	TEST_STRIDE_8K = 8,
+	TEST_STRIDE_16K = 16,
+	TEST_STRIDE_32K = 32,
+} stride_t;
+
+static bool can_draw(uint32_t drm_format)
+{
+	const uint32_t *drm_formats;
+	int format_count, i;
+
+	igt_get_all_cairo_formats(&drm_formats, &format_count);
+
+	for (i = 0; i < format_count; i++)
+		if (drm_formats[i] == drm_format)
+			return true;
+
+	return false;
+}
+
+static void test_format_plane_get_crc(data_t *data, igt_output_t *output, uint32_t format,
+				      igt_plane_t *plane, unsigned int stride,
+				      igt_crc_t *crc /* out */) {
+	drmModeModeInfo *mode;
+	struct igt_fb fb;
+	cairo_t *cr;
+
+	mode = igt_output_get_mode(output);
+
+	if (stride == 0)
+		stride = mode->hdisplay;
+
+	igt_create_fb(data->drm_fd, stride, mode->vdisplay,
+		      format, LOCAL_DRM_FORMAT_MOD_NONE, &fb);
+
+	cr = igt_get_cairo_ctx(data->drm_fd, &fb);
+	igt_paint_test_pattern(cr, mode->hdisplay, mode->vdisplay);
+	igt_assert(cairo_status(cr) == 0);
+	cairo_destroy(cr);
+
+	/* TODO: Do not fail if the stride is not supported, just skip! */
+	igt_plane_set_fb(plane, &fb);
+	igt_display_commit2(&data->display, COMMIT_UNIVERSAL);
+
+	igt_pipe_crc_collect_crc(data->pipe_crc, crc);
+
+	igt_plane_set_fb(plane, NULL);
+	igt_display_commit2(&data->display, COMMIT_UNIVERSAL);
+
+	igt_remove_fb(data->drm_fd, &fb);
+}
+
+static void test_format_plane(data_t *data, enum pipe pipe, igt_output_t *output,
+			      igt_plane_t *plane, stride_t stride)
+{
+	igt_plane_t *primary;
+	struct igt_fb primary_fb;
+	igt_crc_t crc_ref, crc;
+	int i;
+	uint32_t format;
+
+	/* do not try testing the stride on cursor planes */
+	if (plane->type == DRM_PLANE_TYPE_CURSOR)
+		return;
+
+	igt_debug("Testing stride %uK on connector %s on %s plane %s.%u\n", stride,
+		  igt_output_name(output), kmstest_plane_type_name(plane->type),
+		  kmstest_pipe_name(pipe), plane->index);
+
+	igt_output_set_pipe(output, pipe);
+
+	for (i = 0; i < plane->drm_plane->count_formats; i++) {
+		format = plane->drm_plane->formats[i];
+
+		if (!can_draw(format))
+			continue;
+
+		igt_debug("Testing format 0x%x on %s.%u\n",
+			  format, kmstest_pipe_name(pipe), plane->index);
+
+		test_format_plane_get_crc(data, output, format, plane, 0, &crc_ref);
+		test_format_plane_get_crc(data, output, format, plane, 960 * stride, &crc);
+		igt_assert_crc_equal(&crc_ref, &crc);
+	}
+}
+
+static void
+test_pixel_formats(data_t *data, enum pipe pipe, stride_t stride)
+{
+	igt_output_t *output;
+
+	igt_display_require_output_on_pipe(&data->display, pipe);
+
+	for_each_valid_output_on_pipe(&data->display, pipe, output) {
+		igt_plane_t *plane;
+
+		data->pipe_crc = igt_pipe_crc_new(data->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
+		for_each_plane_on_pipe(&data->display, pipe, plane)
+			test_format_plane(data, pipe, output, plane, stride);
+		igt_pipe_crc_stop(data->pipe_crc);
+		igt_pipe_crc_free(data->pipe_crc);
+
+		igt_output_set_pipe(output, PIPE_ANY);
+	}
+}
+
+static void
+run_tests_for_pipe_plane(data_t *data, enum pipe pipe)
+{
+	igt_fixture {
+		igt_skip_on(pipe >= data->display.n_pipes);
+		igt_require(data->display.pipes[pipe].n_planes > 0);
+	}
+
+	igt_subtest_f("pipe-%s-stride-4K", kmstest_pipe_name(pipe))
+		test_pixel_formats(data, pipe, TEST_STRIDE_4K);
+
+	igt_subtest_f("pipe-%s-stride-8K", kmstest_pipe_name(pipe))
+		test_pixel_formats(data, pipe, TEST_STRIDE_8K);
+
+	igt_subtest_f("pipe-%s-stride-16K", kmstest_pipe_name(pipe))
+		test_pixel_formats(data, pipe, TEST_STRIDE_16K);
+
+	igt_subtest_f("pipe-%s-stride-32K", kmstest_pipe_name(pipe))
+		test_pixel_formats(data, pipe, TEST_STRIDE_32K);
+}
+
+
+static data_t data;
+
+igt_main
+{
+	enum pipe pipe;
+
+	igt_fixture {
+		data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
+
+		kmstest_set_vt_graphics_mode();
+
+		igt_require_pipe_crc(data.drm_fd);
+		igt_display_init(&data.display, data.drm_fd);
+	}
+
+	for_each_pipe_static(pipe)
+		run_tests_for_pipe_plane(&data, pipe);
+
+	igt_fixture {
+		igt_display_fini(&data.display);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 2322217d..4632f1f8 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -159,6 +159,7 @@ test_progs = [
 	'kms_cursor_legacy',
 	'kms_draw_crc',
 	'kms_fbcon_fbt',
+	'kms_fb_stride',
 	'kms_fence_pin_leak',
 	'kms_flip',
 	'kms_flip_event_leak',
-- 
2.16.1



More information about the igt-dev mailing list