[Intel-gfx] [PATCH v2 4/4] drm/selftests: Add drm_rect selftests

Daniel Vetter daniel at ffwll.ch
Tue Nov 26 15:18:02 UTC 2019


On Fri, Nov 22, 2019 at 07:56:23PM +0200, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> 
> Add selftests for drm_rect. A few basic ones for clipped and unclipped
> cases, and a few special ones for specific bugs we had in the code.
> 
> I'm too lazy to think of more corner cases to check at this time.
> Maybe later.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> ---
>  drivers/gpu/drm/selftests/Makefile            |   3 +-
>  .../gpu/drm/selftests/drm_modeset_selftests.h |   4 +
>  .../drm/selftests/test-drm_modeset_common.h   |   7 +
>  drivers/gpu/drm/selftests/test-drm_rect.c     | 223 ++++++++++++++++++
>  include/drm/drm_rect.h                        |   2 +
>  5 files changed, 238 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/selftests/test-drm_rect.c
> 
> diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
> index d2137342b371..0856e4b12f70 100644
> --- a/drivers/gpu/drm/selftests/Makefile
> +++ b/drivers/gpu/drm/selftests/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
>                        test-drm_format.o test-drm_framebuffer.o \
> -		      test-drm_damage_helper.o test-drm_dp_mst_helper.o
> +		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
> +		      test-drm_rect.o
>  
>  obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
> diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
> index 1898de0b4a4d..782e285ca383 100644
> --- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
> @@ -6,6 +6,10 @@
>   *
>   * Tests are executed in order by igt/drm_selftests_helper
>   */
> +selftest(drm_rect_clip_scaled_div_by_zero, igt_drm_rect_clip_scaled_div_by_zero)
> +selftest(drm_rect_clip_scaled_not_clipped, igt_drm_rect_clip_scaled_not_clipped)
> +selftest(drm_rect_clip_scaled_clipped, igt_drm_rect_clip_scaled_clipped)
> +selftest(drm_rect_clip_scaled_signed_vs_unsigned, igt_drm_rect_clip_scaled_signed_vs_unsigned)
>  selftest(check_plane_state, igt_check_plane_state)
>  selftest(check_drm_format_block_width, igt_check_drm_format_block_width)
>  selftest(check_drm_format_block_height, igt_check_drm_format_block_height)
> diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
> index 0fcb8bbc6a1b..cfb51d8da2bc 100644
> --- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h
> +++ b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
> @@ -3,6 +3,9 @@
>  #ifndef __TEST_DRM_MODESET_COMMON_H__
>  #define __TEST_DRM_MODESET_COMMON_H__
>  
> +#include <linux/errno.h>
> +#include <linux/printk.h>
> +
>  #define FAIL(test, msg, ...) \
>  	do { \
>  		if (test) { \
> @@ -13,6 +16,10 @@
>  
>  #define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
>  
> +int igt_drm_rect_clip_scaled_div_by_zero(void *ignored);
> +int igt_drm_rect_clip_scaled_not_clipped(void *ignored);
> +int igt_drm_rect_clip_scaled_clipped(void *ignored);
> +int igt_drm_rect_clip_scaled_signed_vs_unsigned(void *ignored);
>  int igt_check_plane_state(void *ignored);
>  int igt_check_drm_format_block_width(void *ignored);
>  int igt_check_drm_format_block_height(void *ignored);
> diff --git a/drivers/gpu/drm/selftests/test-drm_rect.c b/drivers/gpu/drm/selftests/test-drm_rect.c
> new file mode 100644
> index 000000000000..3a5ff38321f4
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/test-drm_rect.c
> @@ -0,0 +1,223 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Test cases for the drm_rect functions
> + */
> +
> +#define pr_fmt(fmt) "drm_rect: " fmt
> +
> +#include <linux/limits.h>
> +
> +#include <drm/drm_rect.h>
> +
> +#include "test-drm_modeset_common.h"
> +
> +int igt_drm_rect_clip_scaled_div_by_zero(void *ignored)
> +{
> +	struct drm_rect src, dst, clip;
> +	bool visible;
> +
> +	/*
> +	 * Make sure we don't divide by zero when dst
> +	 * width/height is zero and dst and clip do not intersect.
> +	 */
> +	drm_rect_init(&src, 0, 0, 0, 0);
> +	drm_rect_init(&dst, 0, 0, 0, 0);
> +	drm_rect_init(&clip, 1, 1, 1, 1);
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +	FAIL(visible, "Destination not be visible\n");
			          ^ "should" missing

> +	FAIL(drm_rect_visible(&src), "Source should not be visible\n");
> +
> +	drm_rect_init(&src, 0, 0, 0, 0);
> +	drm_rect_init(&dst, 3, 3, 0, 0);
> +	drm_rect_init(&clip, 1, 1, 1, 1);
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +	FAIL(visible, "Destination not be visible\n");
			          ^ "should" missing

> +	return 0;
> +}
> +
> +int igt_drm_rect_clip_scaled_not_clipped(void *ignored)
> +{
> +	struct drm_rect src, dst, clip;
> +	bool visible;
> +
> +	/* 1:1 scaling */
> +	drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
> +	drm_rect_init(&dst, 0, 0, 1, 1);
> +	drm_rect_init(&clip, 0, 0, 1, 1);
> +
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +
> +	FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
> +	     src.y1 != 0 || src.y2 != 1 << 16,
> +	     "Source badly clipped\n");
> +	FAIL(dst.x1 != 0 || dst.x2 != 1 ||
> +	     dst.y1 != 0 || dst.y2 != 1,
> +	     "Destination badly clipped\n");
> +	FAIL(!visible, "Destination should be visible\n");
> +	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
> +
> +	/* 2:1 scaling */
> +	drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
> +	drm_rect_init(&dst, 0, 0, 1, 1);
> +	drm_rect_init(&clip, 0, 0, 1, 1);
> +
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +
> +	FAIL(src.x1 != 0 || src.x2 != 2 << 16 ||
> +	     src.y1 != 0 || src.y2 != 2 << 16,
> +	     "Source badly clipped\n");
> +	FAIL(dst.x1 != 0 || dst.x2 != 1 ||
> +	     dst.y1 != 0 || dst.y2 != 1,
> +	     "Destination badly clipped\n");
> +	FAIL(!visible, "Destination should be visible\n");
> +	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
> +
> +	/* 1:2 scaling */
> +	drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
> +	drm_rect_init(&dst, 0, 0, 2, 2);
> +	drm_rect_init(&clip, 0, 0, 2, 2);
> +
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +
> +	FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
> +	     src.y1 != 0 || src.y2 != 1 << 16,
> +	     "Source badly clipped\n");
> +	FAIL(dst.x1 != 0 || dst.x2 != 2 ||
> +	     dst.y1 != 0 || dst.y2 != 2,
> +	     "Destination badly clipped\n");
> +	FAIL(!visible, "Destination should be visible\n");
> +	FAIL(!drm_rect_visible(&src), "Source should be visible\n");

I wonder whether an INT_MAX dst, with src = 0,0,1,1 could be interesting
here too. Less practically relevant, it's more about making sure we don't
overflow anywhere in silly ways.

> +
> +	return 0;
> +}
> +
> +int igt_drm_rect_clip_scaled_clipped(void *ignored)
> +{
> +	struct drm_rect src, dst, clip;
> +	bool visible;
> +
> +	/* 1:1 scaling top/left clip */
> +	drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
> +	drm_rect_init(&dst, 0, 0, 2, 2);
> +	drm_rect_init(&clip, 0, 0, 1, 1);
> +
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +
> +	FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
> +	     src.y1 != 0 || src.y2 != 1 << 16,
> +	     "Source badly clipped\n");
> +	FAIL(dst.x1 != 0 || dst.x2 != 1 ||
> +	     dst.y1 != 0 || dst.y2 != 1,
> +	     "Destination badly clipped\n");
> +	FAIL(!visible, "Destination should be visible\n");
> +	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
> +
> +	/* 1:1 scaling bottom/right clip */
> +	drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
> +	drm_rect_init(&dst, 0, 0, 2, 2);
> +	drm_rect_init(&clip, 1, 1, 1, 1);
> +
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +
> +	FAIL(src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
> +	     src.y1 != 1 << 16 || src.y2 != 2 << 16,
> +	     "Source badly clipped\n");
> +	FAIL(dst.x1 != 1 || dst.x2 != 2 ||
> +	     dst.y1 != 1 || dst.y2 != 2,
> +	     "Destination badly clipped\n");
> +	FAIL(!visible, "Destination should be visible\n");
> +	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
> +
> +	/* 2:1 scaling top/left clip */
> +	drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
> +	drm_rect_init(&dst, 0, 0, 2, 2);
> +	drm_rect_init(&clip, 0, 0, 1, 1);
> +
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +
> +	FAIL(src.x1 != 0 || src.x2 != 2 << 16 ||
> +	     src.y1 != 0 || src.y2 != 2 << 16,
> +	     "Source badly clipped\n");
> +	FAIL(dst.x1 != 0 || dst.x2 != 1 ||
> +	     dst.y1 != 0 || dst.y2 != 1,
> +	     "Destination badly clipped\n");
> +	FAIL(!visible, "Destination should be visible\n");
> +	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
> +
> +	/* 2:1 scaling bottom/right clip */
> +	drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
> +	drm_rect_init(&dst, 0, 0, 2, 2);
> +	drm_rect_init(&clip, 1, 1, 1, 1);
> +
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +
> +	FAIL(src.x1 != 2 << 16 || src.x2 != 4 << 16 ||
> +	     src.y1 != 2 << 16 || src.y2 != 4 << 16,
> +	     "Source badly clipped\n");
> +	FAIL(dst.x1 != 1 || dst.x2 != 2 ||
> +	     dst.y1 != 1 || dst.y2 != 2,
> +	     "Destination badly clipped\n");
> +	FAIL(!visible, "Destination should be visible\n");
> +	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
> +
> +	/* 1:2 scaling top/left clip */
> +	drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
> +	drm_rect_init(&dst, 0, 0, 4, 4);
> +	drm_rect_init(&clip, 0, 0, 2, 2);
> +
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +
> +	FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
> +	     src.y1 != 0 || src.y2 != 1 << 16,
> +	     "Source badly clipped\n");
> +	FAIL(dst.x1 != 0 || dst.x2 != 2 ||
> +	     dst.y1 != 0 || dst.y2 != 2,
> +	     "Destination badly clipped\n");
> +	FAIL(!visible, "Destination should be visible\n");
> +	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
> +
> +	/* 1:2 scaling bottom/right clip */
> +	drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
> +	drm_rect_init(&dst, 0, 0, 4, 4);
> +	drm_rect_init(&clip, 2, 2, 2, 2);
> +
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +
> +	FAIL(src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
> +	     src.y1 != 1 << 16 || src.y2 != 2 << 16,
> +	     "Source badly clipped\n");
> +	FAIL(dst.x1 != 2 || dst.x2 != 4 ||
> +	     dst.y1 != 2 || dst.y2 != 4,
> +	     "Destination badly clipped\n");
> +	FAIL(!visible, "Destination should be visible\n");
> +	FAIL(!drm_rect_visible(&src), "Source should be visible\n");

Not sure whether dst/src origin != 0,0 would be interesting, but I think
this is a solid start.

Thanks a lot for typing these.

Reviewed-by: Daniel Vetter <daniel.vetter at ffwll.ch>

> +
> +	return 0;
> +}
> +
> +int igt_drm_rect_clip_scaled_signed_vs_unsigned(void *ignored)
> +{
> +	struct drm_rect src, dst, clip;
> +	bool visible;
> +
> +	/*
> +	 * 'clip.x2 - dst.x1 >= dst width' could result a negative
> +	 * src rectangle width which is no longer expected by the
> +	 * code as it's using unsigned types. This could lead to
> +	 * the clipped source rectangle appering visible when it
> +	 * should have been fully clipped. Make sure both rectangles
> +	 * end up invisible.
> +	 */
> +	drm_rect_init(&src, 0, 0, INT_MAX, INT_MAX);
> +	drm_rect_init(&dst, 0, 0, 2, 2);
> +	drm_rect_init(&clip, 3, 3, 1, 1);
> +
> +	visible = drm_rect_clip_scaled(&src, &dst, &clip);
> +
> +	FAIL(visible, "Destination should not be visible\n");
> +	FAIL(drm_rect_visible(&src), "Source should not be visible\n");
> +
> +	return 0;
> +}
> diff --git a/include/drm/drm_rect.h b/include/drm/drm_rect.h
> index cd0106135b6a..57a3be9e53e4 100644
> --- a/include/drm/drm_rect.h
> +++ b/include/drm/drm_rect.h
> @@ -24,6 +24,8 @@
>  #ifndef DRM_RECT_H
>  #define DRM_RECT_H
>  
> +#include <linux/types.h>
> +
>  /**
>   * DOC: rect utils
>   *
> -- 
> 2.23.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the dri-devel mailing list