162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Test cases for the drm_rect functions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <kunit/test.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <drm/drm_rect.h> 1162306a36Sopenharmony_ci#include <drm/drm_mode.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/string_helpers.h> 1462306a36Sopenharmony_ci#include <linux/errno.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic void drm_rect_compare(struct kunit *test, const struct drm_rect *r, 1762306a36Sopenharmony_ci const struct drm_rect *expected) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, r->x1, expected->x1); 2062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, r->y1, expected->y1); 2162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, drm_rect_width(r), drm_rect_width(expected)); 2262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, drm_rect_height(r), drm_rect_height(expected)); 2362306a36Sopenharmony_ci} 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic void drm_test_rect_clip_scaled_div_by_zero(struct kunit *test) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci struct drm_rect src, dst, clip; 2862306a36Sopenharmony_ci bool visible; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci /* 3162306a36Sopenharmony_ci * Make sure we don't divide by zero when dst 3262306a36Sopenharmony_ci * width/height is zero and dst and clip do not intersect. 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 0, 0); 3562306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 0, 0); 3662306a36Sopenharmony_ci drm_rect_init(&clip, 1, 1, 1, 1); 3762306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n"); 4062306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n"); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 0, 0); 4362306a36Sopenharmony_ci drm_rect_init(&dst, 3, 3, 0, 0); 4462306a36Sopenharmony_ci drm_rect_init(&clip, 1, 1, 1, 1); 4562306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n"); 4862306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n"); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic void drm_test_rect_clip_scaled_not_clipped(struct kunit *test) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci struct drm_rect src, dst, clip; 5462306a36Sopenharmony_ci bool visible; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci /* 1:1 scaling */ 5762306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16); 5862306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 1, 1); 5962306a36Sopenharmony_ci drm_rect_init(&clip, 0, 0, 1, 1); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 || 6462306a36Sopenharmony_ci src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n"); 6562306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || 6662306a36Sopenharmony_ci dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n"); 6762306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); 6862306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci /* 2:1 scaling */ 7162306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); 7262306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 1, 1); 7362306a36Sopenharmony_ci drm_rect_init(&clip, 0, 0, 1, 1); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 || 7862306a36Sopenharmony_ci src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n"); 7962306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || 8062306a36Sopenharmony_ci dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n"); 8162306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); 8262306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci /* 1:2 scaling */ 8562306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16); 8662306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 2, 2); 8762306a36Sopenharmony_ci drm_rect_init(&clip, 0, 0, 2, 2); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 || 9262306a36Sopenharmony_ci src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n"); 9362306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 || 9462306a36Sopenharmony_ci dst.y1 != 0 || dst.y2 != 2, "Destination badly clipped\n"); 9562306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); 9662306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic void drm_test_rect_clip_scaled_clipped(struct kunit *test) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci struct drm_rect src, dst, clip; 10262306a36Sopenharmony_ci bool visible; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* 1:1 scaling top/left clip */ 10562306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); 10662306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 2, 2); 10762306a36Sopenharmony_ci drm_rect_init(&clip, 0, 0, 1, 1); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 || 11262306a36Sopenharmony_ci src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n"); 11362306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || 11462306a36Sopenharmony_ci dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n"); 11562306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); 11662306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* 1:1 scaling bottom/right clip */ 11962306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); 12062306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 2, 2); 12162306a36Sopenharmony_ci drm_rect_init(&clip, 1, 1, 1, 1); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 || 12662306a36Sopenharmony_ci src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n"); 12762306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 || 12862306a36Sopenharmony_ci dst.y2 != 2, "Destination badly clipped\n"); 12962306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); 13062306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /* 2:1 scaling top/left clip */ 13362306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16); 13462306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 2, 2); 13562306a36Sopenharmony_ci drm_rect_init(&clip, 0, 0, 1, 1); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 || 14062306a36Sopenharmony_ci src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n"); 14162306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || dst.y1 != 0 || 14262306a36Sopenharmony_ci dst.y2 != 1, "Destination badly clipped\n"); 14362306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); 14462306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* 2:1 scaling bottom/right clip */ 14762306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16); 14862306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 2, 2); 14962306a36Sopenharmony_ci drm_rect_init(&clip, 1, 1, 1, 1); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 2 << 16 || src.x2 != 4 << 16 || 15462306a36Sopenharmony_ci src.y1 != 2 << 16 || src.y2 != 4 << 16, "Source badly clipped\n"); 15562306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 || 15662306a36Sopenharmony_ci dst.y2 != 2, "Destination badly clipped\n"); 15762306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); 15862306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci /* 1:2 scaling top/left clip */ 16162306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); 16262306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 4, 4); 16362306a36Sopenharmony_ci drm_rect_init(&clip, 0, 0, 2, 2); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 || 16862306a36Sopenharmony_ci src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n"); 16962306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 || dst.y1 != 0 || 17062306a36Sopenharmony_ci dst.y2 != 2, "Destination badly clipped\n"); 17162306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); 17262306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* 1:2 scaling bottom/right clip */ 17562306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16); 17662306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 4, 4); 17762306a36Sopenharmony_ci drm_rect_init(&clip, 2, 2, 2, 2); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 || 18262306a36Sopenharmony_ci src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n"); 18362306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 2 || dst.x2 != 4 || dst.y1 != 2 || 18462306a36Sopenharmony_ci dst.y2 != 4, "Destination badly clipped\n"); 18562306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n"); 18662306a36Sopenharmony_ci KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n"); 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic void drm_test_rect_clip_scaled_signed_vs_unsigned(struct kunit *test) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci struct drm_rect src, dst, clip; 19262306a36Sopenharmony_ci bool visible; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci /* 19562306a36Sopenharmony_ci * 'clip.x2 - dst.x1 >= dst width' could result a negative 19662306a36Sopenharmony_ci * src rectangle width which is no longer expected by the 19762306a36Sopenharmony_ci * code as it's using unsigned types. This could lead to 19862306a36Sopenharmony_ci * the clipped source rectangle appering visible when it 19962306a36Sopenharmony_ci * should have been fully clipped. Make sure both rectangles 20062306a36Sopenharmony_ci * end up invisible. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci drm_rect_init(&src, 0, 0, INT_MAX, INT_MAX); 20362306a36Sopenharmony_ci drm_rect_init(&dst, 0, 0, 2, 2); 20462306a36Sopenharmony_ci drm_rect_init(&clip, 3, 3, 1, 1); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci visible = drm_rect_clip_scaled(&src, &dst, &clip); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination should not be visible\n"); 20962306a36Sopenharmony_ci KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n"); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistruct drm_rect_intersect_case { 21362306a36Sopenharmony_ci const char *description; 21462306a36Sopenharmony_ci struct drm_rect r1, r2; 21562306a36Sopenharmony_ci bool should_be_visible; 21662306a36Sopenharmony_ci struct drm_rect expected_intersection; 21762306a36Sopenharmony_ci}; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic const struct drm_rect_intersect_case drm_rect_intersect_cases[] = { 22062306a36Sopenharmony_ci { 22162306a36Sopenharmony_ci .description = "top-left x bottom-right", 22262306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(1, 1, 2, 2), 22362306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(0, 0, 2, 2), 22462306a36Sopenharmony_ci .should_be_visible = true, 22562306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1), 22662306a36Sopenharmony_ci }, 22762306a36Sopenharmony_ci { 22862306a36Sopenharmony_ci .description = "top-right x bottom-left", 22962306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, 0, 2, 2), 23062306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(1, -1, 2, 2), 23162306a36Sopenharmony_ci .should_be_visible = true, 23262306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1), 23362306a36Sopenharmony_ci }, 23462306a36Sopenharmony_ci { 23562306a36Sopenharmony_ci .description = "bottom-left x top-right", 23662306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(1, -1, 2, 2), 23762306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(0, 0, 2, 2), 23862306a36Sopenharmony_ci .should_be_visible = true, 23962306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1), 24062306a36Sopenharmony_ci }, 24162306a36Sopenharmony_ci { 24262306a36Sopenharmony_ci .description = "bottom-right x top-left", 24362306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, 0, 2, 2), 24462306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(1, 1, 2, 2), 24562306a36Sopenharmony_ci .should_be_visible = true, 24662306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1), 24762306a36Sopenharmony_ci }, 24862306a36Sopenharmony_ci { 24962306a36Sopenharmony_ci .description = "right x left", 25062306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, 0, 2, 1), 25162306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(1, 0, 3, 1), 25262306a36Sopenharmony_ci .should_be_visible = true, 25362306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1), 25462306a36Sopenharmony_ci }, 25562306a36Sopenharmony_ci { 25662306a36Sopenharmony_ci .description = "left x right", 25762306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(1, 0, 3, 1), 25862306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(0, 0, 2, 1), 25962306a36Sopenharmony_ci .should_be_visible = true, 26062306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1), 26162306a36Sopenharmony_ci }, 26262306a36Sopenharmony_ci { 26362306a36Sopenharmony_ci .description = "up x bottom", 26462306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, 0, 1, 2), 26562306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(0, -1, 1, 3), 26662306a36Sopenharmony_ci .should_be_visible = true, 26762306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(0, 0, 1, 2), 26862306a36Sopenharmony_ci }, 26962306a36Sopenharmony_ci { 27062306a36Sopenharmony_ci .description = "bottom x up", 27162306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, -1, 1, 3), 27262306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(0, 0, 1, 2), 27362306a36Sopenharmony_ci .should_be_visible = true, 27462306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(0, 0, 1, 2), 27562306a36Sopenharmony_ci }, 27662306a36Sopenharmony_ci { 27762306a36Sopenharmony_ci .description = "touching corner", 27862306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, 0, 1, 1), 27962306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(1, 1, 2, 2), 28062306a36Sopenharmony_ci .should_be_visible = false, 28162306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(1, 1, 0, 0), 28262306a36Sopenharmony_ci }, 28362306a36Sopenharmony_ci { 28462306a36Sopenharmony_ci .description = "touching side", 28562306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, 0, 1, 1), 28662306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(1, 0, 1, 1), 28762306a36Sopenharmony_ci .should_be_visible = false, 28862306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(1, 0, 0, 1), 28962306a36Sopenharmony_ci }, 29062306a36Sopenharmony_ci { 29162306a36Sopenharmony_ci .description = "equal rects", 29262306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, 0, 2, 2), 29362306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(0, 0, 2, 2), 29462306a36Sopenharmony_ci .should_be_visible = true, 29562306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(0, 0, 2, 2), 29662306a36Sopenharmony_ci }, 29762306a36Sopenharmony_ci { 29862306a36Sopenharmony_ci .description = "inside another", 29962306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, 0, 2, 2), 30062306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(1, 1, 1, 1), 30162306a36Sopenharmony_ci .should_be_visible = true, 30262306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1), 30362306a36Sopenharmony_ci }, 30462306a36Sopenharmony_ci { 30562306a36Sopenharmony_ci .description = "far away", 30662306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, 0, 1, 1), 30762306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(3, 6, 1, 1), 30862306a36Sopenharmony_ci .should_be_visible = false, 30962306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(3, 6, -2, -5), 31062306a36Sopenharmony_ci }, 31162306a36Sopenharmony_ci { 31262306a36Sopenharmony_ci .description = "points intersecting", 31362306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(5, 10, 0, 0), 31462306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(5, 10, 0, 0), 31562306a36Sopenharmony_ci .should_be_visible = false, 31662306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(5, 10, 0, 0), 31762306a36Sopenharmony_ci }, 31862306a36Sopenharmony_ci { 31962306a36Sopenharmony_ci .description = "points not intersecting", 32062306a36Sopenharmony_ci .r1 = DRM_RECT_INIT(0, 0, 0, 0), 32162306a36Sopenharmony_ci .r2 = DRM_RECT_INIT(5, 10, 0, 0), 32262306a36Sopenharmony_ci .should_be_visible = false, 32362306a36Sopenharmony_ci .expected_intersection = DRM_RECT_INIT(5, 10, -5, -10), 32462306a36Sopenharmony_ci }, 32562306a36Sopenharmony_ci}; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic void drm_rect_intersect_case_desc(const struct drm_rect_intersect_case *t, char *desc) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci snprintf(desc, KUNIT_PARAM_DESC_SIZE, 33062306a36Sopenharmony_ci "%s: " DRM_RECT_FMT " x " DRM_RECT_FMT, 33162306a36Sopenharmony_ci t->description, DRM_RECT_ARG(&t->r1), DRM_RECT_ARG(&t->r2)); 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ciKUNIT_ARRAY_PARAM(drm_rect_intersect, drm_rect_intersect_cases, drm_rect_intersect_case_desc); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic void drm_test_rect_intersect(struct kunit *test) 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci const struct drm_rect_intersect_case *params = test->param_value; 33962306a36Sopenharmony_ci struct drm_rect r1_aux = params->r1; 34062306a36Sopenharmony_ci bool visible; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci visible = drm_rect_intersect(&r1_aux, ¶ms->r2); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, visible, params->should_be_visible); 34562306a36Sopenharmony_ci drm_rect_compare(test, &r1_aux, ¶ms->expected_intersection); 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistruct drm_rect_scale_case { 34962306a36Sopenharmony_ci const char *name; 35062306a36Sopenharmony_ci struct drm_rect src, dst; 35162306a36Sopenharmony_ci int min_range, max_range; 35262306a36Sopenharmony_ci int expected_scaling_factor; 35362306a36Sopenharmony_ci}; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic const struct drm_rect_scale_case drm_rect_scale_cases[] = { 35662306a36Sopenharmony_ci { 35762306a36Sopenharmony_ci .name = "normal use", 35862306a36Sopenharmony_ci .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16), 35962306a36Sopenharmony_ci .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16), 36062306a36Sopenharmony_ci .min_range = 0, .max_range = INT_MAX, 36162306a36Sopenharmony_ci .expected_scaling_factor = 2, 36262306a36Sopenharmony_ci }, 36362306a36Sopenharmony_ci { 36462306a36Sopenharmony_ci .name = "out of max range", 36562306a36Sopenharmony_ci .src = DRM_RECT_INIT(0, 0, 10 << 16, 10 << 16), 36662306a36Sopenharmony_ci .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16), 36762306a36Sopenharmony_ci .min_range = 3, .max_range = 5, 36862306a36Sopenharmony_ci .expected_scaling_factor = -ERANGE, 36962306a36Sopenharmony_ci }, 37062306a36Sopenharmony_ci { 37162306a36Sopenharmony_ci .name = "out of min range", 37262306a36Sopenharmony_ci .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16), 37362306a36Sopenharmony_ci .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16), 37462306a36Sopenharmony_ci .min_range = 3, .max_range = 5, 37562306a36Sopenharmony_ci .expected_scaling_factor = -ERANGE, 37662306a36Sopenharmony_ci }, 37762306a36Sopenharmony_ci { 37862306a36Sopenharmony_ci .name = "zero dst", 37962306a36Sopenharmony_ci .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16), 38062306a36Sopenharmony_ci .dst = DRM_RECT_INIT(0, 0, 0 << 16, 0 << 16), 38162306a36Sopenharmony_ci .min_range = 0, .max_range = INT_MAX, 38262306a36Sopenharmony_ci .expected_scaling_factor = 0, 38362306a36Sopenharmony_ci }, 38462306a36Sopenharmony_ci { 38562306a36Sopenharmony_ci .name = "negative src", 38662306a36Sopenharmony_ci .src = DRM_RECT_INIT(0, 0, -(1 << 16), -(1 << 16)), 38762306a36Sopenharmony_ci .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16), 38862306a36Sopenharmony_ci .min_range = 0, .max_range = INT_MAX, 38962306a36Sopenharmony_ci .expected_scaling_factor = -EINVAL, 39062306a36Sopenharmony_ci }, 39162306a36Sopenharmony_ci { 39262306a36Sopenharmony_ci .name = "negative dst", 39362306a36Sopenharmony_ci .src = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16), 39462306a36Sopenharmony_ci .dst = DRM_RECT_INIT(0, 0, -(1 << 16), -(1 << 16)), 39562306a36Sopenharmony_ci .min_range = 0, .max_range = INT_MAX, 39662306a36Sopenharmony_ci .expected_scaling_factor = -EINVAL, 39762306a36Sopenharmony_ci }, 39862306a36Sopenharmony_ci}; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic void drm_rect_scale_case_desc(const struct drm_rect_scale_case *t, char *desc) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ciKUNIT_ARRAY_PARAM(drm_rect_scale, drm_rect_scale_cases, drm_rect_scale_case_desc); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_cistatic void drm_test_rect_calc_hscale(struct kunit *test) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci const struct drm_rect_scale_case *params = test->param_value; 41062306a36Sopenharmony_ci int scaling_factor; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci scaling_factor = drm_rect_calc_hscale(¶ms->src, ¶ms->dst, 41362306a36Sopenharmony_ci params->min_range, params->max_range); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor); 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic void drm_test_rect_calc_vscale(struct kunit *test) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci const struct drm_rect_scale_case *params = test->param_value; 42162306a36Sopenharmony_ci int scaling_factor; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci scaling_factor = drm_rect_calc_vscale(¶ms->src, ¶ms->dst, 42462306a36Sopenharmony_ci params->min_range, params->max_range); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor); 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_cistruct drm_rect_rotate_case { 43062306a36Sopenharmony_ci const char *name; 43162306a36Sopenharmony_ci unsigned int rotation; 43262306a36Sopenharmony_ci struct drm_rect rect; 43362306a36Sopenharmony_ci int width, height; 43462306a36Sopenharmony_ci struct drm_rect expected; 43562306a36Sopenharmony_ci}; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic const struct drm_rect_rotate_case drm_rect_rotate_cases[] = { 43862306a36Sopenharmony_ci { 43962306a36Sopenharmony_ci .name = "reflect-x", 44062306a36Sopenharmony_ci .rotation = DRM_MODE_REFLECT_X, 44162306a36Sopenharmony_ci .rect = DRM_RECT_INIT(0, 0, 5, 5), 44262306a36Sopenharmony_ci .width = 5, .height = 10, 44362306a36Sopenharmony_ci .expected = DRM_RECT_INIT(0, 0, 5, 5), 44462306a36Sopenharmony_ci }, 44562306a36Sopenharmony_ci { 44662306a36Sopenharmony_ci .name = "reflect-y", 44762306a36Sopenharmony_ci .rotation = DRM_MODE_REFLECT_Y, 44862306a36Sopenharmony_ci .rect = DRM_RECT_INIT(2, 0, 5, 5), 44962306a36Sopenharmony_ci .width = 5, .height = 10, 45062306a36Sopenharmony_ci .expected = DRM_RECT_INIT(2, 5, 5, 5), 45162306a36Sopenharmony_ci }, 45262306a36Sopenharmony_ci { 45362306a36Sopenharmony_ci .name = "rotate-0", 45462306a36Sopenharmony_ci .rotation = DRM_MODE_ROTATE_0, 45562306a36Sopenharmony_ci .rect = DRM_RECT_INIT(0, 2, 5, 5), 45662306a36Sopenharmony_ci .width = 5, .height = 10, 45762306a36Sopenharmony_ci .expected = DRM_RECT_INIT(0, 2, 5, 5), 45862306a36Sopenharmony_ci }, 45962306a36Sopenharmony_ci { 46062306a36Sopenharmony_ci .name = "rotate-90", 46162306a36Sopenharmony_ci .rotation = DRM_MODE_ROTATE_90, 46262306a36Sopenharmony_ci .rect = DRM_RECT_INIT(0, 0, 5, 10), 46362306a36Sopenharmony_ci .width = 5, .height = 10, 46462306a36Sopenharmony_ci .expected = DRM_RECT_INIT(0, 0, 10, 5), 46562306a36Sopenharmony_ci }, 46662306a36Sopenharmony_ci { 46762306a36Sopenharmony_ci .name = "rotate-180", 46862306a36Sopenharmony_ci .rotation = DRM_MODE_ROTATE_180, 46962306a36Sopenharmony_ci .rect = DRM_RECT_INIT(11, 3, 5, 10), 47062306a36Sopenharmony_ci .width = 5, .height = 10, 47162306a36Sopenharmony_ci .expected = DRM_RECT_INIT(-11, -3, 5, 10), 47262306a36Sopenharmony_ci }, 47362306a36Sopenharmony_ci { 47462306a36Sopenharmony_ci .name = "rotate-270", 47562306a36Sopenharmony_ci .rotation = DRM_MODE_ROTATE_270, 47662306a36Sopenharmony_ci .rect = DRM_RECT_INIT(6, 3, 5, 10), 47762306a36Sopenharmony_ci .width = 5, .height = 10, 47862306a36Sopenharmony_ci .expected = DRM_RECT_INIT(-3, 6, 10, 5), 47962306a36Sopenharmony_ci }, 48062306a36Sopenharmony_ci}; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistatic void drm_rect_rotate_case_desc(const struct drm_rect_rotate_case *t, char *desc) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ciKUNIT_ARRAY_PARAM(drm_rect_rotate, drm_rect_rotate_cases, drm_rect_rotate_case_desc); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cistatic void drm_test_rect_rotate(struct kunit *test) 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci const struct drm_rect_rotate_case *params = test->param_value; 49262306a36Sopenharmony_ci struct drm_rect r = params->rect; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci drm_rect_rotate(&r, params->width, params->height, params->rotation); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci drm_rect_compare(test, &r, ¶ms->expected); 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_cistatic void drm_test_rect_rotate_inv(struct kunit *test) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci const struct drm_rect_rotate_case *params = test->param_value; 50262306a36Sopenharmony_ci struct drm_rect r = params->expected; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci drm_rect_rotate_inv(&r, params->width, params->height, params->rotation); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci drm_rect_compare(test, &r, ¶ms->rect); 50762306a36Sopenharmony_ci} 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_cistatic struct kunit_case drm_rect_tests[] = { 51062306a36Sopenharmony_ci KUNIT_CASE(drm_test_rect_clip_scaled_div_by_zero), 51162306a36Sopenharmony_ci KUNIT_CASE(drm_test_rect_clip_scaled_not_clipped), 51262306a36Sopenharmony_ci KUNIT_CASE(drm_test_rect_clip_scaled_clipped), 51362306a36Sopenharmony_ci KUNIT_CASE(drm_test_rect_clip_scaled_signed_vs_unsigned), 51462306a36Sopenharmony_ci KUNIT_CASE_PARAM(drm_test_rect_intersect, drm_rect_intersect_gen_params), 51562306a36Sopenharmony_ci KUNIT_CASE_PARAM(drm_test_rect_calc_hscale, drm_rect_scale_gen_params), 51662306a36Sopenharmony_ci KUNIT_CASE_PARAM(drm_test_rect_calc_vscale, drm_rect_scale_gen_params), 51762306a36Sopenharmony_ci KUNIT_CASE_PARAM(drm_test_rect_rotate, drm_rect_rotate_gen_params), 51862306a36Sopenharmony_ci KUNIT_CASE_PARAM(drm_test_rect_rotate_inv, drm_rect_rotate_gen_params), 51962306a36Sopenharmony_ci { } 52062306a36Sopenharmony_ci}; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_cistatic struct kunit_suite drm_rect_test_suite = { 52362306a36Sopenharmony_ci .name = "drm_rect", 52462306a36Sopenharmony_ci .test_cases = drm_rect_tests, 52562306a36Sopenharmony_ci}; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cikunit_test_suite(drm_rect_test_suite); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 530