193de485cSMaíra Canal // SPDX-License-Identifier: GPL-2.0
293de485cSMaíra Canal /*
393de485cSMaíra Canal * Test cases for the drm_rect functions
493de485cSMaíra Canal *
593de485cSMaíra Canal * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>
693de485cSMaíra Canal */
793de485cSMaíra Canal
893de485cSMaíra Canal #include <kunit/test.h>
993de485cSMaíra Canal
1093de485cSMaíra Canal #include <drm/drm_rect.h>
11b5d88ec0SArthur Grillo #include <drm/drm_mode.h>
1293de485cSMaíra Canal
1396c31619SArthur Grillo #include <linux/string_helpers.h>
141f01f224SArthur Grillo #include <linux/errno.h>
1596c31619SArthur Grillo
drm_rect_compare(struct kunit * test,const struct drm_rect * r,const struct drm_rect * expected)1696c31619SArthur Grillo static void drm_rect_compare(struct kunit *test, const struct drm_rect *r,
1796c31619SArthur Grillo const struct drm_rect *expected)
1896c31619SArthur Grillo {
1996c31619SArthur Grillo KUNIT_EXPECT_EQ(test, r->x1, expected->x1);
2096c31619SArthur Grillo KUNIT_EXPECT_EQ(test, r->y1, expected->y1);
2196c31619SArthur Grillo KUNIT_EXPECT_EQ(test, drm_rect_width(r), drm_rect_width(expected));
2296c31619SArthur Grillo KUNIT_EXPECT_EQ(test, drm_rect_height(r), drm_rect_height(expected));
2396c31619SArthur Grillo }
2496c31619SArthur Grillo
drm_test_rect_clip_scaled_div_by_zero(struct kunit * test)25961bcdf9SMaíra Canal static void drm_test_rect_clip_scaled_div_by_zero(struct kunit *test)
2693de485cSMaíra Canal {
2793de485cSMaíra Canal struct drm_rect src, dst, clip;
2893de485cSMaíra Canal bool visible;
2993de485cSMaíra Canal
3093de485cSMaíra Canal /*
3193de485cSMaíra Canal * Make sure we don't divide by zero when dst
3293de485cSMaíra Canal * width/height is zero and dst and clip do not intersect.
3393de485cSMaíra Canal */
3493de485cSMaíra Canal drm_rect_init(&src, 0, 0, 0, 0);
3593de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 0, 0);
3693de485cSMaíra Canal drm_rect_init(&clip, 1, 1, 1, 1);
3793de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
3893de485cSMaíra Canal
3993de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n");
4093de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");
4193de485cSMaíra Canal
4293de485cSMaíra Canal drm_rect_init(&src, 0, 0, 0, 0);
4393de485cSMaíra Canal drm_rect_init(&dst, 3, 3, 0, 0);
4493de485cSMaíra Canal drm_rect_init(&clip, 1, 1, 1, 1);
4593de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
4693de485cSMaíra Canal
4793de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n");
4893de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");
4993de485cSMaíra Canal }
5093de485cSMaíra Canal
drm_test_rect_clip_scaled_not_clipped(struct kunit * test)51961bcdf9SMaíra Canal static void drm_test_rect_clip_scaled_not_clipped(struct kunit *test)
5293de485cSMaíra Canal {
5393de485cSMaíra Canal struct drm_rect src, dst, clip;
5493de485cSMaíra Canal bool visible;
5593de485cSMaíra Canal
5693de485cSMaíra Canal /* 1:1 scaling */
5793de485cSMaíra Canal drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
5893de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 1, 1);
5993de485cSMaíra Canal drm_rect_init(&clip, 0, 0, 1, 1);
6093de485cSMaíra Canal
6193de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
6293de485cSMaíra Canal
6393de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
6493de485cSMaíra Canal src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
6593de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||
6693de485cSMaíra Canal dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");
6793de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
6893de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
6993de485cSMaíra Canal
7093de485cSMaíra Canal /* 2:1 scaling */
7193de485cSMaíra Canal drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
7293de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 1, 1);
7393de485cSMaíra Canal drm_rect_init(&clip, 0, 0, 1, 1);
7493de485cSMaíra Canal
7593de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
7693de485cSMaíra Canal
7793de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 ||
7893de485cSMaíra Canal src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n");
7993de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||
8093de485cSMaíra Canal dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");
8193de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
8293de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
8393de485cSMaíra Canal
8493de485cSMaíra Canal /* 1:2 scaling */
8593de485cSMaíra Canal drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
8693de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 2, 2);
8793de485cSMaíra Canal drm_rect_init(&clip, 0, 0, 2, 2);
8893de485cSMaíra Canal
8993de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
9093de485cSMaíra Canal
9193de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
9293de485cSMaíra Canal src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
9393de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 ||
9493de485cSMaíra Canal dst.y1 != 0 || dst.y2 != 2, "Destination badly clipped\n");
9593de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
9693de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
9793de485cSMaíra Canal }
9893de485cSMaíra Canal
drm_test_rect_clip_scaled_clipped(struct kunit * test)99961bcdf9SMaíra Canal static void drm_test_rect_clip_scaled_clipped(struct kunit *test)
10093de485cSMaíra Canal {
10193de485cSMaíra Canal struct drm_rect src, dst, clip;
10293de485cSMaíra Canal bool visible;
10393de485cSMaíra Canal
10493de485cSMaíra Canal /* 1:1 scaling top/left clip */
10593de485cSMaíra Canal drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
10693de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 2, 2);
10793de485cSMaíra Canal drm_rect_init(&clip, 0, 0, 1, 1);
10893de485cSMaíra Canal
10993de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
11093de485cSMaíra Canal
11193de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
11293de485cSMaíra Canal src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
11393de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||
11493de485cSMaíra Canal dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");
11593de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
11693de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
11793de485cSMaíra Canal
11893de485cSMaíra Canal /* 1:1 scaling bottom/right clip */
11993de485cSMaíra Canal drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
12093de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 2, 2);
12193de485cSMaíra Canal drm_rect_init(&clip, 1, 1, 1, 1);
12293de485cSMaíra Canal
12393de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
12493de485cSMaíra Canal
12593de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
12693de485cSMaíra Canal src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n");
12793de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 ||
12893de485cSMaíra Canal dst.y2 != 2, "Destination badly clipped\n");
12993de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
13093de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
13193de485cSMaíra Canal
13293de485cSMaíra Canal /* 2:1 scaling top/left clip */
13393de485cSMaíra Canal drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
13493de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 2, 2);
13593de485cSMaíra Canal drm_rect_init(&clip, 0, 0, 1, 1);
13693de485cSMaíra Canal
13793de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
13893de485cSMaíra Canal
13993de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 ||
14093de485cSMaíra Canal src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n");
14193de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || dst.y1 != 0 ||
14293de485cSMaíra Canal dst.y2 != 1, "Destination badly clipped\n");
14393de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
14493de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
14593de485cSMaíra Canal
14693de485cSMaíra Canal /* 2:1 scaling bottom/right clip */
14793de485cSMaíra Canal drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
14893de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 2, 2);
14993de485cSMaíra Canal drm_rect_init(&clip, 1, 1, 1, 1);
15093de485cSMaíra Canal
15193de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
15293de485cSMaíra Canal
15393de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 2 << 16 || src.x2 != 4 << 16 ||
15493de485cSMaíra Canal src.y1 != 2 << 16 || src.y2 != 4 << 16, "Source badly clipped\n");
15593de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 ||
15693de485cSMaíra Canal dst.y2 != 2, "Destination badly clipped\n");
15793de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
15893de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
15993de485cSMaíra Canal
16093de485cSMaíra Canal /* 1:2 scaling top/left clip */
16193de485cSMaíra Canal drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
16293de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 4, 4);
16393de485cSMaíra Canal drm_rect_init(&clip, 0, 0, 2, 2);
16493de485cSMaíra Canal
16593de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
16693de485cSMaíra Canal
16793de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
16893de485cSMaíra Canal src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
16993de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 || dst.y1 != 0 ||
17093de485cSMaíra Canal dst.y2 != 2, "Destination badly clipped\n");
17193de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
17293de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
17393de485cSMaíra Canal
17493de485cSMaíra Canal /* 1:2 scaling bottom/right clip */
17593de485cSMaíra Canal drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
17693de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 4, 4);
17793de485cSMaíra Canal drm_rect_init(&clip, 2, 2, 2, 2);
17893de485cSMaíra Canal
17993de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
18093de485cSMaíra Canal
18193de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
18293de485cSMaíra Canal src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n");
18393de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 2 || dst.x2 != 4 || dst.y1 != 2 ||
18493de485cSMaíra Canal dst.y2 != 4, "Destination badly clipped\n");
18593de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
18693de485cSMaíra Canal KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
18793de485cSMaíra Canal }
18893de485cSMaíra Canal
drm_test_rect_clip_scaled_signed_vs_unsigned(struct kunit * test)189961bcdf9SMaíra Canal static void drm_test_rect_clip_scaled_signed_vs_unsigned(struct kunit *test)
19093de485cSMaíra Canal {
19193de485cSMaíra Canal struct drm_rect src, dst, clip;
19293de485cSMaíra Canal bool visible;
19393de485cSMaíra Canal
19493de485cSMaíra Canal /*
19593de485cSMaíra Canal * 'clip.x2 - dst.x1 >= dst width' could result a negative
19693de485cSMaíra Canal * src rectangle width which is no longer expected by the
19793de485cSMaíra Canal * code as it's using unsigned types. This could lead to
19893de485cSMaíra Canal * the clipped source rectangle appering visible when it
19993de485cSMaíra Canal * should have been fully clipped. Make sure both rectangles
20093de485cSMaíra Canal * end up invisible.
20193de485cSMaíra Canal */
20293de485cSMaíra Canal drm_rect_init(&src, 0, 0, INT_MAX, INT_MAX);
20393de485cSMaíra Canal drm_rect_init(&dst, 0, 0, 2, 2);
20493de485cSMaíra Canal drm_rect_init(&clip, 3, 3, 1, 1);
20593de485cSMaíra Canal
20693de485cSMaíra Canal visible = drm_rect_clip_scaled(&src, &dst, &clip);
20793de485cSMaíra Canal
20893de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination should not be visible\n");
20993de485cSMaíra Canal KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");
21093de485cSMaíra Canal }
21193de485cSMaíra Canal
21296c31619SArthur Grillo struct drm_rect_intersect_case {
21396c31619SArthur Grillo const char *description;
21496c31619SArthur Grillo struct drm_rect r1, r2;
21596c31619SArthur Grillo bool should_be_visible;
21696c31619SArthur Grillo struct drm_rect expected_intersection;
21796c31619SArthur Grillo };
21896c31619SArthur Grillo
21996c31619SArthur Grillo static const struct drm_rect_intersect_case drm_rect_intersect_cases[] = {
22096c31619SArthur Grillo {
22196c31619SArthur Grillo .description = "top-left x bottom-right",
22296c31619SArthur Grillo .r1 = DRM_RECT_INIT(1, 1, 2, 2),
22396c31619SArthur Grillo .r2 = DRM_RECT_INIT(0, 0, 2, 2),
22496c31619SArthur Grillo .should_be_visible = true,
22596c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),
22696c31619SArthur Grillo },
22796c31619SArthur Grillo {
22896c31619SArthur Grillo .description = "top-right x bottom-left",
22996c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, 0, 2, 2),
23096c31619SArthur Grillo .r2 = DRM_RECT_INIT(1, -1, 2, 2),
23196c31619SArthur Grillo .should_be_visible = true,
23296c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
23396c31619SArthur Grillo },
23496c31619SArthur Grillo {
23596c31619SArthur Grillo .description = "bottom-left x top-right",
23696c31619SArthur Grillo .r1 = DRM_RECT_INIT(1, -1, 2, 2),
23796c31619SArthur Grillo .r2 = DRM_RECT_INIT(0, 0, 2, 2),
23896c31619SArthur Grillo .should_be_visible = true,
23996c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
24096c31619SArthur Grillo },
24196c31619SArthur Grillo {
24296c31619SArthur Grillo .description = "bottom-right x top-left",
24396c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, 0, 2, 2),
24496c31619SArthur Grillo .r2 = DRM_RECT_INIT(1, 1, 2, 2),
24596c31619SArthur Grillo .should_be_visible = true,
24696c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),
24796c31619SArthur Grillo },
24896c31619SArthur Grillo {
24996c31619SArthur Grillo .description = "right x left",
25096c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, 0, 2, 1),
25196c31619SArthur Grillo .r2 = DRM_RECT_INIT(1, 0, 3, 1),
25296c31619SArthur Grillo .should_be_visible = true,
25396c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
25496c31619SArthur Grillo },
25596c31619SArthur Grillo {
25696c31619SArthur Grillo .description = "left x right",
25796c31619SArthur Grillo .r1 = DRM_RECT_INIT(1, 0, 3, 1),
25896c31619SArthur Grillo .r2 = DRM_RECT_INIT(0, 0, 2, 1),
25996c31619SArthur Grillo .should_be_visible = true,
26096c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
26196c31619SArthur Grillo },
26296c31619SArthur Grillo {
26396c31619SArthur Grillo .description = "up x bottom",
26496c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, 0, 1, 2),
26596c31619SArthur Grillo .r2 = DRM_RECT_INIT(0, -1, 1, 3),
26696c31619SArthur Grillo .should_be_visible = true,
26796c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(0, 0, 1, 2),
26896c31619SArthur Grillo },
26996c31619SArthur Grillo {
27096c31619SArthur Grillo .description = "bottom x up",
27196c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, -1, 1, 3),
27296c31619SArthur Grillo .r2 = DRM_RECT_INIT(0, 0, 1, 2),
27396c31619SArthur Grillo .should_be_visible = true,
27496c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(0, 0, 1, 2),
27596c31619SArthur Grillo },
27696c31619SArthur Grillo {
27796c31619SArthur Grillo .description = "touching corner",
27896c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, 0, 1, 1),
27996c31619SArthur Grillo .r2 = DRM_RECT_INIT(1, 1, 2, 2),
28096c31619SArthur Grillo .should_be_visible = false,
28196c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(1, 1, 0, 0),
28296c31619SArthur Grillo },
28396c31619SArthur Grillo {
28496c31619SArthur Grillo .description = "touching side",
28596c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, 0, 1, 1),
28696c31619SArthur Grillo .r2 = DRM_RECT_INIT(1, 0, 1, 1),
28796c31619SArthur Grillo .should_be_visible = false,
28896c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(1, 0, 0, 1),
28996c31619SArthur Grillo },
29096c31619SArthur Grillo {
29196c31619SArthur Grillo .description = "equal rects",
29296c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, 0, 2, 2),
29396c31619SArthur Grillo .r2 = DRM_RECT_INIT(0, 0, 2, 2),
29496c31619SArthur Grillo .should_be_visible = true,
29596c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(0, 0, 2, 2),
29696c31619SArthur Grillo },
29796c31619SArthur Grillo {
29896c31619SArthur Grillo .description = "inside another",
29996c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, 0, 2, 2),
30096c31619SArthur Grillo .r2 = DRM_RECT_INIT(1, 1, 1, 1),
30196c31619SArthur Grillo .should_be_visible = true,
30296c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),
30396c31619SArthur Grillo },
30496c31619SArthur Grillo {
30596c31619SArthur Grillo .description = "far away",
30696c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, 0, 1, 1),
30796c31619SArthur Grillo .r2 = DRM_RECT_INIT(3, 6, 1, 1),
30896c31619SArthur Grillo .should_be_visible = false,
30996c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(3, 6, -2, -5),
31096c31619SArthur Grillo },
31196c31619SArthur Grillo {
31296c31619SArthur Grillo .description = "points intersecting",
31396c31619SArthur Grillo .r1 = DRM_RECT_INIT(5, 10, 0, 0),
31496c31619SArthur Grillo .r2 = DRM_RECT_INIT(5, 10, 0, 0),
31596c31619SArthur Grillo .should_be_visible = false,
31696c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(5, 10, 0, 0),
31796c31619SArthur Grillo },
31896c31619SArthur Grillo {
31996c31619SArthur Grillo .description = "points not intersecting",
32096c31619SArthur Grillo .r1 = DRM_RECT_INIT(0, 0, 0, 0),
32196c31619SArthur Grillo .r2 = DRM_RECT_INIT(5, 10, 0, 0),
32296c31619SArthur Grillo .should_be_visible = false,
32396c31619SArthur Grillo .expected_intersection = DRM_RECT_INIT(5, 10, -5, -10),
32496c31619SArthur Grillo },
32596c31619SArthur Grillo };
32696c31619SArthur Grillo
drm_rect_intersect_case_desc(const struct drm_rect_intersect_case * t,char * desc)32796c31619SArthur Grillo static void drm_rect_intersect_case_desc(const struct drm_rect_intersect_case *t, char *desc)
32896c31619SArthur Grillo {
32996c31619SArthur Grillo snprintf(desc, KUNIT_PARAM_DESC_SIZE,
33096c31619SArthur Grillo "%s: " DRM_RECT_FMT " x " DRM_RECT_FMT,
33196c31619SArthur Grillo t->description, DRM_RECT_ARG(&t->r1), DRM_RECT_ARG(&t->r2));
33296c31619SArthur Grillo }
33396c31619SArthur Grillo
33496c31619SArthur Grillo KUNIT_ARRAY_PARAM(drm_rect_intersect, drm_rect_intersect_cases, drm_rect_intersect_case_desc);
33596c31619SArthur Grillo
drm_test_rect_intersect(struct kunit * test)33696c31619SArthur Grillo static void drm_test_rect_intersect(struct kunit *test)
33796c31619SArthur Grillo {
33896c31619SArthur Grillo const struct drm_rect_intersect_case *params = test->param_value;
33996c31619SArthur Grillo struct drm_rect r1_aux = params->r1;
34096c31619SArthur Grillo bool visible;
34196c31619SArthur Grillo
34296c31619SArthur Grillo visible = drm_rect_intersect(&r1_aux, ¶ms->r2);
34396c31619SArthur Grillo
34496c31619SArthur Grillo KUNIT_EXPECT_EQ(test, visible, params->should_be_visible);
34596c31619SArthur Grillo drm_rect_compare(test, &r1_aux, ¶ms->expected_intersection);
34696c31619SArthur Grillo }
34796c31619SArthur Grillo
3481f01f224SArthur Grillo struct drm_rect_scale_case {
3491f01f224SArthur Grillo const char *name;
3501f01f224SArthur Grillo struct drm_rect src, dst;
3511f01f224SArthur Grillo int min_range, max_range;
3521f01f224SArthur Grillo int expected_scaling_factor;
3531f01f224SArthur Grillo };
3541f01f224SArthur Grillo
3551f01f224SArthur Grillo static const struct drm_rect_scale_case drm_rect_scale_cases[] = {
3561f01f224SArthur Grillo {
3571f01f224SArthur Grillo .name = "normal use",
3581f01f224SArthur Grillo .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16),
3591f01f224SArthur Grillo .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),
3601f01f224SArthur Grillo .min_range = 0, .max_range = INT_MAX,
3611f01f224SArthur Grillo .expected_scaling_factor = 2,
3621f01f224SArthur Grillo },
3631f01f224SArthur Grillo {
3641f01f224SArthur Grillo .name = "out of max range",
3651f01f224SArthur Grillo .src = DRM_RECT_INIT(0, 0, 10 << 16, 10 << 16),
3661f01f224SArthur Grillo .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),
3671f01f224SArthur Grillo .min_range = 3, .max_range = 5,
3681f01f224SArthur Grillo .expected_scaling_factor = -ERANGE,
3691f01f224SArthur Grillo },
3701f01f224SArthur Grillo {
3711f01f224SArthur Grillo .name = "out of min range",
3721f01f224SArthur Grillo .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16),
3731f01f224SArthur Grillo .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),
3741f01f224SArthur Grillo .min_range = 3, .max_range = 5,
3751f01f224SArthur Grillo .expected_scaling_factor = -ERANGE,
3761f01f224SArthur Grillo },
3771f01f224SArthur Grillo {
3781f01f224SArthur Grillo .name = "zero dst",
3791f01f224SArthur Grillo .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16),
3801f01f224SArthur Grillo .dst = DRM_RECT_INIT(0, 0, 0 << 16, 0 << 16),
3811f01f224SArthur Grillo .min_range = 0, .max_range = INT_MAX,
3821f01f224SArthur Grillo .expected_scaling_factor = 0,
3831f01f224SArthur Grillo },
3841f01f224SArthur Grillo {
3851f01f224SArthur Grillo .name = "negative src",
3861f01f224SArthur Grillo .src = DRM_RECT_INIT(0, 0, -(1 << 16), -(1 << 16)),
3871f01f224SArthur Grillo .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),
3881f01f224SArthur Grillo .min_range = 0, .max_range = INT_MAX,
3891f01f224SArthur Grillo .expected_scaling_factor = -EINVAL,
3901f01f224SArthur Grillo },
3911f01f224SArthur Grillo {
3921f01f224SArthur Grillo .name = "negative dst",
3931f01f224SArthur Grillo .src = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),
3941f01f224SArthur Grillo .dst = DRM_RECT_INIT(0, 0, -(1 << 16), -(1 << 16)),
3951f01f224SArthur Grillo .min_range = 0, .max_range = INT_MAX,
3961f01f224SArthur Grillo .expected_scaling_factor = -EINVAL,
3971f01f224SArthur Grillo },
3981f01f224SArthur Grillo };
3991f01f224SArthur Grillo
drm_rect_scale_case_desc(const struct drm_rect_scale_case * t,char * desc)4001f01f224SArthur Grillo static void drm_rect_scale_case_desc(const struct drm_rect_scale_case *t, char *desc)
4011f01f224SArthur Grillo {
4021f01f224SArthur Grillo strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
4031f01f224SArthur Grillo }
4041f01f224SArthur Grillo
4051f01f224SArthur Grillo KUNIT_ARRAY_PARAM(drm_rect_scale, drm_rect_scale_cases, drm_rect_scale_case_desc);
4061f01f224SArthur Grillo
drm_test_rect_calc_hscale(struct kunit * test)4071f01f224SArthur Grillo static void drm_test_rect_calc_hscale(struct kunit *test)
4081f01f224SArthur Grillo {
4091f01f224SArthur Grillo const struct drm_rect_scale_case *params = test->param_value;
4101f01f224SArthur Grillo int scaling_factor;
4111f01f224SArthur Grillo
4121f01f224SArthur Grillo scaling_factor = drm_rect_calc_hscale(¶ms->src, ¶ms->dst,
4131f01f224SArthur Grillo params->min_range, params->max_range);
4141f01f224SArthur Grillo
4151f01f224SArthur Grillo KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
4161f01f224SArthur Grillo }
4171f01f224SArthur Grillo
drm_test_rect_calc_vscale(struct kunit * test)418881e2a9cSArthur Grillo static void drm_test_rect_calc_vscale(struct kunit *test)
419881e2a9cSArthur Grillo {
420881e2a9cSArthur Grillo const struct drm_rect_scale_case *params = test->param_value;
421881e2a9cSArthur Grillo int scaling_factor;
422881e2a9cSArthur Grillo
423881e2a9cSArthur Grillo scaling_factor = drm_rect_calc_vscale(¶ms->src, ¶ms->dst,
424881e2a9cSArthur Grillo params->min_range, params->max_range);
425881e2a9cSArthur Grillo
426881e2a9cSArthur Grillo KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
427881e2a9cSArthur Grillo }
428881e2a9cSArthur Grillo
429b5d88ec0SArthur Grillo struct drm_rect_rotate_case {
430b5d88ec0SArthur Grillo const char *name;
431b5d88ec0SArthur Grillo unsigned int rotation;
432b5d88ec0SArthur Grillo struct drm_rect rect;
433b5d88ec0SArthur Grillo int width, height;
434b5d88ec0SArthur Grillo struct drm_rect expected;
435b5d88ec0SArthur Grillo };
436b5d88ec0SArthur Grillo
437b5d88ec0SArthur Grillo static const struct drm_rect_rotate_case drm_rect_rotate_cases[] = {
438b5d88ec0SArthur Grillo {
439b5d88ec0SArthur Grillo .name = "reflect-x",
440b5d88ec0SArthur Grillo .rotation = DRM_MODE_REFLECT_X,
441b5d88ec0SArthur Grillo .rect = DRM_RECT_INIT(0, 0, 5, 5),
442b5d88ec0SArthur Grillo .width = 5, .height = 10,
443b5d88ec0SArthur Grillo .expected = DRM_RECT_INIT(0, 0, 5, 5),
444b5d88ec0SArthur Grillo },
445b5d88ec0SArthur Grillo {
446b5d88ec0SArthur Grillo .name = "reflect-y",
447b5d88ec0SArthur Grillo .rotation = DRM_MODE_REFLECT_Y,
448b5d88ec0SArthur Grillo .rect = DRM_RECT_INIT(2, 0, 5, 5),
449b5d88ec0SArthur Grillo .width = 5, .height = 10,
450b5d88ec0SArthur Grillo .expected = DRM_RECT_INIT(2, 5, 5, 5),
451b5d88ec0SArthur Grillo },
452b5d88ec0SArthur Grillo {
453b5d88ec0SArthur Grillo .name = "rotate-0",
454b5d88ec0SArthur Grillo .rotation = DRM_MODE_ROTATE_0,
455b5d88ec0SArthur Grillo .rect = DRM_RECT_INIT(0, 2, 5, 5),
456b5d88ec0SArthur Grillo .width = 5, .height = 10,
457b5d88ec0SArthur Grillo .expected = DRM_RECT_INIT(0, 2, 5, 5),
458b5d88ec0SArthur Grillo },
459b5d88ec0SArthur Grillo {
460b5d88ec0SArthur Grillo .name = "rotate-90",
461b5d88ec0SArthur Grillo .rotation = DRM_MODE_ROTATE_90,
462b5d88ec0SArthur Grillo .rect = DRM_RECT_INIT(0, 0, 5, 10),
463b5d88ec0SArthur Grillo .width = 5, .height = 10,
464b5d88ec0SArthur Grillo .expected = DRM_RECT_INIT(0, 0, 10, 5),
465b5d88ec0SArthur Grillo },
466b5d88ec0SArthur Grillo {
467b5d88ec0SArthur Grillo .name = "rotate-180",
468b5d88ec0SArthur Grillo .rotation = DRM_MODE_ROTATE_180,
469b5d88ec0SArthur Grillo .rect = DRM_RECT_INIT(11, 3, 5, 10),
470b5d88ec0SArthur Grillo .width = 5, .height = 10,
471b5d88ec0SArthur Grillo .expected = DRM_RECT_INIT(-11, -3, 5, 10),
472b5d88ec0SArthur Grillo },
473b5d88ec0SArthur Grillo {
474b5d88ec0SArthur Grillo .name = "rotate-270",
475b5d88ec0SArthur Grillo .rotation = DRM_MODE_ROTATE_270,
476b5d88ec0SArthur Grillo .rect = DRM_RECT_INIT(6, 3, 5, 10),
477b5d88ec0SArthur Grillo .width = 5, .height = 10,
478b5d88ec0SArthur Grillo .expected = DRM_RECT_INIT(-3, 6, 10, 5),
479b5d88ec0SArthur Grillo },
480b5d88ec0SArthur Grillo };
481b5d88ec0SArthur Grillo
drm_rect_rotate_case_desc(const struct drm_rect_rotate_case * t,char * desc)482b5d88ec0SArthur Grillo static void drm_rect_rotate_case_desc(const struct drm_rect_rotate_case *t, char *desc)
483b5d88ec0SArthur Grillo {
484b5d88ec0SArthur Grillo strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
485b5d88ec0SArthur Grillo }
486b5d88ec0SArthur Grillo
487b5d88ec0SArthur Grillo KUNIT_ARRAY_PARAM(drm_rect_rotate, drm_rect_rotate_cases, drm_rect_rotate_case_desc);
488b5d88ec0SArthur Grillo
drm_test_rect_rotate(struct kunit * test)489b5d88ec0SArthur Grillo static void drm_test_rect_rotate(struct kunit *test)
490b5d88ec0SArthur Grillo {
491b5d88ec0SArthur Grillo const struct drm_rect_rotate_case *params = test->param_value;
492b5d88ec0SArthur Grillo struct drm_rect r = params->rect;
493b5d88ec0SArthur Grillo
494b5d88ec0SArthur Grillo drm_rect_rotate(&r, params->width, params->height, params->rotation);
495b5d88ec0SArthur Grillo
496b5d88ec0SArthur Grillo drm_rect_compare(test, &r, ¶ms->expected);
497b5d88ec0SArthur Grillo }
498b5d88ec0SArthur Grillo
drm_test_rect_rotate_inv(struct kunit * test)499*8356b979SArthur Grillo static void drm_test_rect_rotate_inv(struct kunit *test)
500*8356b979SArthur Grillo {
501*8356b979SArthur Grillo const struct drm_rect_rotate_case *params = test->param_value;
502*8356b979SArthur Grillo struct drm_rect r = params->expected;
503*8356b979SArthur Grillo
504*8356b979SArthur Grillo drm_rect_rotate_inv(&r, params->width, params->height, params->rotation);
505*8356b979SArthur Grillo
506*8356b979SArthur Grillo drm_rect_compare(test, &r, ¶ms->rect);
507*8356b979SArthur Grillo }
508*8356b979SArthur Grillo
50993de485cSMaíra Canal static struct kunit_case drm_rect_tests[] = {
510961bcdf9SMaíra Canal KUNIT_CASE(drm_test_rect_clip_scaled_div_by_zero),
511961bcdf9SMaíra Canal KUNIT_CASE(drm_test_rect_clip_scaled_not_clipped),
512961bcdf9SMaíra Canal KUNIT_CASE(drm_test_rect_clip_scaled_clipped),
513961bcdf9SMaíra Canal KUNIT_CASE(drm_test_rect_clip_scaled_signed_vs_unsigned),
51496c31619SArthur Grillo KUNIT_CASE_PARAM(drm_test_rect_intersect, drm_rect_intersect_gen_params),
5151f01f224SArthur Grillo KUNIT_CASE_PARAM(drm_test_rect_calc_hscale, drm_rect_scale_gen_params),
516881e2a9cSArthur Grillo KUNIT_CASE_PARAM(drm_test_rect_calc_vscale, drm_rect_scale_gen_params),
517b5d88ec0SArthur Grillo KUNIT_CASE_PARAM(drm_test_rect_rotate, drm_rect_rotate_gen_params),
518*8356b979SArthur Grillo KUNIT_CASE_PARAM(drm_test_rect_rotate_inv, drm_rect_rotate_gen_params),
51993de485cSMaíra Canal { }
52093de485cSMaíra Canal };
52193de485cSMaíra Canal
52293de485cSMaíra Canal static struct kunit_suite drm_rect_test_suite = {
52393de485cSMaíra Canal .name = "drm_rect",
52493de485cSMaíra Canal .test_cases = drm_rect_tests,
52593de485cSMaíra Canal };
52693de485cSMaíra Canal
52793de485cSMaíra Canal kunit_test_suite(drm_rect_test_suite);
52893de485cSMaíra Canal
52993de485cSMaíra Canal MODULE_LICENSE("GPL");
530