[igt-dev] [PATCH i-g-t 2/2] tests/kms_chamelium: Fix *-cmp-random and *-crc-random tests, v3.

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Fri Apr 5 12:52:16 UTC 2019


The random tests allowed potentially invalid things:
- 1x1 fb's to be created. Force a minimum of 32 on YUV so a scaled
  planar format plane will be at least 16x16. This will fix
  scaled/planar format support in i915 and avoid a div by zero when
  calculating a value modulo h/2 and w/2.
- Downscaling to any amount, restrict it to 2x to make the test pass.
- Some hw may not allow scaling, in those cases we should fallback
  to no scaling at all.
- Attempting to configure a minimum of 4 planes, instead of a maximum.
  This fails with a null pointer deref if the hw doesn't have 4
  configurable overlay planes.

Changes since v1:
- Enforce a minimum displayed size of 16x16 for intel only,
  otherwise it's 1x1.
- Fix comments.
Changes since v2:
- Fix comments harder.
- Pick a random format and its modifier from the plane itself,
  instead of using igt_format_array_fill(). This will cause the test
  to use all valid combinations of modifiers and formats.
- Set minimum dimension to 8 for !yuv, and 16 for YUV.
- Generate format / modifier before

Cc: Paul Kocialkowski <paul.kocialkowski at bootlin.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 tests/kms_chamelium.c | 318 +++++++++++++++++++++++++-----------------
 1 file changed, 193 insertions(+), 125 deletions(-)

diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
index 2dc1049d2dda..a55bd86c77f5 100644
--- a/tests/kms_chamelium.c
+++ b/tests/kms_chamelium.c
@@ -710,17 +710,48 @@ test_display_frame_dump(data_t *data, struct chamelium_port *port)
 	drmModeFreeConnector(connector);
 }
 
-static void select_tiled_modifier(igt_plane_t *plane, uint32_t width,
+
+static void randomize_plane_stride(data_t *data,
+				   uint32_t width, uint32_t height,
+				   uint32_t format, uint64_t modifier,
+				   size_t *stride)
+{
+	size_t stride_min;
+	uint32_t max_tile_w = 4, tile_w, tile_h;
+	int i;
+	struct igt_fb dummy;
+
+	stride_min = width * igt_format_plane_bpp(format, 0) / 8;
+
+	/* Randomize the stride to less than twice the minimum. */
+	*stride = (rand() % stride_min) + stride_min;
+
+	/*
+	 * Create a dummy FB to determine bpp for each plane, and calculate
+	 * the maximum tile width from that.
+	 */
+	igt_create_fb(data->drm_fd, 64, 64, format, modifier, &dummy);
+	for (i = 0; i < dummy.num_planes; i++) {
+		igt_get_fb_tile_size(data->drm_fd, modifier, dummy.plane_bpp[i], &tile_w, &tile_h);
+
+		if (tile_w > max_tile_w)
+			max_tile_w = tile_w;
+	}
+	igt_remove_fb(data->drm_fd, &dummy);
+
+	/*
+	 * Pixman requires the stride to be aligned to 32-bits, which is
+	 * reflected in the initial value of max_tile_w and the hw
+	 * may require a multiple of tile width, choose biggest of the 2.
+	 */
+	*stride = ALIGN(*stride, max_tile_w);
+}
+
+static void update_tiled_modifier(igt_plane_t *plane, uint32_t width,
 				  uint32_t height, uint32_t format,
 				  uint64_t *modifier)
 {
-	if (igt_plane_has_format_mod(plane, format,
-				     DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED)) {
-		igt_debug("Selecting VC4 T-tiling\n");
-
-		*modifier = DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED;
-	} else if (igt_plane_has_format_mod(plane, format,
-					    DRM_FORMAT_MOD_BROADCOM_SAND256)) {
+	if (*modifier == DRM_FORMAT_MOD_BROADCOM_SAND256) {
 		/* Randomize the column height to less than twice the minimum. */
 		size_t column_height = (rand() % height) + height;
 
@@ -728,90 +759,84 @@ static void select_tiled_modifier(igt_plane_t *plane, uint32_t width,
 			  column_height);
 
 		*modifier = DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(column_height);
-	} else {
-		*modifier = DRM_FORMAT_MOD_LINEAR;
 	}
 }
 
-static void randomize_plane_format_stride(igt_plane_t *plane,
-					  uint32_t width, uint32_t height,
-					  uint32_t *format, uint64_t *modifier,
-					  size_t *stride, bool allow_yuv)
+static void randomize_plane_setup(data_t *data, igt_plane_t *plane,
+				  drmModeModeInfo *mode,
+				  uint32_t *width, uint32_t *height,
+				  uint32_t *format, uint64_t *modifier,
+				  bool allow_yuv)
 {
-	size_t stride_min;
-	uint32_t *formats_array;
-	unsigned int formats_count;
+	int min_dim;
+	uint32_t idx[plane->format_mod_count];
 	unsigned int count = 0;
 	unsigned int i;
-	bool tiled;
-	int index;
-
-	igt_format_array_fill(&formats_array, &formats_count, allow_yuv);
 
 	/* First pass to count the supported formats. */
-	for (i = 0; i < formats_count; i++)
-		if (igt_plane_has_format_mod(plane, formats_array[i],
-					     DRM_FORMAT_MOD_LINEAR))
-			count++;
+	for (i = 0; i < plane->format_mod_count; i++)
+		if (igt_fb_supported_format(plane->formats[i]) &&
+		    (allow_yuv || !igt_format_is_yuv(plane->formats[i])))
+			idx[count++] = i;
 
 	igt_assert(count > 0);
 
-	index = rand() % count;
-
-	/* Second pass to get the index-th supported format. */
-	for (i = 0; i < formats_count; i++) {
-		if (!igt_plane_has_format_mod(plane, formats_array[i],
-					      DRM_FORMAT_MOD_LINEAR))
-			continue;
-
-		if (!index--) {
-			*format = formats_array[i];
-			break;
-		}
-	}
-
-	free(formats_array);
+	i = idx[rand() % count];
+	*format = plane->formats[i];
+	*modifier = plane->modifiers[i];
 
-	igt_assert(index < 0);
+	update_tiled_modifier(plane, *width, *height, *format, modifier);
 
-	stride_min = width * igt_format_plane_bpp(*format, 0) / 8;
+	/*
+	 * Randomize width and height in the mode dimensions range.
+	 *
+	 * Restrict to a min of 2 * min_dim, this way src_w/h are always at
+	 * least min_dim, because src_w = width - (rand % w / 2).
+	 *
+	 * Use a minimum dimension of 16 for YUV, because planar YUV
+	 * subsamples the UV plane.
+	 */
+	min_dim = igt_format_is_yuv(*format) ? 16 : 8;
 
-	/* Randomize the stride to less than twice the minimum. */
-	*stride = (rand() % stride_min) + stride_min;
+	*width = max((rand() % mode->hdisplay) + 1, 2 * min_dim);
+	*height = max((rand() % mode->vdisplay) + 1, 2 * min_dim);
+}
 
-	/* Pixman requires the stride to be aligned to 32-byte words. */
-	*stride = ALIGN(*stride, sizeof(uint32_t));
+static void configure_plane(igt_plane_t *plane, uint32_t src_w, uint32_t src_h,
+			    uint32_t src_x, uint32_t src_y, uint32_t crtc_w,
+			    uint32_t crtc_h, int32_t crtc_x, int32_t crtc_y,
+			    struct igt_fb *fb)
+{
+	igt_plane_set_fb(plane, fb);
 
-	/* Randomize the use of a tiled mode with a 1/4 probability. */
-	tiled = ((rand() % 4) == 0);
+	igt_plane_set_position(plane, crtc_x, crtc_y);
+	igt_plane_set_size(plane, crtc_w, crtc_h);
 
-	if (tiled)
-		select_tiled_modifier(plane, width, height, *format, modifier);
-	else
-		*modifier = DRM_FORMAT_MOD_LINEAR;
+	igt_fb_set_position(fb, plane, src_x, src_y);
+	igt_fb_set_size(fb, plane, src_w, src_h);
 }
 
-static void randomize_plane_dimensions(drmModeModeInfo *mode,
-				       uint32_t *width, uint32_t *height,
-				       uint32_t *src_w, uint32_t *src_h,
-				       uint32_t *src_x, uint32_t *src_y,
-				       uint32_t *crtc_w, uint32_t *crtc_h,
-				       int32_t *crtc_x, int32_t *crtc_y,
-				       bool allow_scaling)
+static void randomize_plane_coordinates(data_t *data, igt_plane_t *plane,
+					drmModeModeInfo *mode,
+					struct igt_fb *fb,
+					uint32_t *src_w, uint32_t *src_h,
+					uint32_t *src_x, uint32_t *src_y,
+					uint32_t *crtc_w, uint32_t *crtc_h,
+					int32_t *crtc_x, int32_t *crtc_y,
+					bool allow_scaling)
 {
+	bool is_yuv = igt_format_is_yuv(fb->drm_format);
+	uint32_t width = fb->width, height = fb->height;
 	double ratio;
-
-	/* Randomize width and height in the mode dimensions range. */
-	*width = (rand() % mode->hdisplay) + 1;
-	*height = (rand() % mode->vdisplay) + 1;
+	int ret;
 
 	/* Randomize source offset in the first half of the original size. */
-	*src_x = rand() % (*width / 2);
-	*src_y = rand() % (*height / 2);
+	*src_x = rand() % (width / 2);
+	*src_y = rand() % (height / 2);
 
 	/* The source size only includes the active source area. */
-	*src_w = *width - *src_x;
-	*src_h = *height - *src_y;
+	*src_w = width - *src_x;
+	*src_h = height - *src_y;
 
 	if (allow_scaling) {
 		*crtc_w = (rand() % mode->hdisplay) + 1;
@@ -821,17 +846,22 @@ static void randomize_plane_dimensions(drmModeModeInfo *mode,
 		 * Don't bother with scaling if dimensions are quite close in
 		 * order to get non-scaling cases more frequently. Also limit
 		 * scaling to 3x to avoid agressive filtering that makes
-		 * comparison less reliable.
+		 * comparison less reliable, and don't go above 2x downsampling
+		 * to avoid possible hw limitations.
 		 */
 
 		ratio = ((double) *crtc_w / *src_w);
-		if (ratio > 0.8 && ratio < 1.2)
+		if (ratio < 0.5)
+			*src_w = *crtc_w * 2;
+		else if (ratio > 0.8 && ratio < 1.2)
 			*crtc_w = *src_w;
 		else if (ratio > 3.0)
 			*crtc_w = *src_w * 3;
 
 		ratio = ((double) *crtc_h / *src_h);
-		if (ratio > 0.8 && ratio < 1.2)
+		if (ratio < 0.5)
+			*src_h = *crtc_h * 2;
+		else if (ratio > 0.8 && ratio < 1.2)
 			*crtc_h = *src_h;
 		else if (ratio > 3.0)
 			*crtc_h = *src_h * 3;
@@ -846,8 +876,15 @@ static void randomize_plane_dimensions(drmModeModeInfo *mode,
 		 * scaled clipping may result in decimal dimensions, that most
 		 * drivers don't support.
 		 */
-		*crtc_x = rand() % (mode->hdisplay - *crtc_w);
-		*crtc_y = rand() % (mode->vdisplay - *crtc_h);
+		if (*crtc_w < mode->hdisplay)
+			*crtc_x = rand() % (mode->hdisplay - *crtc_w);
+		else
+			*crtc_x = 0;
+
+		if (*crtc_h < mode->vdisplay)
+			*crtc_y = rand() % (mode->vdisplay - *crtc_h);
+		else
+			*crtc_y = 0;
 	} else {
 		/*
 		 * Randomize the on-crtc position and allow the plane to go
@@ -856,6 +893,62 @@ static void randomize_plane_dimensions(drmModeModeInfo *mode,
 		*crtc_x = (rand() % mode->hdisplay) - *crtc_w / 2;
 		*crtc_y = (rand() % mode->vdisplay) - *crtc_h / 2;
 	}
+
+	configure_plane(plane, *src_w, *src_h, *src_x, *src_y,
+			*crtc_w, *crtc_h, *crtc_x, *crtc_y, fb);
+	ret = igt_display_try_commit_atomic(&data->display,
+					    DRM_MODE_ATOMIC_TEST_ONLY |
+					    DRM_MODE_ATOMIC_ALLOW_MODESET,
+					    NULL);
+	if (!ret)
+		return;
+
+	/* Coordinates are logged in the dumped debug log, so only report w/h on failure here. */
+	igt_assert_f(ret != -ENOSPC,"Failure in testcase, invalid coordinates on a %ux%u fb\n", width, height);
+
+	/* Make YUV coordinates a multiple of 2 and retry the math. */
+	if (is_yuv) {
+		*src_x &= ~1;
+		*src_y &= ~1;
+		*src_w &= ~1;
+		*src_h &= ~1;
+		/* To handle 1:1 scaling, clear crtc_w/h too. */
+		*crtc_w &= ~1;
+		*crtc_h &= ~1;
+
+		if (*crtc_x < 0 && (*crtc_x & 1))
+			(*crtc_x)++;
+		else
+			*crtc_x &= ~1;
+
+		/* If negative, round up to 0 instead of down */
+		if (*crtc_y < 0 && (*crtc_y & 1))
+			(*crtc_y)++;
+		else
+			*crtc_y &= ~1;
+
+		configure_plane(plane, *src_w, *src_h, *src_x, *src_y, *crtc_w,
+				*crtc_h, *crtc_x, *crtc_y, fb);
+		ret = igt_display_try_commit_atomic(&data->display,
+						DRM_MODE_ATOMIC_TEST_ONLY |
+						DRM_MODE_ATOMIC_ALLOW_MODESET,
+						NULL);
+		if (!ret)
+			return;
+	}
+
+	igt_assert(!ret || allow_scaling);
+	igt_info("Scaling ratio %g / %g failed, trying without scaling.\n",
+		  ((double) *crtc_w / *src_w), ((double) *crtc_h / *src_h));
+
+	*crtc_w = *src_w;
+	*crtc_h = *src_h;
+
+	configure_plane(plane, *src_w, *src_h, *src_x, *src_y, *crtc_w,
+			*crtc_h, *crtc_x, *crtc_y, fb);
+	igt_display_commit_atomic(&data->display,
+				  DRM_MODE_ATOMIC_TEST_ONLY |
+				  DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
 }
 
 static void blit_plane_cairo(data_t *data, cairo_surface_t *result,
@@ -914,20 +1007,6 @@ static void blit_plane_cairo(data_t *data, cairo_surface_t *result,
 	cairo_destroy(cr);
 }
 
-static void configure_plane(igt_plane_t *plane, uint32_t src_w, uint32_t src_h,
-			    uint32_t src_x, uint32_t src_y, uint32_t crtc_w,
-			    uint32_t crtc_h, int32_t crtc_x, int32_t crtc_y,
-			    struct igt_fb *fb)
-{
-	igt_plane_set_fb(plane, fb);
-
-	igt_plane_set_position(plane, crtc_x, crtc_y);
-	igt_plane_set_size(plane, crtc_w, crtc_h);
-
-	igt_fb_set_position(fb, plane, src_x, src_y);
-	igt_fb_set_size(fb, plane, src_w, src_h);
-}
-
 static void prepare_randomized_plane(data_t *data,
 				     drmModeModeInfo *mode,
 				     igt_plane_t *plane,
@@ -948,51 +1027,49 @@ static void prepare_randomized_plane(data_t *data,
 	bool tiled;
 	int fb_id;
 
-	randomize_plane_dimensions(mode, &overlay_fb_w, &overlay_fb_h,
-				   &overlay_src_w, &overlay_src_h,
-				   &overlay_src_x, &overlay_src_y,
-				   &overlay_crtc_w, &overlay_crtc_h,
-				   &overlay_crtc_x, &overlay_crtc_y,
-				   allow_scaling);
+	randomize_plane_setup(data, plane, mode, &overlay_fb_w, &overlay_fb_h,
+			      &format, &modifier, allow_yuv);
 
-	igt_debug("Plane %d: framebuffer size %dx%d\n", index,
-		  overlay_fb_w, overlay_fb_h);
-	igt_debug("Plane %d: on-crtc size %dx%d\n", index,
-		  overlay_crtc_w, overlay_crtc_h);
-	igt_debug("Plane %d: on-crtc position %dx%d\n", index,
-		  overlay_crtc_x, overlay_crtc_y);
-	igt_debug("Plane %d: in-framebuffer size %dx%d\n", index,
-		  overlay_src_w, overlay_src_h);
-	igt_debug("Plane %d: in-framebuffer position %dx%d\n", index,
-		  overlay_src_x, overlay_src_y);
+	tiled = (modifier != LOCAL_DRM_FORMAT_MOD_NONE);
+	igt_debug("Plane %d: framebuffer size %dx%d %s format (%s)\n",
+		  index, overlay_fb_w, overlay_fb_h,
+		  igt_format_str(format), tiled ? "tiled" : "linear");
 
 	/* Get a pattern framebuffer for the overlay plane. */
 	fb_id = chamelium_get_pattern_fb(data, overlay_fb_w, overlay_fb_h,
 					 DRM_FORMAT_XRGB8888, 32, &pattern_fb);
 	igt_assert(fb_id > 0);
 
-	randomize_plane_format_stride(plane, overlay_fb_w, overlay_fb_h,
-				      &format, &modifier, &stride, allow_yuv);
-
-	tiled = (modifier != LOCAL_DRM_FORMAT_MOD_NONE);
+	randomize_plane_stride(data, overlay_fb_w, overlay_fb_h,
+			       format, modifier, &stride);
 
-	igt_debug("Plane %d: %s format (%s) with stride %ld\n", index,
-		  igt_format_str(format), tiled ? "tiled" : "linear", stride);
+	igt_debug("Plane %d: stride %ld\n", index, stride);
 
 	fb_id = igt_fb_convert_with_stride(overlay_fb, &pattern_fb, format,
 					   modifier, stride);
 	igt_assert(fb_id > 0);
 
+	randomize_plane_coordinates(data, plane, mode, overlay_fb,
+				    &overlay_src_w, &overlay_src_h,
+				    &overlay_src_x, &overlay_src_y,
+				    &overlay_crtc_w, &overlay_crtc_h,
+				    &overlay_crtc_x, &overlay_crtc_y,
+				    allow_scaling);
+
+	igt_debug("Plane %d: in-framebuffer size %dx%d\n", index,
+		  overlay_src_w, overlay_src_h);
+	igt_debug("Plane %d: in-framebuffer position %dx%d\n", index,
+		  overlay_src_x, overlay_src_y);
+	igt_debug("Plane %d: on-crtc size %dx%d\n", index,
+		  overlay_crtc_w, overlay_crtc_h);
+	igt_debug("Plane %d: on-crtc position %dx%d\n", index,
+		  overlay_crtc_x, overlay_crtc_y);
+
 	blit_plane_cairo(data, result_surface, overlay_src_w, overlay_src_h,
 			 overlay_src_x, overlay_src_y,
 			 overlay_crtc_w, overlay_crtc_h,
 			 overlay_crtc_x, overlay_crtc_y, &pattern_fb);
 
-	configure_plane(plane, overlay_src_w, overlay_src_h,
-			overlay_src_x, overlay_src_y,
-			overlay_crtc_w, overlay_crtc_h,
-			overlay_crtc_x, overlay_crtc_y, overlay_fb);
-
 	/* Remove the original pattern framebuffer. */
 	igt_remove_fb(data->drm_fd, &pattern_fb);
 }
@@ -1068,7 +1145,7 @@ static void test_display_planes_random(data_t *data,
 		igt_output_count_plane_type(output, DRM_PLANE_TYPE_OVERLAY);
 
 	/* Limit the number of planes to a reasonable scene. */
-	overlay_planes_max = max(overlay_planes_max, 4);
+	overlay_planes_max = min(overlay_planes_max, 4);
 
 	overlay_planes_count = (rand() % overlay_planes_max) + 1;
 	igt_debug("Using %d overlay planes\n", overlay_planes_count);
@@ -1121,17 +1198,8 @@ static void test_display_planes_random(data_t *data,
 		chamelium_destroy_frame_dump(dump);
 	}
 
-	for (i = 0; i < overlay_planes_count; i++) {
-		struct igt_fb *overlay_fb = &overlay_fbs[i];
-		igt_plane_t *plane;
-
-		plane = igt_output_get_plane_type_index(output,
-							DRM_PLANE_TYPE_OVERLAY,
-							i);
-		igt_assert(plane);
-
-		igt_remove_fb(data->drm_fd, overlay_fb);
-	}
+	for (i = 0; i < overlay_planes_count; i++)
+		igt_remove_fb(data->drm_fd, &overlay_fbs[i]);
 
 	free(overlay_fbs);
 
-- 
2.20.1



More information about the igt-dev mailing list