All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes
@ 2018-02-09 14:24 Juha-Pekka Heikkila
  2018-02-09 17:49 ` [igt-dev] ✓ Fi.CI.BAT: success for " Patchwork
  2018-02-09 20:02 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  0 siblings, 2 replies; 11+ messages in thread
From: Juha-Pekka Heikkila @ 2018-02-09 14:24 UTC (permalink / raw)
  To: igt-dev

Ask from kernel about supported modes for each plane and try setting
them on display and verify functionality with crc.

DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888 skip crc testing on
primary and overlay planes because they produce incorrect crcs from
hardware. DRM_FORMAT_ARGB8888 is tested on cursor plane.

There is preparation for planar formats but I didn't see stable
implementation yet so it has holes.

Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
---

This is tested on HSW and SKL. There are pieces to support NV12 but it was
not succesfully tested anywhere, probably need work still.

 tests/Makefile.sources          |   1 +
 tests/kms_available_modes_crc.c | 471 ++++++++++++++++++++++++++++++++++++++++
 tests/meson.build               |   1 +
 3 files changed, 473 insertions(+)
 create mode 100644 tests/kms_available_modes_crc.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 870c909..9b804fd 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -171,6 +171,7 @@ TESTS_progs = \
 	kms_atomic \
 	kms_atomic_interruptible \
 	kms_atomic_transition \
+	kms_available_modes_crc \
 	kms_busy \
 	kms_ccs \
 	kms_chv_cursor_fail \
diff --git a/tests/kms_available_modes_crc.c b/tests/kms_available_modes_crc.c
new file mode 100644
index 0000000..206edbc
--- /dev/null
+++ b/tests/kms_available_modes_crc.c
@@ -0,0 +1,471 @@
+/*
+ * 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.
+ *
+ */
+
+#include "drm_mode.h"
+#include "drm_fourcc.h"
+#include "igt.h"
+#include <sys/ioctl.h>
+
+IGT_TEST_DESCRIPTION("CRC test all different plane modes which kernel advertises.");
+
+typedef struct {
+	int gfx_fd;
+	igt_display_t display;
+	enum igt_commit_style commit;
+
+	struct igt_fb fb;
+	struct igt_fb primary_fb;
+
+	char format_name[5];
+	bool separateprimaryplane;
+
+	uint32_t gem_handle;
+	unsigned int size;
+	unsigned char* buf;
+
+	/*
+	 * comparison crcs
+	 */
+	igt_crc_t *cursor_crc;
+	igt_crc_t *fullscreen_crc;
+} data_t;
+
+static int do_write(int fd, int handle, void *buf, int offset, int size)
+{
+	struct drm_i915_gem_pwrite write;
+	memset(&write, 0x00, sizeof(write));
+	write.handle = handle;
+	write.data_ptr = (uintptr_t)buf;
+	write.size = size;
+	write.offset = offset;
+	return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write);
+}
+
+static void generate_comparison_crc_list(data_t *data, igt_output_t *output,
+					enum pipe pipe)
+{
+	drmModeModeInfo *mode;
+	uint64_t w, h, c;
+	int fbid;
+	cairo_t *cr;
+	igt_pipe_crc_t *pipe_crc;
+	igt_plane_t *primary;
+
+
+	igt_output_set_pipe(output, pipe);
+
+	mode = igt_output_get_mode(output);
+	fbid = igt_create_color_fb(data->gfx_fd,
+				   mode->hdisplay,
+				   mode->vdisplay,
+				   DRM_FORMAT_XRGB8888,
+				   LOCAL_DRM_FORMAT_MOD_NONE,
+				   0, 0, 0,
+				   &data->primary_fb);
+
+	igt_assert(fbid);
+
+	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
+	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
+
+	cr = igt_get_cairo_ctx(data->gfx_fd, &data->primary_fb);
+	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
+			    0.0, 0.0, 0.0);
+	igt_paint_color(cr, 0, 0, w, h, 1.0, 1.0, 1.0);
+	igt_assert(cairo_status(cr) == 0);
+
+	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
+	igt_plane_set_fb(primary, &data->primary_fb);
+	igt_display_commit2(&data->display, data->commit);
+
+	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
+	igt_pipe_crc_start(pipe_crc);
+	c = igt_pipe_crc_get_crcs(pipe_crc, 3, &data->cursor_crc);
+	igt_assert(c==3);
+	igt_pipe_crc_stop(pipe_crc);
+	igt_pipe_crc_free(pipe_crc);
+
+	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
+			1.0, 1.0, 1.0);
+
+	igt_plane_set_fb(primary, &data->primary_fb);
+	igt_display_commit2(&data->display, data->commit);
+
+	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
+	igt_pipe_crc_start(pipe_crc);
+	c = igt_pipe_crc_get_crcs(pipe_crc, 3, &data->fullscreen_crc);
+	igt_assert(c==3);
+	igt_pipe_crc_stop(pipe_crc);
+	igt_pipe_crc_free(pipe_crc);
+
+	cairo_destroy(cr);
+	igt_remove_fb(data->gfx_fd, &data->primary_fb);
+}
+
+static bool do_crc_tests(data_t *data, igt_output_t *output, enum pipe pipe,
+			 igt_plane_t *plane, uint32_t format)
+{
+	int i, c;
+	unsigned short* ptemp_16_buf;
+	unsigned int* ptemp_32_buf;
+	igt_crc_t *crcs = NULL;
+	igt_pipe_crc_t *pipe_crc;
+
+	const struct {
+		uint32_t	fourcc;
+		char		zeropadding;
+		enum		{ BYTES_PP_1=1, BYTES_PP_2=2, BYTES_PP_4=4,
+				  NV12, SKIP } bpp;
+		uint32_t	value;
+	} fillers[] = {
+		{ DRM_FORMAT_C8, 0, BYTES_PP_1, 0xff},
+		{ DRM_FORMAT_RGB565, 0, BYTES_PP_2, 0xffff},
+		{ DRM_FORMAT_XRGB8888, 0, BYTES_PP_4, 0xffffffff},
+		{ DRM_FORMAT_XBGR8888, 0, BYTES_PP_4, 0xffffffff},
+
+		/*
+		 * These two are skipped because blending seems to work
+		 * incorrectly with exception of AR24 on cursor plane.
+		 * Test still creates the planes, just filling plane
+		 * and getting crc is skipped.
+		 */
+		{ DRM_FORMAT_ARGB8888, 0, SKIP, 0xffffffff},
+		{ DRM_FORMAT_ABGR8888, 0, SKIP, 0x00ffffff},
+
+		{ DRM_FORMAT_XRGB2101010, 0, BYTES_PP_4, 0xffffffff},
+		{ DRM_FORMAT_XBGR2101010, 0, BYTES_PP_4, 0xffffffff},
+
+		{ DRM_FORMAT_YUYV, 0, BYTES_PP_4, 0x7fff7fff},
+		{ DRM_FORMAT_YVYU, 0, BYTES_PP_4, 0x7fff7fff},
+		{ DRM_FORMAT_UYVY, 0, BYTES_PP_4, 0xff7fff7f},
+		{ DRM_FORMAT_VYUY, 0, BYTES_PP_4, 0xff7fff7f},
+
+		{ DRM_FORMAT_NV12, 0, NV12, 0x7fff},
+
+		{ 0, 0, 0, 0 }
+	};
+
+
+	int maxformats = sizeof(fillers)/sizeof(fillers[0])-1;
+
+	for( i = 0; i < maxformats; i++ ) {
+		if( fillers[i].fourcc == format )
+			break;
+	}
+
+	switch (fillers[i].bpp) {
+	case BYTES_PP_4:
+		ptemp_32_buf = (unsigned int*)data->buf;
+		for (c = 0; c < data->size/4; c++)
+			ptemp_32_buf[c] = fillers[i].value;
+		break;
+	case BYTES_PP_2:
+		ptemp_16_buf = (unsigned short*)data->buf;
+		for (c = 0; c < data->size/2; c++)
+			ptemp_16_buf[c] = (unsigned short)fillers[i].value;
+		break;
+	case BYTES_PP_1:
+		memset((void*)data->buf, fillers[i].value, data->size);
+		break;
+	case NV12:
+		memset((void*)data->buf, fillers[i].value&0xff,
+		       data->size*2/3);
+
+		memset((void*)(data->buf+data->size*2/3),
+		       (fillers[i].value>>8)&0xff, data->size/3);
+		break;
+	case SKIP:
+		if (fillers[i].fourcc == DRM_FORMAT_ARGB8888 &&
+		    plane->type == DRM_PLANE_TYPE_CURSOR) {
+		/*
+		 * special for cursor plane where blending works correctly.
+		 */
+			ptemp_32_buf = (unsigned int*)data->buf;
+			for (c = 0; c < data->size/4; c++)
+				ptemp_32_buf[c] = fillers[i].value;
+			break;
+		}
+		igt_info("Format %s CRC comparison skipped by design.\n",
+			 (char*)&fillers[i].fourcc);
+
+		return true;
+	default:
+		igt_info("Unsupported mode for test %s\n",
+			 (char*)&fillers[i].fourcc);
+		return true;
+	}
+
+	do_write(data->gfx_fd, data->gem_handle, (void*)data->buf, 0,
+		 data->size);
+
+	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
+				    INTEL_PIPE_CRC_SOURCE_AUTO);
+
+	igt_pipe_crc_start(pipe_crc);
+
+	c = igt_pipe_crc_get_crcs(pipe_crc, 3, &crcs);
+	igt_assert(c==3);
+
+	igt_pipe_crc_stop(pipe_crc);
+	igt_pipe_crc_free(pipe_crc);
+
+	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+		igt_assert_crc_equal(&crcs[2], &data->fullscreen_crc[2]);
+	} else {
+		igt_assert_crc_equal(&crcs[2], &data->cursor_crc[2]);
+	}
+
+	free(crcs);
+	return true;
+}
+
+
+static bool setup_fb(data_t *data, igt_output_t *output, enum pipe pipe,
+		     igt_plane_t *plane, uint32_t format)
+{
+	uint64_t tiling = LOCAL_DRM_FORMAT_MOD_NONE;
+	drmModeModeInfo *mode;
+	unsigned int stride;
+	uint64_t w, h;
+	int bpp;
+	int ret;
+	uint32_t offsets[4];
+
+	bpp = 32; //cheating! Don't really care as long as its enough.
+
+	mode = igt_output_get_mode(output);
+	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+		w = mode->hdisplay ;
+		h = mode->vdisplay;
+	} else {
+		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
+		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
+	}
+
+	for (stride = 512; stride < (w * bpp / 8); stride *= 2)
+		;
+	for (data->size = 1024*1024; data->size < stride * h; data->size *= 2)
+		;
+
+	data->gem_handle = gem_create(data->gfx_fd, data->size);
+	ret = __gem_set_tiling(data->gfx_fd, data->gem_handle,
+			       I915_TILING_NONE, stride);
+
+	igt_assert_eq(ret, 0);
+
+	switch(format) {
+	case DRM_FORMAT_NV12:
+		offsets[0] = 0;
+		offsets[1] = data->size*2/3;
+
+		ret = __kms_addfb(data->gfx_fd, data->gem_handle, w, h,
+				  stride, format, tiling,
+				  (uint32_t *)&offsets,
+				  LOCAL_DRM_MODE_FB_MODIFIERS,
+				  &data->fb.fb_id);
+		break;
+	default:
+		ret = __kms_addfb(data->gfx_fd, data->gem_handle, w, h,
+				  stride, format, tiling, NULL,
+				  LOCAL_DRM_MODE_FB_MODIFIERS,
+				  &data->fb.fb_id);
+		break;
+	}
+
+	if(ret < 0) {
+		igt_info("Creating fb for format %s failed, return code %d\n",
+			 (char*)&data->format_name, ret);
+
+		return false;
+	}
+
+	data->fb.width = w;
+	data->fb.height = h;
+	data->fb.gem_handle = data->gem_handle;
+
+	igt_plane_set_fb(plane, &data->fb);
+	igt_fb_set_size(&data->fb, plane, w, h);
+	igt_plane_set_size(plane, w, h);
+	igt_fb_set_position(&data->fb, plane, 0, 0);
+	igt_display_commit2(&data->display, data->commit);
+	return true;
+}
+
+
+static void remove_fb(data_t* data, igt_output_t* output, igt_plane_t* plane)
+{
+	if (data->separateprimaryplane) {
+		igt_plane_t* primary = igt_output_get_plane_type(output,
+								 DRM_PLANE_TYPE_PRIMARY);
+		igt_plane_set_fb(primary, NULL);
+		igt_remove_fb(data->gfx_fd, &data->primary_fb);
+		igt_display_commit2(&data->display, data->commit);
+		data->separateprimaryplane = false;
+	}
+
+	igt_remove_fb(data->gfx_fd, &data->fb);
+	igt_display_commit2(&data->display, data->commit);
+	free(data->buf);
+}
+
+static bool prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
+			 igt_plane_t *plane, uint32_t format)
+{
+	drmModeModeInfo *mode;
+	igt_plane_t *primary;
+
+	igt_output_set_pipe(output, pipe);
+
+	if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
+		mode = igt_output_get_mode(output);
+		igt_create_color_fb(data->gfx_fd,
+				    mode->hdisplay, mode->vdisplay,
+				    DRM_FORMAT_XRGB8888,
+				    LOCAL_DRM_FORMAT_MOD_NONE,
+				    0, 0, 0,
+				    &data->primary_fb);
+		primary = igt_output_get_plane_type(output,
+						    DRM_PLANE_TYPE_PRIMARY);
+
+		igt_plane_set_fb(primary, &data->primary_fb);
+		igt_display_commit2(&data->display, data->commit);
+
+		data->separateprimaryplane = true;
+	}
+
+	if (!setup_fb(data, output, pipe, plane, format))
+		return false;
+
+	data->buf = (unsigned char*)malloc(data->size);
+	return true;
+}
+
+static int
+test_one_mode(data_t* data, igt_output_t *output, igt_plane_t* plane,
+	      enum pipe pipe, int mode)
+{
+	if ( prepare_crtc(data, output, pipe, plane, mode)){
+		do_crc_tests(data, output, pipe, plane, mode);
+
+		remove_fb(data, output, plane);
+		return 0;
+	}
+	return 1;
+}
+
+static void
+test_available_modes(data_t* data)
+{
+	igt_output_t *output;
+	igt_plane_t *plane;
+	int* u32ptr_formats = NULL;
+	int modeindex;
+	enum pipe pipe;
+	struct drm_mode_get_plane one_plane = {};
+	int invalids = 0;
+
+	char	planetype[3][8] = {"OVERLAY\0", "PRIMARY\0", "CURSOR\0" };
+
+	for_each_pipe_with_valid_output(&data->display, pipe, output) {
+		igt_output_set_pipe(output, pipe);
+
+		/*
+		 * regenerate comparison crcs for each pipe just in case.
+		 */
+		generate_comparison_crc_list(data, output, pipe);
+
+		for_each_plane_on_pipe(&data->display, pipe, plane) {
+
+			memset((void*)&one_plane, 0,
+			       sizeof(struct drm_mode_get_plane));
+			one_plane.plane_id = plane->drm_plane->plane_id;
+			/*
+			 * first call again to know how much space needed,
+			 * second call to get list of supported modes.
+			 */
+			igt_ioctl(data->gfx_fd, DRM_IOCTL_MODE_GETPLANE,
+				  &one_plane);
+			igt_assert(one_plane.count_format_types > 0);
+
+			u32ptr_formats = (int*)calloc(one_plane.count_format_types,
+						      sizeof(int));
+
+			one_plane.format_type_ptr = (__u64)u32ptr_formats;
+			igt_ioctl(data->gfx_fd, DRM_IOCTL_MODE_GETPLANE,
+				  &one_plane);
+
+			for (modeindex = 0;
+			     modeindex < one_plane.count_format_types;
+			     modeindex++) {
+				data->format_name[0] = u32ptr_formats[modeindex]&0xff;
+				data->format_name[1] = (u32ptr_formats[modeindex]>>8)&0xff;
+				data->format_name[2] = (u32ptr_formats[modeindex]>>16)&0xff;
+				data->format_name[3] = (u32ptr_formats[modeindex]>>24)&0xff;
+
+				igt_info("Testing connector %s using pipe %s" \
+					 " plane index %d type %s mode %s\n",
+					 igt_output_name(output),
+					 kmstest_pipe_name(pipe),
+					 plane->index,
+					 planetype[plane->type],
+					 (char*)&data->format_name);
+
+				invalids += test_one_mode(data, output,
+							  plane, pipe,
+							  u32ptr_formats[modeindex]);
+			}
+
+			free((void*)one_plane.format_type_ptr);
+		}
+		free(data->cursor_crc);
+		free(data->fullscreen_crc);
+	}
+
+	igt_assert(invalids == 0);
+}
+
+igt_main
+{
+	data_t data = {};
+
+	igt_skip_on_simulation();
+
+	igt_fixture {
+		data.gfx_fd = drm_open_driver_master(DRIVER_INTEL);
+		kmstest_set_vt_graphics_mode();
+		igt_require_pipe_crc(data.gfx_fd);
+		igt_display_init(&data.display, data.gfx_fd);
+	}
+
+	data.commit = data.display.is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
+
+	igt_subtest("available_mode_test_crc") {
+		test_available_modes(&data);
+	}
+
+	igt_fixture {
+		kmstest_restore_vt_mode();
+		igt_display_fini(&data.display);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 521a4c4..6b45111 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -149,6 +149,7 @@ test_progs = [
 	'kms_atomic',
 	'kms_atomic_interruptible',
 	'kms_atomic_transition',
+	'kms_available_modes_crc',
 	'kms_busy',
 	'kms_ccs',
 	'kms_chv_cursor_fail',
-- 
2.7.4

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [igt-dev] ✓ Fi.CI.BAT: success for tests/kms_available_modes_crc: Test all modes on all planes
  2018-02-09 14:24 [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes Juha-Pekka Heikkila
@ 2018-02-09 17:49 ` Patchwork
  2018-02-09 20:02 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  1 sibling, 0 replies; 11+ messages in thread
From: Patchwork @ 2018-02-09 17:49 UTC (permalink / raw)
  To: Juha-Pekka Heikkila; +Cc: igt-dev

== Series Details ==

Series: tests/kms_available_modes_crc: Test all modes on all planes
URL   : https://patchwork.freedesktop.org/series/38007/
State : success

== Summary ==

IGT patchset tested on top of latest successful build
3af87d45da24015b7a6124b59b2c4b854381cab6 tools/intel_aubdump: Simulate "enhanced execlist" submission for gen11+

with latest DRM-Tip kernel build CI_DRM_3750
897018779f8b drm-tip: 2018y-02m-09d-16h-18m-21s UTC integration manifest

Testlist changes:
+igt@kms_available_modes_crc@available_mode_test_crc

Test debugfs_test:
        Subgroup read_all_entries:
                incomplete -> PASS       (fi-snb-2520m) fdo#103713
Test kms_pipe_crc_basic:
        Subgroup suspend-read-crc-pipe-b:
                dmesg-warn -> PASS       (fi-cnl-y3) fdo#104951

fdo#103713 https://bugs.freedesktop.org/show_bug.cgi?id=103713
fdo#104951 https://bugs.freedesktop.org/show_bug.cgi?id=104951

fi-bdw-5557u     total:288  pass:267  dwarn:0   dfail:0   fail:0   skip:21  time:421s
fi-bdw-gvtdvm    total:288  pass:264  dwarn:0   dfail:0   fail:0   skip:24  time:427s
fi-blb-e6850     total:288  pass:223  dwarn:1   dfail:0   fail:0   skip:64  time:376s
fi-bsw-n3050     total:288  pass:242  dwarn:0   dfail:0   fail:0   skip:46  time:501s
fi-bwr-2160      total:288  pass:183  dwarn:0   dfail:0   fail:0   skip:105 time:289s
fi-bxt-dsi       total:288  pass:258  dwarn:0   dfail:0   fail:0   skip:30  time:485s
fi-bxt-j4205     total:288  pass:259  dwarn:0   dfail:0   fail:0   skip:29  time:495s
fi-byt-j1900     total:288  pass:253  dwarn:0   dfail:0   fail:0   skip:35  time:474s
fi-byt-n2820     total:288  pass:249  dwarn:0   dfail:0   fail:0   skip:39  time:462s
fi-cfl-s2        total:288  pass:262  dwarn:0   dfail:0   fail:0   skip:26  time:563s
fi-cnl-y3        total:288  pass:262  dwarn:0   dfail:0   fail:0   skip:26  time:582s
fi-elk-e7500     total:288  pass:229  dwarn:0   dfail:0   fail:0   skip:59  time:424s
fi-gdg-551       total:288  pass:179  dwarn:0   dfail:0   fail:1   skip:108 time:288s
fi-glk-1         total:288  pass:260  dwarn:0   dfail:0   fail:0   skip:28  time:513s
fi-hsw-4770      total:288  pass:261  dwarn:0   dfail:0   fail:0   skip:27  time:390s
fi-ilk-650       total:288  pass:228  dwarn:0   dfail:0   fail:0   skip:60  time:414s
fi-ivb-3520m     total:288  pass:259  dwarn:0   dfail:0   fail:0   skip:29  time:450s
fi-ivb-3770      total:288  pass:255  dwarn:0   dfail:0   fail:0   skip:33  time:415s
fi-kbl-7500u     total:288  pass:263  dwarn:1   dfail:0   fail:0   skip:24  time:461s
fi-kbl-7560u     total:288  pass:269  dwarn:0   dfail:0   fail:0   skip:19  time:501s
fi-kbl-r         total:288  pass:261  dwarn:0   dfail:0   fail:0   skip:27  time:501s
fi-pnv-d510      total:288  pass:222  dwarn:1   dfail:0   fail:0   skip:65  time:607s
fi-skl-6260u     total:288  pass:268  dwarn:0   dfail:0   fail:0   skip:20  time:434s
fi-skl-6600u     total:288  pass:261  dwarn:0   dfail:0   fail:0   skip:27  time:509s
fi-skl-6700hq    total:288  pass:262  dwarn:0   dfail:0   fail:0   skip:26  time:529s
fi-skl-6700k2    total:288  pass:264  dwarn:0   dfail:0   fail:0   skip:24  time:490s
fi-skl-6770hq    total:288  pass:268  dwarn:0   dfail:0   fail:0   skip:20  time:486s
fi-skl-guc       total:288  pass:260  dwarn:0   dfail:0   fail:0   skip:28  time:416s
fi-skl-gvtdvm    total:288  pass:265  dwarn:0   dfail:0   fail:0   skip:23  time:432s
fi-snb-2520m     total:288  pass:248  dwarn:0   dfail:0   fail:0   skip:40  time:531s
fi-snb-2600      total:288  pass:248  dwarn:0   dfail:0   fail:0   skip:40  time:398s
Blacklisted hosts:
fi-glk-dsi       total:288  pass:258  dwarn:0   dfail:0   fail:0   skip:30  time:471s

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_894/issues.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [igt-dev] ✓ Fi.CI.IGT: success for tests/kms_available_modes_crc: Test all modes on all planes
  2018-02-09 14:24 [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes Juha-Pekka Heikkila
  2018-02-09 17:49 ` [igt-dev] ✓ Fi.CI.BAT: success for " Patchwork
@ 2018-02-09 20:02 ` Patchwork
  1 sibling, 0 replies; 11+ messages in thread
From: Patchwork @ 2018-02-09 20:02 UTC (permalink / raw)
  To: Juha-Pekka Heikkila; +Cc: igt-dev

== Series Details ==

Series: tests/kms_available_modes_crc: Test all modes on all planes
URL   : https://patchwork.freedesktop.org/series/38007/
State : success

== Summary ==

Test kms_sysfs_edid_timing:
                pass       -> WARN       (shard-apl) fdo#100047
Test kms_flip:
        Subgroup dpms-vs-vblank-race-interruptible:
                pass       -> FAIL       (shard-hsw) fdo#103060
Test perf:
        Subgroup enable-disable:
                pass       -> FAIL       (shard-apl) fdo#103715

fdo#100047 https://bugs.freedesktop.org/show_bug.cgi?id=100047
fdo#103060 https://bugs.freedesktop.org/show_bug.cgi?id=103060
fdo#103715 https://bugs.freedesktop.org/show_bug.cgi?id=103715

shard-apl        total:3412 pass:1767 dwarn:1   dfail:0   fail:21  skip:1621 time:12335s
shard-hsw        total:3445 pass:1760 dwarn:1   dfail:0   fail:12  skip:1671 time:11819s
shard-snb        total:3445 pass:1351 dwarn:1   dfail:0   fail:11  skip:2082 time:6669s
Blacklisted hosts:
shard-kbl        total:3398 pass:1885 dwarn:1   dfail:0   fail:21  skip:1490 time:9398s

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_894/shards.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes
  2018-05-18 12:20 Juha-Pekka Heikkila
@ 2018-05-22 10:48 ` Mika Kahola
  0 siblings, 0 replies; 11+ messages in thread
From: Mika Kahola @ 2018-05-22 10:48 UTC (permalink / raw)
  To: Juha-Pekka Heikkila, igt-dev

pushed, thanks for the patch!

On Fri, 2018-05-18 at 15:20 +0300, Juha-Pekka Heikkila wrote:
> Ask from kernel about supported modes for each plane and try setting
> them on display and verify functionality with crc.
> 
> DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888 skip crc testing on
> primary and overlay planes because they produce incorrect crcs from
> hardware. DRM_FORMAT_ARGB8888 is tested on cursor plane.
> 
> v3: address review comments from Mika Kahola.
> Stop crc at end of test before freeing it. Use libdrm instead
> of mixing ioctl and libdrm.
> 
> v2: Address review comments from Mika Kahola.
> Keep crc running for all tests while on same pipe, set tile height
> to 16 and read only one crc per test.
> 
> Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
> Reviewed-by: Mika Kahola <mika.kahola@intel.com>
> ---
> 
> I didn't go adding igt_exit() at the end of the test because I use
> igt_main
> which will do igt_exit() for me.
> 
>  tests/Makefile.sources          |   1 +
>  tests/kms_available_modes_crc.c | 523
> ++++++++++++++++++++++++++++++++++++++++
>  tests/meson.build               |   1 +
>  3 files changed, 525 insertions(+)
>  create mode 100644 tests/kms_available_modes_crc.c
> 
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index ddcc18f..6aa0306 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -173,6 +173,7 @@ TESTS_progs = \
>  	kms_atomic \
>  	kms_atomic_interruptible \
>  	kms_atomic_transition \
> +	kms_available_modes_crc \
>  	kms_busy \
>  	kms_ccs \
>  	kms_chv_cursor_fail \
> diff --git a/tests/kms_available_modes_crc.c
> b/tests/kms_available_modes_crc.c
> new file mode 100644
> index 0000000..da58ee5
> --- /dev/null
> +++ b/tests/kms_available_modes_crc.c
> @@ -0,0 +1,523 @@
> +/*
> + * 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.
> + *
> + */
> +
> +#include "drm_mode.h"
> +#include "drm_fourcc.h"
> +#include "igt.h"
> +
> +IGT_TEST_DESCRIPTION("CRC test all different plane modes which
> kernel advertises.");
> +
> +typedef struct {
> +	int gfx_fd;
> +	igt_display_t display;
> +	enum igt_commit_style commit;
> +
> +	struct igt_fb fb;
> +	struct igt_fb primary_fb;
> +
> +	union {
> +		char name[5];
> +		uint32_t dword;
> +	} format;
> +	bool separateprimaryplane;
> +
> +	uint32_t gem_handle;
> +	uint32_t gem_handle_yuv;
> +	unsigned int size;
> +	unsigned char* buf;
> +
> +	/*
> +	 * comparison crcs
> +	 */
> +	igt_pipe_crc_t *pipe_crc;
> +
> +	igt_crc_t cursor_crc;
> +	igt_crc_t fullscreen_crc;
> +} data_t;
> +
> +
> +static int do_write(int fd, int handle, void *buf, int size)
> +{
> +	struct drm_i915_gem_pwrite write;
> +	memset(&write, 0x00, sizeof(write));
> +	write.handle = handle;
> +	write.data_ptr = (uintptr_t)buf;
> +	write.size = size;
> +	write.offset = 0;
> +	return igt_ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write);
> +}
> +
> +
> +static void generate_comparison_crc_list(data_t *data, igt_output_t
> *output)
> +{
> +	drmModeModeInfo *mode;
> +	uint64_t w, h;
> +	int fbid;
> +	cairo_t *cr;
> +	igt_plane_t *primary;
> +
> +	mode = igt_output_get_mode(output);
> +	fbid = igt_create_color_fb(data->gfx_fd,
> +				   mode->hdisplay,
> +				   mode->vdisplay,
> +				   intel_gen(intel_get_drm_devid(dat
> a->gfx_fd)) < 9 ? DRM_FORMAT_XRGB8888 : DRM_FORMAT_ARGB8888,
> +				   LOCAL_DRM_FORMAT_MOD_NONE,
> +				   0, 0, 0,
> +				   &data->primary_fb);
> +
> +	igt_assert(fbid);
> +
> +	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
> +	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
> +
> +	cr = igt_get_cairo_ctx(data->gfx_fd, &data->primary_fb);
> +	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
> +			    0.0, 0.0, 0.0);
> +	igt_paint_color(cr, 0, 0, w, h, 1.0, 1.0, 1.0);
> +	igt_assert(cairo_status(cr) == 0);
> +
> +	primary = igt_output_get_plane_type(output,
> DRM_PLANE_TYPE_PRIMARY);
> +	igt_plane_set_fb(primary, &data->primary_fb);
> +	igt_display_commit2(&data->display, data->commit);
> +
> +	igt_pipe_crc_drain(data->pipe_crc);
> +	igt_pipe_crc_get_single(data->pipe_crc, &data->cursor_crc);
> +	igt_plane_set_fb(primary, NULL);
> +	igt_display_commit2(&data->display, data->commit);
> +
> +	intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ?
> +		  igt_paint_color(cr, 0, 0, mode->hdisplay, mode-
> >vdisplay, 1.0, 1.0, 1.0) :
> +		  igt_paint_color_alpha(cr, 0, 0, mode->hdisplay,
> mode->vdisplay, 1.0, 1.0, 1.0, 1.0);
> +
> +	igt_plane_set_fb(primary, &data->primary_fb);
> +	igt_display_commit2(&data->display, data->commit);
> +
> +	igt_pipe_crc_drain(data->pipe_crc);
> +	igt_pipe_crc_get_single(data->pipe_crc, &data-
> >fullscreen_crc);
> +
> +	cairo_destroy(cr);
> +	igt_remove_fb(data->gfx_fd, &data->primary_fb);
> +}
> +
> +/*
> + * fill_in_fb tell in return value if selected mode should be
> + * proceed to crc check
> + */
> +static bool fill_in_fb(data_t *data, igt_output_t *output,
> igt_plane_t *plane,
> +		       uint32_t format)
> +{
> +	signed i, c, writesize;
> +	unsigned short* ptemp_16_buf;
> +	unsigned int* ptemp_32_buf;
> +
> +	const struct {
> +		uint32_t	fourcc;
> +		char		zeropadding;
> +		enum		{ BYTES_PP_1=1,
> +				  BYTES_PP_2=2,
> +				  BYTES_PP_4=4,
> +				  NV12,
> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> defined(DRM_FORMAT_P016)
> +				  P010,
> +#endif
> +				  SKIP } bpp;
> +		uint32_t	value;
> +	} fillers[] = {
> +		{ DRM_FORMAT_C8, 0, BYTES_PP_1, 0xff},
> +		{ DRM_FORMAT_RGB565, 0, BYTES_PP_2, 0xffff},
> +		{ DRM_FORMAT_XRGB8888, 0, BYTES_PP_4, 0xffffffff},
> +		{ DRM_FORMAT_XBGR8888, 0, BYTES_PP_4, 0xffffffff},
> +
> +		/*
> +		 * following two are skipped because blending seems
> to work
> +		 * incorrectly with exception of AR24 on cursor
> plane.
> +		 * Test still creates the planes, just filling plane
> +		 * and getting crc is skipped.
> +		 */
> +		{ DRM_FORMAT_ARGB8888, 0, SKIP, 0xffffffff},
> +		{ DRM_FORMAT_ABGR8888, 0, SKIP, 0x00ffffff},
> +
> +		{ DRM_FORMAT_XRGB2101010, 0, BYTES_PP_4,
> 0xffffffff},
> +		{ DRM_FORMAT_XBGR2101010, 0, BYTES_PP_4,
> 0xffffffff},
> +
> +		{ DRM_FORMAT_YUYV, 0, BYTES_PP_4, 0x80eb80eb},
> +		{ DRM_FORMAT_YVYU, 0, BYTES_PP_4, 0x80eb80eb},
> +		{ DRM_FORMAT_VYUY, 0, BYTES_PP_4, 0xeb80eb80},
> +		{ DRM_FORMAT_UYVY, 0, BYTES_PP_4, 0xeb80eb80},
> +
> +		/*
> +		 * (semi-)planar formats
> +		 */
> +		{ DRM_FORMAT_NV12, 0, NV12, 0x80eb},
> +#ifdef DRM_FORMAT_P010
> +		{ DRM_FORMAT_P010, 0, P010, 0x8000eb00},
> +#endif
> +#ifdef DRM_FORMAT_P012
> +		{ DRM_FORMAT_P012, 0, P010, 0x8000eb00},
> +#endif
> +#ifdef DRM_FORMAT_P016
> +		{ DRM_FORMAT_P016, 0, P010, 0x8000eb00},
> +#endif
> +		{ 0, 0, 0, 0 }
> +	};
> +
> +	for( i = 0; fillers[i].fourcc != 0; i++ ) {
> +		if( fillers[i].fourcc == format )
> +			break;
> +	}
> +
> +	switch (fillers[i].bpp) {
> +	case BYTES_PP_4:
> +		ptemp_32_buf = (unsigned int*)data->buf;
> +		for (c = 0; c < data->size/4; c++)
> +			ptemp_32_buf[c] = fillers[i].value;
> +		writesize = data->size;
> +		break;
> +	case BYTES_PP_2:
> +		ptemp_16_buf = (unsigned short*)data->buf;
> +		for (c = 0; c < data->size/2; c++)
> +			ptemp_16_buf[c] = (unsigned
> short)fillers[i].value;
> +		writesize = data->size;
> +		break;
> +	case BYTES_PP_1:
> +		memset((void*)data->buf, fillers[i].value, data-
> >size);
> +		writesize = data->size;
> +		break;
> +	case NV12:
> +		memset((void*)data->buf, fillers[i].value&0xff,
> +		       data->size);
> +
> +		memset((void*)(data->buf+data->size),
> +		       (fillers[i].value>>8)&0xff, data->size/2);
> +
> +		writesize = data->size+data->size/2;
> +		break;
> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> defined(DRM_FORMAT_P016)
> +	case P010:
> +		ptemp_16_buf = (unsigned short*)data->buf;
> +		for (c = 0; c < data->size/2; c++)
> +			ptemp_16_buf[c] = (unsigned
> short)fillers[i].value&0xffff;
> +
> +		ptemp_16_buf = (unsigned short*)(data->buf+data-
> >size);
> +		for (c = 0; c < data->size/2; c++)
> +			ptemp_16_buf[c] = (unsigned
> short)(fillers[i].value>>16)&0xffff;
> +
> +		writesize = data->size+data->size/2;
> +		break;
> +#endif
> +	case SKIP:
> +		if (fillers[i].fourcc == DRM_FORMAT_ARGB8888 &&
> +		    plane->type == DRM_PLANE_TYPE_CURSOR) {
> +		/*
> +		 * special for cursor plane where blending works
> correctly.
> +		 */
> +			ptemp_32_buf = (unsigned int*)data->buf;
> +			for (c = 0; c < data->size/4; c++)
> +				ptemp_32_buf[c] = fillers[i].value;
> +			writesize = data->size;
> +			break;
> +		}
> +		igt_info("Format %s CRC comparison skipped by
> design.\n",
> +			 (char*)&fillers[i].fourcc);
> +
> +		return false;
> +	default:
> +		igt_info("Unsupported mode for test %s\n",
> +			 (char*)&fillers[i].fourcc);
> +		return false;
> +	}
> +
> +	do_write(data->gfx_fd, data->gem_handle, (void*)data->buf,
> writesize);
> +	return true;
> +}
> +
> +
> +static bool setup_fb(data_t *data, igt_output_t *output, igt_plane_t
> *plane,
> +		     uint32_t format)
> +{
> +	drmModeModeInfo *mode;
> +	uint64_t w, h;
> +	signed ret, gemsize = 0;
> +	unsigned tile_width, tile_height, stride;
> +	uint32_t offsets[4] = {};
> +	uint32_t* offsetpointer = NULL;
> +
> +	mode = igt_output_get_mode(output);
> +	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
> +		w = mode->hdisplay ;
> +		h = mode->vdisplay;
> +	} else {
> +		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
> +		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
> +	}
> +
> +	switch(format) {
> +#ifdef DRM_FORMAT_P010
> +	case DRM_FORMAT_P010:
> +#endif
> +#ifdef DRM_FORMAT_P012
> +	case DRM_FORMAT_P012:
> +#endif
> +#ifdef DRM_FORMAT_P016
> +	case DRM_FORMAT_P016:
> +#endif
> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> defined(DRM_FORMAT_P016)
> +		tile_width = 512;
> +		tile_height = 16;
> +		stride = ALIGN(w*2, tile_width);
> +		data->size = offsets[1] = stride*ALIGN(h,
> tile_height);
> +		gemsize = data->size*2;
> +		offsetpointer = (uint32_t*)&offsets;
> +		break;
> +#endif
> +	case DRM_FORMAT_NV12:
> +		tile_width = 512;
> +		tile_height = 16;
> +		stride = ALIGN(w, tile_width);
> +		data->size = offsets[1] = stride*ALIGN(h,
> tile_height);
> +		gemsize = data->size*2;
> +		offsetpointer = (uint32_t*)&offsets;
> +		break;
> +	default:
> +		tile_width = 512;
> +		tile_height = 16;
> +
> +		/*
> +		 * w*4 so there's enough space
> +		 */
> +		stride = ALIGN(w*4, tile_width);
> +		data->size = stride*ALIGN(h, tile_height);
> +		offsetpointer = NULL;
> +		gemsize = data->size;
> +		break;
> +	}
> +
> +	data->gem_handle = gem_create(data->gfx_fd, gemsize);
> +	ret = __gem_set_tiling(data->gfx_fd, data->gem_handle,
> +			       I915_TILING_NONE, stride);
> +
> +	igt_assert_eq(ret, 0);
> +
> +	ret = __kms_addfb(data->gfx_fd, data->gem_handle, w, h,
> +			  stride, format, LOCAL_DRM_FORMAT_MOD_NONE,
> +			  offsetpointer,
> LOCAL_DRM_MODE_FB_MODIFIERS,
> +			  &data->fb.fb_id);
> +
> +	if(ret < 0) {
> +		igt_info("Creating fb for format %s failed, return
> code %d\n",
> +			 (char*)&data->format.name, ret);
> +
> +		return false;
> +	}
> +
> +	data->fb.width = w;
> +	data->fb.height = h;
> +	data->fb.gem_handle = data->gem_handle;
> +	return true;
> +}
> +
> +
> +static void remove_fb(data_t* data, igt_output_t* output,
> igt_plane_t* plane)
> +{
> +	if (data->separateprimaryplane) {
> +		igt_plane_t* primary =
> igt_output_get_plane_type(output,
> +								 DRM
> _PLANE_TYPE_PRIMARY);
> +		igt_plane_set_fb(primary, NULL);
> +		igt_remove_fb(data->gfx_fd, &data->primary_fb);
> +		data->separateprimaryplane = false;
> +	}
> +
> +	igt_remove_fb(data->gfx_fd, &data->fb);
> +	free(data->buf);
> +	data->buf = NULL;
> +}
> +
> +
> +static bool prepare_crtc(data_t *data, igt_output_t *output,
> +			 igt_plane_t *plane, uint32_t format)
> +{
> +	drmModeModeInfo *mode;
> +	igt_plane_t *primary;
> +
> +	if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
> +		mode = igt_output_get_mode(output);
> +		igt_create_color_fb(data->gfx_fd,
> +				    mode->hdisplay, mode->vdisplay,
> +				    DRM_FORMAT_XRGB8888,
> +				    LOCAL_DRM_FORMAT_MOD_NONE,
> +				    0, 0, 0,
> +				    &data->primary_fb);
> +
> +		primary = igt_output_get_plane_type(output,
> +						    DRM_PLANE_TYPE_P
> RIMARY);
> +
> +		igt_plane_set_fb(primary, &data->primary_fb);
> +		igt_display_commit2(&data->display, data->commit);
> +		data->separateprimaryplane = true;
> +	}
> +
> +	if (!setup_fb(data, output, plane, format))
> +		return false;
> +
> +	free((void*)data->buf);
> +	data->buf = (unsigned char*)calloc(data->size*2, 1);
> +	return true;
> +}
> +
> +
> +static int
> +test_one_mode(data_t* data, igt_output_t *output, igt_plane_t*
> plane,
> +	      int mode)
> +{
> +	igt_crc_t current_crc;
> +	signed rVal = 0;
> +	bool do_crc;
> +	char* crccompare[2];
> +
> +	if (prepare_crtc(data, output, plane, mode)){
> +		/*
> +		 * we have fb from prepare_crtc(..) so now fill it
> in
> +		 * correctly in fill_in_fb(..)
> +		 */
> +		do_crc = fill_in_fb(data, output, plane, mode);
> +
> +		igt_plane_set_fb(plane, &data->fb);
> +		igt_fb_set_size(&data->fb, plane, data->fb.width,
> data->fb.height);
> +		igt_plane_set_size(plane, data->fb.width, data-
> >fb.height);
> +		igt_fb_set_position(&data->fb, plane, 0, 0);
> +		igt_display_commit2(&data->display, data->commit);
> +
> +		if (do_crc) {
> +			igt_pipe_crc_drain(data->pipe_crc);
> +			igt_pipe_crc_get_single(data->pipe_crc,
> &current_crc);
> +
> +			if (plane->type != DRM_PLANE_TYPE_CURSOR) {
> +				if
> (!igt_check_crc_equal(&current_crc,
> +					&data->fullscreen_crc)) {
> +					crccompare[0] =
> igt_crc_to_string(&current_crc);
> +					crccompare[1] =
> igt_crc_to_string(&data->fullscreen_crc);
> +					igt_warn("crc mismatch.
> target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
> +					free(crccompare[0]);
> +					free(crccompare[1]);
> +					rVal++;
> +				}
> +			} else {
> +				if
> (!igt_check_crc_equal(&current_crc,
> +					&data->cursor_crc)) {
> +					crccompare[0] =
> igt_crc_to_string(&current_crc);
> +					crccompare[1] =
> igt_crc_to_string(&data->cursor_crc);
> +					igt_warn("crc mismatch.
> target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
> +					free(crccompare[0]);
> +					free(crccompare[1]);
> +					rVal++;
> +				}
> +			}
> +		}
> +		remove_fb(data, output, plane);
> +		return rVal;
> +	}
> +	return 1;
> +}
> +
> +
> +static void
> +test_available_modes(data_t* data)
> +{
> +	igt_output_t *output;
> +	igt_plane_t *plane;
> +	int modeindex;
> +	enum pipe pipe;
> +	int invalids = 0;
> +	drmModePlane *modePlane;
> +	char planetype[3][8] = {"OVERLAY\0", "PRIMARY\0", "CURSOR\0"
> };
> +
> +	for_each_pipe_with_valid_output(&data->display, pipe,
> output) {
> +		igt_output_set_pipe(output, pipe);
> +		igt_display_commit2(&data->display, data->commit);
> +
> +		data->pipe_crc = igt_pipe_crc_new(data->gfx_fd,
> pipe,
> +						  INTEL_PIPE_CRC_SOU
> RCE_AUTO);
> +
> +		igt_pipe_crc_start(data->pipe_crc);
> +
> +		/*
> +		 * regenerate comparison crcs for each pipe just in
> case.
> +		 */
> +		generate_comparison_crc_list(data, output);
> +
> +		for_each_plane_on_pipe(&data->display, pipe, plane)
> {
> +			modePlane = drmModeGetPlane(data->gfx_fd,
> +						    plane-
> >drm_plane->plane_id);
> +
> +			for (modeindex = 0;
> +			     modeindex < modePlane->count_formats;
> +			     modeindex++) {
> +				data->format.dword = modePlane-
> >formats[modeindex];
> +
> +				igt_info("Testing connector %s using
> pipe %s" \
> +					 " plane index %d type %s
> mode %s\n",
> +					 igt_output_name(output),
> +					 kmstest_pipe_name(pipe),
> +					 plane->index,
> +					 planetype[plane->type],
> +					 (char*)&data->format.name);
> +
> +				invalids += test_one_mode(data,
> output,
> +							  plane,
> +							  modePlane-
> >formats[modeindex]);
> +			}
> +			drmModeFreePlane(modePlane);
> +		}
> +		igt_pipe_crc_stop(data->pipe_crc);
> +		igt_pipe_crc_free(data->pipe_crc);
> +		igt_display_commit2(&data->display, data->commit);
> +	}
> +	igt_assert(invalids == 0);
> +}
> +
> +
> +igt_main
> +{
> +	data_t data = {};
> +
> +	igt_skip_on_simulation();
> +
> +	igt_fixture {
> +		data.gfx_fd = drm_open_driver_master(DRIVER_INTEL);
> +		kmstest_set_vt_graphics_mode();
> +		igt_display_init(&data.display, data.gfx_fd);
> +		igt_require_pipe_crc(data.gfx_fd);
> +	}
> +
> +	data.commit = data.display.is_atomic ? COMMIT_ATOMIC :
> COMMIT_LEGACY;
> +
> +	igt_subtest("available_mode_test_crc") {
> +		test_available_modes(&data);
> +	}
> +
> +	igt_fixture {
> +		kmstest_restore_vt_mode();
> +		igt_display_fini(&data.display);
> +	}
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index ee03866..81ae16f 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -149,6 +149,7 @@ test_progs = [
>  	'kms_atomic',
>  	'kms_atomic_interruptible',
>  	'kms_atomic_transition',
> +	'kms_available_modes_crc',
>  	'kms_busy',
>  	'kms_ccs',
>  	'kms_chv_cursor_fail',
-- 
Mika Kahola - Intel OTC

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes
@ 2018-05-18 12:20 Juha-Pekka Heikkila
  2018-05-22 10:48 ` Mika Kahola
  0 siblings, 1 reply; 11+ messages in thread
From: Juha-Pekka Heikkila @ 2018-05-18 12:20 UTC (permalink / raw)
  To: igt-dev

Ask from kernel about supported modes for each plane and try setting
them on display and verify functionality with crc.

DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888 skip crc testing on
primary and overlay planes because they produce incorrect crcs from
hardware. DRM_FORMAT_ARGB8888 is tested on cursor plane.

v3: address review comments from Mika Kahola.
Stop crc at end of test before freeing it. Use libdrm instead
of mixing ioctl and libdrm.

v2: Address review comments from Mika Kahola.
Keep crc running for all tests while on same pipe, set tile height
to 16 and read only one crc per test.

Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Reviewed-by: Mika Kahola <mika.kahola@intel.com>
---

I didn't go adding igt_exit() at the end of the test because I use igt_main
which will do igt_exit() for me.

 tests/Makefile.sources          |   1 +
 tests/kms_available_modes_crc.c | 523 ++++++++++++++++++++++++++++++++++++++++
 tests/meson.build               |   1 +
 3 files changed, 525 insertions(+)
 create mode 100644 tests/kms_available_modes_crc.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index ddcc18f..6aa0306 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -173,6 +173,7 @@ TESTS_progs = \
 	kms_atomic \
 	kms_atomic_interruptible \
 	kms_atomic_transition \
+	kms_available_modes_crc \
 	kms_busy \
 	kms_ccs \
 	kms_chv_cursor_fail \
diff --git a/tests/kms_available_modes_crc.c b/tests/kms_available_modes_crc.c
new file mode 100644
index 0000000..da58ee5
--- /dev/null
+++ b/tests/kms_available_modes_crc.c
@@ -0,0 +1,523 @@
+/*
+ * 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.
+ *
+ */
+
+#include "drm_mode.h"
+#include "drm_fourcc.h"
+#include "igt.h"
+
+IGT_TEST_DESCRIPTION("CRC test all different plane modes which kernel advertises.");
+
+typedef struct {
+	int gfx_fd;
+	igt_display_t display;
+	enum igt_commit_style commit;
+
+	struct igt_fb fb;
+	struct igt_fb primary_fb;
+
+	union {
+		char name[5];
+		uint32_t dword;
+	} format;
+	bool separateprimaryplane;
+
+	uint32_t gem_handle;
+	uint32_t gem_handle_yuv;
+	unsigned int size;
+	unsigned char* buf;
+
+	/*
+	 * comparison crcs
+	 */
+	igt_pipe_crc_t *pipe_crc;
+
+	igt_crc_t cursor_crc;
+	igt_crc_t fullscreen_crc;
+} data_t;
+
+
+static int do_write(int fd, int handle, void *buf, int size)
+{
+	struct drm_i915_gem_pwrite write;
+	memset(&write, 0x00, sizeof(write));
+	write.handle = handle;
+	write.data_ptr = (uintptr_t)buf;
+	write.size = size;
+	write.offset = 0;
+	return igt_ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write);
+}
+
+
+static void generate_comparison_crc_list(data_t *data, igt_output_t *output)
+{
+	drmModeModeInfo *mode;
+	uint64_t w, h;
+	int fbid;
+	cairo_t *cr;
+	igt_plane_t *primary;
+
+	mode = igt_output_get_mode(output);
+	fbid = igt_create_color_fb(data->gfx_fd,
+				   mode->hdisplay,
+				   mode->vdisplay,
+				   intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ? DRM_FORMAT_XRGB8888 : DRM_FORMAT_ARGB8888,
+				   LOCAL_DRM_FORMAT_MOD_NONE,
+				   0, 0, 0,
+				   &data->primary_fb);
+
+	igt_assert(fbid);
+
+	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
+	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
+
+	cr = igt_get_cairo_ctx(data->gfx_fd, &data->primary_fb);
+	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
+			    0.0, 0.0, 0.0);
+	igt_paint_color(cr, 0, 0, w, h, 1.0, 1.0, 1.0);
+	igt_assert(cairo_status(cr) == 0);
+
+	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
+	igt_plane_set_fb(primary, &data->primary_fb);
+	igt_display_commit2(&data->display, data->commit);
+
+	igt_pipe_crc_drain(data->pipe_crc);
+	igt_pipe_crc_get_single(data->pipe_crc, &data->cursor_crc);
+	igt_plane_set_fb(primary, NULL);
+	igt_display_commit2(&data->display, data->commit);
+
+	intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ?
+		  igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay, 1.0, 1.0, 1.0) :
+		  igt_paint_color_alpha(cr, 0, 0, mode->hdisplay, mode->vdisplay, 1.0, 1.0, 1.0, 1.0);
+
+	igt_plane_set_fb(primary, &data->primary_fb);
+	igt_display_commit2(&data->display, data->commit);
+
+	igt_pipe_crc_drain(data->pipe_crc);
+	igt_pipe_crc_get_single(data->pipe_crc, &data->fullscreen_crc);
+
+	cairo_destroy(cr);
+	igt_remove_fb(data->gfx_fd, &data->primary_fb);
+}
+
+/*
+ * fill_in_fb tell in return value if selected mode should be
+ * proceed to crc check
+ */
+static bool fill_in_fb(data_t *data, igt_output_t *output, igt_plane_t *plane,
+		       uint32_t format)
+{
+	signed i, c, writesize;
+	unsigned short* ptemp_16_buf;
+	unsigned int* ptemp_32_buf;
+
+	const struct {
+		uint32_t	fourcc;
+		char		zeropadding;
+		enum		{ BYTES_PP_1=1,
+				  BYTES_PP_2=2,
+				  BYTES_PP_4=4,
+				  NV12,
+#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) || defined(DRM_FORMAT_P016)
+				  P010,
+#endif
+				  SKIP } bpp;
+		uint32_t	value;
+	} fillers[] = {
+		{ DRM_FORMAT_C8, 0, BYTES_PP_1, 0xff},
+		{ DRM_FORMAT_RGB565, 0, BYTES_PP_2, 0xffff},
+		{ DRM_FORMAT_XRGB8888, 0, BYTES_PP_4, 0xffffffff},
+		{ DRM_FORMAT_XBGR8888, 0, BYTES_PP_4, 0xffffffff},
+
+		/*
+		 * following two are skipped because blending seems to work
+		 * incorrectly with exception of AR24 on cursor plane.
+		 * Test still creates the planes, just filling plane
+		 * and getting crc is skipped.
+		 */
+		{ DRM_FORMAT_ARGB8888, 0, SKIP, 0xffffffff},
+		{ DRM_FORMAT_ABGR8888, 0, SKIP, 0x00ffffff},
+
+		{ DRM_FORMAT_XRGB2101010, 0, BYTES_PP_4, 0xffffffff},
+		{ DRM_FORMAT_XBGR2101010, 0, BYTES_PP_4, 0xffffffff},
+
+		{ DRM_FORMAT_YUYV, 0, BYTES_PP_4, 0x80eb80eb},
+		{ DRM_FORMAT_YVYU, 0, BYTES_PP_4, 0x80eb80eb},
+		{ DRM_FORMAT_VYUY, 0, BYTES_PP_4, 0xeb80eb80},
+		{ DRM_FORMAT_UYVY, 0, BYTES_PP_4, 0xeb80eb80},
+
+		/*
+		 * (semi-)planar formats
+		 */
+		{ DRM_FORMAT_NV12, 0, NV12, 0x80eb},
+#ifdef DRM_FORMAT_P010
+		{ DRM_FORMAT_P010, 0, P010, 0x8000eb00},
+#endif
+#ifdef DRM_FORMAT_P012
+		{ DRM_FORMAT_P012, 0, P010, 0x8000eb00},
+#endif
+#ifdef DRM_FORMAT_P016
+		{ DRM_FORMAT_P016, 0, P010, 0x8000eb00},
+#endif
+		{ 0, 0, 0, 0 }
+	};
+
+	for( i = 0; fillers[i].fourcc != 0; i++ ) {
+		if( fillers[i].fourcc == format )
+			break;
+	}
+
+	switch (fillers[i].bpp) {
+	case BYTES_PP_4:
+		ptemp_32_buf = (unsigned int*)data->buf;
+		for (c = 0; c < data->size/4; c++)
+			ptemp_32_buf[c] = fillers[i].value;
+		writesize = data->size;
+		break;
+	case BYTES_PP_2:
+		ptemp_16_buf = (unsigned short*)data->buf;
+		for (c = 0; c < data->size/2; c++)
+			ptemp_16_buf[c] = (unsigned short)fillers[i].value;
+		writesize = data->size;
+		break;
+	case BYTES_PP_1:
+		memset((void*)data->buf, fillers[i].value, data->size);
+		writesize = data->size;
+		break;
+	case NV12:
+		memset((void*)data->buf, fillers[i].value&0xff,
+		       data->size);
+
+		memset((void*)(data->buf+data->size),
+		       (fillers[i].value>>8)&0xff, data->size/2);
+
+		writesize = data->size+data->size/2;
+		break;
+#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) || defined(DRM_FORMAT_P016)
+	case P010:
+		ptemp_16_buf = (unsigned short*)data->buf;
+		for (c = 0; c < data->size/2; c++)
+			ptemp_16_buf[c] = (unsigned short)fillers[i].value&0xffff;
+
+		ptemp_16_buf = (unsigned short*)(data->buf+data->size);
+		for (c = 0; c < data->size/2; c++)
+			ptemp_16_buf[c] = (unsigned short)(fillers[i].value>>16)&0xffff;
+
+		writesize = data->size+data->size/2;
+		break;
+#endif
+	case SKIP:
+		if (fillers[i].fourcc == DRM_FORMAT_ARGB8888 &&
+		    plane->type == DRM_PLANE_TYPE_CURSOR) {
+		/*
+		 * special for cursor plane where blending works correctly.
+		 */
+			ptemp_32_buf = (unsigned int*)data->buf;
+			for (c = 0; c < data->size/4; c++)
+				ptemp_32_buf[c] = fillers[i].value;
+			writesize = data->size;
+			break;
+		}
+		igt_info("Format %s CRC comparison skipped by design.\n",
+			 (char*)&fillers[i].fourcc);
+
+		return false;
+	default:
+		igt_info("Unsupported mode for test %s\n",
+			 (char*)&fillers[i].fourcc);
+		return false;
+	}
+
+	do_write(data->gfx_fd, data->gem_handle, (void*)data->buf, writesize);
+	return true;
+}
+
+
+static bool setup_fb(data_t *data, igt_output_t *output, igt_plane_t *plane,
+		     uint32_t format)
+{
+	drmModeModeInfo *mode;
+	uint64_t w, h;
+	signed ret, gemsize = 0;
+	unsigned tile_width, tile_height, stride;
+	uint32_t offsets[4] = {};
+	uint32_t* offsetpointer = NULL;
+
+	mode = igt_output_get_mode(output);
+	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+		w = mode->hdisplay ;
+		h = mode->vdisplay;
+	} else {
+		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
+		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
+	}
+
+	switch(format) {
+#ifdef DRM_FORMAT_P010
+	case DRM_FORMAT_P010:
+#endif
+#ifdef DRM_FORMAT_P012
+	case DRM_FORMAT_P012:
+#endif
+#ifdef DRM_FORMAT_P016
+	case DRM_FORMAT_P016:
+#endif
+#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) || defined(DRM_FORMAT_P016)
+		tile_width = 512;
+		tile_height = 16;
+		stride = ALIGN(w*2, tile_width);
+		data->size = offsets[1] = stride*ALIGN(h, tile_height);
+		gemsize = data->size*2;
+		offsetpointer = (uint32_t*)&offsets;
+		break;
+#endif
+	case DRM_FORMAT_NV12:
+		tile_width = 512;
+		tile_height = 16;
+		stride = ALIGN(w, tile_width);
+		data->size = offsets[1] = stride*ALIGN(h, tile_height);
+		gemsize = data->size*2;
+		offsetpointer = (uint32_t*)&offsets;
+		break;
+	default:
+		tile_width = 512;
+		tile_height = 16;
+
+		/*
+		 * w*4 so there's enough space
+		 */
+		stride = ALIGN(w*4, tile_width);
+		data->size = stride*ALIGN(h, tile_height);
+		offsetpointer = NULL;
+		gemsize = data->size;
+		break;
+	}
+
+	data->gem_handle = gem_create(data->gfx_fd, gemsize);
+	ret = __gem_set_tiling(data->gfx_fd, data->gem_handle,
+			       I915_TILING_NONE, stride);
+
+	igt_assert_eq(ret, 0);
+
+	ret = __kms_addfb(data->gfx_fd, data->gem_handle, w, h,
+			  stride, format, LOCAL_DRM_FORMAT_MOD_NONE,
+			  offsetpointer, LOCAL_DRM_MODE_FB_MODIFIERS,
+			  &data->fb.fb_id);
+
+	if(ret < 0) {
+		igt_info("Creating fb for format %s failed, return code %d\n",
+			 (char*)&data->format.name, ret);
+
+		return false;
+	}
+
+	data->fb.width = w;
+	data->fb.height = h;
+	data->fb.gem_handle = data->gem_handle;
+	return true;
+}
+
+
+static void remove_fb(data_t* data, igt_output_t* output, igt_plane_t* plane)
+{
+	if (data->separateprimaryplane) {
+		igt_plane_t* primary = igt_output_get_plane_type(output,
+								 DRM_PLANE_TYPE_PRIMARY);
+		igt_plane_set_fb(primary, NULL);
+		igt_remove_fb(data->gfx_fd, &data->primary_fb);
+		data->separateprimaryplane = false;
+	}
+
+	igt_remove_fb(data->gfx_fd, &data->fb);
+	free(data->buf);
+	data->buf = NULL;
+}
+
+
+static bool prepare_crtc(data_t *data, igt_output_t *output,
+			 igt_plane_t *plane, uint32_t format)
+{
+	drmModeModeInfo *mode;
+	igt_plane_t *primary;
+
+	if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
+		mode = igt_output_get_mode(output);
+		igt_create_color_fb(data->gfx_fd,
+				    mode->hdisplay, mode->vdisplay,
+				    DRM_FORMAT_XRGB8888,
+				    LOCAL_DRM_FORMAT_MOD_NONE,
+				    0, 0, 0,
+				    &data->primary_fb);
+
+		primary = igt_output_get_plane_type(output,
+						    DRM_PLANE_TYPE_PRIMARY);
+
+		igt_plane_set_fb(primary, &data->primary_fb);
+		igt_display_commit2(&data->display, data->commit);
+		data->separateprimaryplane = true;
+	}
+
+	if (!setup_fb(data, output, plane, format))
+		return false;
+
+	free((void*)data->buf);
+	data->buf = (unsigned char*)calloc(data->size*2, 1);
+	return true;
+}
+
+
+static int
+test_one_mode(data_t* data, igt_output_t *output, igt_plane_t* plane,
+	      int mode)
+{
+	igt_crc_t current_crc;
+	signed rVal = 0;
+	bool do_crc;
+	char* crccompare[2];
+
+	if (prepare_crtc(data, output, plane, mode)){
+		/*
+		 * we have fb from prepare_crtc(..) so now fill it in
+		 * correctly in fill_in_fb(..)
+		 */
+		do_crc = fill_in_fb(data, output, plane, mode);
+
+		igt_plane_set_fb(plane, &data->fb);
+		igt_fb_set_size(&data->fb, plane, data->fb.width, data->fb.height);
+		igt_plane_set_size(plane, data->fb.width, data->fb.height);
+		igt_fb_set_position(&data->fb, plane, 0, 0);
+		igt_display_commit2(&data->display, data->commit);
+
+		if (do_crc) {
+			igt_pipe_crc_drain(data->pipe_crc);
+			igt_pipe_crc_get_single(data->pipe_crc, &current_crc);
+
+			if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+				if (!igt_check_crc_equal(&current_crc,
+					&data->fullscreen_crc)) {
+					crccompare[0] = igt_crc_to_string(&current_crc);
+					crccompare[1] = igt_crc_to_string(&data->fullscreen_crc);
+					igt_warn("crc mismatch. target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
+					free(crccompare[0]);
+					free(crccompare[1]);
+					rVal++;
+				}
+			} else {
+				if (!igt_check_crc_equal(&current_crc,
+					&data->cursor_crc)) {
+					crccompare[0] = igt_crc_to_string(&current_crc);
+					crccompare[1] = igt_crc_to_string(&data->cursor_crc);
+					igt_warn("crc mismatch. target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
+					free(crccompare[0]);
+					free(crccompare[1]);
+					rVal++;
+				}
+			}
+		}
+		remove_fb(data, output, plane);
+		return rVal;
+	}
+	return 1;
+}
+
+
+static void
+test_available_modes(data_t* data)
+{
+	igt_output_t *output;
+	igt_plane_t *plane;
+	int modeindex;
+	enum pipe pipe;
+	int invalids = 0;
+	drmModePlane *modePlane;
+	char planetype[3][8] = {"OVERLAY\0", "PRIMARY\0", "CURSOR\0" };
+
+	for_each_pipe_with_valid_output(&data->display, pipe, output) {
+		igt_output_set_pipe(output, pipe);
+		igt_display_commit2(&data->display, data->commit);
+
+		data->pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
+						  INTEL_PIPE_CRC_SOURCE_AUTO);
+
+		igt_pipe_crc_start(data->pipe_crc);
+
+		/*
+		 * regenerate comparison crcs for each pipe just in case.
+		 */
+		generate_comparison_crc_list(data, output);
+
+		for_each_plane_on_pipe(&data->display, pipe, plane) {
+			modePlane = drmModeGetPlane(data->gfx_fd,
+						    plane->drm_plane->plane_id);
+
+			for (modeindex = 0;
+			     modeindex < modePlane->count_formats;
+			     modeindex++) {
+				data->format.dword = modePlane->formats[modeindex];
+
+				igt_info("Testing connector %s using pipe %s" \
+					 " plane index %d type %s mode %s\n",
+					 igt_output_name(output),
+					 kmstest_pipe_name(pipe),
+					 plane->index,
+					 planetype[plane->type],
+					 (char*)&data->format.name);
+
+				invalids += test_one_mode(data, output,
+							  plane,
+							  modePlane->formats[modeindex]);
+			}
+			drmModeFreePlane(modePlane);
+		}
+		igt_pipe_crc_stop(data->pipe_crc);
+		igt_pipe_crc_free(data->pipe_crc);
+		igt_display_commit2(&data->display, data->commit);
+	}
+	igt_assert(invalids == 0);
+}
+
+
+igt_main
+{
+	data_t data = {};
+
+	igt_skip_on_simulation();
+
+	igt_fixture {
+		data.gfx_fd = drm_open_driver_master(DRIVER_INTEL);
+		kmstest_set_vt_graphics_mode();
+		igt_display_init(&data.display, data.gfx_fd);
+		igt_require_pipe_crc(data.gfx_fd);
+	}
+
+	data.commit = data.display.is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
+
+	igt_subtest("available_mode_test_crc") {
+		test_available_modes(&data);
+	}
+
+	igt_fixture {
+		kmstest_restore_vt_mode();
+		igt_display_fini(&data.display);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index ee03866..81ae16f 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -149,6 +149,7 @@ test_progs = [
 	'kms_atomic',
 	'kms_atomic_interruptible',
 	'kms_atomic_transition',
+	'kms_available_modes_crc',
 	'kms_busy',
 	'kms_ccs',
 	'kms_chv_cursor_fail',
-- 
2.7.4

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes
  2018-03-20 16:13 Juha-Pekka Heikkila
@ 2018-05-15  9:15 ` Mika Kahola
  0 siblings, 0 replies; 11+ messages in thread
From: Mika Kahola @ 2018-05-15  9:15 UTC (permalink / raw)
  To: Juha-Pekka Heikkila, igt-dev

On Tue, 2018-03-20 at 18:13 +0200, Juha-Pekka Heikkila wrote:
> Ask from kernel about supported modes for each plane and try setting
> them on display and verify functionality with crc.
> 
> DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888 skip crc testing on
> primary and overlay planes because they produce incorrect crcs from
> hardware. DRM_FORMAT_ARGB8888 is tested on cursor plane.
> 
> v2: Added support for planar formats.
> 
> v3: Address review comments from Mika Kahola.
> Keep crc running for all tests while on same pipe, set tile height
> to 16 and read only one crc per test.
> 
> Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
> ---
>  tests/Makefile.sources          |   1 +
>  tests/kms_available_modes_crc.c | 541
> ++++++++++++++++++++++++++++++++++++++++
>  tests/meson.build               |   1 +
>  3 files changed, 543 insertions(+)
>  create mode 100644 tests/kms_available_modes_crc.c
> 
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index f1d1cba..0622048 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -173,6 +173,7 @@ TESTS_progs = \
>  	kms_atomic \
>  	kms_atomic_interruptible \
>  	kms_atomic_transition \
> +	kms_available_modes_crc \
>  	kms_busy \
>  	kms_ccs \
>  	kms_chv_cursor_fail \
> diff --git a/tests/kms_available_modes_crc.c
> b/tests/kms_available_modes_crc.c
> new file mode 100644
> index 0000000..18c3685
> --- /dev/null
> +++ b/tests/kms_available_modes_crc.c
> @@ -0,0 +1,541 @@
> +/*
> + * 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.
> + *
> + */
> +
> +#include "drm_mode.h"
> +#include "drm_fourcc.h"
> +#include "igt.h"
> +#include <sys/ioctl.h>
> +
> +IGT_TEST_DESCRIPTION("CRC test all different plane modes which
> kernel advertises.");
> +
> +typedef struct {
> +	int gfx_fd;
> +	igt_display_t display;
> +	enum igt_commit_style commit;
> +
> +	struct igt_fb fb;
> +	struct igt_fb primary_fb;
> +
> +	char format_name[5];
> +	bool separateprimaryplane;
> +
> +	uint32_t gem_handle;
> +	uint32_t gem_handle_yuv;
> +	unsigned int size;
> +	unsigned char* buf;
> +
> +	/*
> +	 * comparison crcs
> +	 */
> +	igt_pipe_crc_t *pipe_crc;
> +
> +	igt_crc_t cursor_crc;
> +	igt_crc_t fullscreen_crc;
> +} data_t;
> +
> +
> +static int do_write(int fd, int handle, void *buf, int size)
> +{
> +	struct drm_i915_gem_pwrite write;
> +	memset(&write, 0x00, sizeof(write));
> +	write.handle = handle;
> +	write.data_ptr = (uintptr_t)buf;
> +	write.size = size;
> +	write.offset = 0;
> +	return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write);
> +}
> +
> +
> +static void generate_comparison_crc_list(data_t *data, igt_output_t
> *output)
> +{
> +	drmModeModeInfo *mode;
> +	uint64_t w, h;
> +	int fbid;
> +	cairo_t *cr;
> +	igt_plane_t *primary;
> +
> +	mode = igt_output_get_mode(output);
> +	fbid = igt_create_color_fb(data->gfx_fd,
> +				   mode->hdisplay,
> +				   mode->vdisplay,
> +				   intel_gen(intel_get_drm_devid(dat
> a->gfx_fd)) < 9 ? DRM_FORMAT_XRGB8888 : DRM_FORMAT_ARGB8888,
> +				   LOCAL_DRM_FORMAT_MOD_NONE,
> +				   0, 0, 0,
> +				   &data->primary_fb);
> +
> +	igt_assert(fbid);
> +
> +	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
> +	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
> +
> +	cr = igt_get_cairo_ctx(data->gfx_fd, &data->primary_fb);
> +	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
> +			    0.0, 0.0, 0.0);
> +	igt_paint_color(cr, 0, 0, w, h, 1.0, 1.0, 1.0);
> +	igt_assert(cairo_status(cr) == 0);
> +
> +	primary = igt_output_get_plane_type(output,
> DRM_PLANE_TYPE_PRIMARY);
> +	igt_plane_set_fb(primary, &data->primary_fb);
> +	igt_display_commit2(&data->display, data->commit);
> +
> +	igt_pipe_crc_drain(data->pipe_crc);
> +	igt_pipe_crc_get_single(data->pipe_crc, &data->cursor_crc);
> +	igt_plane_set_fb(primary, NULL);
> +	igt_display_commit2(&data->display, data->commit);
> +
> +	intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ?
> +		  igt_paint_color(cr, 0, 0, mode->hdisplay, mode-
> >vdisplay, 1.0, 1.0, 1.0) :
> +		  igt_paint_color_alpha(cr, 0, 0, mode->hdisplay,
> mode->vdisplay, 1.0, 1.0, 1.0, 1.0);
> +
> +	igt_plane_set_fb(primary, &data->primary_fb);
> +	igt_display_commit2(&data->display, data->commit);
> +
> +	igt_pipe_crc_drain(data->pipe_crc);
> +	igt_pipe_crc_get_single(data->pipe_crc, &data-
> >fullscreen_crc);
> +
> +	cairo_destroy(cr);
> +	igt_remove_fb(data->gfx_fd, &data->primary_fb);
> +}
> +
> +/*
> + * fill_in_fb tell in return value if selected mode should be
> + * proceed to crc check
> + */
> +static bool fill_in_fb(data_t *data, igt_output_t *output,
> igt_plane_t *plane,
> +		       uint32_t format)
> +{
> +	signed i, c, writesize;
> +	unsigned short* ptemp_16_buf;
> +	unsigned int* ptemp_32_buf;
> +
> +	const struct {
> +		uint32_t	fourcc;
> +		char		zeropadding;
> +		enum		{ BYTES_PP_1=1,
> +				  BYTES_PP_2=2,
> +				  BYTES_PP_4=4,
> +				  NV12,
> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> defined(DRM_FORMAT_P016)
> +				  P010,
> +#endif
> +				  SKIP } bpp;
> +		uint32_t	value;
> +	} fillers[] = {
> +		{ DRM_FORMAT_C8, 0, BYTES_PP_1, 0xff},
> +		{ DRM_FORMAT_RGB565, 0, BYTES_PP_2, 0xffff},
> +		{ DRM_FORMAT_XRGB8888, 0, BYTES_PP_4, 0xffffffff},
> +		{ DRM_FORMAT_XBGR8888, 0, BYTES_PP_4, 0xffffffff},
> +
> +		/*
> +		 * following two are skipped because blending seems
> to work
> +		 * incorrectly with exception of AR24 on cursor
> plane.
> +		 * Test still creates the planes, just filling plane
> +		 * and getting crc is skipped.
> +		 */
> +		{ DRM_FORMAT_ARGB8888, 0, SKIP, 0xffffffff},
> +		{ DRM_FORMAT_ABGR8888, 0, SKIP, 0x00ffffff},
> +
> +		{ DRM_FORMAT_XRGB2101010, 0, BYTES_PP_4,
> 0xffffffff},
> +		{ DRM_FORMAT_XBGR2101010, 0, BYTES_PP_4,
> 0xffffffff},
> +
> +		{ DRM_FORMAT_YUYV, 0, BYTES_PP_4, 0x80eb80eb},
> +		{ DRM_FORMAT_YVYU, 0, BYTES_PP_4, 0x80eb80eb},
> +		{ DRM_FORMAT_VYUY, 0, BYTES_PP_4, 0xeb80eb80},
> +		{ DRM_FORMAT_UYVY, 0, BYTES_PP_4, 0xeb80eb80},
> +
> +		/*
> +		 * (semi-)planar formats
> +		 */
> +		{ DRM_FORMAT_NV12, 0, NV12, 0x80eb},
> +#ifdef DRM_FORMAT_P010
> +		{ DRM_FORMAT_P010, 0, P010, 0x8000eb00},
> +#endif
> +#ifdef DRM_FORMAT_P012
> +		{ DRM_FORMAT_P012, 0, P010, 0x8000eb00},
> +#endif
> +#ifdef DRM_FORMAT_P016
> +		{ DRM_FORMAT_P016, 0, P010, 0x8000eb00},
> +#endif
> +		{ 0, 0, 0, 0 }
> +	};
> +
> +	for( i = 0; fillers[i].fourcc != 0; i++ ) {
> +		if( fillers[i].fourcc == format )
> +			break;
> +	}
> +
> +	switch (fillers[i].bpp) {
> +	case BYTES_PP_4:
> +		ptemp_32_buf = (unsigned int*)data->buf;
> +		for (c = 0; c < data->size/4; c++)
> +			ptemp_32_buf[c] = fillers[i].value;
> +		writesize = data->size;
> +		break;
> +	case BYTES_PP_2:
> +		ptemp_16_buf = (unsigned short*)data->buf;
> +		for (c = 0; c < data->size/2; c++)
> +			ptemp_16_buf[c] = (unsigned
> short)fillers[i].value;
> +		writesize = data->size;
> +		break;
> +	case BYTES_PP_1:
> +		memset((void*)data->buf, fillers[i].value, data-
> >size);
> +		writesize = data->size;
> +		break;
> +	case NV12:
> +		memset((void*)data->buf, fillers[i].value&0xff,
> +		       data->size);
> +
> +		memset((void*)(data->buf+data->size),
> +		       (fillers[i].value>>8)&0xff, data->size/2);
> +
> +		writesize = data->size+data->size/2;
> +		break;
> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> defined(DRM_FORMAT_P016)
> +	case P010:
> +		ptemp_16_buf = (unsigned short*)data->buf;
> +		for (c = 0; c < data->size/2; c++)
> +			ptemp_16_buf[c] = (unsigned
> short)fillers[i].value&0xffff;
> +
> +		ptemp_16_buf = (unsigned short*)(data->buf+data-
> >size);
> +		for (c = 0; c < data->size/2; c++)
> +			ptemp_16_buf[c] = (unsigned
> short)(fillers[i].value>>16)&0xffff;
> +
> +		writesize = data->size+data->size/2;
> +		break;
> +#endif
> +	case SKIP:
> +		if (fillers[i].fourcc == DRM_FORMAT_ARGB8888 &&
> +		    plane->type == DRM_PLANE_TYPE_CURSOR) {
> +		/*
> +		 * special for cursor plane where blending works
> correctly.
> +		 */
> +			ptemp_32_buf = (unsigned int*)data->buf;
> +			for (c = 0; c < data->size/4; c++)
> +				ptemp_32_buf[c] = fillers[i].value;
> +			writesize = data->size;
> +			break;
> +		}
> +		igt_info("Format %s CRC comparison skipped by
> design.\n",
> +			 (char*)&fillers[i].fourcc);
> +
> +		return false;
> +	default:
> +		igt_info("Unsupported mode for test %s\n",
> +			 (char*)&fillers[i].fourcc);
> +		return false;
> +	}
> +
> +	do_write(data->gfx_fd, data->gem_handle, (void*)data->buf,
> writesize);
> +	return true;
> +}
> +
> +
> +static bool setup_fb(data_t *data, igt_output_t *output, igt_plane_t
> *plane,
> +		     uint32_t format)
> +{
> +	drmModeModeInfo *mode;
> +	uint64_t w, h;
> +	signed ret, gemsize = 0;
> +	unsigned tile_width, tile_height, stride;
> +	uint32_t offsets[4] = {};
> +	uint32_t* offsetpointer = NULL;
> +
> +	mode = igt_output_get_mode(output);
> +	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
> +		w = mode->hdisplay ;
> +		h = mode->vdisplay;
> +	} else {
> +		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
> +		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
> +	}
> +
> +	switch(format) {
> +#ifdef DRM_FORMAT_P010
> +	case DRM_FORMAT_P010:
> +#endif
> +#ifdef DRM_FORMAT_P012
> +	case DRM_FORMAT_P012:
> +#endif
> +#ifdef DRM_FORMAT_P016
> +	case DRM_FORMAT_P016:
> +#endif
> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> defined(DRM_FORMAT_P016)
> +		tile_width = 512;
> +		tile_height = 16;
> +		stride = ALIGN(w*2, tile_width);
> +		data->size = offsets[1] = stride*ALIGN(h,
> tile_height);
> +		gemsize = data->size*2;
> +		offsetpointer = (uint32_t*)&offsets;
> +		break;
> +#endif
> +	case DRM_FORMAT_NV12:
> +		tile_width = 512;
> +		tile_height = 16;
> +		stride = ALIGN(w, tile_width);
> +		data->size = offsets[1] = stride*ALIGN(h,
> tile_height);
> +		gemsize = data->size*2;
> +		offsetpointer = (uint32_t*)&offsets;
> +		break;
> +	default:
> +		tile_width = 512;
> +		tile_height = 16;
> +
> +		/*
> +		 * w*4 so there's enough space
> +		 */
> +		stride = ALIGN(w*4, tile_width);
> +		data->size = stride*ALIGN(h, tile_height);
> +		offsetpointer = NULL;
> +		gemsize = data->size;
> +		break;
> +	}
> +
> +	data->gem_handle = gem_create(data->gfx_fd, gemsize);
> +	ret = __gem_set_tiling(data->gfx_fd, data->gem_handle,
> +			       I915_TILING_NONE, stride);
> +
> +	igt_assert_eq(ret, 0);
> +
> +	ret = __kms_addfb(data->gfx_fd, data->gem_handle, w, h,
> +			  stride, format, LOCAL_DRM_FORMAT_MOD_NONE,
> +			  offsetpointer,
> LOCAL_DRM_MODE_FB_MODIFIERS,
> +			  &data->fb.fb_id);
> +
> +	if(ret < 0) {
> +		igt_info("Creating fb for format %s failed, return
> code %d\n",
> +			 (char*)&data->format_name, ret);
> +
> +		return false;
> +	}
> +
> +	data->fb.width = w;
> +	data->fb.height = h;
> +	data->fb.gem_handle = data->gem_handle;
> +	return true;
> +}
> +
> +
> +static void remove_fb(data_t* data, igt_output_t* output,
> igt_plane_t* plane)
> +{
> +	if (data->separateprimaryplane) {
> +		igt_plane_t* primary =
> igt_output_get_plane_type(output,
> +								 DRM
> _PLANE_TYPE_PRIMARY);
> +		igt_plane_set_fb(primary, NULL);
> +		igt_remove_fb(data->gfx_fd, &data->primary_fb);
> +		data->separateprimaryplane = false;
> +	}
> +
> +	igt_remove_fb(data->gfx_fd, &data->fb);
> +	free(data->buf);
> +	data->buf = NULL;
> +}
> +
> +
> +static bool prepare_crtc(data_t *data, igt_output_t *output,
> +			 igt_plane_t *plane, uint32_t format)
> +{
> +	drmModeModeInfo *mode;
> +	igt_plane_t *primary;
> +
> +	if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
> +		mode = igt_output_get_mode(output);
> +		igt_create_color_fb(data->gfx_fd,
> +				    mode->hdisplay, mode->vdisplay,
> +				    DRM_FORMAT_XRGB8888,
> +				    LOCAL_DRM_FORMAT_MOD_NONE,
> +				    0, 0, 0,
> +				    &data->primary_fb);
> +
> +		primary = igt_output_get_plane_type(output,
> +						    DRM_PLANE_TYPE_P
> RIMARY);
> +
> +		igt_plane_set_fb(primary, &data->primary_fb);
> +		igt_display_commit2(&data->display, data->commit);
> +		data->separateprimaryplane = true;
> +	}
> +
> +	if (!setup_fb(data, output, plane, format))
> +		return false;
> +
> +	free((void*)data->buf);
> +	data->buf = (unsigned char*)calloc(data->size*2, 1);
> +	return true;
> +}
> +
> +
> +static int
> +test_one_mode(data_t* data, igt_output_t *output, igt_plane_t*
> plane,
> +	      int mode)
> +{
> +	igt_crc_t current_crc;
> +	signed rVal = 0;
> +	bool do_crc;
> +	char* crccompare[2];
> +
> +	if (prepare_crtc(data, output, plane, mode)){
> +		/*
> +		 * we have fb from prepare_crtc(..) so now fill it
> in
> +		 * correctly in fill_in_fb(..)
> +		 */
> +		do_crc = fill_in_fb(data, output, plane, mode);
> +
> +		igt_plane_set_fb(plane, &data->fb);
> +		igt_fb_set_size(&data->fb, plane, data->fb.width,
> data->fb.height);
> +		igt_plane_set_size(plane, data->fb.width, data-
> >fb.height);
> +		igt_fb_set_position(&data->fb, plane, 0, 0);
> +		igt_display_commit2(&data->display, data->commit);
> +
> +		if (do_crc) {
> +			igt_pipe_crc_drain(data->pipe_crc);
> +			igt_pipe_crc_get_single(data->pipe_crc,
> &current_crc);
> +
> +			if (plane->type != DRM_PLANE_TYPE_CURSOR) {
> +				if
> (!igt_check_crc_equal(&current_crc,
> +					&data->fullscreen_crc)) {
> +					crccompare[0] =
> igt_crc_to_string(&current_crc);
> +					crccompare[1] =
> igt_crc_to_string(&data->fullscreen_crc);
> +					igt_warn("crc mismatch.
> target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
> +					free(crccompare[0]);
> +					free(crccompare[1]);
> +					rVal++;
> +				}
> +			} else {
> +				if
> (!igt_check_crc_equal(&current_crc,
> +					&data->cursor_crc)) {
> +					crccompare[0] =
> igt_crc_to_string(&current_crc);
> +					crccompare[1] =
> igt_crc_to_string(&data->cursor_crc);
> +					igt_warn("crc mismatch.
> target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
> +					free(crccompare[0]);
> +					free(crccompare[1]);
> +					rVal++;
> +				}
> +			}
> +		}
> +		remove_fb(data, output, plane);
> +		return rVal;
> +	}
> +	return 1;
> +}
> +
> +
> +static void
> +test_available_modes(data_t* data)
> +{
> +	igt_output_t *output;
> +	igt_plane_t *plane;
> +	int* u32ptr_formats;
> +	int modeindex;
> +	enum pipe pipe;
> +	struct drm_mode_get_plane one_plane = {};
> +	int invalids = 0;
> +
> +	char planetype[3][8] = {"OVERLAY\0", "PRIMARY\0", "CURSOR\0"
> };
> +
> +	for_each_pipe_with_valid_output(&data->display, pipe,
> output) {
> +		igt_output_set_pipe(output, pipe);
> +		igt_display_commit2(&data->display, data->commit);
> +
> +		data->pipe_crc = igt_pipe_crc_new(data->gfx_fd,
> pipe,
> +						  INTEL_PIPE_CRC_SOU
> RCE_AUTO);
> +
> +		igt_pipe_crc_start(data->pipe_crc);
> +
> +		/*
> +		 * regenerate comparison crcs for each pipe just in
> case.
> +		 */
> +		generate_comparison_crc_list(data, output);
> +
> +		for_each_plane_on_pipe(&data->display, pipe, plane)
> {
> +			memset((void*)&one_plane, 0,
> +			       sizeof(struct drm_mode_get_plane));
> +			one_plane.plane_id = plane->drm_plane-
> >plane_id;
> +			/*
> +			 * first call to know how much space needed,
> +			 * second call to get list of supported
> modes.
> +			 */
> +			igt_ioctl(data->gfx_fd,
> DRM_IOCTL_MODE_GETPLANE,
> +				  &one_plane);
drmModeGetPlane() or igt_ioctl(). Both work and is a matter of style
and preference. I'm not sure which one would be more preferred way.

> +			igt_assert(one_plane.count_format_types >
> 0);
> +
> +			u32ptr_formats =
> (int*)calloc(one_plane.count_format_types,
> +						      sizeof(int));
> +
> +			one_plane.format_type_ptr =
> (__u64)u32ptr_formats;
> +			igt_ioctl(data->gfx_fd,
> DRM_IOCTL_MODE_GETPLANE,
> +				  &one_plane);
> +
> +			for (modeindex = 0;
> +			     modeindex <
> one_plane.count_format_types;
> +			     modeindex++) {
> +				data->format_name[0] =
> u32ptr_formats[modeindex]&0xff;
> +				data->format_name[1] =
> (u32ptr_formats[modeindex]>>8)&0xff;
> +				data->format_name[2] =
> (u32ptr_formats[modeindex]>>16)&0xff;
> +				data->format_name[3] =
> (u32ptr_formats[modeindex]>>24)&0xff;
> +
> +				igt_info("Testing connector %s using
> pipe %s" \
> +					 " plane index %d type %s
> mode %s\n",
> +					 igt_output_name(output),
> +					 kmstest_pipe_name(pipe),
> +					 plane->index,
> +					 planetype[plane->type],
> +					 (char*)&data->format_name);
> +
> +				invalids += test_one_mode(data,
> output,
> +							  plane,
> +							  u32ptr_for
> mats[modeindex]);
> +			}
> +			free((void*)one_plane.format_type_ptr);
> +		}
> +
> +		igt_pipe_crc_free(data->pipe_crc);
We should stop collecting crc's before we free the memory.

> +		igt_display_commit2(&data->display, data->commit);
> +	}
> +	igt_assert(invalids == 0);
> +}
> +
> +
> +igt_main
> +{
> +	data_t data = {};
> +
> +	igt_skip_on_simulation();
> +
> +	igt_fixture {
> +		data.gfx_fd = drm_open_driver_master(DRIVER_INTEL);
> +		kmstest_set_vt_graphics_mode();
> +		igt_display_init(&data.display, data.gfx_fd);
> +		igt_require_pipe_crc(data.gfx_fd);
> +	}
> +
> +	data.commit = data.display.is_atomic ? COMMIT_ATOMIC :
> COMMIT_LEGACY;
> +
> +	igt_subtest("available_mode_test_crc") {
> +		test_available_modes(&data);
> +	}
> +
> +	igt_fixture {
> +		kmstest_restore_vt_mode();
> +		igt_display_fini(&data.display);
> +	}
Maybe igt_exit() at the end.

With these minor additions, this patch is

Reviewed-by: Mika Kahola <mika.kahola@intel.com>

> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 22e4ac9..6a5bd96 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -150,6 +150,7 @@ test_progs = [
>  	'kms_atomic',
>  	'kms_atomic_interruptible',
>  	'kms_atomic_transition',
> +	'kms_available_modes_crc',
>  	'kms_busy',
>  	'kms_ccs',
>  	'kms_chv_cursor_fail',
-- 
Mika Kahola - Intel OTC

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes
@ 2018-03-20 16:13 Juha-Pekka Heikkila
  2018-05-15  9:15 ` Mika Kahola
  0 siblings, 1 reply; 11+ messages in thread
From: Juha-Pekka Heikkila @ 2018-03-20 16:13 UTC (permalink / raw)
  To: igt-dev

Ask from kernel about supported modes for each plane and try setting
them on display and verify functionality with crc.

DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888 skip crc testing on
primary and overlay planes because they produce incorrect crcs from
hardware. DRM_FORMAT_ARGB8888 is tested on cursor plane.

v2: Added support for planar formats.

v3: Address review comments from Mika Kahola.
Keep crc running for all tests while on same pipe, set tile height
to 16 and read only one crc per test.

Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
---
 tests/Makefile.sources          |   1 +
 tests/kms_available_modes_crc.c | 541 ++++++++++++++++++++++++++++++++++++++++
 tests/meson.build               |   1 +
 3 files changed, 543 insertions(+)
 create mode 100644 tests/kms_available_modes_crc.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index f1d1cba..0622048 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -173,6 +173,7 @@ TESTS_progs = \
 	kms_atomic \
 	kms_atomic_interruptible \
 	kms_atomic_transition \
+	kms_available_modes_crc \
 	kms_busy \
 	kms_ccs \
 	kms_chv_cursor_fail \
diff --git a/tests/kms_available_modes_crc.c b/tests/kms_available_modes_crc.c
new file mode 100644
index 0000000..18c3685
--- /dev/null
+++ b/tests/kms_available_modes_crc.c
@@ -0,0 +1,541 @@
+/*
+ * 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.
+ *
+ */
+
+#include "drm_mode.h"
+#include "drm_fourcc.h"
+#include "igt.h"
+#include <sys/ioctl.h>
+
+IGT_TEST_DESCRIPTION("CRC test all different plane modes which kernel advertises.");
+
+typedef struct {
+	int gfx_fd;
+	igt_display_t display;
+	enum igt_commit_style commit;
+
+	struct igt_fb fb;
+	struct igt_fb primary_fb;
+
+	char format_name[5];
+	bool separateprimaryplane;
+
+	uint32_t gem_handle;
+	uint32_t gem_handle_yuv;
+	unsigned int size;
+	unsigned char* buf;
+
+	/*
+	 * comparison crcs
+	 */
+	igt_pipe_crc_t *pipe_crc;
+
+	igt_crc_t cursor_crc;
+	igt_crc_t fullscreen_crc;
+} data_t;
+
+
+static int do_write(int fd, int handle, void *buf, int size)
+{
+	struct drm_i915_gem_pwrite write;
+	memset(&write, 0x00, sizeof(write));
+	write.handle = handle;
+	write.data_ptr = (uintptr_t)buf;
+	write.size = size;
+	write.offset = 0;
+	return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write);
+}
+
+
+static void generate_comparison_crc_list(data_t *data, igt_output_t *output)
+{
+	drmModeModeInfo *mode;
+	uint64_t w, h;
+	int fbid;
+	cairo_t *cr;
+	igt_plane_t *primary;
+
+	mode = igt_output_get_mode(output);
+	fbid = igt_create_color_fb(data->gfx_fd,
+				   mode->hdisplay,
+				   mode->vdisplay,
+				   intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ? DRM_FORMAT_XRGB8888 : DRM_FORMAT_ARGB8888,
+				   LOCAL_DRM_FORMAT_MOD_NONE,
+				   0, 0, 0,
+				   &data->primary_fb);
+
+	igt_assert(fbid);
+
+	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
+	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
+
+	cr = igt_get_cairo_ctx(data->gfx_fd, &data->primary_fb);
+	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
+			    0.0, 0.0, 0.0);
+	igt_paint_color(cr, 0, 0, w, h, 1.0, 1.0, 1.0);
+	igt_assert(cairo_status(cr) == 0);
+
+	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
+	igt_plane_set_fb(primary, &data->primary_fb);
+	igt_display_commit2(&data->display, data->commit);
+
+	igt_pipe_crc_drain(data->pipe_crc);
+	igt_pipe_crc_get_single(data->pipe_crc, &data->cursor_crc);
+	igt_plane_set_fb(primary, NULL);
+	igt_display_commit2(&data->display, data->commit);
+
+	intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ?
+		  igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay, 1.0, 1.0, 1.0) :
+		  igt_paint_color_alpha(cr, 0, 0, mode->hdisplay, mode->vdisplay, 1.0, 1.0, 1.0, 1.0);
+
+	igt_plane_set_fb(primary, &data->primary_fb);
+	igt_display_commit2(&data->display, data->commit);
+
+	igt_pipe_crc_drain(data->pipe_crc);
+	igt_pipe_crc_get_single(data->pipe_crc, &data->fullscreen_crc);
+
+	cairo_destroy(cr);
+	igt_remove_fb(data->gfx_fd, &data->primary_fb);
+}
+
+/*
+ * fill_in_fb tell in return value if selected mode should be
+ * proceed to crc check
+ */
+static bool fill_in_fb(data_t *data, igt_output_t *output, igt_plane_t *plane,
+		       uint32_t format)
+{
+	signed i, c, writesize;
+	unsigned short* ptemp_16_buf;
+	unsigned int* ptemp_32_buf;
+
+	const struct {
+		uint32_t	fourcc;
+		char		zeropadding;
+		enum		{ BYTES_PP_1=1,
+				  BYTES_PP_2=2,
+				  BYTES_PP_4=4,
+				  NV12,
+#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) || defined(DRM_FORMAT_P016)
+				  P010,
+#endif
+				  SKIP } bpp;
+		uint32_t	value;
+	} fillers[] = {
+		{ DRM_FORMAT_C8, 0, BYTES_PP_1, 0xff},
+		{ DRM_FORMAT_RGB565, 0, BYTES_PP_2, 0xffff},
+		{ DRM_FORMAT_XRGB8888, 0, BYTES_PP_4, 0xffffffff},
+		{ DRM_FORMAT_XBGR8888, 0, BYTES_PP_4, 0xffffffff},
+
+		/*
+		 * following two are skipped because blending seems to work
+		 * incorrectly with exception of AR24 on cursor plane.
+		 * Test still creates the planes, just filling plane
+		 * and getting crc is skipped.
+		 */
+		{ DRM_FORMAT_ARGB8888, 0, SKIP, 0xffffffff},
+		{ DRM_FORMAT_ABGR8888, 0, SKIP, 0x00ffffff},
+
+		{ DRM_FORMAT_XRGB2101010, 0, BYTES_PP_4, 0xffffffff},
+		{ DRM_FORMAT_XBGR2101010, 0, BYTES_PP_4, 0xffffffff},
+
+		{ DRM_FORMAT_YUYV, 0, BYTES_PP_4, 0x80eb80eb},
+		{ DRM_FORMAT_YVYU, 0, BYTES_PP_4, 0x80eb80eb},
+		{ DRM_FORMAT_VYUY, 0, BYTES_PP_4, 0xeb80eb80},
+		{ DRM_FORMAT_UYVY, 0, BYTES_PP_4, 0xeb80eb80},
+
+		/*
+		 * (semi-)planar formats
+		 */
+		{ DRM_FORMAT_NV12, 0, NV12, 0x80eb},
+#ifdef DRM_FORMAT_P010
+		{ DRM_FORMAT_P010, 0, P010, 0x8000eb00},
+#endif
+#ifdef DRM_FORMAT_P012
+		{ DRM_FORMAT_P012, 0, P010, 0x8000eb00},
+#endif
+#ifdef DRM_FORMAT_P016
+		{ DRM_FORMAT_P016, 0, P010, 0x8000eb00},
+#endif
+		{ 0, 0, 0, 0 }
+	};
+
+	for( i = 0; fillers[i].fourcc != 0; i++ ) {
+		if( fillers[i].fourcc == format )
+			break;
+	}
+
+	switch (fillers[i].bpp) {
+	case BYTES_PP_4:
+		ptemp_32_buf = (unsigned int*)data->buf;
+		for (c = 0; c < data->size/4; c++)
+			ptemp_32_buf[c] = fillers[i].value;
+		writesize = data->size;
+		break;
+	case BYTES_PP_2:
+		ptemp_16_buf = (unsigned short*)data->buf;
+		for (c = 0; c < data->size/2; c++)
+			ptemp_16_buf[c] = (unsigned short)fillers[i].value;
+		writesize = data->size;
+		break;
+	case BYTES_PP_1:
+		memset((void*)data->buf, fillers[i].value, data->size);
+		writesize = data->size;
+		break;
+	case NV12:
+		memset((void*)data->buf, fillers[i].value&0xff,
+		       data->size);
+
+		memset((void*)(data->buf+data->size),
+		       (fillers[i].value>>8)&0xff, data->size/2);
+
+		writesize = data->size+data->size/2;
+		break;
+#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) || defined(DRM_FORMAT_P016)
+	case P010:
+		ptemp_16_buf = (unsigned short*)data->buf;
+		for (c = 0; c < data->size/2; c++)
+			ptemp_16_buf[c] = (unsigned short)fillers[i].value&0xffff;
+
+		ptemp_16_buf = (unsigned short*)(data->buf+data->size);
+		for (c = 0; c < data->size/2; c++)
+			ptemp_16_buf[c] = (unsigned short)(fillers[i].value>>16)&0xffff;
+
+		writesize = data->size+data->size/2;
+		break;
+#endif
+	case SKIP:
+		if (fillers[i].fourcc == DRM_FORMAT_ARGB8888 &&
+		    plane->type == DRM_PLANE_TYPE_CURSOR) {
+		/*
+		 * special for cursor plane where blending works correctly.
+		 */
+			ptemp_32_buf = (unsigned int*)data->buf;
+			for (c = 0; c < data->size/4; c++)
+				ptemp_32_buf[c] = fillers[i].value;
+			writesize = data->size;
+			break;
+		}
+		igt_info("Format %s CRC comparison skipped by design.\n",
+			 (char*)&fillers[i].fourcc);
+
+		return false;
+	default:
+		igt_info("Unsupported mode for test %s\n",
+			 (char*)&fillers[i].fourcc);
+		return false;
+	}
+
+	do_write(data->gfx_fd, data->gem_handle, (void*)data->buf, writesize);
+	return true;
+}
+
+
+static bool setup_fb(data_t *data, igt_output_t *output, igt_plane_t *plane,
+		     uint32_t format)
+{
+	drmModeModeInfo *mode;
+	uint64_t w, h;
+	signed ret, gemsize = 0;
+	unsigned tile_width, tile_height, stride;
+	uint32_t offsets[4] = {};
+	uint32_t* offsetpointer = NULL;
+
+	mode = igt_output_get_mode(output);
+	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+		w = mode->hdisplay ;
+		h = mode->vdisplay;
+	} else {
+		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
+		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
+	}
+
+	switch(format) {
+#ifdef DRM_FORMAT_P010
+	case DRM_FORMAT_P010:
+#endif
+#ifdef DRM_FORMAT_P012
+	case DRM_FORMAT_P012:
+#endif
+#ifdef DRM_FORMAT_P016
+	case DRM_FORMAT_P016:
+#endif
+#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) || defined(DRM_FORMAT_P016)
+		tile_width = 512;
+		tile_height = 16;
+		stride = ALIGN(w*2, tile_width);
+		data->size = offsets[1] = stride*ALIGN(h, tile_height);
+		gemsize = data->size*2;
+		offsetpointer = (uint32_t*)&offsets;
+		break;
+#endif
+	case DRM_FORMAT_NV12:
+		tile_width = 512;
+		tile_height = 16;
+		stride = ALIGN(w, tile_width);
+		data->size = offsets[1] = stride*ALIGN(h, tile_height);
+		gemsize = data->size*2;
+		offsetpointer = (uint32_t*)&offsets;
+		break;
+	default:
+		tile_width = 512;
+		tile_height = 16;
+
+		/*
+		 * w*4 so there's enough space
+		 */
+		stride = ALIGN(w*4, tile_width);
+		data->size = stride*ALIGN(h, tile_height);
+		offsetpointer = NULL;
+		gemsize = data->size;
+		break;
+	}
+
+	data->gem_handle = gem_create(data->gfx_fd, gemsize);
+	ret = __gem_set_tiling(data->gfx_fd, data->gem_handle,
+			       I915_TILING_NONE, stride);
+
+	igt_assert_eq(ret, 0);
+
+	ret = __kms_addfb(data->gfx_fd, data->gem_handle, w, h,
+			  stride, format, LOCAL_DRM_FORMAT_MOD_NONE,
+			  offsetpointer, LOCAL_DRM_MODE_FB_MODIFIERS,
+			  &data->fb.fb_id);
+
+	if(ret < 0) {
+		igt_info("Creating fb for format %s failed, return code %d\n",
+			 (char*)&data->format_name, ret);
+
+		return false;
+	}
+
+	data->fb.width = w;
+	data->fb.height = h;
+	data->fb.gem_handle = data->gem_handle;
+	return true;
+}
+
+
+static void remove_fb(data_t* data, igt_output_t* output, igt_plane_t* plane)
+{
+	if (data->separateprimaryplane) {
+		igt_plane_t* primary = igt_output_get_plane_type(output,
+								 DRM_PLANE_TYPE_PRIMARY);
+		igt_plane_set_fb(primary, NULL);
+		igt_remove_fb(data->gfx_fd, &data->primary_fb);
+		data->separateprimaryplane = false;
+	}
+
+	igt_remove_fb(data->gfx_fd, &data->fb);
+	free(data->buf);
+	data->buf = NULL;
+}
+
+
+static bool prepare_crtc(data_t *data, igt_output_t *output,
+			 igt_plane_t *plane, uint32_t format)
+{
+	drmModeModeInfo *mode;
+	igt_plane_t *primary;
+
+	if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
+		mode = igt_output_get_mode(output);
+		igt_create_color_fb(data->gfx_fd,
+				    mode->hdisplay, mode->vdisplay,
+				    DRM_FORMAT_XRGB8888,
+				    LOCAL_DRM_FORMAT_MOD_NONE,
+				    0, 0, 0,
+				    &data->primary_fb);
+
+		primary = igt_output_get_plane_type(output,
+						    DRM_PLANE_TYPE_PRIMARY);
+
+		igt_plane_set_fb(primary, &data->primary_fb);
+		igt_display_commit2(&data->display, data->commit);
+		data->separateprimaryplane = true;
+	}
+
+	if (!setup_fb(data, output, plane, format))
+		return false;
+
+	free((void*)data->buf);
+	data->buf = (unsigned char*)calloc(data->size*2, 1);
+	return true;
+}
+
+
+static int
+test_one_mode(data_t* data, igt_output_t *output, igt_plane_t* plane,
+	      int mode)
+{
+	igt_crc_t current_crc;
+	signed rVal = 0;
+	bool do_crc;
+	char* crccompare[2];
+
+	if (prepare_crtc(data, output, plane, mode)){
+		/*
+		 * we have fb from prepare_crtc(..) so now fill it in
+		 * correctly in fill_in_fb(..)
+		 */
+		do_crc = fill_in_fb(data, output, plane, mode);
+
+		igt_plane_set_fb(plane, &data->fb);
+		igt_fb_set_size(&data->fb, plane, data->fb.width, data->fb.height);
+		igt_plane_set_size(plane, data->fb.width, data->fb.height);
+		igt_fb_set_position(&data->fb, plane, 0, 0);
+		igt_display_commit2(&data->display, data->commit);
+
+		if (do_crc) {
+			igt_pipe_crc_drain(data->pipe_crc);
+			igt_pipe_crc_get_single(data->pipe_crc, &current_crc);
+
+			if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+				if (!igt_check_crc_equal(&current_crc,
+					&data->fullscreen_crc)) {
+					crccompare[0] = igt_crc_to_string(&current_crc);
+					crccompare[1] = igt_crc_to_string(&data->fullscreen_crc);
+					igt_warn("crc mismatch. target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
+					free(crccompare[0]);
+					free(crccompare[1]);
+					rVal++;
+				}
+			} else {
+				if (!igt_check_crc_equal(&current_crc,
+					&data->cursor_crc)) {
+					crccompare[0] = igt_crc_to_string(&current_crc);
+					crccompare[1] = igt_crc_to_string(&data->cursor_crc);
+					igt_warn("crc mismatch. target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
+					free(crccompare[0]);
+					free(crccompare[1]);
+					rVal++;
+				}
+			}
+		}
+		remove_fb(data, output, plane);
+		return rVal;
+	}
+	return 1;
+}
+
+
+static void
+test_available_modes(data_t* data)
+{
+	igt_output_t *output;
+	igt_plane_t *plane;
+	int* u32ptr_formats;
+	int modeindex;
+	enum pipe pipe;
+	struct drm_mode_get_plane one_plane = {};
+	int invalids = 0;
+
+	char planetype[3][8] = {"OVERLAY\0", "PRIMARY\0", "CURSOR\0" };
+
+	for_each_pipe_with_valid_output(&data->display, pipe, output) {
+		igt_output_set_pipe(output, pipe);
+		igt_display_commit2(&data->display, data->commit);
+
+		data->pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
+						  INTEL_PIPE_CRC_SOURCE_AUTO);
+
+		igt_pipe_crc_start(data->pipe_crc);
+
+		/*
+		 * regenerate comparison crcs for each pipe just in case.
+		 */
+		generate_comparison_crc_list(data, output);
+
+		for_each_plane_on_pipe(&data->display, pipe, plane) {
+			memset((void*)&one_plane, 0,
+			       sizeof(struct drm_mode_get_plane));
+			one_plane.plane_id = plane->drm_plane->plane_id;
+			/*
+			 * first call to know how much space needed,
+			 * second call to get list of supported modes.
+			 */
+			igt_ioctl(data->gfx_fd, DRM_IOCTL_MODE_GETPLANE,
+				  &one_plane);
+			igt_assert(one_plane.count_format_types > 0);
+
+			u32ptr_formats = (int*)calloc(one_plane.count_format_types,
+						      sizeof(int));
+
+			one_plane.format_type_ptr = (__u64)u32ptr_formats;
+			igt_ioctl(data->gfx_fd, DRM_IOCTL_MODE_GETPLANE,
+				  &one_plane);
+
+			for (modeindex = 0;
+			     modeindex < one_plane.count_format_types;
+			     modeindex++) {
+				data->format_name[0] = u32ptr_formats[modeindex]&0xff;
+				data->format_name[1] = (u32ptr_formats[modeindex]>>8)&0xff;
+				data->format_name[2] = (u32ptr_formats[modeindex]>>16)&0xff;
+				data->format_name[3] = (u32ptr_formats[modeindex]>>24)&0xff;
+
+				igt_info("Testing connector %s using pipe %s" \
+					 " plane index %d type %s mode %s\n",
+					 igt_output_name(output),
+					 kmstest_pipe_name(pipe),
+					 plane->index,
+					 planetype[plane->type],
+					 (char*)&data->format_name);
+
+				invalids += test_one_mode(data, output,
+							  plane,
+							  u32ptr_formats[modeindex]);
+			}
+			free((void*)one_plane.format_type_ptr);
+		}
+
+		igt_pipe_crc_free(data->pipe_crc);
+		igt_display_commit2(&data->display, data->commit);
+	}
+	igt_assert(invalids == 0);
+}
+
+
+igt_main
+{
+	data_t data = {};
+
+	igt_skip_on_simulation();
+
+	igt_fixture {
+		data.gfx_fd = drm_open_driver_master(DRIVER_INTEL);
+		kmstest_set_vt_graphics_mode();
+		igt_display_init(&data.display, data.gfx_fd);
+		igt_require_pipe_crc(data.gfx_fd);
+	}
+
+	data.commit = data.display.is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
+
+	igt_subtest("available_mode_test_crc") {
+		test_available_modes(&data);
+	}
+
+	igt_fixture {
+		kmstest_restore_vt_mode();
+		igt_display_fini(&data.display);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 22e4ac9..6a5bd96 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -150,6 +150,7 @@ test_progs = [
 	'kms_atomic',
 	'kms_atomic_interruptible',
 	'kms_atomic_transition',
+	'kms_available_modes_crc',
 	'kms_busy',
 	'kms_ccs',
 	'kms_chv_cursor_fail',
-- 
2.7.4

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes
  2018-03-20 11:37   ` Juha-Pekka Heikkila
@ 2018-03-20 12:45     ` Mika Kahola
  0 siblings, 0 replies; 11+ messages in thread
From: Mika Kahola @ 2018-03-20 12:45 UTC (permalink / raw)
  To: juhapekka.heikkila, igt-dev

On Tue, 2018-03-20 at 13:37 +0200, Juha-Pekka Heikkila wrote:
> On 19.03.2018 14:12, Mika Kahola wrote:
> > 
> > On Fri, 2018-03-16 at 15:39 +0200, Juha-Pekka Heikkila wrote:
> > > 
> > > Ask from kernel about supported modes for each plane and try
> > > setting
> > > them on display and verify functionality with crc.
> > > 
> > > DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888 skip crc testing on
> > > primary and overlay planes because they produce incorrect crcs
> > > from
> > > hardware. DRM_FORMAT_ARGB8888 is tested on cursor plane.
> > > 
> > > Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
> > > ---
> > >   tests/Makefile.sources          |   1 +
> > >   tests/kms_available_modes_crc.c | 574
> > > ++++++++++++++++++++++++++++++++++++++++
> > >   tests/meson.build               |   1 +
> > >   3 files changed, 576 insertions(+)
> > >   create mode 100644 tests/kms_available_modes_crc.c
> > > 
> > > diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> > > index f1d1cba..0622048 100644
> > > --- a/tests/Makefile.sources
> > > +++ b/tests/Makefile.sources
> > > @@ -173,6 +173,7 @@ TESTS_progs = \
> > >   	kms_atomic \
> > >   	kms_atomic_interruptible \
> > >   	kms_atomic_transition \
> > > +	kms_available_modes_crc \
> > >   	kms_busy \
> > >   	kms_ccs \
> > >   	kms_chv_cursor_fail \
> > > diff --git a/tests/kms_available_modes_crc.c
> > > b/tests/kms_available_modes_crc.c
> > > new file mode 100644
> > > index 0000000..9e31346
> > > --- /dev/null
> > > +++ b/tests/kms_available_modes_crc.c
> > > @@ -0,0 +1,574 @@
> > > +/*
> > > + * 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.
> > > + *
> > > + */
> > > +
> > > +#include "drm_mode.h"
> > > +#include "drm_fourcc.h"
> > > +#include "igt.h"
> > > +#include <sys/ioctl.h>
> > > +
> > > +IGT_TEST_DESCRIPTION("CRC test all different plane modes which
> > > kernel advertises.");
> > > +
> > > +#define testcrcamount 3
> > Would grabbing just one CRC be enough for this test? Any reason why
> > we
> > would need 3 CRC's?
> It is just magic number after discussing with Ville Syrjälä about it,
> he 
> once mentioned after starting crc first crc may have garbage if it's 
> started in mid-frame.
Maarten made some improvements on igt library routines and now you can
drain the pipe from garbage before reading it. This should clean up the
garbage if you add 'igt_pipe_crc_drain()'. Note, that you don't need
clean up the garbage right after 'igt_pipe_crc_start()'. 

> 
> > 
> >   
> > > 
> > > +
> > > +typedef struct {
> > > +	int gfx_fd;
> > > +	igt_display_t display;
> > > +	enum igt_commit_style commit;
> > > +
> > > +	struct igt_fb fb;
> > > +	struct igt_fb primary_fb;
> > > +
> > > +	char format_name[5];
> > > +	bool separateprimaryplane;
> > > +
> > > +	uint32_t gem_handle;
> > > +	uint32_t gem_handle_yuv;
> > > +	unsigned int size;
> > > +	unsigned char* buf;
> > > +
> > > +	/*
> > > +	 * comparison crcs
> > > +	 */
> > > +	igt_crc_t *cursor_crc;
> > > +	igt_crc_t *fullscreen_crc;
> > > +} data_t;
> > > +
> > > +
> > > +static int do_write(int fd, int handle, void *buf, int offset,
> > > int
> > > size)
> > > +{
> > > +	struct drm_i915_gem_pwrite write;
> > > +	memset(&write, 0x00, sizeof(write));
> > > +	write.handle = handle;
> > > +	write.data_ptr = (uintptr_t)buf;
> > > +	write.size = size;
> > > +	write.offset = offset;
> > > +	return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write);
> > > +}
> > > +
> > > +
> > > +static void generate_comparison_crc_list(data_t *data,
> > > igt_output_t
> > > *output,
> > > +					enum pipe pipe)
> > > +{
> > > +	drmModeModeInfo *mode;
> > > +	uint64_t w, h, c;
> > > +	int fbid;
> > > +	cairo_t *cr;
> > > +	igt_pipe_crc_t *pipe_crc;
> > > +	igt_plane_t *primary;
> > > +
> > > +
> > > +	igt_output_set_pipe(output, pipe);
> > > +
> > > +	mode = igt_output_get_mode(output);
> > > +	fbid = igt_create_color_fb(data->gfx_fd,
> > > +				   mode->hdisplay,
> > > +				   mode->vdisplay,
> > > +				   intel_gen(intel_get_drm_devid
> > > (dat
> > > a->gfx_fd)) < 9 ? DRM_FORMAT_XRGB8888 : DRM_FORMAT_ARGB8888,
> > > +				   LOCAL_DRM_FORMAT_MOD_NONE,
> > > +				   0, 0, 0,
> > > +				   &data->primary_fb);
> > > +
> > > +	igt_assert(fbid);
> > > +
> > > +	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
> > > +	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
> > > +
> > > +	cr = igt_get_cairo_ctx(data->gfx_fd, &data->primary_fb);
> > > +	igt_paint_color(cr, 0, 0, mode->hdisplay, mode-
> > > >vdisplay,
> > > +			    0.0, 0.0, 0.0);
> > > +	igt_paint_color(cr, 0, 0, w, h, 1.0, 1.0, 1.0);
> > > +	igt_assert(cairo_status(cr) == 0);
> > > +
> > > +	primary = igt_output_get_plane_type(output,
> > > DRM_PLANE_TYPE_PRIMARY);
> > > +	igt_plane_set_fb(primary, &data->primary_fb);
> > > +	igt_display_commit2(&data->display, data->commit);
> > > +
> > > +	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
> > > INTEL_PIPE_CRC_SOURCE_AUTO);
> > > +	igt_pipe_crc_start(pipe_crc);
> > > +	c = igt_pipe_crc_get_crcs(pipe_crc, testcrcamount,
> > > &data-
> > > > 
> > > > cursor_crc);
> > If one CRC would be enough, we could utilize Maarten's library
> > routine
> > 'igt_pipe_crc_get_single()'.
> I'll try this and see how it goes.
> 
> > 
> > > 
> > > +	igt_assert(c==testcrcamount);
> > > +	igt_pipe_crc_stop(pipe_crc);
> > I think we could keep crc going and if we are concerned that we may
> > have incorrect one in the pipe, we could drain them with
> > 'igt_igt_pipe_crc_drain()'
> In mid development I tried leaving crc running but it followed lot
> of 
> messages in dmesg about buffer full. I'll retry and see if it is
> still 
> an issue.
> 
> This test run as one single test going through all pipes, planes and 
> modes. I've been thinking if I should divide it in smaller pieces
> but 
> didn't go that way because it would cause there being different
> amount 
> of tests and different tests on different hw.
> 
> > 
> > 
> > > 
> > > +	igt_pipe_crc_free(pipe_crc);
> > > +	igt_plane_set_fb(primary, NULL);
> > > +	igt_display_commit2(&data->display, data->commit);
> > > +
> > > +	intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ?
> > > +		  igt_paint_color(cr, 0, 0, mode->hdisplay,
> > > mode-
> > > > 
> > > > vdisplay, 1.0, 1.0, 1.0) :
> > > +		  igt_paint_color_alpha(cr, 0, 0, mode-
> > > >hdisplay,
> > > mode->vdisplay, 1.0, 1.0, 1.0, 1.0);
> > > +
> > > +	igt_plane_set_fb(primary, &data->primary_fb);
> > > +	igt_display_commit2(&data->display, data->commit);
> > > +
> > > +	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
> > > INTEL_PIPE_CRC_SOURCE_AUTO);
> > > +	igt_pipe_crc_start(pipe_crc);
> > > +	c = igt_pipe_crc_get_crcs(pipe_crc, testcrcamount,
> > > &data-
> > > > 
> > > > fullscreen_crc);
> > > +	igt_assert(c==testcrcamount);
> > > +	igt_pipe_crc_stop(pipe_crc);
> > > +	igt_pipe_crc_free(pipe_crc);
> > > +
> > > +	cairo_destroy(cr);
> > > +	igt_remove_fb(data->gfx_fd, &data->primary_fb);
> > > +}
> > > +
> > > +/*
> > > + * fill_in_fb tell in return value if selected mode should be
> > > + * proceed to crc check
> > > + */
> > > +static bool fill_in_fb(data_t *data, igt_output_t *output, enum
> > > pipe
> > > pipe,
> > > +			 igt_plane_t *plane, uint32_t format)
> > > +{
> > > +	signed i, c, writesize;
> > > +	unsigned short* ptemp_16_buf;
> > > +	unsigned int* ptemp_32_buf;
> > > +
> > > +	const struct {
> > > +		uint32_t	fourcc;
> > > +		char		zeropadding;
> > > +		enum		{ BYTES_PP_1=1,
> > > +				  BYTES_PP_2=2,
> > > +				  BYTES_PP_4=4,
> > > +				  NV12,
> > > +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> > > defined(DRM_FORMAT_P016)
> > > +				  P010,
> > > +#endif
> > > +				  SKIP } bpp;
> > > +		uint32_t	value;
> > > +	} fillers[] = {
> > > +		{ DRM_FORMAT_C8, 0, BYTES_PP_1, 0xff},
> > > +		{ DRM_FORMAT_RGB565, 0, BYTES_PP_2, 0xffff},
> > > +		{ DRM_FORMAT_XRGB8888, 0, BYTES_PP_4,
> > > 0xffffffff},
> > > +		{ DRM_FORMAT_XBGR8888, 0, BYTES_PP_4,
> > > 0xffffffff},
> > > +
> > > +		/*
> > > +		 * following two are skipped because blending
> > > seems
> > > to work
> > > +		 * incorrectly with exception of AR24 on cursor
> > > plane.
> > > +		 * Test still creates the planes, just filling
> > > plane
> > > +		 * and getting crc is skipped.
> > > +		 */
> > > +		{ DRM_FORMAT_ARGB8888, 0, SKIP, 0xffffffff},
> > > +		{ DRM_FORMAT_ABGR8888, 0, SKIP, 0x00ffffff},
> > > +
> > > +		{ DRM_FORMAT_XRGB2101010, 0, BYTES_PP_4,
> > > 0xffffffff},
> > > +		{ DRM_FORMAT_XBGR2101010, 0, BYTES_PP_4,
> > > 0xffffffff},
> > > +
> > > +		{ DRM_FORMAT_YUYV, 0, BYTES_PP_4, 0x80eb80eb},
> > > +		{ DRM_FORMAT_YVYU, 0, BYTES_PP_4, 0x80eb80eb},
> > > +		{ DRM_FORMAT_VYUY, 0, BYTES_PP_4, 0xeb80eb80},
> > > +		{ DRM_FORMAT_UYVY, 0, BYTES_PP_4, 0xeb80eb80},
> > > +
> > > +		/*
> > > +		 * (semi-)planar formats
> > > +		 */
> > > +		{ DRM_FORMAT_NV12, 0, NV12, 0x80eb},
> > > +#ifdef DRM_FORMAT_P010
> > > +		{ DRM_FORMAT_P010, 0, P010, 0x8000eb00},
> > > +#endif
> > > +#ifdef DRM_FORMAT_P012
> > > +		{ DRM_FORMAT_P012, 0, P010, 0x8000eb00},
> > > +#endif
> > > +#ifdef DRM_FORMAT_P016
> > > +		{ DRM_FORMAT_P016, 0, P010, 0x8000eb00},
> > > +#endif
> > > +		{ 0, 0, 0, 0 }
> > > +	};
> > > +
> > > +	for( i = 0; fillers[i].fourcc != 0; i++ ) {
> > > +		if( fillers[i].fourcc == format )
> > > +			break;
> > > +	}
> > > +
> > > +	switch (fillers[i].bpp) {
> > > +	case BYTES_PP_4:
> > > +		ptemp_32_buf = (unsigned int*)data->buf;
> > > +		for (c = 0; c < data->size/4; c++)
> > > +			ptemp_32_buf[c] = fillers[i].value;
> > > +		writesize = data->size;
> > > +		break;
> > > +	case BYTES_PP_2:
> > > +		ptemp_16_buf = (unsigned short*)data->buf;
> > > +		for (c = 0; c < data->size/2; c++)
> > > +			ptemp_16_buf[c] = (unsigned
> > > short)fillers[i].value;
> > > +		writesize = data->size;
> > > +		break;
> > > +	case BYTES_PP_1:
> > > +		memset((void*)data->buf, fillers[i].value, data-
> > > > 
> > > > size);
> > > +		writesize = data->size;
> > > +		break;
> > > +	case NV12:
> > > +		memset((void*)data->buf, fillers[i].value&0xff,
> > > +		       data->size);
> > > +
> > > +		memset((void*)(data->buf+data->size),
> > > +		       (fillers[i].value>>8)&0xff, data-
> > > >size/2);
> > > +
> > > +		writesize = data->size+data->size/2;
> > > +		break;
> > > +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> > > defined(DRM_FORMAT_P016)
> > > +	case P010:
> > > +		ptemp_16_buf = (unsigned short*)data->buf;
> > > +		for (c = 0; c < data->size/2; c++)
> > > +			ptemp_16_buf[c] = (unsigned
> > > short)fillers[i].value&0xffff;
> > > +
> > > +		ptemp_16_buf = (unsigned short*)(data->buf+data-
> > > > 
> > > > size);
> > > +		for (c = 0; c < data->size/2; c++)
> > > +			ptemp_16_buf[c] = (unsigned
> > > short)(fillers[i].value>>16)&0xffff;
> > > +
> > > +		writesize = data->size+data->size/2;
> > > +		break;
> > > +#endif
> > > +	case SKIP:
> > > +		if (fillers[i].fourcc == DRM_FORMAT_ARGB8888 &&
> > > +		    plane->type == DRM_PLANE_TYPE_CURSOR) {
> > > +		/*
> > > +		 * special for cursor plane where blending works
> > > correctly.
> > > +		 */
> > > +			ptemp_32_buf = (unsigned int*)data->buf;
> > > +			for (c = 0; c < data->size/4; c++)
> > > +				ptemp_32_buf[c] =
> > > fillers[i].value;
> > > +			writesize = data->size;
> > > +			break;
> > > +		}
> > > +		igt_info("Format %s CRC comparison skipped by
> > > design.\n",
> > > +			 (char*)&fillers[i].fourcc);
> > > +
> > > +		return false;
> > > +	default:
> > > +		igt_info("Unsupported mode for test %s\n",
> > > +			 (char*)&fillers[i].fourcc);
> > > +		return false;
> > > +	}
> > > +
> > > +	do_write(data->gfx_fd, data->gem_handle, (void*)data-
> > > >buf,
> > > 0,
> > > +		 writesize);
> > > +
> > > +	return true;
> > > +}
> > > +
> > > +
> > > +static bool setup_fb(data_t *data, igt_output_t *output, enum
> > > pipe
> > > pipe,
> > > +		     igt_plane_t *plane, uint32_t format)
> > > +{
> > > +	drmModeModeInfo *mode;
> > > +	uint64_t w, h;
> > > +	signed ret, gemsize = 0;
> > > +	unsigned tile_width, tile_height, stride;
> > > +	uint32_t offsets[4] = {};
> > > +	uint32_t* offsetpointer = NULL;
> > > +
> > > +	mode = igt_output_get_mode(output);
> > > +	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
> > > +		w = mode->hdisplay ;
> > > +		h = mode->vdisplay;
> > > +	} else {
> > > +		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH,
> > > &w);
> > > +		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT,
> > > &h);
> > > +	}
> > > +
> > > +	switch(format) {
> > > +#ifdef DRM_FORMAT_P010
> > > +	case DRM_FORMAT_P010:
> > > +#endif
> > > +#ifdef DRM_FORMAT_P012
> > > +	case DRM_FORMAT_P012:
> > > +#endif
> > > +#ifdef DRM_FORMAT_P016
> > > +	case DRM_FORMAT_P016:
> > > +#endif
> > > +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> > > defined(DRM_FORMAT_P016)
> > > +		tile_width = 512;
> > > +		tile_height = 8;
> > > +
> > > +		stride = ALIGN(w*2, tile_width);
> > > +		data->size = offsets[1] = stride*ALIGN(h,
> > > tile_height);
> > > +
> > > +		gemsize = data->size*2;
> > > +		offsetpointer = (uint32_t*)&offsets;
> > > +		break;
> > > +#endif
> > > +	case DRM_FORMAT_NV12:
> > > +		tile_width = 512;
> > > +		tile_height = 8;
> > The minimum height is 16 for NV12. This has been discussed in this
> > patch
> > 
> > https://patchwork.freedesktop.org/patch/208171/
> > 
> Thanks, I'll fix. I did this test on top of Vidya's set submitted on 
> feb22 where it still was 8. Same issue will apply for Pxxx formats.
> 
> > 
> > 
> > > 
> > > +
> > > +		stride = ALIGN(w, tile_width);
> > > +		data->size = offsets[1] = stride*ALIGN(h,
> > > tile_height);
> > > +
> > > +		gemsize = data->size*2;
> > > +		offsetpointer = (uint32_t*)&offsets;
> > > +		break;
> > > +	default:
> > > +		tile_width = 512;
> > > +		tile_height = 8;
> > > +
> > > +		/*
> > > +		 * w*4 so there's enough space
> > > +		 */
> > > +		stride = ALIGN(w*4, tile_width);
> > > +		data->size = stride*ALIGN(h, tile_height);
> > > +		offsetpointer = NULL;
> > > +
> > > +		gemsize = data->size;
> > > +		break;
> > > +	}
> > > +
> > > +	data->gem_handle = gem_create(data->gfx_fd, gemsize);
> > > +	ret = __gem_set_tiling(data->gfx_fd, data->gem_handle,
> > > +			       I915_TILING_NONE, stride);
> > > +
> > > +	igt_assert_eq(ret, 0);
> > > +
> > > +	ret = __kms_addfb(data->gfx_fd, data->gem_handle, w, h,
> > > +			  stride, format,
> > > LOCAL_DRM_FORMAT_MOD_NONE,
> > > +			  offsetpointer,
> > > LOCAL_DRM_MODE_FB_MODIFIERS,
> > > +			  &data->fb.fb_id);
> > > +
> > > +	if(ret < 0) {
> > > +		igt_info("Creating fb for format %s failed,
> > > return
> > > code %d\n",
> > > +			 (char*)&data->format_name, ret);
> > > +
> > > +		return false;
> > > +	}
> > > +
> > > +	data->fb.width = w;
> > > +	data->fb.height = h;
> > > +	data->fb.gem_handle = data->gem_handle;
> > > +	return true;
> > > +}
> > > +
> > > +
> > > +static void remove_fb(data_t* data, igt_output_t* output,
> > > igt_plane_t* plane)
> > > +{
> > > +	if (data->separateprimaryplane) {
> > > +		igt_plane_t* primary =
> > > igt_output_get_plane_type(output,
> > > +								
> > >  DRM
> > > _PLANE_TYPE_PRIMARY);
> > > +		igt_plane_set_fb(primary, NULL);
> > > +		igt_remove_fb(data->gfx_fd, &data->primary_fb);
> > > +		igt_display_commit2(&data->display, data-
> > > >commit);
> > > +		data->separateprimaryplane = false;
> > > +	}
> > > +
> > > +	igt_remove_fb(data->gfx_fd, &data->fb);
> > > +	igt_display_commit2(&data->display, data->commit);
> > > +	free(data->buf);
> > > +	data->buf = NULL;
> > > +}
> > > +
> > > +
> > > +static bool prepare_crtc(data_t *data, igt_output_t *output,
> > > enum
> > > pipe pipe,
> > > +			 igt_plane_t *plane, uint32_t format)
> > > +{
> > > +	drmModeModeInfo *mode;
> > > +	igt_plane_t *primary;
> > > +
> > > +	if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
> > > +		mode = igt_output_get_mode(output);
> > > +		igt_create_color_fb(data->gfx_fd,
> > > +				    mode->hdisplay, mode-
> > > >vdisplay,
> > > +				    DRM_FORMAT_XRGB8888,
> > > +				    LOCAL_DRM_FORMAT_MOD_NONE,
> > > +				    0, 0, 0,
> > > +				    &data->primary_fb);
> > > +
> > > +		primary = igt_output_get_plane_type(output,
> > > +						    DRM_PLANE_TY
> > > PE_P
> > > RIMARY);
> > > +
> > > +		igt_plane_set_fb(primary, &data->primary_fb);
> > > +		igt_display_commit2(&data->display, data-
> > > >commit);
> > > +		data->separateprimaryplane = true;
> > > +	}
> > > +
> > > +	if (!setup_fb(data, output, pipe, plane, format))
> > > +		return false;
> > > +
> > > +	if (data->buf != NULL) {
> > > +		free((void*)data->buf);
> > > +		data->buf = NULL;
> > > +	}
> > > +
> > > +	data->buf = (unsigned char*)calloc(data->size*2, 1);
> > > +	return true;
> > > +}
> > > +
> > > +
> > > +static int
> > > +test_one_mode(data_t* data, igt_output_t *output, igt_plane_t*
> > > plane,
> > > +	      enum pipe pipe, int mode)
> > > +{
> > > +
> > > +	igt_crc_t *crcs = NULL;
> > > +	igt_pipe_crc_t *pipe_crc;
> > > +	signed count, rVal = 0;
> > > +	bool do_crc;
> > > +	char* crccompare[2];
> > > +
> > > +	if (prepare_crtc(data, output, pipe, plane, mode)){
> > > +
> > > +		/*
> > > +		 * we have fb from prepare_crtc(..) so now fill
> > > it
> > > in
> > > +		 * correctly in fill_in_fb(..)
> > > +		 */
> > > +		do_crc = fill_in_fb(data, output, pipe, plane,
> > > mode);
> > > +
> > > +		igt_plane_set_fb(plane, &data->fb);
> > > +		igt_fb_set_size(&data->fb, plane, data-
> > > >fb.width,
> > > data->fb.height);
> > > +		igt_plane_set_size(plane, data->fb.width, data-
> > > > 
> > > > fb.height);
> > > +		igt_fb_set_position(&data->fb, plane, 0, 0);
> > > +		igt_display_commit2(&data->display, data-
> > > >commit);
> > > +
> > > +		if (do_crc) {
> > > +			pipe_crc = igt_pipe_crc_new(data-
> > > >gfx_fd,
> > > pipe,
> > > +						    INTEL_PIPE_C
> > > RC_S
> > > OURCE_AUTO);
> > > +
> > > +			igt_pipe_crc_start(pipe_crc);
> > > +
> > > +			count = igt_pipe_crc_get_crcs(pipe_crc,
> > > testcrcamount, &crcs);
> > > +			igt_assert( count==testcrcamount );
> > > +
> > > +			igt_pipe_crc_stop(pipe_crc);
> > > +			igt_pipe_crc_free(pipe_crc);
> > > +
> > > +			if (plane->type !=
> > > DRM_PLANE_TYPE_CURSOR) {
> > > +				if
> > > (!igt_check_crc_equal(&crcs[testcrcamount-1],
> > > +					&data-
> > > > 
> > > > fullscreen_crc[testcrcamount-1])) {
> > > +					crccompare[0] =
> > > igt_crc_to_string(&crcs[testcrcamount-1]);
> > > +					crccompare[1] =
> > > igt_crc_to_string(&data->fullscreen_crc[testcrcamount-1]);
> > > +					igt_warn("crc mismatch.
> > > target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
> > > +					free(crccompare[0]);
> > > +					free(crccompare[1]);
> > > +					rVal++;
> > > +				}
> > > +			} else {
> > > +				if
> > > (!igt_check_crc_equal(&crcs[testcrcamount-1],
> > > +					&data-
> > > > 
> > > > cursor_crc[testcrcamount-1])) {
> > > +					crccompare[0] =
> > > igt_crc_to_string(&crcs[testcrcamount-1]);
> > > +					crccompare[1] =
> > > igt_crc_to_string(&data->cursor_crc[testcrcamount-1]);
> > > +					igt_warn("crc mismatch.
> > > target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
> > > +					free(crccompare[0]);
> > > +					free(crccompare[1]);
> > > +					rVal++;
> > > +				}
> > > +			}
> > > +			free(crcs);
> > > +		}
> > > +		remove_fb(data, output, plane);
> > > +		return rVal;
> > > +	}
> > > +	return 1;
> > > +}
> > > +
> > > +
> > > +static void
> > > +test_available_modes(data_t* data)
> > > +{
> > > +	igt_output_t *output;
> > > +	igt_plane_t *plane;
> > > +	int* u32ptr_formats;
> > > +	int modeindex;
> > > +	enum pipe pipe;
> > > +	struct drm_mode_get_plane one_plane = {};
> > > +	int invalids = 0;
> > > +
> > > +	char planetype[3][8] = {"OVERLAY\0", "PRIMARY\0",
> > > "CURSOR\0"
> > > };
> > > +
> > > +	for_each_pipe_with_valid_output(&data->display, pipe,
> > > output) {
> > > +		igt_output_set_pipe(output, pipe);
> > > +
> > > +		/*
> > > +		 * regenerate comparison crcs for each pipe just
> > > in
> > > case.
> > > +		 */
> > > +		generate_comparison_crc_list(data, output,
> > > pipe);
> > > +
> > > +		for_each_plane_on_pipe(&data->display, pipe,
> > > plane)
> > > {
> > > +			memset((void*)&one_plane, 0,
> > > +			       sizeof(struct
> > > drm_mode_get_plane));
> > > +			one_plane.plane_id = plane->drm_plane-
> > > > 
> > > > plane_id;
> > > +			/*
> > > +			 * first call to know how much space
> > > needed,
> > > +			 * second call to get list of supported
> > > modes.
> > > +			 */
> > > +			igt_ioctl(data->gfx_fd,
> > > DRM_IOCTL_MODE_GETPLANE,
> > > +				  &one_plane);
> > > +			igt_assert(one_plane.count_format_types
> > > >
> > > 0);
> > > +
> > > +			u32ptr_formats =
> > > (int*)calloc(one_plane.count_format_types,
> > > +						      sizeof(int
> > > ));
> > > +
> > > +			one_plane.format_type_ptr =
> > > (__u64)u32ptr_formats;
> > > +			igt_ioctl(data->gfx_fd,
> > > DRM_IOCTL_MODE_GETPLANE,
> > > +				  &one_plane);
> > > +
> > > +			for (modeindex = 0;
> > > +			     modeindex <
> > > one_plane.count_format_types;
> > > +			     modeindex++) {
> > > +				data->format_name[0] =
> > > u32ptr_formats[modeindex]&0xff;
> > > +				data->format_name[1] =
> > > (u32ptr_formats[modeindex]>>8)&0xff;
> > > +				data->format_name[2] =
> > > (u32ptr_formats[modeindex]>>16)&0xff;
> > > +				data->format_name[3] =
> > > (u32ptr_formats[modeindex]>>24)&0xff;
> > > +
> > > +				igt_info("Testing connector %s
> > > using
> > > pipe %s" \
> > > +					 " plane index %d type
> > > %s
> > > mode %s\n",
> > > +					 igt_output_name(output)
> > > ,
> > > +					 kmstest_pipe_name(pipe)
> > > ,
> > > +					 plane->index,
> > > +					 planetype[plane->type],
> > > +					 (char*)&data-
> > > >format_name);
> > > +
> > > +				invalids += test_one_mode(data,
> > > output,
> > > +							  plane,
> > > pipe,
> > > +							  u32ptr
> > > _for
> > > mats[modeindex]);
> > > +			}
> > > +			free((void*)one_plane.format_type_ptr);
> > > +		}
> > > +		free(data->cursor_crc);
> > > +		free(data->fullscreen_crc);
> > > +	}
> > > +	igt_assert(invalids == 0);
> > > +}
> > > +
> > > +
> > > +igt_main
> > > +{
> > > +	data_t data = {};
> > > +
> > > +	igt_skip_on_simulation();
> > > +
> > > +	igt_fixture {
> > > +		data.gfx_fd =
> > > drm_open_driver_master(DRIVER_INTEL);
> > > +		kmstest_set_vt_graphics_mode();
> > > +
> > > +		igt_display_init(&data.display, data.gfx_fd);
> > > +
> > > +		igt_require_pipe_crc(data.gfx_fd);
> > > +	}
> > > +
> > > +	data.commit = data.display.is_atomic ? COMMIT_ATOMIC :
> > > COMMIT_LEGACY;
> > > +
> > > +	igt_subtest("available_mode_test_crc") {
> > > +		test_available_modes(&data);
> > > +	}
> > > +
> > > +	igt_fixture {
> > > +		kmstest_restore_vt_mode();
> > > +		igt_display_fini(&data.display);
> > > +	}
> > > +}
> > > diff --git a/tests/meson.build b/tests/meson.build
> > > index 22e4ac9..6a5bd96 100644
> > > --- a/tests/meson.build
> > > +++ b/tests/meson.build
> > > @@ -150,6 +150,7 @@ test_progs = [
> > >   	'kms_atomic',
> > >   	'kms_atomic_interruptible',
> > >   	'kms_atomic_transition',
> > > +	'kms_available_modes_crc',
> > >   	'kms_busy',
> > >   	'kms_ccs',
> > >   	'kms_chv_cursor_fail',
-- 
Mika Kahola - Intel OTC

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes
  2018-03-19 12:12 ` Mika Kahola
@ 2018-03-20 11:37   ` Juha-Pekka Heikkila
  2018-03-20 12:45     ` Mika Kahola
  0 siblings, 1 reply; 11+ messages in thread
From: Juha-Pekka Heikkila @ 2018-03-20 11:37 UTC (permalink / raw)
  To: mika.kahola, igt-dev

On 19.03.2018 14:12, Mika Kahola wrote:
> On Fri, 2018-03-16 at 15:39 +0200, Juha-Pekka Heikkila wrote:
>> Ask from kernel about supported modes for each plane and try setting
>> them on display and verify functionality with crc.
>>
>> DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888 skip crc testing on
>> primary and overlay planes because they produce incorrect crcs from
>> hardware. DRM_FORMAT_ARGB8888 is tested on cursor plane.
>>
>> Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
>> ---
>>   tests/Makefile.sources          |   1 +
>>   tests/kms_available_modes_crc.c | 574
>> ++++++++++++++++++++++++++++++++++++++++
>>   tests/meson.build               |   1 +
>>   3 files changed, 576 insertions(+)
>>   create mode 100644 tests/kms_available_modes_crc.c
>>
>> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
>> index f1d1cba..0622048 100644
>> --- a/tests/Makefile.sources
>> +++ b/tests/Makefile.sources
>> @@ -173,6 +173,7 @@ TESTS_progs = \
>>   	kms_atomic \
>>   	kms_atomic_interruptible \
>>   	kms_atomic_transition \
>> +	kms_available_modes_crc \
>>   	kms_busy \
>>   	kms_ccs \
>>   	kms_chv_cursor_fail \
>> diff --git a/tests/kms_available_modes_crc.c
>> b/tests/kms_available_modes_crc.c
>> new file mode 100644
>> index 0000000..9e31346
>> --- /dev/null
>> +++ b/tests/kms_available_modes_crc.c
>> @@ -0,0 +1,574 @@
>> +/*
>> + * 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.
>> + *
>> + */
>> +
>> +#include "drm_mode.h"
>> +#include "drm_fourcc.h"
>> +#include "igt.h"
>> +#include <sys/ioctl.h>
>> +
>> +IGT_TEST_DESCRIPTION("CRC test all different plane modes which
>> kernel advertises.");
>> +
>> +#define testcrcamount 3
> Would grabbing just one CRC be enough for this test? Any reason why we
> would need 3 CRC's?

It is just magic number after discussing with Ville Syrjälä about it, he 
once mentioned after starting crc first crc may have garbage if it's 
started in mid-frame.

>   
>> +
>> +typedef struct {
>> +	int gfx_fd;
>> +	igt_display_t display;
>> +	enum igt_commit_style commit;
>> +
>> +	struct igt_fb fb;
>> +	struct igt_fb primary_fb;
>> +
>> +	char format_name[5];
>> +	bool separateprimaryplane;
>> +
>> +	uint32_t gem_handle;
>> +	uint32_t gem_handle_yuv;
>> +	unsigned int size;
>> +	unsigned char* buf;
>> +
>> +	/*
>> +	 * comparison crcs
>> +	 */
>> +	igt_crc_t *cursor_crc;
>> +	igt_crc_t *fullscreen_crc;
>> +} data_t;
>> +
>> +
>> +static int do_write(int fd, int handle, void *buf, int offset, int
>> size)
>> +{
>> +	struct drm_i915_gem_pwrite write;
>> +	memset(&write, 0x00, sizeof(write));
>> +	write.handle = handle;
>> +	write.data_ptr = (uintptr_t)buf;
>> +	write.size = size;
>> +	write.offset = offset;
>> +	return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write);
>> +}
>> +
>> +
>> +static void generate_comparison_crc_list(data_t *data, igt_output_t
>> *output,
>> +					enum pipe pipe)
>> +{
>> +	drmModeModeInfo *mode;
>> +	uint64_t w, h, c;
>> +	int fbid;
>> +	cairo_t *cr;
>> +	igt_pipe_crc_t *pipe_crc;
>> +	igt_plane_t *primary;
>> +
>> +
>> +	igt_output_set_pipe(output, pipe);
>> +
>> +	mode = igt_output_get_mode(output);
>> +	fbid = igt_create_color_fb(data->gfx_fd,
>> +				   mode->hdisplay,
>> +				   mode->vdisplay,
>> +				   intel_gen(intel_get_drm_devid(dat
>> a->gfx_fd)) < 9 ? DRM_FORMAT_XRGB8888 : DRM_FORMAT_ARGB8888,
>> +				   LOCAL_DRM_FORMAT_MOD_NONE,
>> +				   0, 0, 0,
>> +				   &data->primary_fb);
>> +
>> +	igt_assert(fbid);
>> +
>> +	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
>> +	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
>> +
>> +	cr = igt_get_cairo_ctx(data->gfx_fd, &data->primary_fb);
>> +	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
>> +			    0.0, 0.0, 0.0);
>> +	igt_paint_color(cr, 0, 0, w, h, 1.0, 1.0, 1.0);
>> +	igt_assert(cairo_status(cr) == 0);
>> +
>> +	primary = igt_output_get_plane_type(output,
>> DRM_PLANE_TYPE_PRIMARY);
>> +	igt_plane_set_fb(primary, &data->primary_fb);
>> +	igt_display_commit2(&data->display, data->commit);
>> +
>> +	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
>> INTEL_PIPE_CRC_SOURCE_AUTO);
>> +	igt_pipe_crc_start(pipe_crc);
>> +	c = igt_pipe_crc_get_crcs(pipe_crc, testcrcamount, &data-
>>> cursor_crc);
> If one CRC would be enough, we could utilize Maarten's library routine
> 'igt_pipe_crc_get_single()'.

I'll try this and see how it goes.

>> +	igt_assert(c==testcrcamount);
>> +	igt_pipe_crc_stop(pipe_crc);
> I think we could keep crc going and if we are concerned that we may
> have incorrect one in the pipe, we could drain them with
> 'igt_igt_pipe_crc_drain()'

In mid development I tried leaving crc running but it followed lot of 
messages in dmesg about buffer full. I'll retry and see if it is still 
an issue.

This test run as one single test going through all pipes, planes and 
modes. I've been thinking if I should divide it in smaller pieces but 
didn't go that way because it would cause there being different amount 
of tests and different tests on different hw.

> 
>> +	igt_pipe_crc_free(pipe_crc);
>> +	igt_plane_set_fb(primary, NULL);
>> +	igt_display_commit2(&data->display, data->commit);
>> +
>> +	intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ?
>> +		  igt_paint_color(cr, 0, 0, mode->hdisplay, mode-
>>> vdisplay, 1.0, 1.0, 1.0) :
>> +		  igt_paint_color_alpha(cr, 0, 0, mode->hdisplay,
>> mode->vdisplay, 1.0, 1.0, 1.0, 1.0);
>> +
>> +	igt_plane_set_fb(primary, &data->primary_fb);
>> +	igt_display_commit2(&data->display, data->commit);
>> +
>> +	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
>> INTEL_PIPE_CRC_SOURCE_AUTO);
>> +	igt_pipe_crc_start(pipe_crc);
>> +	c = igt_pipe_crc_get_crcs(pipe_crc, testcrcamount, &data-
>>> fullscreen_crc);
>> +	igt_assert(c==testcrcamount);
>> +	igt_pipe_crc_stop(pipe_crc);
>> +	igt_pipe_crc_free(pipe_crc);
>> +
>> +	cairo_destroy(cr);
>> +	igt_remove_fb(data->gfx_fd, &data->primary_fb);
>> +}
>> +
>> +/*
>> + * fill_in_fb tell in return value if selected mode should be
>> + * proceed to crc check
>> + */
>> +static bool fill_in_fb(data_t *data, igt_output_t *output, enum pipe
>> pipe,
>> +			 igt_plane_t *plane, uint32_t format)
>> +{
>> +	signed i, c, writesize;
>> +	unsigned short* ptemp_16_buf;
>> +	unsigned int* ptemp_32_buf;
>> +
>> +	const struct {
>> +		uint32_t	fourcc;
>> +		char		zeropadding;
>> +		enum		{ BYTES_PP_1=1,
>> +				  BYTES_PP_2=2,
>> +				  BYTES_PP_4=4,
>> +				  NV12,
>> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
>> defined(DRM_FORMAT_P016)
>> +				  P010,
>> +#endif
>> +				  SKIP } bpp;
>> +		uint32_t	value;
>> +	} fillers[] = {
>> +		{ DRM_FORMAT_C8, 0, BYTES_PP_1, 0xff},
>> +		{ DRM_FORMAT_RGB565, 0, BYTES_PP_2, 0xffff},
>> +		{ DRM_FORMAT_XRGB8888, 0, BYTES_PP_4, 0xffffffff},
>> +		{ DRM_FORMAT_XBGR8888, 0, BYTES_PP_4, 0xffffffff},
>> +
>> +		/*
>> +		 * following two are skipped because blending seems
>> to work
>> +		 * incorrectly with exception of AR24 on cursor
>> plane.
>> +		 * Test still creates the planes, just filling plane
>> +		 * and getting crc is skipped.
>> +		 */
>> +		{ DRM_FORMAT_ARGB8888, 0, SKIP, 0xffffffff},
>> +		{ DRM_FORMAT_ABGR8888, 0, SKIP, 0x00ffffff},
>> +
>> +		{ DRM_FORMAT_XRGB2101010, 0, BYTES_PP_4,
>> 0xffffffff},
>> +		{ DRM_FORMAT_XBGR2101010, 0, BYTES_PP_4,
>> 0xffffffff},
>> +
>> +		{ DRM_FORMAT_YUYV, 0, BYTES_PP_4, 0x80eb80eb},
>> +		{ DRM_FORMAT_YVYU, 0, BYTES_PP_4, 0x80eb80eb},
>> +		{ DRM_FORMAT_VYUY, 0, BYTES_PP_4, 0xeb80eb80},
>> +		{ DRM_FORMAT_UYVY, 0, BYTES_PP_4, 0xeb80eb80},
>> +
>> +		/*
>> +		 * (semi-)planar formats
>> +		 */
>> +		{ DRM_FORMAT_NV12, 0, NV12, 0x80eb},
>> +#ifdef DRM_FORMAT_P010
>> +		{ DRM_FORMAT_P010, 0, P010, 0x8000eb00},
>> +#endif
>> +#ifdef DRM_FORMAT_P012
>> +		{ DRM_FORMAT_P012, 0, P010, 0x8000eb00},
>> +#endif
>> +#ifdef DRM_FORMAT_P016
>> +		{ DRM_FORMAT_P016, 0, P010, 0x8000eb00},
>> +#endif
>> +		{ 0, 0, 0, 0 }
>> +	};
>> +
>> +	for( i = 0; fillers[i].fourcc != 0; i++ ) {
>> +		if( fillers[i].fourcc == format )
>> +			break;
>> +	}
>> +
>> +	switch (fillers[i].bpp) {
>> +	case BYTES_PP_4:
>> +		ptemp_32_buf = (unsigned int*)data->buf;
>> +		for (c = 0; c < data->size/4; c++)
>> +			ptemp_32_buf[c] = fillers[i].value;
>> +		writesize = data->size;
>> +		break;
>> +	case BYTES_PP_2:
>> +		ptemp_16_buf = (unsigned short*)data->buf;
>> +		for (c = 0; c < data->size/2; c++)
>> +			ptemp_16_buf[c] = (unsigned
>> short)fillers[i].value;
>> +		writesize = data->size;
>> +		break;
>> +	case BYTES_PP_1:
>> +		memset((void*)data->buf, fillers[i].value, data-
>>> size);
>> +		writesize = data->size;
>> +		break;
>> +	case NV12:
>> +		memset((void*)data->buf, fillers[i].value&0xff,
>> +		       data->size);
>> +
>> +		memset((void*)(data->buf+data->size),
>> +		       (fillers[i].value>>8)&0xff, data->size/2);
>> +
>> +		writesize = data->size+data->size/2;
>> +		break;
>> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
>> defined(DRM_FORMAT_P016)
>> +	case P010:
>> +		ptemp_16_buf = (unsigned short*)data->buf;
>> +		for (c = 0; c < data->size/2; c++)
>> +			ptemp_16_buf[c] = (unsigned
>> short)fillers[i].value&0xffff;
>> +
>> +		ptemp_16_buf = (unsigned short*)(data->buf+data-
>>> size);
>> +		for (c = 0; c < data->size/2; c++)
>> +			ptemp_16_buf[c] = (unsigned
>> short)(fillers[i].value>>16)&0xffff;
>> +
>> +		writesize = data->size+data->size/2;
>> +		break;
>> +#endif
>> +	case SKIP:
>> +		if (fillers[i].fourcc == DRM_FORMAT_ARGB8888 &&
>> +		    plane->type == DRM_PLANE_TYPE_CURSOR) {
>> +		/*
>> +		 * special for cursor plane where blending works
>> correctly.
>> +		 */
>> +			ptemp_32_buf = (unsigned int*)data->buf;
>> +			for (c = 0; c < data->size/4; c++)
>> +				ptemp_32_buf[c] = fillers[i].value;
>> +			writesize = data->size;
>> +			break;
>> +		}
>> +		igt_info("Format %s CRC comparison skipped by
>> design.\n",
>> +			 (char*)&fillers[i].fourcc);
>> +
>> +		return false;
>> +	default:
>> +		igt_info("Unsupported mode for test %s\n",
>> +			 (char*)&fillers[i].fourcc);
>> +		return false;
>> +	}
>> +
>> +	do_write(data->gfx_fd, data->gem_handle, (void*)data->buf,
>> 0,
>> +		 writesize);
>> +
>> +	return true;
>> +}
>> +
>> +
>> +static bool setup_fb(data_t *data, igt_output_t *output, enum pipe
>> pipe,
>> +		     igt_plane_t *plane, uint32_t format)
>> +{
>> +	drmModeModeInfo *mode;
>> +	uint64_t w, h;
>> +	signed ret, gemsize = 0;
>> +	unsigned tile_width, tile_height, stride;
>> +	uint32_t offsets[4] = {};
>> +	uint32_t* offsetpointer = NULL;
>> +
>> +	mode = igt_output_get_mode(output);
>> +	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
>> +		w = mode->hdisplay ;
>> +		h = mode->vdisplay;
>> +	} else {
>> +		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
>> +		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
>> +	}
>> +
>> +	switch(format) {
>> +#ifdef DRM_FORMAT_P010
>> +	case DRM_FORMAT_P010:
>> +#endif
>> +#ifdef DRM_FORMAT_P012
>> +	case DRM_FORMAT_P012:
>> +#endif
>> +#ifdef DRM_FORMAT_P016
>> +	case DRM_FORMAT_P016:
>> +#endif
>> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
>> defined(DRM_FORMAT_P016)
>> +		tile_width = 512;
>> +		tile_height = 8;
>> +
>> +		stride = ALIGN(w*2, tile_width);
>> +		data->size = offsets[1] = stride*ALIGN(h,
>> tile_height);
>> +
>> +		gemsize = data->size*2;
>> +		offsetpointer = (uint32_t*)&offsets;
>> +		break;
>> +#endif
>> +	case DRM_FORMAT_NV12:
>> +		tile_width = 512;
>> +		tile_height = 8;
> The minimum height is 16 for NV12. This has been discussed in this
> patch
> 
> https://patchwork.freedesktop.org/patch/208171/
> 

Thanks, I'll fix. I did this test on top of Vidya's set submitted on 
feb22 where it still was 8. Same issue will apply for Pxxx formats.

> 
>> +
>> +		stride = ALIGN(w, tile_width);
>> +		data->size = offsets[1] = stride*ALIGN(h,
>> tile_height);
>> +
>> +		gemsize = data->size*2;
>> +		offsetpointer = (uint32_t*)&offsets;
>> +		break;
>> +	default:
>> +		tile_width = 512;
>> +		tile_height = 8;
>> +
>> +		/*
>> +		 * w*4 so there's enough space
>> +		 */
>> +		stride = ALIGN(w*4, tile_width);
>> +		data->size = stride*ALIGN(h, tile_height);
>> +		offsetpointer = NULL;
>> +
>> +		gemsize = data->size;
>> +		break;
>> +	}
>> +
>> +	data->gem_handle = gem_create(data->gfx_fd, gemsize);
>> +	ret = __gem_set_tiling(data->gfx_fd, data->gem_handle,
>> +			       I915_TILING_NONE, stride);
>> +
>> +	igt_assert_eq(ret, 0);
>> +
>> +	ret = __kms_addfb(data->gfx_fd, data->gem_handle, w, h,
>> +			  stride, format, LOCAL_DRM_FORMAT_MOD_NONE,
>> +			  offsetpointer,
>> LOCAL_DRM_MODE_FB_MODIFIERS,
>> +			  &data->fb.fb_id);
>> +
>> +	if(ret < 0) {
>> +		igt_info("Creating fb for format %s failed, return
>> code %d\n",
>> +			 (char*)&data->format_name, ret);
>> +
>> +		return false;
>> +	}
>> +
>> +	data->fb.width = w;
>> +	data->fb.height = h;
>> +	data->fb.gem_handle = data->gem_handle;
>> +	return true;
>> +}
>> +
>> +
>> +static void remove_fb(data_t* data, igt_output_t* output,
>> igt_plane_t* plane)
>> +{
>> +	if (data->separateprimaryplane) {
>> +		igt_plane_t* primary =
>> igt_output_get_plane_type(output,
>> +								 DRM
>> _PLANE_TYPE_PRIMARY);
>> +		igt_plane_set_fb(primary, NULL);
>> +		igt_remove_fb(data->gfx_fd, &data->primary_fb);
>> +		igt_display_commit2(&data->display, data->commit);
>> +		data->separateprimaryplane = false;
>> +	}
>> +
>> +	igt_remove_fb(data->gfx_fd, &data->fb);
>> +	igt_display_commit2(&data->display, data->commit);
>> +	free(data->buf);
>> +	data->buf = NULL;
>> +}
>> +
>> +
>> +static bool prepare_crtc(data_t *data, igt_output_t *output, enum
>> pipe pipe,
>> +			 igt_plane_t *plane, uint32_t format)
>> +{
>> +	drmModeModeInfo *mode;
>> +	igt_plane_t *primary;
>> +
>> +	if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
>> +		mode = igt_output_get_mode(output);
>> +		igt_create_color_fb(data->gfx_fd,
>> +				    mode->hdisplay, mode->vdisplay,
>> +				    DRM_FORMAT_XRGB8888,
>> +				    LOCAL_DRM_FORMAT_MOD_NONE,
>> +				    0, 0, 0,
>> +				    &data->primary_fb);
>> +
>> +		primary = igt_output_get_plane_type(output,
>> +						    DRM_PLANE_TYPE_P
>> RIMARY);
>> +
>> +		igt_plane_set_fb(primary, &data->primary_fb);
>> +		igt_display_commit2(&data->display, data->commit);
>> +		data->separateprimaryplane = true;
>> +	}
>> +
>> +	if (!setup_fb(data, output, pipe, plane, format))
>> +		return false;
>> +
>> +	if (data->buf != NULL) {
>> +		free((void*)data->buf);
>> +		data->buf = NULL;
>> +	}
>> +
>> +	data->buf = (unsigned char*)calloc(data->size*2, 1);
>> +	return true;
>> +}
>> +
>> +
>> +static int
>> +test_one_mode(data_t* data, igt_output_t *output, igt_plane_t*
>> plane,
>> +	      enum pipe pipe, int mode)
>> +{
>> +
>> +	igt_crc_t *crcs = NULL;
>> +	igt_pipe_crc_t *pipe_crc;
>> +	signed count, rVal = 0;
>> +	bool do_crc;
>> +	char* crccompare[2];
>> +
>> +	if (prepare_crtc(data, output, pipe, plane, mode)){
>> +
>> +		/*
>> +		 * we have fb from prepare_crtc(..) so now fill it
>> in
>> +		 * correctly in fill_in_fb(..)
>> +		 */
>> +		do_crc = fill_in_fb(data, output, pipe, plane,
>> mode);
>> +
>> +		igt_plane_set_fb(plane, &data->fb);
>> +		igt_fb_set_size(&data->fb, plane, data->fb.width,
>> data->fb.height);
>> +		igt_plane_set_size(plane, data->fb.width, data-
>>> fb.height);
>> +		igt_fb_set_position(&data->fb, plane, 0, 0);
>> +		igt_display_commit2(&data->display, data->commit);
>> +
>> +		if (do_crc) {
>> +			pipe_crc = igt_pipe_crc_new(data->gfx_fd,
>> pipe,
>> +						    INTEL_PIPE_CRC_S
>> OURCE_AUTO);
>> +
>> +			igt_pipe_crc_start(pipe_crc);
>> +
>> +			count = igt_pipe_crc_get_crcs(pipe_crc,
>> testcrcamount, &crcs);
>> +			igt_assert( count==testcrcamount );
>> +
>> +			igt_pipe_crc_stop(pipe_crc);
>> +			igt_pipe_crc_free(pipe_crc);
>> +
>> +			if (plane->type != DRM_PLANE_TYPE_CURSOR) {
>> +				if
>> (!igt_check_crc_equal(&crcs[testcrcamount-1],
>> +					&data-
>>> fullscreen_crc[testcrcamount-1])) {
>> +					crccompare[0] =
>> igt_crc_to_string(&crcs[testcrcamount-1]);
>> +					crccompare[1] =
>> igt_crc_to_string(&data->fullscreen_crc[testcrcamount-1]);
>> +					igt_warn("crc mismatch.
>> target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
>> +					free(crccompare[0]);
>> +					free(crccompare[1]);
>> +					rVal++;
>> +				}
>> +			} else {
>> +				if
>> (!igt_check_crc_equal(&crcs[testcrcamount-1],
>> +					&data-
>>> cursor_crc[testcrcamount-1])) {
>> +					crccompare[0] =
>> igt_crc_to_string(&crcs[testcrcamount-1]);
>> +					crccompare[1] =
>> igt_crc_to_string(&data->cursor_crc[testcrcamount-1]);
>> +					igt_warn("crc mismatch.
>> target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
>> +					free(crccompare[0]);
>> +					free(crccompare[1]);
>> +					rVal++;
>> +				}
>> +			}
>> +			free(crcs);
>> +		}
>> +		remove_fb(data, output, plane);
>> +		return rVal;
>> +	}
>> +	return 1;
>> +}
>> +
>> +
>> +static void
>> +test_available_modes(data_t* data)
>> +{
>> +	igt_output_t *output;
>> +	igt_plane_t *plane;
>> +	int* u32ptr_formats;
>> +	int modeindex;
>> +	enum pipe pipe;
>> +	struct drm_mode_get_plane one_plane = {};
>> +	int invalids = 0;
>> +
>> +	char planetype[3][8] = {"OVERLAY\0", "PRIMARY\0", "CURSOR\0"
>> };
>> +
>> +	for_each_pipe_with_valid_output(&data->display, pipe,
>> output) {
>> +		igt_output_set_pipe(output, pipe);
>> +
>> +		/*
>> +		 * regenerate comparison crcs for each pipe just in
>> case.
>> +		 */
>> +		generate_comparison_crc_list(data, output, pipe);
>> +
>> +		for_each_plane_on_pipe(&data->display, pipe, plane)
>> {
>> +			memset((void*)&one_plane, 0,
>> +			       sizeof(struct drm_mode_get_plane));
>> +			one_plane.plane_id = plane->drm_plane-
>>> plane_id;
>> +			/*
>> +			 * first call to know how much space needed,
>> +			 * second call to get list of supported
>> modes.
>> +			 */
>> +			igt_ioctl(data->gfx_fd,
>> DRM_IOCTL_MODE_GETPLANE,
>> +				  &one_plane);
>> +			igt_assert(one_plane.count_format_types >
>> 0);
>> +
>> +			u32ptr_formats =
>> (int*)calloc(one_plane.count_format_types,
>> +						      sizeof(int));
>> +
>> +			one_plane.format_type_ptr =
>> (__u64)u32ptr_formats;
>> +			igt_ioctl(data->gfx_fd,
>> DRM_IOCTL_MODE_GETPLANE,
>> +				  &one_plane);
>> +
>> +			for (modeindex = 0;
>> +			     modeindex <
>> one_plane.count_format_types;
>> +			     modeindex++) {
>> +				data->format_name[0] =
>> u32ptr_formats[modeindex]&0xff;
>> +				data->format_name[1] =
>> (u32ptr_formats[modeindex]>>8)&0xff;
>> +				data->format_name[2] =
>> (u32ptr_formats[modeindex]>>16)&0xff;
>> +				data->format_name[3] =
>> (u32ptr_formats[modeindex]>>24)&0xff;
>> +
>> +				igt_info("Testing connector %s using
>> pipe %s" \
>> +					 " plane index %d type %s
>> mode %s\n",
>> +					 igt_output_name(output),
>> +					 kmstest_pipe_name(pipe),
>> +					 plane->index,
>> +					 planetype[plane->type],
>> +					 (char*)&data->format_name);
>> +
>> +				invalids += test_one_mode(data,
>> output,
>> +							  plane,
>> pipe,
>> +							  u32ptr_for
>> mats[modeindex]);
>> +			}
>> +			free((void*)one_plane.format_type_ptr);
>> +		}
>> +		free(data->cursor_crc);
>> +		free(data->fullscreen_crc);
>> +	}
>> +	igt_assert(invalids == 0);
>> +}
>> +
>> +
>> +igt_main
>> +{
>> +	data_t data = {};
>> +
>> +	igt_skip_on_simulation();
>> +
>> +	igt_fixture {
>> +		data.gfx_fd = drm_open_driver_master(DRIVER_INTEL);
>> +		kmstest_set_vt_graphics_mode();
>> +
>> +		igt_display_init(&data.display, data.gfx_fd);
>> +
>> +		igt_require_pipe_crc(data.gfx_fd);
>> +	}
>> +
>> +	data.commit = data.display.is_atomic ? COMMIT_ATOMIC :
>> COMMIT_LEGACY;
>> +
>> +	igt_subtest("available_mode_test_crc") {
>> +		test_available_modes(&data);
>> +	}
>> +
>> +	igt_fixture {
>> +		kmstest_restore_vt_mode();
>> +		igt_display_fini(&data.display);
>> +	}
>> +}
>> diff --git a/tests/meson.build b/tests/meson.build
>> index 22e4ac9..6a5bd96 100644
>> --- a/tests/meson.build
>> +++ b/tests/meson.build
>> @@ -150,6 +150,7 @@ test_progs = [
>>   	'kms_atomic',
>>   	'kms_atomic_interruptible',
>>   	'kms_atomic_transition',
>> +	'kms_available_modes_crc',
>>   	'kms_busy',
>>   	'kms_ccs',
>>   	'kms_chv_cursor_fail',

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes
  2018-03-16 13:39 [igt-dev] [PATCH i-g-t] " Juha-Pekka Heikkila
@ 2018-03-19 12:12 ` Mika Kahola
  2018-03-20 11:37   ` Juha-Pekka Heikkila
  0 siblings, 1 reply; 11+ messages in thread
From: Mika Kahola @ 2018-03-19 12:12 UTC (permalink / raw)
  To: Juha-Pekka Heikkila, igt-dev

On Fri, 2018-03-16 at 15:39 +0200, Juha-Pekka Heikkila wrote:
> Ask from kernel about supported modes for each plane and try setting
> them on display and verify functionality with crc.
> 
> DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888 skip crc testing on
> primary and overlay planes because they produce incorrect crcs from
> hardware. DRM_FORMAT_ARGB8888 is tested on cursor plane.
> 
> Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
> ---
>  tests/Makefile.sources          |   1 +
>  tests/kms_available_modes_crc.c | 574
> ++++++++++++++++++++++++++++++++++++++++
>  tests/meson.build               |   1 +
>  3 files changed, 576 insertions(+)
>  create mode 100644 tests/kms_available_modes_crc.c
> 
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index f1d1cba..0622048 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -173,6 +173,7 @@ TESTS_progs = \
>  	kms_atomic \
>  	kms_atomic_interruptible \
>  	kms_atomic_transition \
> +	kms_available_modes_crc \
>  	kms_busy \
>  	kms_ccs \
>  	kms_chv_cursor_fail \
> diff --git a/tests/kms_available_modes_crc.c
> b/tests/kms_available_modes_crc.c
> new file mode 100644
> index 0000000..9e31346
> --- /dev/null
> +++ b/tests/kms_available_modes_crc.c
> @@ -0,0 +1,574 @@
> +/*
> + * 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.
> + *
> + */
> +
> +#include "drm_mode.h"
> +#include "drm_fourcc.h"
> +#include "igt.h"
> +#include <sys/ioctl.h>
> +
> +IGT_TEST_DESCRIPTION("CRC test all different plane modes which
> kernel advertises.");
> +
> +#define testcrcamount 3
Would grabbing just one CRC be enough for this test? Any reason why we
would need 3 CRC's?
 
> +
> +typedef struct {
> +	int gfx_fd;
> +	igt_display_t display;
> +	enum igt_commit_style commit;
> +
> +	struct igt_fb fb;
> +	struct igt_fb primary_fb;
> +
> +	char format_name[5];
> +	bool separateprimaryplane;
> +
> +	uint32_t gem_handle;
> +	uint32_t gem_handle_yuv;
> +	unsigned int size;
> +	unsigned char* buf;
> +
> +	/*
> +	 * comparison crcs
> +	 */
> +	igt_crc_t *cursor_crc;
> +	igt_crc_t *fullscreen_crc;
> +} data_t;
> +
> +
> +static int do_write(int fd, int handle, void *buf, int offset, int
> size)
> +{
> +	struct drm_i915_gem_pwrite write;
> +	memset(&write, 0x00, sizeof(write));
> +	write.handle = handle;
> +	write.data_ptr = (uintptr_t)buf;
> +	write.size = size;
> +	write.offset = offset;
> +	return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write);
> +}
> +
> +
> +static void generate_comparison_crc_list(data_t *data, igt_output_t
> *output,
> +					enum pipe pipe)
> +{
> +	drmModeModeInfo *mode;
> +	uint64_t w, h, c;
> +	int fbid;
> +	cairo_t *cr;
> +	igt_pipe_crc_t *pipe_crc;
> +	igt_plane_t *primary;
> +
> +
> +	igt_output_set_pipe(output, pipe);
> +
> +	mode = igt_output_get_mode(output);
> +	fbid = igt_create_color_fb(data->gfx_fd,
> +				   mode->hdisplay,
> +				   mode->vdisplay,
> +				   intel_gen(intel_get_drm_devid(dat
> a->gfx_fd)) < 9 ? DRM_FORMAT_XRGB8888 : DRM_FORMAT_ARGB8888,
> +				   LOCAL_DRM_FORMAT_MOD_NONE,
> +				   0, 0, 0,
> +				   &data->primary_fb);
> +
> +	igt_assert(fbid);
> +
> +	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
> +	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
> +
> +	cr = igt_get_cairo_ctx(data->gfx_fd, &data->primary_fb);
> +	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
> +			    0.0, 0.0, 0.0);
> +	igt_paint_color(cr, 0, 0, w, h, 1.0, 1.0, 1.0);
> +	igt_assert(cairo_status(cr) == 0);
> +
> +	primary = igt_output_get_plane_type(output,
> DRM_PLANE_TYPE_PRIMARY);
> +	igt_plane_set_fb(primary, &data->primary_fb);
> +	igt_display_commit2(&data->display, data->commit);
> +
> +	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
> INTEL_PIPE_CRC_SOURCE_AUTO);
> +	igt_pipe_crc_start(pipe_crc);
> +	c = igt_pipe_crc_get_crcs(pipe_crc, testcrcamount, &data-
> >cursor_crc);
If one CRC would be enough, we could utilize Maarten's library routine
'igt_pipe_crc_get_single()'.
> +	igt_assert(c==testcrcamount);
> +	igt_pipe_crc_stop(pipe_crc);
I think we could keep crc going and if we are concerned that we may
have incorrect one in the pipe, we could drain them with
'igt_igt_pipe_crc_drain()'

> +	igt_pipe_crc_free(pipe_crc);
> +	igt_plane_set_fb(primary, NULL);
> +	igt_display_commit2(&data->display, data->commit);
> +
> +	intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ?
> +		  igt_paint_color(cr, 0, 0, mode->hdisplay, mode-
> >vdisplay, 1.0, 1.0, 1.0) :
> +		  igt_paint_color_alpha(cr, 0, 0, mode->hdisplay,
> mode->vdisplay, 1.0, 1.0, 1.0, 1.0);
> +
> +	igt_plane_set_fb(primary, &data->primary_fb);
> +	igt_display_commit2(&data->display, data->commit);
> +
> +	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
> INTEL_PIPE_CRC_SOURCE_AUTO);
> +	igt_pipe_crc_start(pipe_crc);
> +	c = igt_pipe_crc_get_crcs(pipe_crc, testcrcamount, &data-
> >fullscreen_crc);
> +	igt_assert(c==testcrcamount);
> +	igt_pipe_crc_stop(pipe_crc);
> +	igt_pipe_crc_free(pipe_crc);
> +
> +	cairo_destroy(cr);
> +	igt_remove_fb(data->gfx_fd, &data->primary_fb);
> +}
> +
> +/*
> + * fill_in_fb tell in return value if selected mode should be
> + * proceed to crc check
> + */
> +static bool fill_in_fb(data_t *data, igt_output_t *output, enum pipe
> pipe,
> +			 igt_plane_t *plane, uint32_t format)
> +{
> +	signed i, c, writesize;
> +	unsigned short* ptemp_16_buf;
> +	unsigned int* ptemp_32_buf;
> +
> +	const struct {
> +		uint32_t	fourcc;
> +		char		zeropadding;
> +		enum		{ BYTES_PP_1=1,
> +				  BYTES_PP_2=2,
> +				  BYTES_PP_4=4,
> +				  NV12,
> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> defined(DRM_FORMAT_P016)
> +				  P010,
> +#endif
> +				  SKIP } bpp;
> +		uint32_t	value;
> +	} fillers[] = {
> +		{ DRM_FORMAT_C8, 0, BYTES_PP_1, 0xff},
> +		{ DRM_FORMAT_RGB565, 0, BYTES_PP_2, 0xffff},
> +		{ DRM_FORMAT_XRGB8888, 0, BYTES_PP_4, 0xffffffff},
> +		{ DRM_FORMAT_XBGR8888, 0, BYTES_PP_4, 0xffffffff},
> +
> +		/*
> +		 * following two are skipped because blending seems
> to work
> +		 * incorrectly with exception of AR24 on cursor
> plane.
> +		 * Test still creates the planes, just filling plane
> +		 * and getting crc is skipped.
> +		 */
> +		{ DRM_FORMAT_ARGB8888, 0, SKIP, 0xffffffff},
> +		{ DRM_FORMAT_ABGR8888, 0, SKIP, 0x00ffffff},
> +
> +		{ DRM_FORMAT_XRGB2101010, 0, BYTES_PP_4,
> 0xffffffff},
> +		{ DRM_FORMAT_XBGR2101010, 0, BYTES_PP_4,
> 0xffffffff},
> +
> +		{ DRM_FORMAT_YUYV, 0, BYTES_PP_4, 0x80eb80eb},
> +		{ DRM_FORMAT_YVYU, 0, BYTES_PP_4, 0x80eb80eb},
> +		{ DRM_FORMAT_VYUY, 0, BYTES_PP_4, 0xeb80eb80},
> +		{ DRM_FORMAT_UYVY, 0, BYTES_PP_4, 0xeb80eb80},
> +
> +		/*
> +		 * (semi-)planar formats
> +		 */
> +		{ DRM_FORMAT_NV12, 0, NV12, 0x80eb},
> +#ifdef DRM_FORMAT_P010
> +		{ DRM_FORMAT_P010, 0, P010, 0x8000eb00},
> +#endif
> +#ifdef DRM_FORMAT_P012
> +		{ DRM_FORMAT_P012, 0, P010, 0x8000eb00},
> +#endif
> +#ifdef DRM_FORMAT_P016
> +		{ DRM_FORMAT_P016, 0, P010, 0x8000eb00},
> +#endif
> +		{ 0, 0, 0, 0 }
> +	};
> +
> +	for( i = 0; fillers[i].fourcc != 0; i++ ) {
> +		if( fillers[i].fourcc == format )
> +			break;
> +	}
> +
> +	switch (fillers[i].bpp) {
> +	case BYTES_PP_4:
> +		ptemp_32_buf = (unsigned int*)data->buf;
> +		for (c = 0; c < data->size/4; c++)
> +			ptemp_32_buf[c] = fillers[i].value;
> +		writesize = data->size;
> +		break;
> +	case BYTES_PP_2:
> +		ptemp_16_buf = (unsigned short*)data->buf;
> +		for (c = 0; c < data->size/2; c++)
> +			ptemp_16_buf[c] = (unsigned
> short)fillers[i].value;
> +		writesize = data->size;
> +		break;
> +	case BYTES_PP_1:
> +		memset((void*)data->buf, fillers[i].value, data-
> >size);
> +		writesize = data->size;
> +		break;
> +	case NV12:
> +		memset((void*)data->buf, fillers[i].value&0xff,
> +		       data->size);
> +
> +		memset((void*)(data->buf+data->size),
> +		       (fillers[i].value>>8)&0xff, data->size/2);
> +
> +		writesize = data->size+data->size/2;
> +		break;
> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> defined(DRM_FORMAT_P016)
> +	case P010:
> +		ptemp_16_buf = (unsigned short*)data->buf;
> +		for (c = 0; c < data->size/2; c++)
> +			ptemp_16_buf[c] = (unsigned
> short)fillers[i].value&0xffff;
> +
> +		ptemp_16_buf = (unsigned short*)(data->buf+data-
> >size);
> +		for (c = 0; c < data->size/2; c++)
> +			ptemp_16_buf[c] = (unsigned
> short)(fillers[i].value>>16)&0xffff;
> +
> +		writesize = data->size+data->size/2;
> +		break;
> +#endif
> +	case SKIP:
> +		if (fillers[i].fourcc == DRM_FORMAT_ARGB8888 &&
> +		    plane->type == DRM_PLANE_TYPE_CURSOR) {
> +		/*
> +		 * special for cursor plane where blending works
> correctly.
> +		 */
> +			ptemp_32_buf = (unsigned int*)data->buf;
> +			for (c = 0; c < data->size/4; c++)
> +				ptemp_32_buf[c] = fillers[i].value;
> +			writesize = data->size;
> +			break;
> +		}
> +		igt_info("Format %s CRC comparison skipped by
> design.\n",
> +			 (char*)&fillers[i].fourcc);
> +
> +		return false;
> +	default:
> +		igt_info("Unsupported mode for test %s\n",
> +			 (char*)&fillers[i].fourcc);
> +		return false;
> +	}
> +
> +	do_write(data->gfx_fd, data->gem_handle, (void*)data->buf,
> 0,
> +		 writesize);
> +
> +	return true;
> +}
> +
> +
> +static bool setup_fb(data_t *data, igt_output_t *output, enum pipe
> pipe,
> +		     igt_plane_t *plane, uint32_t format)
> +{
> +	drmModeModeInfo *mode;
> +	uint64_t w, h;
> +	signed ret, gemsize = 0;
> +	unsigned tile_width, tile_height, stride;
> +	uint32_t offsets[4] = {};
> +	uint32_t* offsetpointer = NULL;
> +
> +	mode = igt_output_get_mode(output);
> +	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
> +		w = mode->hdisplay ;
> +		h = mode->vdisplay;
> +	} else {
> +		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
> +		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
> +	}
> +
> +	switch(format) {
> +#ifdef DRM_FORMAT_P010
> +	case DRM_FORMAT_P010:
> +#endif
> +#ifdef DRM_FORMAT_P012
> +	case DRM_FORMAT_P012:
> +#endif
> +#ifdef DRM_FORMAT_P016
> +	case DRM_FORMAT_P016:
> +#endif
> +#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) ||
> defined(DRM_FORMAT_P016)
> +		tile_width = 512;
> +		tile_height = 8;
> +
> +		stride = ALIGN(w*2, tile_width);
> +		data->size = offsets[1] = stride*ALIGN(h,
> tile_height);
> +
> +		gemsize = data->size*2;
> +		offsetpointer = (uint32_t*)&offsets;
> +		break;
> +#endif
> +	case DRM_FORMAT_NV12:
> +		tile_width = 512;
> +		tile_height = 8;
The minimum height is 16 for NV12. This has been discussed in this
patch

https://patchwork.freedesktop.org/patch/208171/


> +
> +		stride = ALIGN(w, tile_width);
> +		data->size = offsets[1] = stride*ALIGN(h,
> tile_height);
> +
> +		gemsize = data->size*2;
> +		offsetpointer = (uint32_t*)&offsets;
> +		break;
> +	default:
> +		tile_width = 512;
> +		tile_height = 8;
> +
> +		/*
> +		 * w*4 so there's enough space
> +		 */
> +		stride = ALIGN(w*4, tile_width);
> +		data->size = stride*ALIGN(h, tile_height);
> +		offsetpointer = NULL;
> +
> +		gemsize = data->size;
> +		break;
> +	}
> +
> +	data->gem_handle = gem_create(data->gfx_fd, gemsize);
> +	ret = __gem_set_tiling(data->gfx_fd, data->gem_handle,
> +			       I915_TILING_NONE, stride);
> +
> +	igt_assert_eq(ret, 0);
> +
> +	ret = __kms_addfb(data->gfx_fd, data->gem_handle, w, h,
> +			  stride, format, LOCAL_DRM_FORMAT_MOD_NONE,
> +			  offsetpointer,
> LOCAL_DRM_MODE_FB_MODIFIERS,
> +			  &data->fb.fb_id);
> +
> +	if(ret < 0) {
> +		igt_info("Creating fb for format %s failed, return
> code %d\n",
> +			 (char*)&data->format_name, ret);
> +
> +		return false;
> +	}
> +
> +	data->fb.width = w;
> +	data->fb.height = h;
> +	data->fb.gem_handle = data->gem_handle;
> +	return true;
> +}
> +
> +
> +static void remove_fb(data_t* data, igt_output_t* output,
> igt_plane_t* plane)
> +{
> +	if (data->separateprimaryplane) {
> +		igt_plane_t* primary =
> igt_output_get_plane_type(output,
> +								 DRM
> _PLANE_TYPE_PRIMARY);
> +		igt_plane_set_fb(primary, NULL);
> +		igt_remove_fb(data->gfx_fd, &data->primary_fb);
> +		igt_display_commit2(&data->display, data->commit);
> +		data->separateprimaryplane = false;
> +	}
> +
> +	igt_remove_fb(data->gfx_fd, &data->fb);
> +	igt_display_commit2(&data->display, data->commit);
> +	free(data->buf);
> +	data->buf = NULL;
> +}
> +
> +
> +static bool prepare_crtc(data_t *data, igt_output_t *output, enum
> pipe pipe,
> +			 igt_plane_t *plane, uint32_t format)
> +{
> +	drmModeModeInfo *mode;
> +	igt_plane_t *primary;
> +
> +	if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
> +		mode = igt_output_get_mode(output);
> +		igt_create_color_fb(data->gfx_fd,
> +				    mode->hdisplay, mode->vdisplay,
> +				    DRM_FORMAT_XRGB8888,
> +				    LOCAL_DRM_FORMAT_MOD_NONE,
> +				    0, 0, 0,
> +				    &data->primary_fb);
> +
> +		primary = igt_output_get_plane_type(output,
> +						    DRM_PLANE_TYPE_P
> RIMARY);
> +
> +		igt_plane_set_fb(primary, &data->primary_fb);
> +		igt_display_commit2(&data->display, data->commit);
> +		data->separateprimaryplane = true;
> +	}
> +
> +	if (!setup_fb(data, output, pipe, plane, format))
> +		return false;
> +
> +	if (data->buf != NULL) {
> +		free((void*)data->buf);
> +		data->buf = NULL;
> +	}
> +
> +	data->buf = (unsigned char*)calloc(data->size*2, 1);
> +	return true;
> +}
> +
> +
> +static int
> +test_one_mode(data_t* data, igt_output_t *output, igt_plane_t*
> plane,
> +	      enum pipe pipe, int mode)
> +{
> +
> +	igt_crc_t *crcs = NULL;
> +	igt_pipe_crc_t *pipe_crc;
> +	signed count, rVal = 0;
> +	bool do_crc;
> +	char* crccompare[2];
> +
> +	if (prepare_crtc(data, output, pipe, plane, mode)){
> +
> +		/*
> +		 * we have fb from prepare_crtc(..) so now fill it
> in
> +		 * correctly in fill_in_fb(..)
> +		 */
> +		do_crc = fill_in_fb(data, output, pipe, plane,
> mode);
> +
> +		igt_plane_set_fb(plane, &data->fb);
> +		igt_fb_set_size(&data->fb, plane, data->fb.width,
> data->fb.height);
> +		igt_plane_set_size(plane, data->fb.width, data-
> >fb.height);
> +		igt_fb_set_position(&data->fb, plane, 0, 0);
> +		igt_display_commit2(&data->display, data->commit);
> +
> +		if (do_crc) {
> +			pipe_crc = igt_pipe_crc_new(data->gfx_fd,
> pipe,
> +						    INTEL_PIPE_CRC_S
> OURCE_AUTO);
> +
> +			igt_pipe_crc_start(pipe_crc);
> +
> +			count = igt_pipe_crc_get_crcs(pipe_crc,
> testcrcamount, &crcs);
> +			igt_assert( count==testcrcamount );
> +
> +			igt_pipe_crc_stop(pipe_crc);
> +			igt_pipe_crc_free(pipe_crc);
> +
> +			if (plane->type != DRM_PLANE_TYPE_CURSOR) {
> +				if
> (!igt_check_crc_equal(&crcs[testcrcamount-1],
> +					&data-
> >fullscreen_crc[testcrcamount-1])) {
> +					crccompare[0] =
> igt_crc_to_string(&crcs[testcrcamount-1]);
> +					crccompare[1] =
> igt_crc_to_string(&data->fullscreen_crc[testcrcamount-1]);
> +					igt_warn("crc mismatch.
> target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
> +					free(crccompare[0]);
> +					free(crccompare[1]);
> +					rVal++;
> +				}
> +			} else {
> +				if
> (!igt_check_crc_equal(&crcs[testcrcamount-1],
> +					&data-
> >cursor_crc[testcrcamount-1])) {
> +					crccompare[0] =
> igt_crc_to_string(&crcs[testcrcamount-1]);
> +					crccompare[1] =
> igt_crc_to_string(&data->cursor_crc[testcrcamount-1]);
> +					igt_warn("crc mismatch.
> target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
> +					free(crccompare[0]);
> +					free(crccompare[1]);
> +					rVal++;
> +				}
> +			}
> +			free(crcs);
> +		}
> +		remove_fb(data, output, plane);
> +		return rVal;
> +	}
> +	return 1;
> +}
> +
> +
> +static void
> +test_available_modes(data_t* data)
> +{
> +	igt_output_t *output;
> +	igt_plane_t *plane;
> +	int* u32ptr_formats;
> +	int modeindex;
> +	enum pipe pipe;
> +	struct drm_mode_get_plane one_plane = {};
> +	int invalids = 0;
> +
> +	char planetype[3][8] = {"OVERLAY\0", "PRIMARY\0", "CURSOR\0"
> };
> +
> +	for_each_pipe_with_valid_output(&data->display, pipe,
> output) {
> +		igt_output_set_pipe(output, pipe);
> +
> +		/*
> +		 * regenerate comparison crcs for each pipe just in
> case.
> +		 */
> +		generate_comparison_crc_list(data, output, pipe);
> +
> +		for_each_plane_on_pipe(&data->display, pipe, plane)
> {
> +			memset((void*)&one_plane, 0,
> +			       sizeof(struct drm_mode_get_plane));
> +			one_plane.plane_id = plane->drm_plane-
> >plane_id;
> +			/*
> +			 * first call to know how much space needed,
> +			 * second call to get list of supported
> modes.
> +			 */
> +			igt_ioctl(data->gfx_fd,
> DRM_IOCTL_MODE_GETPLANE,
> +				  &one_plane);
> +			igt_assert(one_plane.count_format_types >
> 0);
> +
> +			u32ptr_formats =
> (int*)calloc(one_plane.count_format_types,
> +						      sizeof(int));
> +
> +			one_plane.format_type_ptr =
> (__u64)u32ptr_formats;
> +			igt_ioctl(data->gfx_fd,
> DRM_IOCTL_MODE_GETPLANE,
> +				  &one_plane);
> +
> +			for (modeindex = 0;
> +			     modeindex <
> one_plane.count_format_types;
> +			     modeindex++) {
> +				data->format_name[0] =
> u32ptr_formats[modeindex]&0xff;
> +				data->format_name[1] =
> (u32ptr_formats[modeindex]>>8)&0xff;
> +				data->format_name[2] =
> (u32ptr_formats[modeindex]>>16)&0xff;
> +				data->format_name[3] =
> (u32ptr_formats[modeindex]>>24)&0xff;
> +
> +				igt_info("Testing connector %s using
> pipe %s" \
> +					 " plane index %d type %s
> mode %s\n",
> +					 igt_output_name(output),
> +					 kmstest_pipe_name(pipe),
> +					 plane->index,
> +					 planetype[plane->type],
> +					 (char*)&data->format_name);
> +
> +				invalids += test_one_mode(data,
> output,
> +							  plane,
> pipe,
> +							  u32ptr_for
> mats[modeindex]);
> +			}
> +			free((void*)one_plane.format_type_ptr);
> +		}
> +		free(data->cursor_crc);
> +		free(data->fullscreen_crc);
> +	}
> +	igt_assert(invalids == 0);
> +}
> +
> +
> +igt_main
> +{
> +	data_t data = {};
> +
> +	igt_skip_on_simulation();
> +
> +	igt_fixture {
> +		data.gfx_fd = drm_open_driver_master(DRIVER_INTEL);
> +		kmstest_set_vt_graphics_mode();
> +
> +		igt_display_init(&data.display, data.gfx_fd);
> +
> +		igt_require_pipe_crc(data.gfx_fd);
> +	}
> +
> +	data.commit = data.display.is_atomic ? COMMIT_ATOMIC :
> COMMIT_LEGACY;
> +
> +	igt_subtest("available_mode_test_crc") {
> +		test_available_modes(&data);
> +	}
> +
> +	igt_fixture {
> +		kmstest_restore_vt_mode();
> +		igt_display_fini(&data.display);
> +	}
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 22e4ac9..6a5bd96 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -150,6 +150,7 @@ test_progs = [
>  	'kms_atomic',
>  	'kms_atomic_interruptible',
>  	'kms_atomic_transition',
> +	'kms_available_modes_crc',
>  	'kms_busy',
>  	'kms_ccs',
>  	'kms_chv_cursor_fail',
-- 
Mika Kahola - Intel OTC

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes
@ 2018-03-16 13:39 Juha-Pekka Heikkila
  2018-03-19 12:12 ` Mika Kahola
  0 siblings, 1 reply; 11+ messages in thread
From: Juha-Pekka Heikkila @ 2018-03-16 13:39 UTC (permalink / raw)
  To: igt-dev

Ask from kernel about supported modes for each plane and try setting
them on display and verify functionality with crc.

DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888 skip crc testing on
primary and overlay planes because they produce incorrect crcs from
hardware. DRM_FORMAT_ARGB8888 is tested on cursor plane.

Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
---
 tests/Makefile.sources          |   1 +
 tests/kms_available_modes_crc.c | 574 ++++++++++++++++++++++++++++++++++++++++
 tests/meson.build               |   1 +
 3 files changed, 576 insertions(+)
 create mode 100644 tests/kms_available_modes_crc.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index f1d1cba..0622048 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -173,6 +173,7 @@ TESTS_progs = \
 	kms_atomic \
 	kms_atomic_interruptible \
 	kms_atomic_transition \
+	kms_available_modes_crc \
 	kms_busy \
 	kms_ccs \
 	kms_chv_cursor_fail \
diff --git a/tests/kms_available_modes_crc.c b/tests/kms_available_modes_crc.c
new file mode 100644
index 0000000..9e31346
--- /dev/null
+++ b/tests/kms_available_modes_crc.c
@@ -0,0 +1,574 @@
+/*
+ * 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.
+ *
+ */
+
+#include "drm_mode.h"
+#include "drm_fourcc.h"
+#include "igt.h"
+#include <sys/ioctl.h>
+
+IGT_TEST_DESCRIPTION("CRC test all different plane modes which kernel advertises.");
+
+#define testcrcamount 3
+
+typedef struct {
+	int gfx_fd;
+	igt_display_t display;
+	enum igt_commit_style commit;
+
+	struct igt_fb fb;
+	struct igt_fb primary_fb;
+
+	char format_name[5];
+	bool separateprimaryplane;
+
+	uint32_t gem_handle;
+	uint32_t gem_handle_yuv;
+	unsigned int size;
+	unsigned char* buf;
+
+	/*
+	 * comparison crcs
+	 */
+	igt_crc_t *cursor_crc;
+	igt_crc_t *fullscreen_crc;
+} data_t;
+
+
+static int do_write(int fd, int handle, void *buf, int offset, int size)
+{
+	struct drm_i915_gem_pwrite write;
+	memset(&write, 0x00, sizeof(write));
+	write.handle = handle;
+	write.data_ptr = (uintptr_t)buf;
+	write.size = size;
+	write.offset = offset;
+	return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write);
+}
+
+
+static void generate_comparison_crc_list(data_t *data, igt_output_t *output,
+					enum pipe pipe)
+{
+	drmModeModeInfo *mode;
+	uint64_t w, h, c;
+	int fbid;
+	cairo_t *cr;
+	igt_pipe_crc_t *pipe_crc;
+	igt_plane_t *primary;
+
+
+	igt_output_set_pipe(output, pipe);
+
+	mode = igt_output_get_mode(output);
+	fbid = igt_create_color_fb(data->gfx_fd,
+				   mode->hdisplay,
+				   mode->vdisplay,
+				   intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ? DRM_FORMAT_XRGB8888 : DRM_FORMAT_ARGB8888,
+				   LOCAL_DRM_FORMAT_MOD_NONE,
+				   0, 0, 0,
+				   &data->primary_fb);
+
+	igt_assert(fbid);
+
+	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
+	drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
+
+	cr = igt_get_cairo_ctx(data->gfx_fd, &data->primary_fb);
+	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
+			    0.0, 0.0, 0.0);
+	igt_paint_color(cr, 0, 0, w, h, 1.0, 1.0, 1.0);
+	igt_assert(cairo_status(cr) == 0);
+
+	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
+	igt_plane_set_fb(primary, &data->primary_fb);
+	igt_display_commit2(&data->display, data->commit);
+
+	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
+	igt_pipe_crc_start(pipe_crc);
+	c = igt_pipe_crc_get_crcs(pipe_crc, testcrcamount, &data->cursor_crc);
+	igt_assert(c==testcrcamount);
+	igt_pipe_crc_stop(pipe_crc);
+	igt_pipe_crc_free(pipe_crc);
+	igt_plane_set_fb(primary, NULL);
+	igt_display_commit2(&data->display, data->commit);
+
+	intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9 ?
+		  igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay, 1.0, 1.0, 1.0) :
+		  igt_paint_color_alpha(cr, 0, 0, mode->hdisplay, mode->vdisplay, 1.0, 1.0, 1.0, 1.0);
+
+	igt_plane_set_fb(primary, &data->primary_fb);
+	igt_display_commit2(&data->display, data->commit);
+
+	pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
+	igt_pipe_crc_start(pipe_crc);
+	c = igt_pipe_crc_get_crcs(pipe_crc, testcrcamount, &data->fullscreen_crc);
+	igt_assert(c==testcrcamount);
+	igt_pipe_crc_stop(pipe_crc);
+	igt_pipe_crc_free(pipe_crc);
+
+	cairo_destroy(cr);
+	igt_remove_fb(data->gfx_fd, &data->primary_fb);
+}
+
+/*
+ * fill_in_fb tell in return value if selected mode should be
+ * proceed to crc check
+ */
+static bool fill_in_fb(data_t *data, igt_output_t *output, enum pipe pipe,
+			 igt_plane_t *plane, uint32_t format)
+{
+	signed i, c, writesize;
+	unsigned short* ptemp_16_buf;
+	unsigned int* ptemp_32_buf;
+
+	const struct {
+		uint32_t	fourcc;
+		char		zeropadding;
+		enum		{ BYTES_PP_1=1,
+				  BYTES_PP_2=2,
+				  BYTES_PP_4=4,
+				  NV12,
+#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) || defined(DRM_FORMAT_P016)
+				  P010,
+#endif
+				  SKIP } bpp;
+		uint32_t	value;
+	} fillers[] = {
+		{ DRM_FORMAT_C8, 0, BYTES_PP_1, 0xff},
+		{ DRM_FORMAT_RGB565, 0, BYTES_PP_2, 0xffff},
+		{ DRM_FORMAT_XRGB8888, 0, BYTES_PP_4, 0xffffffff},
+		{ DRM_FORMAT_XBGR8888, 0, BYTES_PP_4, 0xffffffff},
+
+		/*
+		 * following two are skipped because blending seems to work
+		 * incorrectly with exception of AR24 on cursor plane.
+		 * Test still creates the planes, just filling plane
+		 * and getting crc is skipped.
+		 */
+		{ DRM_FORMAT_ARGB8888, 0, SKIP, 0xffffffff},
+		{ DRM_FORMAT_ABGR8888, 0, SKIP, 0x00ffffff},
+
+		{ DRM_FORMAT_XRGB2101010, 0, BYTES_PP_4, 0xffffffff},
+		{ DRM_FORMAT_XBGR2101010, 0, BYTES_PP_4, 0xffffffff},
+
+		{ DRM_FORMAT_YUYV, 0, BYTES_PP_4, 0x80eb80eb},
+		{ DRM_FORMAT_YVYU, 0, BYTES_PP_4, 0x80eb80eb},
+		{ DRM_FORMAT_VYUY, 0, BYTES_PP_4, 0xeb80eb80},
+		{ DRM_FORMAT_UYVY, 0, BYTES_PP_4, 0xeb80eb80},
+
+		/*
+		 * (semi-)planar formats
+		 */
+		{ DRM_FORMAT_NV12, 0, NV12, 0x80eb},
+#ifdef DRM_FORMAT_P010
+		{ DRM_FORMAT_P010, 0, P010, 0x8000eb00},
+#endif
+#ifdef DRM_FORMAT_P012
+		{ DRM_FORMAT_P012, 0, P010, 0x8000eb00},
+#endif
+#ifdef DRM_FORMAT_P016
+		{ DRM_FORMAT_P016, 0, P010, 0x8000eb00},
+#endif
+		{ 0, 0, 0, 0 }
+	};
+
+	for( i = 0; fillers[i].fourcc != 0; i++ ) {
+		if( fillers[i].fourcc == format )
+			break;
+	}
+
+	switch (fillers[i].bpp) {
+	case BYTES_PP_4:
+		ptemp_32_buf = (unsigned int*)data->buf;
+		for (c = 0; c < data->size/4; c++)
+			ptemp_32_buf[c] = fillers[i].value;
+		writesize = data->size;
+		break;
+	case BYTES_PP_2:
+		ptemp_16_buf = (unsigned short*)data->buf;
+		for (c = 0; c < data->size/2; c++)
+			ptemp_16_buf[c] = (unsigned short)fillers[i].value;
+		writesize = data->size;
+		break;
+	case BYTES_PP_1:
+		memset((void*)data->buf, fillers[i].value, data->size);
+		writesize = data->size;
+		break;
+	case NV12:
+		memset((void*)data->buf, fillers[i].value&0xff,
+		       data->size);
+
+		memset((void*)(data->buf+data->size),
+		       (fillers[i].value>>8)&0xff, data->size/2);
+
+		writesize = data->size+data->size/2;
+		break;
+#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) || defined(DRM_FORMAT_P016)
+	case P010:
+		ptemp_16_buf = (unsigned short*)data->buf;
+		for (c = 0; c < data->size/2; c++)
+			ptemp_16_buf[c] = (unsigned short)fillers[i].value&0xffff;
+
+		ptemp_16_buf = (unsigned short*)(data->buf+data->size);
+		for (c = 0; c < data->size/2; c++)
+			ptemp_16_buf[c] = (unsigned short)(fillers[i].value>>16)&0xffff;
+
+		writesize = data->size+data->size/2;
+		break;
+#endif
+	case SKIP:
+		if (fillers[i].fourcc == DRM_FORMAT_ARGB8888 &&
+		    plane->type == DRM_PLANE_TYPE_CURSOR) {
+		/*
+		 * special for cursor plane where blending works correctly.
+		 */
+			ptemp_32_buf = (unsigned int*)data->buf;
+			for (c = 0; c < data->size/4; c++)
+				ptemp_32_buf[c] = fillers[i].value;
+			writesize = data->size;
+			break;
+		}
+		igt_info("Format %s CRC comparison skipped by design.\n",
+			 (char*)&fillers[i].fourcc);
+
+		return false;
+	default:
+		igt_info("Unsupported mode for test %s\n",
+			 (char*)&fillers[i].fourcc);
+		return false;
+	}
+
+	do_write(data->gfx_fd, data->gem_handle, (void*)data->buf, 0,
+		 writesize);
+
+	return true;
+}
+
+
+static bool setup_fb(data_t *data, igt_output_t *output, enum pipe pipe,
+		     igt_plane_t *plane, uint32_t format)
+{
+	drmModeModeInfo *mode;
+	uint64_t w, h;
+	signed ret, gemsize = 0;
+	unsigned tile_width, tile_height, stride;
+	uint32_t offsets[4] = {};
+	uint32_t* offsetpointer = NULL;
+
+	mode = igt_output_get_mode(output);
+	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+		w = mode->hdisplay ;
+		h = mode->vdisplay;
+	} else {
+		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_WIDTH, &w);
+		drmGetCap(data->gfx_fd, DRM_CAP_CURSOR_HEIGHT, &h);
+	}
+
+	switch(format) {
+#ifdef DRM_FORMAT_P010
+	case DRM_FORMAT_P010:
+#endif
+#ifdef DRM_FORMAT_P012
+	case DRM_FORMAT_P012:
+#endif
+#ifdef DRM_FORMAT_P016
+	case DRM_FORMAT_P016:
+#endif
+#if defined(DRM_FORMAT_P010) || defined(DRM_FORMAT_P012) || defined(DRM_FORMAT_P016)
+		tile_width = 512;
+		tile_height = 8;
+
+		stride = ALIGN(w*2, tile_width);
+		data->size = offsets[1] = stride*ALIGN(h, tile_height);
+
+		gemsize = data->size*2;
+		offsetpointer = (uint32_t*)&offsets;
+		break;
+#endif
+	case DRM_FORMAT_NV12:
+		tile_width = 512;
+		tile_height = 8;
+
+		stride = ALIGN(w, tile_width);
+		data->size = offsets[1] = stride*ALIGN(h, tile_height);
+
+		gemsize = data->size*2;
+		offsetpointer = (uint32_t*)&offsets;
+		break;
+	default:
+		tile_width = 512;
+		tile_height = 8;
+
+		/*
+		 * w*4 so there's enough space
+		 */
+		stride = ALIGN(w*4, tile_width);
+		data->size = stride*ALIGN(h, tile_height);
+		offsetpointer = NULL;
+
+		gemsize = data->size;
+		break;
+	}
+
+	data->gem_handle = gem_create(data->gfx_fd, gemsize);
+	ret = __gem_set_tiling(data->gfx_fd, data->gem_handle,
+			       I915_TILING_NONE, stride);
+
+	igt_assert_eq(ret, 0);
+
+	ret = __kms_addfb(data->gfx_fd, data->gem_handle, w, h,
+			  stride, format, LOCAL_DRM_FORMAT_MOD_NONE,
+			  offsetpointer, LOCAL_DRM_MODE_FB_MODIFIERS,
+			  &data->fb.fb_id);
+
+	if(ret < 0) {
+		igt_info("Creating fb for format %s failed, return code %d\n",
+			 (char*)&data->format_name, ret);
+
+		return false;
+	}
+
+	data->fb.width = w;
+	data->fb.height = h;
+	data->fb.gem_handle = data->gem_handle;
+	return true;
+}
+
+
+static void remove_fb(data_t* data, igt_output_t* output, igt_plane_t* plane)
+{
+	if (data->separateprimaryplane) {
+		igt_plane_t* primary = igt_output_get_plane_type(output,
+								 DRM_PLANE_TYPE_PRIMARY);
+		igt_plane_set_fb(primary, NULL);
+		igt_remove_fb(data->gfx_fd, &data->primary_fb);
+		igt_display_commit2(&data->display, data->commit);
+		data->separateprimaryplane = false;
+	}
+
+	igt_remove_fb(data->gfx_fd, &data->fb);
+	igt_display_commit2(&data->display, data->commit);
+	free(data->buf);
+	data->buf = NULL;
+}
+
+
+static bool prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
+			 igt_plane_t *plane, uint32_t format)
+{
+	drmModeModeInfo *mode;
+	igt_plane_t *primary;
+
+	if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
+		mode = igt_output_get_mode(output);
+		igt_create_color_fb(data->gfx_fd,
+				    mode->hdisplay, mode->vdisplay,
+				    DRM_FORMAT_XRGB8888,
+				    LOCAL_DRM_FORMAT_MOD_NONE,
+				    0, 0, 0,
+				    &data->primary_fb);
+
+		primary = igt_output_get_plane_type(output,
+						    DRM_PLANE_TYPE_PRIMARY);
+
+		igt_plane_set_fb(primary, &data->primary_fb);
+		igt_display_commit2(&data->display, data->commit);
+		data->separateprimaryplane = true;
+	}
+
+	if (!setup_fb(data, output, pipe, plane, format))
+		return false;
+
+	if (data->buf != NULL) {
+		free((void*)data->buf);
+		data->buf = NULL;
+	}
+
+	data->buf = (unsigned char*)calloc(data->size*2, 1);
+	return true;
+}
+
+
+static int
+test_one_mode(data_t* data, igt_output_t *output, igt_plane_t* plane,
+	      enum pipe pipe, int mode)
+{
+
+	igt_crc_t *crcs = NULL;
+	igt_pipe_crc_t *pipe_crc;
+	signed count, rVal = 0;
+	bool do_crc;
+	char* crccompare[2];
+
+	if (prepare_crtc(data, output, pipe, plane, mode)){
+
+		/*
+		 * we have fb from prepare_crtc(..) so now fill it in
+		 * correctly in fill_in_fb(..)
+		 */
+		do_crc = fill_in_fb(data, output, pipe, plane, mode);
+
+		igt_plane_set_fb(plane, &data->fb);
+		igt_fb_set_size(&data->fb, plane, data->fb.width, data->fb.height);
+		igt_plane_set_size(plane, data->fb.width, data->fb.height);
+		igt_fb_set_position(&data->fb, plane, 0, 0);
+		igt_display_commit2(&data->display, data->commit);
+
+		if (do_crc) {
+			pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
+						    INTEL_PIPE_CRC_SOURCE_AUTO);
+
+			igt_pipe_crc_start(pipe_crc);
+
+			count = igt_pipe_crc_get_crcs(pipe_crc, testcrcamount, &crcs);
+			igt_assert( count==testcrcamount );
+
+			igt_pipe_crc_stop(pipe_crc);
+			igt_pipe_crc_free(pipe_crc);
+
+			if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+				if (!igt_check_crc_equal(&crcs[testcrcamount-1],
+					&data->fullscreen_crc[testcrcamount-1])) {
+					crccompare[0] = igt_crc_to_string(&crcs[testcrcamount-1]);
+					crccompare[1] = igt_crc_to_string(&data->fullscreen_crc[testcrcamount-1]);
+					igt_warn("crc mismatch. target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
+					free(crccompare[0]);
+					free(crccompare[1]);
+					rVal++;
+				}
+			} else {
+				if (!igt_check_crc_equal(&crcs[testcrcamount-1],
+					&data->cursor_crc[testcrcamount-1])) {
+					crccompare[0] = igt_crc_to_string(&crcs[testcrcamount-1]);
+					crccompare[1] = igt_crc_to_string(&data->cursor_crc[testcrcamount-1]);
+					igt_warn("crc mismatch. target %.8s, result %.8s.\n", crccompare[0], crccompare[1]);
+					free(crccompare[0]);
+					free(crccompare[1]);
+					rVal++;
+				}
+			}
+			free(crcs);
+		}
+		remove_fb(data, output, plane);
+		return rVal;
+	}
+	return 1;
+}
+
+
+static void
+test_available_modes(data_t* data)
+{
+	igt_output_t *output;
+	igt_plane_t *plane;
+	int* u32ptr_formats;
+	int modeindex;
+	enum pipe pipe;
+	struct drm_mode_get_plane one_plane = {};
+	int invalids = 0;
+
+	char planetype[3][8] = {"OVERLAY\0", "PRIMARY\0", "CURSOR\0" };
+
+	for_each_pipe_with_valid_output(&data->display, pipe, output) {
+		igt_output_set_pipe(output, pipe);
+
+		/*
+		 * regenerate comparison crcs for each pipe just in case.
+		 */
+		generate_comparison_crc_list(data, output, pipe);
+
+		for_each_plane_on_pipe(&data->display, pipe, plane) {
+			memset((void*)&one_plane, 0,
+			       sizeof(struct drm_mode_get_plane));
+			one_plane.plane_id = plane->drm_plane->plane_id;
+			/*
+			 * first call to know how much space needed,
+			 * second call to get list of supported modes.
+			 */
+			igt_ioctl(data->gfx_fd, DRM_IOCTL_MODE_GETPLANE,
+				  &one_plane);
+			igt_assert(one_plane.count_format_types > 0);
+
+			u32ptr_formats = (int*)calloc(one_plane.count_format_types,
+						      sizeof(int));
+
+			one_plane.format_type_ptr = (__u64)u32ptr_formats;
+			igt_ioctl(data->gfx_fd, DRM_IOCTL_MODE_GETPLANE,
+				  &one_plane);
+
+			for (modeindex = 0;
+			     modeindex < one_plane.count_format_types;
+			     modeindex++) {
+				data->format_name[0] = u32ptr_formats[modeindex]&0xff;
+				data->format_name[1] = (u32ptr_formats[modeindex]>>8)&0xff;
+				data->format_name[2] = (u32ptr_formats[modeindex]>>16)&0xff;
+				data->format_name[3] = (u32ptr_formats[modeindex]>>24)&0xff;
+
+				igt_info("Testing connector %s using pipe %s" \
+					 " plane index %d type %s mode %s\n",
+					 igt_output_name(output),
+					 kmstest_pipe_name(pipe),
+					 plane->index,
+					 planetype[plane->type],
+					 (char*)&data->format_name);
+
+				invalids += test_one_mode(data, output,
+							  plane, pipe,
+							  u32ptr_formats[modeindex]);
+			}
+			free((void*)one_plane.format_type_ptr);
+		}
+		free(data->cursor_crc);
+		free(data->fullscreen_crc);
+	}
+	igt_assert(invalids == 0);
+}
+
+
+igt_main
+{
+	data_t data = {};
+
+	igt_skip_on_simulation();
+
+	igt_fixture {
+		data.gfx_fd = drm_open_driver_master(DRIVER_INTEL);
+		kmstest_set_vt_graphics_mode();
+
+		igt_display_init(&data.display, data.gfx_fd);
+
+		igt_require_pipe_crc(data.gfx_fd);
+	}
+
+	data.commit = data.display.is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY;
+
+	igt_subtest("available_mode_test_crc") {
+		test_available_modes(&data);
+	}
+
+	igt_fixture {
+		kmstest_restore_vt_mode();
+		igt_display_fini(&data.display);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 22e4ac9..6a5bd96 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -150,6 +150,7 @@ test_progs = [
 	'kms_atomic',
 	'kms_atomic_interruptible',
 	'kms_atomic_transition',
+	'kms_available_modes_crc',
 	'kms_busy',
 	'kms_ccs',
 	'kms_chv_cursor_fail',
-- 
2.7.4

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-05-22 10:48 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-09 14:24 [igt-dev] [PATCH i-g-t] tests/kms_available_modes_crc: Test all modes on all planes Juha-Pekka Heikkila
2018-02-09 17:49 ` [igt-dev] ✓ Fi.CI.BAT: success for " Patchwork
2018-02-09 20:02 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
2018-03-16 13:39 [igt-dev] [PATCH i-g-t] " Juha-Pekka Heikkila
2018-03-19 12:12 ` Mika Kahola
2018-03-20 11:37   ` Juha-Pekka Heikkila
2018-03-20 12:45     ` Mika Kahola
2018-03-20 16:13 Juha-Pekka Heikkila
2018-05-15  9:15 ` Mika Kahola
2018-05-18 12:20 Juha-Pekka Heikkila
2018-05-22 10:48 ` Mika Kahola

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.