Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 19struct convert_to_gray8_result {
 20	unsigned int dst_pitch;
 21	const u8 expected[TEST_BUF_SIZE];
 22};
 23
 24struct convert_to_rgb332_result {
 25	unsigned int dst_pitch;
 26	const u8 expected[TEST_BUF_SIZE];
 27};
 28
 29struct convert_to_rgb565_result {
 30	unsigned int dst_pitch;
 31	const u16 expected[TEST_BUF_SIZE];
 32	const u16 expected_swab[TEST_BUF_SIZE];
 33};
 34
 35struct convert_to_rgb888_result {
 36	unsigned int dst_pitch;
 37	const u8 expected[TEST_BUF_SIZE];
 38};
 39
 40struct convert_to_xrgb2101010_result {
 41	unsigned int dst_pitch;
 42	const u32 expected[TEST_BUF_SIZE];
 43};
 44
 45struct convert_xrgb8888_case {
 46	const char *name;
 47	unsigned int pitch;
 48	struct drm_rect clip;
 49	const u32 xrgb8888[TEST_BUF_SIZE];
 50	struct convert_to_gray8_result gray8_result;
 51	struct convert_to_rgb332_result rgb332_result;
 52	struct convert_to_rgb565_result rgb565_result;
 53	struct convert_to_rgb888_result rgb888_result;
 54	struct convert_to_xrgb2101010_result xrgb2101010_result;
 55};
 56
 57static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
 58	{
 59		.name = "single_pixel_source_buffer",
 60		.pitch = 1 * 4,
 61		.clip = DRM_RECT_INIT(0, 0, 1, 1),
 62		.xrgb8888 = { 0x01FF0000 },
 63		.gray8_result = {
 64			.dst_pitch = 0,
 65			.expected = { 0x4C },
 66		},
 67		.rgb332_result = {
 68			.dst_pitch = 0,
 69			.expected = { 0xE0 },
 70		},
 71		.rgb565_result = {
 72			.dst_pitch = 0,
 73			.expected = { 0xF800 },
 74			.expected_swab = { 0x00F8 },
 75		},
 76		.rgb888_result = {
 77			.dst_pitch = 0,
 78			.expected = { 0x00, 0x00, 0xFF },
 79		},
 80		.xrgb2101010_result = {
 81			.dst_pitch = 0,
 82			.expected = { 0x3FF00000 },
 83		},
 84	},
 85	{
 86		.name = "single_pixel_clip_rectangle",
 87		.pitch = 2 * 4,
 88		.clip = DRM_RECT_INIT(1, 1, 1, 1),
 89		.xrgb8888 = {
 90			0x00000000, 0x00000000,
 91			0x00000000, 0x10FF0000,
 92		},
 93		.gray8_result = {
 94			.dst_pitch = 0,
 95			.expected = { 0x4C },
 96		},
 97		.rgb332_result = {
 98			.dst_pitch = 0,
 99			.expected = { 0xE0 },
100		},
101		.rgb565_result = {
102			.dst_pitch = 0,
103			.expected = { 0xF800 },
104			.expected_swab = { 0x00F8 },
105		},
106		.rgb888_result = {
107			.dst_pitch = 0,
108			.expected = { 0x00, 0x00, 0xFF },
109		},
110		.xrgb2101010_result = {
111			.dst_pitch = 0,
112			.expected = { 0x3FF00000 },
113		},
114	},
115	{
116		/* Well known colors: White, black, red, green, blue, magenta,
117		 * yellow and cyan. Different values for the X in XRGB8888 to
118		 * make sure it is ignored. Partial clip area.
119		 */
120		.name = "well_known_colors",
121		.pitch = 4 * 4,
122		.clip = DRM_RECT_INIT(1, 1, 2, 4),
123		.xrgb8888 = {
124			0x00000000, 0x00000000, 0x00000000, 0x00000000,
125			0x00000000, 0x11FFFFFF, 0x22000000, 0x00000000,
126			0x00000000, 0x33FF0000, 0x4400FF00, 0x00000000,
127			0x00000000, 0x550000FF, 0x66FF00FF, 0x00000000,
128			0x00000000, 0x77FFFF00, 0x8800FFFF, 0x00000000,
129		},
130		.gray8_result = {
131			.dst_pitch = 0,
132			.expected = {
133				0xFF, 0x00,
134				0x4C, 0x99,
135				0x19, 0x66,
136				0xE5, 0xB2,
137			},
138		},
139		.rgb332_result = {
140			.dst_pitch = 0,
141			.expected = {
142				0xFF, 0x00,
143				0xE0, 0x1C,
144				0x03, 0xE3,
145				0xFC, 0x1F,
146			},
147		},
148		.rgb565_result = {
149			.dst_pitch = 0,
150			.expected = {
151				0xFFFF, 0x0000,
152				0xF800, 0x07E0,
153				0x001F, 0xF81F,
154				0xFFE0, 0x07FF,
155			},
156			.expected_swab = {
157				0xFFFF, 0x0000,
158				0x00F8, 0xE007,
159				0x1F00, 0x1FF8,
160				0xE0FF, 0xFF07,
161			},
162		},
163		.rgb888_result = {
164			.dst_pitch = 0,
165			.expected = {
166				0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
167				0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,
168				0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF,
169				0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
170			},
171		},
172		.xrgb2101010_result = {
173			.dst_pitch = 0,
174			.expected = {
175				0x3FFFFFFF, 0x00000000,
176				0x3FF00000, 0x000FFC00,
177				0x000003FF, 0x3FF003FF,
178				0x3FFFFC00, 0x000FFFFF,
179			},
180		},
181	},
182	{
183		/* Randomly picked colors. Full buffer within the clip area. */
184		.name = "destination_pitch",
185		.pitch = 3 * 4,
186		.clip = DRM_RECT_INIT(0, 0, 3, 3),
187		.xrgb8888 = {
188			0xA10E449C, 0xB1114D05, 0xC1A80303,
189			0xD16C7073, 0xA20E449C, 0xB2114D05,
190			0xC2A80303, 0xD26C7073, 0xA30E449C,
191		},
192		.gray8_result = {
193			.dst_pitch = 5,
194			.expected = {
195				0x3C, 0x33, 0x34, 0x00, 0x00,
196				0x6F, 0x3C, 0x33, 0x00, 0x00,
197				0x34, 0x6F, 0x3C, 0x00, 0x00,
198			},
199		},
200		.rgb332_result = {
201			.dst_pitch = 5,
202			.expected = {
203				0x0A, 0x08, 0xA0, 0x00, 0x00,
204				0x6D, 0x0A, 0x08, 0x00, 0x00,
205				0xA0, 0x6D, 0x0A, 0x00, 0x00,
206			},
207		},
208		.rgb565_result = {
209			.dst_pitch = 10,
210			.expected = {
211				0x0A33, 0x1260, 0xA800, 0x0000, 0x0000,
212				0x6B8E, 0x0A33, 0x1260, 0x0000, 0x0000,
213				0xA800, 0x6B8E, 0x0A33, 0x0000, 0x0000,
214			},
215			.expected_swab = {
216				0x330A, 0x6012, 0x00A8, 0x0000, 0x0000,
217				0x8E6B, 0x330A, 0x6012, 0x0000, 0x0000,
218				0x00A8, 0x8E6B, 0x330A, 0x0000, 0x0000,
219			},
220		},
221		.rgb888_result = {
222			.dst_pitch = 15,
223			.expected = {
224				0x9C, 0x44, 0x0E, 0x05, 0x4D, 0x11, 0x03, 0x03, 0xA8,
225				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226				0x73, 0x70, 0x6C, 0x9C, 0x44, 0x0E, 0x05, 0x4D, 0x11,
227				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228				0x03, 0x03, 0xA8, 0x73, 0x70, 0x6C, 0x9C, 0x44, 0x0E,
229				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230			},
231		},
232		.xrgb2101010_result = {
233			.dst_pitch = 20,
234			.expected = {
235				0x03844672, 0x0444D414, 0x2A20300C, 0x00000000, 0x00000000,
236				0x1B1705CD, 0x03844672, 0x0444D414, 0x00000000, 0x00000000,
237				0x2A20300C, 0x1B1705CD, 0x03844672, 0x00000000, 0x00000000,
238			},
239		},
240	},
241};
242
243/*
244 * conversion_buf_size - Return the destination buffer size required to convert
245 * between formats.
246 * @dst_format: destination buffer pixel format (DRM_FORMAT_*)
247 * @dst_pitch: Number of bytes between two consecutive scanlines within dst
248 * @clip: Clip rectangle area to convert
249 *
250 * Returns:
251 * The size of the destination buffer or negative value on error.
252 */
253static size_t conversion_buf_size(u32 dst_format, unsigned int dst_pitch,
254				  const struct drm_rect *clip)
255{
256	const struct drm_format_info *dst_fi = drm_format_info(dst_format);
257
258	if (!dst_fi)
259		return -EINVAL;
260
261	if (!dst_pitch)
262		dst_pitch = drm_rect_width(clip) * dst_fi->cpp[0];
263
264	return dst_pitch * drm_rect_height(clip);
265}
266
267static u32 *le32buf_to_cpu(struct kunit *test, const u32 *buf, size_t buf_size)
268{
269	u32 *dst = NULL;
270	int n;
271
272	dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
273	if (!dst)
274		return NULL;
275
276	for (n = 0; n < buf_size; n++)
277		dst[n] = le32_to_cpu((__force __le32)buf[n]);
278
279	return dst;
280}
281
282static void convert_xrgb8888_case_desc(struct convert_xrgb8888_case *t,
283				       char *desc)
284{
285	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
286}
287
288KUNIT_ARRAY_PARAM(convert_xrgb8888, convert_xrgb8888_cases,
289		  convert_xrgb8888_case_desc);
290
291static void drm_test_fb_xrgb8888_to_gray8(struct kunit *test)
292{
293	const struct convert_xrgb8888_case *params = test->param_value;
294	const struct convert_to_gray8_result *result = &params->gray8_result;
295	size_t dst_size;
296	__u8 *buf = NULL;
297	__u32 *xrgb8888 = NULL;
298	struct iosys_map dst, src;
299
300	struct drm_framebuffer fb = {
301		.format = drm_format_info(DRM_FORMAT_XRGB8888),
302		.pitches = { params->pitch, 0, 0 },
303	};
304
305	dst_size = conversion_buf_size(DRM_FORMAT_R8, result->dst_pitch,
306				       &params->clip);
307	KUNIT_ASSERT_GT(test, dst_size, 0);
308
309	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
310	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
311	iosys_map_set_vaddr(&dst, buf);
312
313	xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
314	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
315	iosys_map_set_vaddr(&src, xrgb8888);
316
317	drm_fb_xrgb8888_to_gray8(&dst, &result->dst_pitch, &src, &fb, &params->clip);
318	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
319}
320
321static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test)
322{
323	const struct convert_xrgb8888_case *params = test->param_value;
324	const struct convert_to_rgb332_result *result = &params->rgb332_result;
325	size_t dst_size;
326	__u8 *buf = NULL;
327	__u32 *xrgb8888 = NULL;
328	struct iosys_map dst, src;
329
330	struct drm_framebuffer fb = {
331		.format = drm_format_info(DRM_FORMAT_XRGB8888),
332		.pitches = { params->pitch, 0, 0 },
333	};
334
335	dst_size = conversion_buf_size(DRM_FORMAT_RGB332, result->dst_pitch,
336				       &params->clip);
337	KUNIT_ASSERT_GT(test, dst_size, 0);
338
339	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
340	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
341	iosys_map_set_vaddr(&dst, buf);
342
343	xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
344	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
345	iosys_map_set_vaddr(&src, xrgb8888);
346
347	drm_fb_xrgb8888_to_rgb332(&dst, &result->dst_pitch, &src, &fb, &params->clip);
348	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
349}
350
351static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
352{
353	const struct convert_xrgb8888_case *params = test->param_value;
354	const struct convert_to_rgb565_result *result = &params->rgb565_result;
355	size_t dst_size;
356	__u16 *buf = NULL;
357	__u32 *xrgb8888 = NULL;
358	struct iosys_map dst, src;
359
360	struct drm_framebuffer fb = {
361		.format = drm_format_info(DRM_FORMAT_XRGB8888),
362		.pitches = { params->pitch, 0, 0 },
363	};
364
365	dst_size = conversion_buf_size(DRM_FORMAT_RGB565, result->dst_pitch,
366				       &params->clip);
367	KUNIT_ASSERT_GT(test, dst_size, 0);
368
369	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
370	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
371	iosys_map_set_vaddr(&dst, buf);
372
373	xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
374	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
375	iosys_map_set_vaddr(&src, xrgb8888);
376
377	drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, false);
378	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
379
380	drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, true);
381	KUNIT_EXPECT_MEMEQ(test, buf, result->expected_swab, dst_size);
382}
383
384static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
385{
386	const struct convert_xrgb8888_case *params = test->param_value;
387	const struct convert_to_rgb888_result *result = &params->rgb888_result;
388	size_t dst_size;
389	__u8 *buf = NULL;
390	__u32 *xrgb8888 = NULL;
391	struct iosys_map dst, src;
392
393	struct drm_framebuffer fb = {
394		.format = drm_format_info(DRM_FORMAT_XRGB8888),
395		.pitches = { params->pitch, 0, 0 },
396	};
397
398	dst_size = conversion_buf_size(DRM_FORMAT_RGB888, result->dst_pitch,
399				       &params->clip);
400	KUNIT_ASSERT_GT(test, dst_size, 0);
401
402	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
403	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
404	iosys_map_set_vaddr(&dst, buf);
405
406	xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
407	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
408	iosys_map_set_vaddr(&src, xrgb8888);
409
410	drm_fb_xrgb8888_to_rgb888(&dst, &result->dst_pitch, &src, &fb, &params->clip);
411	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
412}
413
414static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
415{
416	const struct convert_xrgb8888_case *params = test->param_value;
417	const struct convert_to_xrgb2101010_result *result = &params->xrgb2101010_result;
418	size_t dst_size;
419	__u32 *buf = NULL;
420	__u32 *xrgb8888 = NULL;
421	struct iosys_map dst, src;
422
423	struct drm_framebuffer fb = {
424		.format = drm_format_info(DRM_FORMAT_XRGB8888),
425		.pitches = { params->pitch, 0, 0 },
426	};
427
428	dst_size = conversion_buf_size(DRM_FORMAT_XRGB2101010,
429				       result->dst_pitch, &params->clip);
430	KUNIT_ASSERT_GT(test, dst_size, 0);
431
432	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
433	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
434	iosys_map_set_vaddr(&dst, buf);
435
436	xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
437	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
438	iosys_map_set_vaddr(&src, xrgb8888);
439
440	drm_fb_xrgb8888_to_xrgb2101010(&dst, &result->dst_pitch, &src, &fb, &params->clip);
441	buf = le32buf_to_cpu(test, buf, dst_size / sizeof(u32));
442	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
443}
444
445static struct kunit_case drm_format_helper_test_cases[] = {
446	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_gray8, convert_xrgb8888_gen_params),
447	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb332, convert_xrgb8888_gen_params),
448	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb565, convert_xrgb8888_gen_params),
449	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb888, convert_xrgb8888_gen_params),
450	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params),
451	{}
452};
453
454static struct kunit_suite drm_format_helper_test_suite = {
455	.name = "drm_format_helper_test",
456	.test_cases = drm_format_helper_test_cases,
457};
458
459kunit_test_suite(drm_format_helper_test_suite);
460
461MODULE_DESCRIPTION("KUnit tests for the drm_format_helper APIs");
462MODULE_LICENSE("GPL");
463MODULE_AUTHOR("José Expósito <jose.exposito89@gmail.com>");