1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include <kunit/test.h> 4 5 #include <drm/drm_device.h> 6 #include <drm/drm_file.h> 7 #include <drm/drm_format_helper.h> 8 #include <drm/drm_fourcc.h> 9 #include <drm/drm_framebuffer.h> 10 #include <drm/drm_gem_framebuffer_helper.h> 11 #include <drm/drm_mode.h> 12 #include <drm/drm_print.h> 13 #include <drm/drm_rect.h> 14 15 #include "../drm_crtc_internal.h" 16 17 #define TEST_BUF_SIZE 50 18 19 struct xrgb8888_to_rgb332_case { 20 const char *name; 21 unsigned int pitch; 22 unsigned int dst_pitch; 23 struct drm_rect clip; 24 const u32 xrgb8888[TEST_BUF_SIZE]; 25 const u8 expected[4 * TEST_BUF_SIZE]; 26 }; 27 28 static struct xrgb8888_to_rgb332_case xrgb8888_to_rgb332_cases[] = { 29 { 30 .name = "single_pixel_source_buffer", 31 .pitch = 1 * 4, 32 .dst_pitch = 0, 33 .clip = DRM_RECT_INIT(0, 0, 1, 1), 34 .xrgb8888 = { 0x01FF0000 }, 35 .expected = { 0xE0 }, 36 }, 37 { 38 .name = "single_pixel_clip_rectangle", 39 .pitch = 2 * 4, 40 .dst_pitch = 0, 41 .clip = DRM_RECT_INIT(1, 1, 1, 1), 42 .xrgb8888 = { 43 0x00000000, 0x00000000, 44 0x00000000, 0x10FF0000, 45 }, 46 .expected = { 0xE0 }, 47 }, 48 { 49 /* Well known colors: White, black, red, green, blue, magenta, 50 * yellow and cyan. Different values for the X in XRGB8888 to 51 * make sure it is ignored. Partial clip area. 52 */ 53 .name = "well_known_colors", 54 .pitch = 4 * 4, 55 .dst_pitch = 0, 56 .clip = DRM_RECT_INIT(1, 1, 2, 4), 57 .xrgb8888 = { 58 0x00000000, 0x00000000, 0x00000000, 0x00000000, 59 0x00000000, 0x11FFFFFF, 0x22000000, 0x00000000, 60 0x00000000, 0x33FF0000, 0x4400FF00, 0x00000000, 61 0x00000000, 0x550000FF, 0x66FF00FF, 0x00000000, 62 0x00000000, 0x77FFFF00, 0x8800FFFF, 0x00000000, 63 }, 64 .expected = { 65 0xFF, 0x00, 66 0xE0, 0x1C, 67 0x03, 0xE3, 68 0xFC, 0x1F, 69 }, 70 }, 71 { 72 /* Randomly picked colors. Full buffer within the clip area. */ 73 .name = "destination_pitch", 74 .pitch = 3 * 4, 75 .dst_pitch = 5, 76 .clip = DRM_RECT_INIT(0, 0, 3, 3), 77 .xrgb8888 = { 78 0xA10E449C, 0xB1114D05, 0xC1A80303, 79 0xD16C7073, 0xA20E449C, 0xB2114D05, 80 0xC2A80303, 0xD26C7073, 0xA30E449C, 81 }, 82 .expected = { 83 0x0A, 0x08, 0xA0, 0x00, 0x00, 84 0x6D, 0x0A, 0x08, 0x00, 0x00, 85 0xA0, 0x6D, 0x0A, 0x00, 0x00, 86 }, 87 }, 88 }; 89 90 /* 91 * conversion_buf_size - Return the destination buffer size required to convert 92 * between formats. 93 * @dst_format: destination buffer pixel format (DRM_FORMAT_*) 94 * @dst_pitch: Number of bytes between two consecutive scanlines within dst 95 * @clip: Clip rectangle area to convert 96 * 97 * Returns: 98 * The size of the destination buffer or negative value on error. 99 */ 100 static size_t conversion_buf_size(u32 dst_format, unsigned int dst_pitch, 101 const struct drm_rect *clip) 102 { 103 const struct drm_format_info *dst_fi = drm_format_info(dst_format); 104 105 if (!dst_fi) 106 return -EINVAL; 107 108 if (!dst_pitch) 109 dst_pitch = drm_rect_width(clip) * dst_fi->cpp[0]; 110 111 return dst_pitch * drm_rect_height(clip); 112 } 113 114 static void xrgb8888_to_rgb332_case_desc(struct xrgb8888_to_rgb332_case *t, 115 char *desc) 116 { 117 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); 118 } 119 120 KUNIT_ARRAY_PARAM(xrgb8888_to_rgb332, xrgb8888_to_rgb332_cases, 121 xrgb8888_to_rgb332_case_desc); 122 123 static void xrgb8888_to_rgb332_test(struct kunit *test) 124 { 125 const struct xrgb8888_to_rgb332_case *params = test->param_value; 126 size_t dst_size; 127 __u8 *dst = NULL; 128 129 struct drm_framebuffer fb = { 130 .format = drm_format_info(DRM_FORMAT_XRGB8888), 131 .pitches = { params->pitch, 0, 0 }, 132 }; 133 134 dst_size = conversion_buf_size(DRM_FORMAT_RGB332, params->dst_pitch, 135 ¶ms->clip); 136 KUNIT_ASSERT_GT(test, dst_size, 0); 137 138 dst = kunit_kzalloc(test, dst_size, GFP_KERNEL); 139 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dst); 140 141 drm_fb_xrgb8888_to_rgb332(dst, params->dst_pitch, params->xrgb8888, 142 &fb, ¶ms->clip); 143 KUNIT_EXPECT_EQ(test, memcmp(dst, params->expected, dst_size), 0); 144 } 145 146 static struct kunit_case drm_format_helper_test_cases[] = { 147 KUNIT_CASE_PARAM(xrgb8888_to_rgb332_test, 148 xrgb8888_to_rgb332_gen_params), 149 {} 150 }; 151 152 static struct kunit_suite drm_format_helper_test_suite = { 153 .name = "drm_format_helper_test", 154 .test_cases = drm_format_helper_test_cases, 155 }; 156 157 kunit_test_suite(drm_format_helper_test_suite); 158 159 MODULE_DESCRIPTION("KUnit tests for the drm_format_helper APIs"); 160 MODULE_LICENSE("GPL"); 161 MODULE_AUTHOR("José Expósito <jose.exposito89@gmail.com>"); 162