[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 Intel-gfx
mailing list