File Index
Files and directories
Sign in
FILE

vkms_color_test.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/vkms/tests/vkms_color_test.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2
  3#include <kunit/test.h>
  4
  5#include <drm/drm_fixed.h>
  6#include <drm/drm_mode.h>
  7#include "../vkms_composer.h"
  8#include "../vkms_drv.h"
  9#include "../vkms_luts.h"
 10
 11#define TEST_LUT_SIZE 16
 12
 13MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
 14
 15static struct drm_color_lut test_linear_array[TEST_LUT_SIZE] = {
 16	{ 0x0, 0x0, 0x0, 0 },
 17	{ 0x1111, 0x1111, 0x1111, 0 },
 18	{ 0x2222, 0x2222, 0x2222, 0 },
 19	{ 0x3333, 0x3333, 0x3333, 0 },
 20	{ 0x4444, 0x4444, 0x4444, 0 },
 21	{ 0x5555, 0x5555, 0x5555, 0 },
 22	{ 0x6666, 0x6666, 0x6666, 0 },
 23	{ 0x7777, 0x7777, 0x7777, 0 },
 24	{ 0x8888, 0x8888, 0x8888, 0 },
 25	{ 0x9999, 0x9999, 0x9999, 0 },
 26	{ 0xaaaa, 0xaaaa, 0xaaaa, 0 },
 27	{ 0xbbbb, 0xbbbb, 0xbbbb, 0 },
 28	{ 0xcccc, 0xcccc, 0xcccc, 0 },
 29	{ 0xdddd, 0xdddd, 0xdddd, 0 },
 30	{ 0xeeee, 0xeeee, 0xeeee, 0 },
 31	{ 0xffff, 0xffff, 0xffff, 0 },
 32};
 33
 34/* lerp test parameters */
 35struct vkms_color_test_lerp_params {
 36	s64 t;
 37	__u16 a;
 38	__u16 b;
 39	__u16 expected;
 40};
 41
 42/* lerp test cases */
 43static const struct vkms_color_test_lerp_params color_test_lerp_cases[] = {
 44	/* Half-way round down */
 45	{ 0x80000000 - 1, 0x0, 0x10, 0x8 },
 46	{ 0x80000000 - 1, 0x1, 0x10, 0x8 },	/* Odd a */
 47	{ 0x80000000 - 1, 0x1, 0xf, 0x8 },	/* Odd b */
 48	{ 0x80000000 - 1, 0x10, 0x10, 0x10 },	/* b = a */
 49	{ 0x80000000 - 1, 0x10, 0x11, 0x10 },	/* b = a + 1*/
 50	/* Half-way round up */
 51	{ 0x80000000, 0x0, 0x10, 0x8 },
 52	{ 0x80000000, 0x1, 0x10, 0x9 },		/* Odd a */
 53	{ 0x80000000, 0x1, 0xf, 0x8 },		/* Odd b */
 54	{ 0x80000000, 0x10, 0x10, 0x10 },	/* b = a */
 55	{ 0x80000000, 0x10, 0x11, 0x11 },	/* b = a + 1*/
 56	/*  t = 0.0 */
 57	{ 0x0, 0x0, 0x10, 0x0 },
 58	{ 0x0, 0x1, 0x10, 0x1 },		/* Odd a */
 59	{ 0x0, 0x1, 0xf, 0x1 },			/* Odd b */
 60	{ 0x0, 0x10, 0x10, 0x10 },		/* b = a */
 61	{ 0x0, 0x10, 0x11, 0x10 },		/* b = a + 1*/
 62	/*  t = 1.0 */
 63	{ 0x100000000, 0x0, 0x10, 0x10 },
 64	{ 0x100000000, 0x1, 0x10, 0x10 },	/* Odd a */
 65	{ 0x100000000, 0x1, 0xf, 0xf },		/* Odd b */
 66	{ 0x100000000, 0x10, 0x10, 0x10 },	/* b = a */
 67	{ 0x100000000, 0x10, 0x11, 0x11 },	/* b = a + 1*/
 68	/*  t = 0.0 + 1 */
 69	{ 0x0 + 1, 0x0, 0x10, 0x0 },
 70	{ 0x0 + 1, 0x1, 0x10, 0x1 },		/* Odd a */
 71	{ 0x0 + 1, 0x1, 0xf, 0x1 },		/* Odd b */
 72	{ 0x0 + 1, 0x10, 0x10, 0x10 },		/* b = a */
 73	{ 0x0 + 1, 0x10, 0x11, 0x10 },		/* b = a + 1*/
 74	/*  t = 1.0 - 1 */
 75	{ 0x100000000 - 1, 0x0, 0x10, 0x10 },
 76	{ 0x100000000 - 1, 0x1, 0x10, 0x10 },	/* Odd a */
 77	{ 0x100000000 - 1, 0x1, 0xf, 0xf },	/* Odd b */
 78	{ 0x100000000 - 1, 0x10, 0x10, 0x10 },	/* b = a */
 79	{ 0x100000000 - 1, 0x10, 0x11, 0x11 },	/* b = a + 1*/
 80	/*  t chosen to verify the flipping point of result a (or b) to a+1 (or b-1) */
 81	{ 0x80000000 - 1, 0x0, 0x1, 0x0 },
 82	{ 0x80000000, 0x0, 0x1, 0x1 },
 83};
 84
 85static const struct vkms_color_lut test_linear_lut = {
 86	.base = test_linear_array,
 87	.lut_length = TEST_LUT_SIZE,
 88	.channel_value2index_ratio = 0xf000fll
 89};
 90
 91static void vkms_color_test_get_lut_index(struct kunit *test)
 92{
 93	s64 lut_index;
 94	int i;
 95
 96	lut_index = get_lut_index(&test_linear_lut, test_linear_array[0].red);
 97	KUNIT_EXPECT_EQ(test, drm_fixp2int(lut_index), 0);
 98
 99	for (i = 0; i < TEST_LUT_SIZE; i++) {
100		lut_index = get_lut_index(&test_linear_lut, test_linear_array[i].red);
101		KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(lut_index), i);
102	}
103
104	KUNIT_EXPECT_EQ(test, drm_fixp2int(get_lut_index(&srgb_eotf, 0x0)), 0x0);
105	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_eotf, 0x0)), 0x0);
106	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_eotf, 0x101)), 0x1);
107	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_eotf, 0x202)), 0x2);
108
109	KUNIT_EXPECT_EQ(test, drm_fixp2int(get_lut_index(&srgb_inv_eotf, 0x0)), 0x0);
110	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_inv_eotf, 0x0)), 0x0);
111	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_inv_eotf, 0x101)), 0x1);
112	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_inv_eotf, 0x202)), 0x2);
113
114	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_eotf, 0xfefe)), 0xfe);
115	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_eotf, 0xffff)), 0xff);
116}
117
118static void vkms_color_test_lerp(struct kunit *test)
119{
120	int i;
121
122	for (i = 0; i < ARRAY_SIZE(color_test_lerp_cases); i++) {
123		const struct vkms_color_test_lerp_params *params = &color_test_lerp_cases[i];
124
125		KUNIT_EXPECT_EQ(test, lerp_u16(params->a, params->b, params->t), params->expected);
126	}
127}
128
129static void vkms_color_test_linear(struct kunit *test)
130{
131	for (int i = 0; i < LUT_SIZE; i++) {
132		int linear = apply_lut_to_channel_value(&linear_eotf, i * 0x101, LUT_RED);
133
134		KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(linear, 0x101), i);
135	}
136}
137
138static void vkms_color_srgb_inv_srgb(struct kunit *test)
139{
140	u16 srgb, final;
141
142	for (int i = 0; i < LUT_SIZE; i++) {
143		srgb = apply_lut_to_channel_value(&srgb_eotf, i * 0x101, LUT_RED);
144		final = apply_lut_to_channel_value(&srgb_inv_eotf, srgb, LUT_RED);
145
146		KUNIT_EXPECT_GE(test, final / 0x101, i - 1);
147		KUNIT_EXPECT_LE(test, final / 0x101, i + 1);
148	}
149}
150
151#define FIXPT_HALF        (DRM_FIXED_ONE >> 1)
152#define FIXPT_QUARTER     (DRM_FIXED_ONE >> 2)
153
154static const struct drm_color_ctm_3x4 test_matrix_3x4_50_desat = { {
155	FIXPT_HALF, FIXPT_QUARTER, FIXPT_QUARTER, 0,
156	FIXPT_QUARTER, FIXPT_HALF, FIXPT_QUARTER, 0,
157	FIXPT_QUARTER, FIXPT_QUARTER, FIXPT_HALF, 0
158} };
159
160static void vkms_color_ctm_3x4_50_desat(struct kunit *test)
161{
162	struct pixel_argb_s32 ref, out;
163
164	/* full white */
165	ref.a = 0xffff;
166	ref.r = 0xffff;
167	ref.g = 0xffff;
168	ref.b = 0xffff;
169
170	memcpy(&out, &ref, sizeof(out));
171	apply_3x4_matrix(&out, &test_matrix_3x4_50_desat);
172
173	KUNIT_EXPECT_MEMEQ(test, &ref, &out, sizeof(out));
174
175	/* full black */
176	ref.a = 0xffff;
177	ref.r = 0x0;
178	ref.g = 0x0;
179	ref.b = 0x0;
180
181	memcpy(&out, &ref, sizeof(out));
182	apply_3x4_matrix(&out, &test_matrix_3x4_50_desat);
183
184	KUNIT_EXPECT_MEMEQ(test, &ref, &out, sizeof(out));
185
186	/* 50% grey */
187	ref.a = 0xffff;
188	ref.r = 0x8000;
189	ref.g = 0x8000;
190	ref.b = 0x8000;
191
192	memcpy(&out, &ref, sizeof(out));
193	apply_3x4_matrix(&out, &test_matrix_3x4_50_desat);
194
195	KUNIT_EXPECT_MEMEQ(test, &ref, &out, sizeof(out));
196
197	/* full red to 50% desat */
198	ref.a = 0xffff;
199	ref.r = 0x8000;
200	ref.g = 0x4000;
201	ref.b = 0x4000;
202
203	out.a = 0xffff;
204	out.r = 0xffff;
205	out.g = 0x0;
206	out.b = 0x0;
207
208	apply_3x4_matrix(&out, &test_matrix_3x4_50_desat);
209
210	KUNIT_EXPECT_MEMEQ(test, &ref, &out, sizeof(out));
211}
212
213/*
214 * BT.709 encoding matrix
215 *
216 * Values printed from within IGT when converting
217 * igt_matrix_3x4_bt709_enc to the fixed-point format expected
218 * by DRM/KMS.
219 */
220static const struct drm_color_ctm_3x4 test_matrix_3x4_bt709_enc = { {
221	0x00000000366cf400ull, 0x00000000b7175900ull, 0x0000000127bb300ull, 0,
222	0x800000001993b3a0ull, 0x800000005609fe80ull, 0x000000006f9db200ull, 0,
223	0x000000009d70a400ull, 0x800000008f011100ull, 0x800000000e6f9330ull, 0
224} };
225
226static void vkms_color_ctm_3x4_bt709(struct kunit *test)
227{
228	struct pixel_argb_s32 out;
229
230	/* full white to bt709 */
231	out.a = 0xffff;
232	out.r = 0xffff;
233	out.g = 0xffff;
234	out.b = 0xffff;
235
236	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
237
238	/* Y 255 */
239	KUNIT_EXPECT_GT(test, out.r, 0xfe00);
240	KUNIT_EXPECT_LT(test, out.r, 0x10000);
241
242	/* U 0 */
243	KUNIT_EXPECT_LT(test, out.g, 0x0100);
244
245	/* V 0 */
246	KUNIT_EXPECT_LT(test, out.b, 0x0100);
247
248	/* full black to bt709 */
249	out.a = 0xffff;
250	out.r = 0x0;
251	out.g = 0x0;
252	out.b = 0x0;
253
254	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
255
256	/* Y 0 */
257	KUNIT_EXPECT_LT(test, out.r, 0x100);
258
259	/* U 0 */
260	KUNIT_EXPECT_LT(test, out.g, 0x0100);
261
262	/* V 0 */
263	KUNIT_EXPECT_LT(test, out.b, 0x0100);
264
265	/* gray to bt709 */
266	out.a = 0xffff;
267	out.r = 0x7fff;
268	out.g = 0x7fff;
269	out.b = 0x7fff;
270
271	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
272
273	/* Y 127 */
274	KUNIT_EXPECT_GT(test, out.r, 0x7e00);
275	KUNIT_EXPECT_LT(test, out.r, 0x8000);
276
277	/* U 0 */
278	KUNIT_EXPECT_LT(test, out.g, 0x0100);
279
280	/* V 0 */
281	KUNIT_EXPECT_LT(test, out.b, 0x0100);
282
283	/* == red 255 - bt709 enc == */
284	out.a = 0xffff;
285	out.r = 0xffff;
286	out.g = 0x0;
287	out.b = 0x0;
288
289	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
290
291	/* Y 54 */
292	KUNIT_EXPECT_GT(test, out.r, 0x3500);
293	KUNIT_EXPECT_LT(test, out.r, 0x3700);
294
295	/* U 0 */
296	KUNIT_EXPECT_LT(test, out.g, 0x0100);
297
298	/* V 157 */
299	KUNIT_EXPECT_GT(test, out.b, 0x9C00);
300	KUNIT_EXPECT_LT(test, out.b, 0x9E00);
301
302	/* == green 255 - bt709 enc == */
303	out.a = 0xffff;
304	out.r = 0x0;
305	out.g = 0xffff;
306	out.b = 0x0;
307
308	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
309
310	/* Y 182 */
311	KUNIT_EXPECT_GT(test, out.r, 0xB500);
312	KUNIT_EXPECT_LT(test, out.r, 0xB780); /* laxed by half*/
313
314	/* U 0 */
315	KUNIT_EXPECT_LT(test, out.g, 0x0100);
316
317	/* V 0 */
318	KUNIT_EXPECT_LT(test, out.b, 0x0100);
319
320	/* == blue 255 - bt709 enc == */
321	out.a = 0xffff;
322	out.r = 0x0;
323	out.g = 0x0;
324	out.b = 0xffff;
325
326	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
327
328	/* Y 18 */
329	KUNIT_EXPECT_GT(test, out.r, 0x1100);
330	KUNIT_EXPECT_LT(test, out.r, 0x1300);
331
332	/* U 111 */
333	KUNIT_EXPECT_GT(test, out.g, 0x6E00);
334	KUNIT_EXPECT_LT(test, out.g, 0x7000);
335
336	/* V 0 */
337	KUNIT_EXPECT_LT(test, out.b, 0x0100);
338
339	/* == red 140 - bt709 enc == */
340	out.a = 0xffff;
341	out.r = 0x8c8c;
342	out.g = 0x0;
343	out.b = 0x0;
344
345	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
346
347	/* Y 30 */
348	KUNIT_EXPECT_GT(test, out.r, 0x1D00);
349	KUNIT_EXPECT_LT(test, out.r, 0x1F00);
350
351	/* U 0 */
352	KUNIT_EXPECT_LT(test, out.g, 0x100);
353
354	/* V 87 */
355	KUNIT_EXPECT_GT(test, out.b, 0x5600);
356	KUNIT_EXPECT_LT(test, out.b, 0x5800);
357
358	/* == green 140 - bt709 enc == */
359	out.a = 0xffff;
360	out.r = 0x0;
361	out.g = 0x8c8c;
362	out.b = 0x0;
363
364	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
365
366	/* Y 30 */
367	KUNIT_EXPECT_GT(test, out.r, 0x6400);
368	KUNIT_EXPECT_LT(test, out.r, 0x6600);
369
370	/* U 0 */
371	KUNIT_EXPECT_LT(test, out.g, 0x100);
372
373	/* V 0 */
374	KUNIT_EXPECT_LT(test, out.b, 0x100);
375
376	/* == blue 140 - bt709 enc == */
377	out.a = 0xffff;
378	out.r = 0x0;
379	out.g = 0x0;
380	out.b = 0x8c8c;
381
382	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
383
384	/* Y 30 */
385	KUNIT_EXPECT_GT(test, out.r, 0x900);
386	KUNIT_EXPECT_LT(test, out.r, 0xB00);
387
388	/* U 61 */
389	KUNIT_EXPECT_GT(test, out.g, 0x3C00);
390	KUNIT_EXPECT_LT(test, out.g, 0x3E00);
391
392	/* V 0 */
393	KUNIT_EXPECT_LT(test, out.b, 0x100);
394}
395
396static struct kunit_case vkms_color_test_cases[] = {
397	KUNIT_CASE(vkms_color_test_get_lut_index),
398	KUNIT_CASE(vkms_color_test_lerp),
399	KUNIT_CASE(vkms_color_test_linear),
400	KUNIT_CASE(vkms_color_srgb_inv_srgb),
401	KUNIT_CASE(vkms_color_ctm_3x4_50_desat),
402	KUNIT_CASE(vkms_color_ctm_3x4_bt709),
403	{}
404};
405
406static struct kunit_suite vkms_color_test_suite = {
407	.name = "vkms-color",
408	.test_cases = vkms_color_test_cases,
409};
410
411kunit_test_suite(vkms_color_test_suite);
412
413MODULE_DESCRIPTION("Kunit test for VKMS LUT handling");
414MODULE_LICENSE("GPL");
~/ Read-only file preview.