xref: /aosp_15_r20/external/libdrm/tests/util/pattern.c (revision 7688df22e49036ff52a766b7101da3a49edadb8c)
1 /*
2  * Copyright 2008 Tungsten Graphics
3  *   Jakob Bornecrantz <[email protected]>
4  * Copyright 2008 Intel Corporation
5  *   Jesse Barnes <[email protected]>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23  * IN THE SOFTWARE.
24  */
25 
26 #include <stdbool.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include <drm_fourcc.h>
33 
34 #if HAVE_CAIRO
35 #include <cairo.h>
36 #include <math.h>
37 #endif
38 
39 #include "common.h"
40 #include "format.h"
41 #include "pattern.h"
42 
43 struct color_rgb24 {
44 	unsigned int value:24;
45 } __attribute__((__packed__));
46 
47 struct color_yuv {
48 	unsigned char y;
49 	unsigned char u;
50 	unsigned char v;
51 };
52 
53 #define MAKE_YUV_601_Y(r, g, b) \
54 	((( 66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
55 #define MAKE_YUV_601_U(r, g, b) \
56 	(((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
57 #define MAKE_YUV_601_V(r, g, b) \
58 	(((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
59 
60 #define MAKE_YUV_601(r, g, b) \
61 	{ .y = MAKE_YUV_601_Y(r, g, b), \
62 	  .u = MAKE_YUV_601_U(r, g, b), \
63 	  .v = MAKE_YUV_601_V(r, g, b) }
64 
swap16(uint16_t x)65 static inline uint16_t swap16(uint16_t x)
66 {
67 	return ((x & 0x00ffU) << 8) | ((x & 0xff00U) >> 8);
68 }
69 
swap32(uint32_t x)70 static inline uint32_t swap32(uint32_t x)
71 {
72 	return ((x & 0x000000ffU) << 24) |
73 	       ((x & 0x0000ff00U) <<  8) |
74 	       ((x & 0x00ff0000U) >>  8) |
75 	       ((x & 0xff000000U) >> 24);
76 }
77 
78 #ifdef HAVE_BIG_ENDIAN
79 #define cpu_to_be16(x)			(x)
80 #define cpu_to_le16(x)			swap16(x)
81 #define cpu_to_le32(x)			swap32(x)
82 #define fb_foreign_endian(format)	(!((format) & DRM_FORMAT_BIG_ENDIAN))
83 #else
84 #define cpu_to_be16(x)			swap16(x)
85 #define cpu_to_le16(x)			(x)
86 #define cpu_to_le32(x)			(x)
87 #define fb_foreign_endian(format)	((format) & DRM_FORMAT_BIG_ENDIAN)
88 #endif
89 
90 #define cpu_to_fb16(x)	(fb_be ? cpu_to_be16(x) : cpu_to_le16(x))
91 
92 /* This function takes 8-bit color values */
shiftcolor8(const struct util_color_component * comp,uint32_t value)93 static inline uint32_t shiftcolor8(const struct util_color_component *comp,
94 				  uint32_t value)
95 {
96 	value &= 0xff;
97 	/* Fill the low bits with the high bits. */
98 	value = (value << 8) | value;
99 	/* Shift down to remove unwanted low bits */
100 	value = value >> (16 - comp->length);
101 	/* Shift back up to where the value should be */
102 	return value << comp->offset;
103 }
104 
105 /* This function takes 10-bit color values */
shiftcolor10(const struct util_color_component * comp,uint32_t value)106 static inline uint32_t shiftcolor10(const struct util_color_component *comp,
107 				    uint32_t value)
108 {
109 	value &= 0x3ff;
110 	/* Fill the low bits with the high bits. */
111 	value = (value << 6) | (value >> 4);
112 	/* Shift down to remove unwanted low bits */
113 	value = value >> (16 - comp->length);
114 	/* Shift back up to where the value should be */
115 	return value << comp->offset;
116 }
117 
118 /* This function takes 16-bit color values */
shiftcolor16(const struct util_color_component * comp,uint64_t value)119 static inline uint64_t shiftcolor16(const struct util_color_component *comp,
120 				    uint64_t value)
121 {
122 	value &= 0xffff;
123 	/* Shift down to remove unwanted low bits */
124 	value = value >> (16 - comp->length);
125 	/* Shift back up to where the value should be */
126 	return value << comp->offset;
127 }
128 
129 #define MAKE_RGBA10(rgb, r, g, b, a) \
130 	(shiftcolor10(&(rgb)->red, (r)) | \
131 	 shiftcolor10(&(rgb)->green, (g)) | \
132 	 shiftcolor10(&(rgb)->blue, (b)) | \
133 	 shiftcolor10(&(rgb)->alpha, (a)))
134 
135 #define MAKE_RGBA(rgb, r, g, b, a) \
136 	(shiftcolor8(&(rgb)->red, (r)) | \
137 	 shiftcolor8(&(rgb)->green, (g)) | \
138 	 shiftcolor8(&(rgb)->blue, (b)) | \
139 	 shiftcolor8(&(rgb)->alpha, (a)))
140 
141 #define MAKE_RGB24(rgb, r, g, b) \
142 	{ .value = MAKE_RGBA(rgb, r, g, b, 0) }
143 
144 
145 /**
146   * Takes a uint16_t, divides by 65536, converts the infinite-precision
147   * result to fp16 with round-to-zero.
148   *
149   * Copied from mesa:src/util/half_float.c
150   */
uint16_div_64k_to_half(uint16_t v)151 static uint16_t uint16_div_64k_to_half(uint16_t v)
152 {
153 	/* Zero or subnormal. Set the mantissa to (v << 8) and return. */
154 	if (v < 4)
155 		return v << 8;
156 
157 	/* Count the leading 0s in the uint16_t */
158 	int n = __builtin_clz(v) - 16;
159 
160 	/* Shift the mantissa up so bit 16 is the hidden 1 bit,
161 	 * mask it off, then shift back down to 10 bits
162 	 */
163 	int m = ( ((uint32_t)v << (n + 1)) & 0xffff ) >> 6;
164 
165 	/*  (0{n} 1 X{15-n}) * 2^-16
166 	 * = 1.X * 2^(15-n-16)
167 	 * = 1.X * 2^(14-n - 15)
168 	 * which is the FP16 form with e = 14 - n
169 	 */
170 	int e = 14 - n;
171 
172 	return (e << 10) | m;
173 }
174 
175 #define MAKE_RGBA8FP16(rgb, r, g, b, a) \
176 	(shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 8)) | \
177 	 shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 8)) | \
178 	 shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 8)) | \
179 	 shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 8)))
180 
181 #define MAKE_RGBA10FP16(rgb, r, g, b, a) \
182 	(shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 6)) | \
183 	 shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 6)) | \
184 	 shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 6)) | \
185 	 shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 6)))
186 
fill_smpte_yuv_planar(const struct util_yuv_info * yuv,unsigned char * y_mem,unsigned char * u_mem,unsigned char * v_mem,unsigned int width,unsigned int height,unsigned int stride)187 static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv,
188 				  unsigned char *y_mem, unsigned char *u_mem,
189 				  unsigned char *v_mem, unsigned int width,
190 				  unsigned int height, unsigned int stride)
191 {
192 	const struct color_yuv colors_top[] = {
193 		MAKE_YUV_601(192, 192, 192),	/* grey */
194 		MAKE_YUV_601(192, 192, 0),	/* yellow */
195 		MAKE_YUV_601(0, 192, 192),	/* cyan */
196 		MAKE_YUV_601(0, 192, 0),	/* green */
197 		MAKE_YUV_601(192, 0, 192),	/* magenta */
198 		MAKE_YUV_601(192, 0, 0),	/* red */
199 		MAKE_YUV_601(0, 0, 192),	/* blue */
200 	};
201 	const struct color_yuv colors_middle[] = {
202 		MAKE_YUV_601(0, 0, 192),	/* blue */
203 		MAKE_YUV_601(19, 19, 19),	/* black */
204 		MAKE_YUV_601(192, 0, 192),	/* magenta */
205 		MAKE_YUV_601(19, 19, 19),	/* black */
206 		MAKE_YUV_601(0, 192, 192),	/* cyan */
207 		MAKE_YUV_601(19, 19, 19),	/* black */
208 		MAKE_YUV_601(192, 192, 192),	/* grey */
209 	};
210 	const struct color_yuv colors_bottom[] = {
211 		MAKE_YUV_601(0, 33, 76),	/* in-phase */
212 		MAKE_YUV_601(255, 255, 255),	/* super white */
213 		MAKE_YUV_601(50, 0, 106),	/* quadrature */
214 		MAKE_YUV_601(19, 19, 19),	/* black */
215 		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
216 		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
217 		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
218 		MAKE_YUV_601(19, 19, 19),	/* black */
219 	};
220 	unsigned int cs = yuv->chroma_stride;
221 	unsigned int xsub = yuv->xsub;
222 	unsigned int ysub = yuv->ysub;
223 	unsigned int x;
224 	unsigned int y;
225 
226 	/* Luma */
227 	for (y = 0; y < height * 6 / 9; ++y) {
228 		for (x = 0; x < width; ++x)
229 			y_mem[x] = colors_top[x * 7 / width].y;
230 		y_mem += stride;
231 	}
232 
233 	for (; y < height * 7 / 9; ++y) {
234 		for (x = 0; x < width; ++x)
235 			y_mem[x] = colors_middle[x * 7 / width].y;
236 		y_mem += stride;
237 	}
238 
239 	for (; y < height; ++y) {
240 		for (x = 0; x < width * 5 / 7; ++x)
241 			y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
242 		for (; x < width * 6 / 7; ++x)
243 			y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
244 						 / (width / 7) + 4].y;
245 		for (; x < width; ++x)
246 			y_mem[x] = colors_bottom[7].y;
247 		y_mem += stride;
248 	}
249 
250 	/* Chroma */
251 	for (y = 0; y < height / ysub * 6 / 9; ++y) {
252 		for (x = 0; x < width; x += xsub) {
253 			u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
254 			v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
255 		}
256 		u_mem += stride * cs / xsub;
257 		v_mem += stride * cs / xsub;
258 	}
259 
260 	for (; y < height / ysub * 7 / 9; ++y) {
261 		for (x = 0; x < width; x += xsub) {
262 			u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
263 			v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
264 		}
265 		u_mem += stride * cs / xsub;
266 		v_mem += stride * cs / xsub;
267 	}
268 
269 	for (; y < height / ysub; ++y) {
270 		for (x = 0; x < width * 5 / 7; x += xsub) {
271 			u_mem[x*cs/xsub] =
272 				colors_bottom[x * 4 / (width * 5 / 7)].u;
273 			v_mem[x*cs/xsub] =
274 				colors_bottom[x * 4 / (width * 5 / 7)].v;
275 		}
276 		for (; x < width * 6 / 7; x += xsub) {
277 			u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
278 							 3 / (width / 7) + 4].u;
279 			v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
280 							 3 / (width / 7) + 4].v;
281 		}
282 		for (; x < width; x += xsub) {
283 			u_mem[x*cs/xsub] = colors_bottom[7].u;
284 			v_mem[x*cs/xsub] = colors_bottom[7].v;
285 		}
286 		u_mem += stride * cs / xsub;
287 		v_mem += stride * cs / xsub;
288 	}
289 }
290 
write_pixels_10bpp(unsigned char * mem,unsigned short a,unsigned short b,unsigned short c,unsigned short d)291 static void write_pixels_10bpp(unsigned char *mem,
292 			       unsigned short a,
293 			       unsigned short b,
294 			       unsigned short c,
295 			       unsigned short d)
296 {
297 	  mem[0] = (a & 0xff);
298 	  mem[1] = ((a >> 8) & 0x3) | ((b & 0x3f) << 2);
299 	  mem[2] = ((b >> 6) & 0xf) | ((c & 0xf) << 4);
300 	  mem[3] = ((c >> 4) & 0x3f) | ((d & 0x3) << 6);
301 	  mem[4] = ((d >> 2) & 0xff);
302 }
303 
fill_smpte_yuv_planar_10bpp(const struct util_yuv_info * yuv,unsigned char * y_mem,unsigned char * uv_mem,unsigned int width,unsigned int height,unsigned int stride)304 static void fill_smpte_yuv_planar_10bpp(const struct util_yuv_info *yuv,
305 					unsigned char *y_mem,
306 					unsigned char *uv_mem,
307 					unsigned int width,
308 					unsigned int height,
309 					unsigned int stride)
310 {
311 	const struct color_yuv colors_top[] = {
312 		MAKE_YUV_601(192, 192, 192),	/* grey */
313 		MAKE_YUV_601(192, 192, 0),	/* yellow */
314 		MAKE_YUV_601(0, 192, 192),	/* cyan */
315 		MAKE_YUV_601(0, 192, 0),	/* green */
316 		MAKE_YUV_601(192, 0, 192),	/* magenta */
317 		MAKE_YUV_601(192, 0, 0),	/* red */
318 		MAKE_YUV_601(0, 0, 192),	/* blue */
319 	};
320 	const struct color_yuv colors_middle[] = {
321 		MAKE_YUV_601(0, 0, 192),	/* blue */
322 		MAKE_YUV_601(19, 19, 19),	/* black */
323 		MAKE_YUV_601(192, 0, 192),	/* magenta */
324 		MAKE_YUV_601(19, 19, 19),	/* black */
325 		MAKE_YUV_601(0, 192, 192),	/* cyan */
326 		MAKE_YUV_601(19, 19, 19),	/* black */
327 		MAKE_YUV_601(192, 192, 192),	/* grey */
328 	};
329 	const struct color_yuv colors_bottom[] = {
330 		MAKE_YUV_601(0, 33, 76),	/* in-phase */
331 		MAKE_YUV_601(255, 255, 255),	/* super white */
332 		MAKE_YUV_601(50, 0, 106),	/* quadrature */
333 		MAKE_YUV_601(19, 19, 19),	/* black */
334 		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
335 		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
336 		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
337 		MAKE_YUV_601(19, 19, 19),	/* black */
338 	};
339 	unsigned int cs = yuv->chroma_stride;
340 	unsigned int xsub = yuv->xsub;
341 	unsigned int ysub = yuv->ysub;
342 	unsigned int xstep = cs * xsub;
343 	unsigned int x;
344 	unsigned int y;
345 
346 	/* Luma */
347 	for (y = 0; y < height * 6 / 9; ++y) {
348 		for (x = 0; x < width; x += 4)
349 			write_pixels_10bpp(&y_mem[(x * 5) / 4],
350 				colors_top[(x+0) * 7 / width].y << 2,
351 				colors_top[(x+1) * 7 / width].y << 2,
352 				colors_top[(x+2) * 7 / width].y << 2,
353 				colors_top[(x+3) * 7 / width].y << 2);
354 		y_mem += stride;
355 	}
356 
357 	for (; y < height * 7 / 9; ++y) {
358 		for (x = 0; x < width; x += 4)
359 			write_pixels_10bpp(&y_mem[(x * 5) / 4],
360 				colors_middle[(x+0) * 7 / width].y << 2,
361 				colors_middle[(x+1) * 7 / width].y << 2,
362 				colors_middle[(x+2) * 7 / width].y << 2,
363 				colors_middle[(x+3) * 7 / width].y << 2);
364 		y_mem += stride;
365 	}
366 
367 	for (; y < height; ++y) {
368 		for (x = 0; x < width * 5 / 7; x += 4)
369 			write_pixels_10bpp(&y_mem[(x * 5) / 4],
370 				colors_bottom[(x+0) * 4 / (width * 5 / 7)].y << 2,
371 				colors_bottom[(x+1) * 4 / (width * 5 / 7)].y << 2,
372 				colors_bottom[(x+2) * 4 / (width * 5 / 7)].y << 2,
373 				colors_bottom[(x+3) * 4 / (width * 5 / 7)].y << 2);
374 		for (; x < width * 6 / 7; x += 4)
375 			write_pixels_10bpp(&y_mem[(x * 5) / 4],
376 				colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2,
377 				colors_bottom[((x+1) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2,
378 				colors_bottom[((x+2) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2,
379 				colors_bottom[((x+3) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2);
380 		for (; x < width; x += 4)
381 			write_pixels_10bpp(&y_mem[(x * 5) / 4],
382 				colors_bottom[7].y << 2,
383 				colors_bottom[7].y << 2,
384 				colors_bottom[7].y << 2,
385 				colors_bottom[7].y << 2);
386 		y_mem += stride;
387 	}
388 
389 	/* Chroma */
390 	for (y = 0; y < height * 6 / 9; y += ysub) {
391 		for (x = 0; x < width; x += xstep)
392 			write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
393 				colors_top[(x+0) * 7 / width].u << 2,
394 				colors_top[(x+0) * 7 / width].v << 2,
395 				colors_top[(x+xsub) * 7 / width].u << 2,
396 				colors_top[(x+xsub) * 7 / width].v << 2);
397 		uv_mem += stride * cs / xsub;
398 	}
399 
400 	for (; y < height * 7 / 9; y += ysub) {
401 		for (x = 0; x < width; x += xstep)
402 			write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
403 				colors_middle[(x+0) * 7 / width].u << 2,
404 				colors_middle[(x+0) * 7 / width].v << 2,
405 				colors_middle[(x+xsub) * 7 / width].u << 2,
406 				colors_middle[(x+xsub) * 7 / width].v << 2);
407 		uv_mem += stride * cs / xsub;
408 	}
409 
410 	for (; y < height; y += ysub) {
411 		for (x = 0; x < width * 5 / 7; x += xstep)
412 			write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
413 				colors_bottom[(x+0) * 4 / (width * 5 / 7)].u << 2,
414 				colors_bottom[(x+0) * 4 / (width * 5 / 7)].v << 2,
415 				colors_bottom[(x+xsub) * 4 / (width * 5 / 7)].u << 2,
416 				colors_bottom[(x+xsub) * 4 / (width * 5 / 7)].v << 2);
417 		for (; x < width * 6 / 7; x += xstep)
418 			write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
419 				colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].u << 2,
420 				colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].v << 2,
421 				colors_bottom[((x+xsub) - width * 5 / 7) * 3 / (width / 7) + 4].u << 2,
422 				colors_bottom[((x+xsub) - width * 5 / 7) * 3 / (width / 7) + 4].v << 2);
423 		for (; x < width; x += xstep)
424 			write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
425 				colors_bottom[7].u << 2,
426 				colors_bottom[7].v << 2,
427 				colors_bottom[7].u << 2,
428 				colors_bottom[7].v << 2);
429 		uv_mem += stride * cs / xsub;
430 	}
431 }
432 
fill_smpte_yuv_packed(const struct util_yuv_info * yuv,void * mem,unsigned int width,unsigned int height,unsigned int stride)433 static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem,
434 				  unsigned int width, unsigned int height,
435 				  unsigned int stride)
436 {
437 	const struct color_yuv colors_top[] = {
438 		MAKE_YUV_601(192, 192, 192),	/* grey */
439 		MAKE_YUV_601(192, 192, 0),	/* yellow */
440 		MAKE_YUV_601(0, 192, 192),	/* cyan */
441 		MAKE_YUV_601(0, 192, 0),	/* green */
442 		MAKE_YUV_601(192, 0, 192),	/* magenta */
443 		MAKE_YUV_601(192, 0, 0),	/* red */
444 		MAKE_YUV_601(0, 0, 192),	/* blue */
445 	};
446 	const struct color_yuv colors_middle[] = {
447 		MAKE_YUV_601(0, 0, 192),	/* blue */
448 		MAKE_YUV_601(19, 19, 19),	/* black */
449 		MAKE_YUV_601(192, 0, 192),	/* magenta */
450 		MAKE_YUV_601(19, 19, 19),	/* black */
451 		MAKE_YUV_601(0, 192, 192),	/* cyan */
452 		MAKE_YUV_601(19, 19, 19),	/* black */
453 		MAKE_YUV_601(192, 192, 192),	/* grey */
454 	};
455 	const struct color_yuv colors_bottom[] = {
456 		MAKE_YUV_601(0, 33, 76),	/* in-phase */
457 		MAKE_YUV_601(255, 255, 255),	/* super white */
458 		MAKE_YUV_601(50, 0, 106),	/* quadrature */
459 		MAKE_YUV_601(19, 19, 19),	/* black */
460 		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
461 		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
462 		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
463 		MAKE_YUV_601(19, 19, 19),	/* black */
464 	};
465 	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
466 	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
467 	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
468 	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
469 	unsigned int x;
470 	unsigned int y;
471 
472 	/* Luma */
473 	for (y = 0; y < height * 6 / 9; ++y) {
474 		for (x = 0; x < width; ++x)
475 			y_mem[2*x] = colors_top[x * 7 / width].y;
476 		y_mem += stride;
477 	}
478 
479 	for (; y < height * 7 / 9; ++y) {
480 		for (x = 0; x < width; ++x)
481 			y_mem[2*x] = colors_middle[x * 7 / width].y;
482 		y_mem += stride;
483 	}
484 
485 	for (; y < height; ++y) {
486 		for (x = 0; x < width * 5 / 7; ++x)
487 			y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
488 		for (; x < width * 6 / 7; ++x)
489 			y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
490 						   / (width / 7) + 4].y;
491 		for (; x < width; ++x)
492 			y_mem[2*x] = colors_bottom[7].y;
493 		y_mem += stride;
494 	}
495 
496 	/* Chroma */
497 	for (y = 0; y < height * 6 / 9; ++y) {
498 		for (x = 0; x < width; x += 2) {
499 			c_mem[2*x+u] = colors_top[x * 7 / width].u;
500 			c_mem[2*x+v] = colors_top[x * 7 / width].v;
501 		}
502 		c_mem += stride;
503 	}
504 
505 	for (; y < height * 7 / 9; ++y) {
506 		for (x = 0; x < width; x += 2) {
507 			c_mem[2*x+u] = colors_middle[x * 7 / width].u;
508 			c_mem[2*x+v] = colors_middle[x * 7 / width].v;
509 		}
510 		c_mem += stride;
511 	}
512 
513 	for (; y < height; ++y) {
514 		for (x = 0; x < width * 5 / 7; x += 2) {
515 			c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
516 			c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
517 		}
518 		for (; x < width * 6 / 7; x += 2) {
519 			c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
520 						     3 / (width / 7) + 4].u;
521 			c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
522 						     3 / (width / 7) + 4].v;
523 		}
524 		for (; x < width; x += 2) {
525 			c_mem[2*x+u] = colors_bottom[7].u;
526 			c_mem[2*x+v] = colors_bottom[7].v;
527 		}
528 		c_mem += stride;
529 	}
530 }
531 
fill_smpte_rgb16(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride,bool fb_be)532 static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
533 			     unsigned int width, unsigned int height,
534 			     unsigned int stride, bool fb_be)
535 {
536 	const uint16_t colors_top[] = {
537 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
538 		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
539 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
540 		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
541 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
542 		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
543 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
544 	};
545 	const uint16_t colors_middle[] = {
546 		MAKE_RGBA(rgb, 0, 0, 192, 127),		/* blue */
547 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
548 		MAKE_RGBA(rgb, 192, 0, 192, 127),	/* magenta */
549 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
550 		MAKE_RGBA(rgb, 0, 192, 192, 127),	/* cyan */
551 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
552 		MAKE_RGBA(rgb, 192, 192, 192, 127),	/* grey */
553 	};
554 	const uint16_t colors_bottom[] = {
555 		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
556 		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
557 		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
558 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
559 		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
560 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
561 		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
562 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
563 	};
564 	unsigned int x;
565 	unsigned int y;
566 
567 	for (y = 0; y < height * 6 / 9; ++y) {
568 		for (x = 0; x < width; ++x)
569 			((uint16_t *)mem)[x] = cpu_to_fb16(colors_top[x * 7 / width]);
570 		mem += stride;
571 	}
572 
573 	for (; y < height * 7 / 9; ++y) {
574 		for (x = 0; x < width; ++x)
575 			((uint16_t *)mem)[x] = cpu_to_fb16(colors_middle[x * 7 / width]);
576 		mem += stride;
577 	}
578 
579 	for (; y < height; ++y) {
580 		for (x = 0; x < width * 5 / 7; ++x)
581 			((uint16_t *)mem)[x] =
582 				cpu_to_fb16(colors_bottom[x * 4 / (width * 5 / 7)]);
583 		for (; x < width * 6 / 7; ++x)
584 			((uint16_t *)mem)[x] =
585 				cpu_to_fb16(colors_bottom[(x - width * 5 / 7) * 3
586 							  / (width / 7) + 4]);
587 		for (; x < width; ++x)
588 			((uint16_t *)mem)[x] = cpu_to_fb16(colors_bottom[7]);
589 		mem += stride;
590 	}
591 }
592 
fill_smpte_rgb24(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)593 static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem,
594 			     unsigned int width, unsigned int height,
595 			     unsigned int stride)
596 {
597 	const struct color_rgb24 colors_top[] = {
598 		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
599 		MAKE_RGB24(rgb, 192, 192, 0),	/* yellow */
600 		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
601 		MAKE_RGB24(rgb, 0, 192, 0),	/* green */
602 		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
603 		MAKE_RGB24(rgb, 192, 0, 0),	/* red */
604 		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
605 	};
606 	const struct color_rgb24 colors_middle[] = {
607 		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
608 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
609 		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
610 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
611 		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
612 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
613 		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
614 	};
615 	const struct color_rgb24 colors_bottom[] = {
616 		MAKE_RGB24(rgb, 0, 33, 76),	/* in-phase */
617 		MAKE_RGB24(rgb, 255, 255, 255),	/* super white */
618 		MAKE_RGB24(rgb, 50, 0, 106),	/* quadrature */
619 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
620 		MAKE_RGB24(rgb, 9, 9, 9),	/* 3.5% */
621 		MAKE_RGB24(rgb, 19, 19, 19),	/* 7.5% */
622 		MAKE_RGB24(rgb, 29, 29, 29),	/* 11.5% */
623 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
624 	};
625 	unsigned int x;
626 	unsigned int y;
627 
628 	for (y = 0; y < height * 6 / 9; ++y) {
629 		for (x = 0; x < width; ++x)
630 			((struct color_rgb24 *)mem)[x] =
631 				colors_top[x * 7 / width];
632 		mem += stride;
633 	}
634 
635 	for (; y < height * 7 / 9; ++y) {
636 		for (x = 0; x < width; ++x)
637 			((struct color_rgb24 *)mem)[x] =
638 				colors_middle[x * 7 / width];
639 		mem += stride;
640 	}
641 
642 	for (; y < height; ++y) {
643 		for (x = 0; x < width * 5 / 7; ++x)
644 			((struct color_rgb24 *)mem)[x] =
645 				colors_bottom[x * 4 / (width * 5 / 7)];
646 		for (; x < width * 6 / 7; ++x)
647 			((struct color_rgb24 *)mem)[x] =
648 				colors_bottom[(x - width * 5 / 7) * 3
649 					      / (width / 7) + 4];
650 		for (; x < width; ++x)
651 			((struct color_rgb24 *)mem)[x] = colors_bottom[7];
652 		mem += stride;
653 	}
654 }
655 
fill_smpte_rgb32(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)656 static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem,
657 			     unsigned int width, unsigned int height,
658 			     unsigned int stride)
659 {
660 	const uint32_t colors_top[] = {
661 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
662 		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
663 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
664 		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
665 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
666 		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
667 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
668 	};
669 	const uint32_t colors_middle[] = {
670 		MAKE_RGBA(rgb, 0, 0, 192, 127),		/* blue */
671 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
672 		MAKE_RGBA(rgb, 192, 0, 192, 127),	/* magenta */
673 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
674 		MAKE_RGBA(rgb, 0, 192, 192, 127),	/* cyan */
675 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
676 		MAKE_RGBA(rgb, 192, 192, 192, 127),	/* grey */
677 	};
678 	const uint32_t colors_bottom[] = {
679 		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
680 		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
681 		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
682 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
683 		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
684 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
685 		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
686 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
687 	};
688 	unsigned int x;
689 	unsigned int y;
690 
691 	for (y = 0; y < height * 6 / 9; ++y) {
692 		for (x = 0; x < width; ++x)
693 			((uint32_t *)mem)[x] = cpu_to_le32(colors_top[x * 7 / width]);
694 		mem += stride;
695 	}
696 
697 	for (; y < height * 7 / 9; ++y) {
698 		for (x = 0; x < width; ++x)
699 			((uint32_t *)mem)[x] = cpu_to_le32(colors_middle[x * 7 / width]);
700 		mem += stride;
701 	}
702 
703 	for (; y < height; ++y) {
704 		for (x = 0; x < width * 5 / 7; ++x)
705 			((uint32_t *)mem)[x] =
706 				cpu_to_le32(colors_bottom[x * 4 / (width * 5 / 7)]);
707 		for (; x < width * 6 / 7; ++x)
708 			((uint32_t *)mem)[x] =
709 				cpu_to_le32(colors_bottom[(x - width * 5 / 7) * 3
710 							  / (width / 7) + 4]);
711 		for (; x < width; ++x)
712 			((uint32_t *)mem)[x] = cpu_to_le32(colors_bottom[7]);
713 		mem += stride;
714 	}
715 }
716 
fill_smpte_rgb16fp(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)717 static void fill_smpte_rgb16fp(const struct util_rgb_info *rgb, void *mem,
718 			       unsigned int width, unsigned int height,
719 			       unsigned int stride)
720 {
721 	const uint64_t colors_top[] = {
722 		MAKE_RGBA8FP16(rgb, 192, 192, 192, 255),/* grey */
723 		MAKE_RGBA8FP16(rgb, 192, 192, 0, 255),	/* yellow */
724 		MAKE_RGBA8FP16(rgb, 0, 192, 192, 255),	/* cyan */
725 		MAKE_RGBA8FP16(rgb, 0, 192, 0, 255),	/* green */
726 		MAKE_RGBA8FP16(rgb, 192, 0, 192, 255),	/* magenta */
727 		MAKE_RGBA8FP16(rgb, 192, 0, 0, 255),	/* red */
728 		MAKE_RGBA8FP16(rgb, 0, 0, 192, 255),	/* blue */
729 	};
730 	const uint64_t colors_middle[] = {
731 		MAKE_RGBA8FP16(rgb, 0, 0, 192, 127),	/* blue */
732 		MAKE_RGBA8FP16(rgb, 19, 19, 19, 127),	/* black */
733 		MAKE_RGBA8FP16(rgb, 192, 0, 192, 127),	/* magenta */
734 		MAKE_RGBA8FP16(rgb, 19, 19, 19, 127),	/* black */
735 		MAKE_RGBA8FP16(rgb, 0, 192, 192, 127),	/* cyan */
736 		MAKE_RGBA8FP16(rgb, 19, 19, 19, 127),	/* black */
737 		MAKE_RGBA8FP16(rgb, 192, 192, 192, 127),/* grey */
738 	};
739 	const uint64_t colors_bottom[] = {
740 		MAKE_RGBA8FP16(rgb, 0, 33, 76, 255),	/* in-phase */
741 		MAKE_RGBA8FP16(rgb, 255, 255, 255, 255),/* super white */
742 		MAKE_RGBA8FP16(rgb, 50, 0, 106, 255),	/* quadrature */
743 		MAKE_RGBA8FP16(rgb, 19, 19, 19, 255),	/* black */
744 		MAKE_RGBA8FP16(rgb, 9, 9, 9, 255),	/* 3.5% */
745 		MAKE_RGBA8FP16(rgb, 19, 19, 19, 255),	/* 7.5% */
746 		MAKE_RGBA8FP16(rgb, 29, 29, 29, 255),	/* 11.5% */
747 		MAKE_RGBA8FP16(rgb, 19, 19, 19, 255),	/* black */
748 	};
749 	unsigned int x;
750 	unsigned int y;
751 
752 	for (y = 0; y < height * 6 / 9; ++y) {
753 		for (x = 0; x < width; ++x)
754 			((uint64_t *)mem)[x] = colors_top[x * 7 / width];
755 		mem += stride;
756 	}
757 
758 	for (; y < height * 7 / 9; ++y) {
759 		for (x = 0; x < width; ++x)
760 			((uint64_t *)mem)[x] = colors_middle[x * 7 / width];
761 		mem += stride;
762 	}
763 
764 	for (; y < height; ++y) {
765 		for (x = 0; x < width * 5 / 7; ++x)
766 			((uint64_t *)mem)[x] =
767 				colors_bottom[x * 4 / (width * 5 / 7)];
768 		for (; x < width * 6 / 7; ++x)
769 			((uint64_t *)mem)[x] =
770 				colors_bottom[(x - width * 5 / 7) * 3
771 					      / (width / 7) + 4];
772 		for (; x < width; ++x)
773 			((uint64_t *)mem)[x] = colors_bottom[7];
774 		mem += stride;
775 	}
776 }
777 
778 enum smpte_colors {
779 	SMPTE_COLOR_GREY,
780 	SMPTE_COLOR_YELLOW,
781 	SMPTE_COLOR_CYAN,
782 	SMPTE_COLOR_GREEN,
783 	SMPTE_COLOR_MAGENTA,
784 	SMPTE_COLOR_RED,
785 	SMPTE_COLOR_BLUE,
786 	SMPTE_COLOR_BLACK,
787 	SMPTE_COLOR_IN_PHASE,
788 	SMPTE_COLOR_SUPER_WHITE,
789 	SMPTE_COLOR_QUADRATURE,
790 	SMPTE_COLOR_3PC5,
791 	SMPTE_COLOR_11PC5,
792 };
793 
794 static unsigned int smpte_top[7] = {
795 	SMPTE_COLOR_GREY,
796 	SMPTE_COLOR_YELLOW,
797 	SMPTE_COLOR_CYAN,
798 	SMPTE_COLOR_GREEN,
799 	SMPTE_COLOR_MAGENTA,
800 	SMPTE_COLOR_RED,
801 	SMPTE_COLOR_BLUE,
802 };
803 
804 static unsigned int smpte_middle[7] = {
805 	SMPTE_COLOR_BLUE,
806 	SMPTE_COLOR_BLACK,
807 	SMPTE_COLOR_MAGENTA,
808 	SMPTE_COLOR_BLACK,
809 	SMPTE_COLOR_CYAN,
810 	SMPTE_COLOR_BLACK,
811 	SMPTE_COLOR_GREY,
812 };
813 
814 static unsigned int smpte_bottom[8] = {
815 	SMPTE_COLOR_IN_PHASE,
816 	SMPTE_COLOR_SUPER_WHITE,
817 	SMPTE_COLOR_QUADRATURE,
818 	SMPTE_COLOR_BLACK,
819 	SMPTE_COLOR_3PC5,
820 	SMPTE_COLOR_BLACK,
821 	SMPTE_COLOR_11PC5,
822 	SMPTE_COLOR_BLACK,
823 };
824 
825 #define EXPAND_COLOR(r, g, b)	{ (r) * 0x101, (g) * 0x101, (b) * 0x101 }
826 
827 static const struct drm_color_lut bw_color_lut[] = {
828 	EXPAND_COLOR(  0,   0,   0),	/* black */
829 	EXPAND_COLOR(255, 255, 255),	/* white */
830 };
831 
832 static const struct drm_color_lut pentile_color_lut[] = {
833 	/* PenTile RG-GB */
834 	EXPAND_COLOR(  0,   0,   0),	/* black */
835 	EXPAND_COLOR(255,   0,   0),	/* red */
836 	EXPAND_COLOR(  0, 207,   0),	/* green */
837 	EXPAND_COLOR(  0,   0, 255),	/* blue */
838 };
839 
840 static const struct drm_color_lut smpte_color_lut[] = {
841 	[SMPTE_COLOR_GREY] =        EXPAND_COLOR(192, 192, 192),
842 	[SMPTE_COLOR_YELLOW] =      EXPAND_COLOR(192, 192,   0),
843 	[SMPTE_COLOR_CYAN] =        EXPAND_COLOR(  0, 192, 192),
844 	[SMPTE_COLOR_GREEN] =       EXPAND_COLOR(  0, 192,   0),
845 	[SMPTE_COLOR_MAGENTA] =     EXPAND_COLOR(192,   0, 192),
846 	[SMPTE_COLOR_RED] =         EXPAND_COLOR(192,   0,   0),
847 	[SMPTE_COLOR_BLUE] =        EXPAND_COLOR(  0,   0, 192),
848 	[SMPTE_COLOR_BLACK] =       EXPAND_COLOR( 19,  19,  19),
849 	[SMPTE_COLOR_IN_PHASE] =    EXPAND_COLOR(  0,  33,  76),
850 	[SMPTE_COLOR_SUPER_WHITE] = EXPAND_COLOR(255, 255, 255),
851 	[SMPTE_COLOR_QUADRATURE] =  EXPAND_COLOR( 50,   0, 106),
852 	[SMPTE_COLOR_3PC5] =        EXPAND_COLOR(  9,   9,   9),
853 	[SMPTE_COLOR_11PC5] =       EXPAND_COLOR( 29,  29,  29),
854 };
855 
856 #undef EXPAND_COLOR
857 
858 /*
859  * Floyd-Steinberg dithering
860  */
861 
862 struct fsd {
863 	unsigned int width;
864 	unsigned int x;
865 	unsigned int i;
866 	int red;
867 	int green;
868 	int blue;
869 	int error[];
870 };
871 
fsd_alloc(unsigned int width)872 static struct fsd *fsd_alloc(unsigned int width)
873 {
874 	unsigned int n = 3 * (width + 1);
875 	struct fsd *fsd = malloc(sizeof(*fsd) + n * sizeof(fsd->error[0]));
876 
877 	fsd->width = width;
878 	fsd->x = 0;
879 	fsd->i = 0;
880 	memset(fsd->error, 0, n * sizeof(fsd->error[0]));
881 
882 	return fsd;
883 }
884 
clamp(int val,int min,int max)885 static inline int clamp(int val, int min, int max)
886 {
887 	if (val < min)
888 		return min;
889 	if (val > max)
890 		return max;
891 	return val;
892 }
893 
fsd_dither(struct fsd * fsd,struct drm_color_lut * color)894 static void fsd_dither(struct fsd *fsd, struct drm_color_lut *color)
895 {
896 	unsigned int i = fsd->i;
897 
898 	fsd->red = (int)color->red + (fsd->error[3 * i] + 8) / 16;
899 	fsd->green = (int)color->green + (fsd->error[3 * i + 1] + 8) / 16;
900 	fsd->blue = (int)color->blue + (fsd->error[3 * i + 2] + 8) / 16;
901 
902 	color->red = clamp(fsd->red, 0, 65535);
903 	color->green = clamp(fsd->green, 0, 65535);
904 	color->blue = clamp(fsd->blue, 0, 65535);
905 }
906 
fsd_update(struct fsd * fsd,const struct drm_color_lut * actual)907 static void fsd_update(struct fsd *fsd, const struct drm_color_lut *actual)
908 {
909 	int error_red = fsd->red - (int)actual->red;
910 	int error_green = fsd->green - (int)actual->green;
911 	int error_blue = fsd->blue - (int)actual->blue;
912 	unsigned int width = fsd->width;
913 	unsigned int i = fsd->i, j;
914 	unsigned int n = width + 1;
915 
916 	/* Distribute errors over neighboring pixels */
917 	if (fsd->x == width - 1) {
918 		/* Last pixel on this scanline */
919 		/* South East: initialize to zero */
920 		fsd->error[3 * i] = 0;
921 		fsd->error[3 * i + 1] = 0;
922 		fsd->error[3 * i + 2] = 0;
923 	} else {
924 		/* East: accumulate error */
925 		j = (i + 1) % n;
926 		fsd->error[3 * j] += 7 * error_red;
927 		fsd->error[3 * j + 1] += 7 * error_green;
928 		fsd->error[3 * j + 2] += 7 * error_blue;
929 
930 		/* South East: initial error */
931 		fsd->error[3 * i] = error_red;
932 		fsd->error[3 * i + 1] = error_green;
933 		fsd->error[3 * i + 2] = error_blue;
934 	}
935 	/* South West: accumulate error */
936 	j = (i + width - 1) % n;
937 	fsd->error[3 * j] += 3 * error_red;
938 	fsd->error[3 * j + 1] += 3 * error_green;
939 	fsd->error[3 * j + 2] += 3 * error_blue;
940 
941 	/* South: accumulate error */
942 	j = (i + width) % n;
943 	fsd->error[3 * j] += 5 * error_red;
944 	fsd->error[3 * j + 1] += 5 * error_green;
945 	fsd->error[3 * j + 2] += 5 * error_blue;
946 
947 	fsd->x = (fsd->x + 1) % width;
948 	fsd->i = (fsd->i + 1) % n;
949 }
950 
write_pixel_1(uint8_t * mem,unsigned int x,unsigned int pixel)951 static void write_pixel_1(uint8_t *mem, unsigned int x, unsigned int pixel)
952 {
953 	unsigned int shift = 7 - (x & 7);
954 	unsigned int mask = 1U << shift;
955 
956 	mem[x / 8] = (mem[x / 8] & ~mask) | ((pixel << shift) & mask);
957 }
958 
write_color_1(struct fsd * fsd,uint8_t * mem,unsigned int x,unsigned int index)959 static void write_color_1(struct fsd *fsd, uint8_t *mem, unsigned int x,
960 			  unsigned int index)
961 {
962 	struct drm_color_lut color = smpte_color_lut[index];
963 	unsigned int pixel;
964 
965 	fsd_dither(fsd, &color);
966 
967 	/* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
968 	if (3 * color.red + 6 * color.green + color.blue >= 10 * 32768) {
969 		pixel = 1;
970 		color.red = color.green = color.blue = 65535;
971 	} else {
972 		pixel = 0;
973 		color.red = color.green = color.blue = 0;
974 	}
975 
976 	fsd_update(fsd, &color);
977 
978 	write_pixel_1(mem, x, pixel);
979 }
980 
fill_smpte_c1(void * mem,unsigned int width,unsigned int height,unsigned int stride)981 static void fill_smpte_c1(void *mem, unsigned int width, unsigned int height,
982 			  unsigned int stride)
983 {
984 	struct fsd *fsd = fsd_alloc(width);
985 	unsigned int x;
986 	unsigned int y;
987 
988 	for (y = 0; y < height * 6 / 9; ++y) {
989 		for (x = 0; x < width; ++x)
990 			write_color_1(fsd, mem, x, smpte_top[x * 7 / width]);
991 		mem += stride;
992 	}
993 
994 	for (; y < height * 7 / 9; ++y) {
995 		for (x = 0; x < width; ++x)
996 			write_color_1(fsd, mem, x, smpte_middle[x * 7 / width]);
997 		mem += stride;
998 	}
999 
1000 	for (; y < height; ++y) {
1001 		for (x = 0; x < width * 5 / 7; ++x)
1002 			write_color_1(fsd, mem, x,
1003 				      smpte_bottom[x * 4 / (width * 5 / 7)]);
1004 		for (; x < width * 6 / 7; ++x)
1005 			write_color_1(fsd, mem, x,
1006 				      smpte_bottom[(x - width * 5 / 7) * 3 /
1007 						   (width / 7) + 4]);
1008 		for (; x < width; ++x)
1009 			write_color_1(fsd, mem, x, smpte_bottom[7]);
1010 		mem += stride;
1011 	}
1012 
1013 	free(fsd);
1014 }
1015 
write_pixel_2(uint8_t * mem,unsigned int x,unsigned int pixel)1016 static void write_pixel_2(uint8_t *mem, unsigned int x, unsigned int pixel)
1017 {
1018 	unsigned int shift = 6 - 2 * (x & 3);
1019 	unsigned int mask = 3U << shift;
1020 
1021 	mem[x / 4] = (mem[x / 4] & ~mask) | ((pixel << shift) & mask);
1022 }
1023 
write_color_2(struct fsd * fsd,uint8_t * mem,unsigned int stride,unsigned int x,unsigned int index)1024 static void write_color_2(struct fsd *fsd, uint8_t *mem, unsigned int stride,
1025 			  unsigned int x, unsigned int index)
1026 {
1027 	struct drm_color_lut color = smpte_color_lut[index];
1028 	unsigned int r, g, b;
1029 
1030 	fsd_dither(fsd, &color);
1031 
1032 	if (color.red >= 32768) {
1033 		r = 1;
1034 		color.red = 65535;
1035 	} else {
1036 		r = 0;
1037 		color.red = 0;
1038 	}
1039 	if (color.green >= 32768) {
1040 		g = 2;
1041 		color.green = 65535;
1042 	} else {
1043 		g = 0;
1044 		color.green = 0;
1045 	}
1046 	if (color.blue >= 32768) {
1047 		b = 3;
1048 		color.blue = 65535;
1049 	} else {
1050 		b = 0;
1051 		color.blue = 0;
1052 	}
1053 
1054 	fsd_update(fsd, &color);
1055 
1056 	/* Use PenTile RG-GB */
1057 	write_pixel_2(mem, 2 * x, r);
1058 	write_pixel_2(mem, 2 * x + 1, g);
1059 	write_pixel_2(mem + stride, 2 * x, g);
1060 	write_pixel_2(mem + stride, 2 * x + 1, b);
1061 }
1062 
fill_smpte_c2(void * mem,unsigned int width,unsigned int height,unsigned int stride)1063 static void fill_smpte_c2(void *mem, unsigned int width, unsigned int height,
1064 			  unsigned int stride)
1065 {
1066 	struct fsd *fsd = fsd_alloc(width);
1067 	unsigned int x;
1068 	unsigned int y;
1069 
1070 	/* Half resolution for PenTile RG-GB */
1071 	width /= 2;
1072 	height /= 2;
1073 
1074 	for (y = 0; y < height * 6 / 9; ++y) {
1075 		for (x = 0; x < width; ++x)
1076 			write_color_2(fsd, mem, stride, x, smpte_top[x * 7 / width]);
1077 		mem += 2 * stride;
1078 	}
1079 
1080 	for (; y < height * 7 / 9; ++y) {
1081 		for (x = 0; x < width; ++x)
1082 			write_color_2(fsd, mem, stride, x, smpte_middle[x * 7 / width]);
1083 		mem += 2 * stride;
1084 	}
1085 
1086 	for (; y < height; ++y) {
1087 		for (x = 0; x < width * 5 / 7; ++x)
1088 			write_color_2(fsd, mem, stride, x,
1089 				      smpte_bottom[x * 4 / (width * 5 / 7)]);
1090 		for (; x < width * 6 / 7; ++x)
1091 			write_color_2(fsd, mem, stride, x,
1092 				      smpte_bottom[(x - width * 5 / 7) * 3 /
1093 						   (width / 7) + 4]);
1094 		for (; x < width; ++x)
1095 			write_color_2(fsd, mem, stride, x, smpte_bottom[7]);
1096 		mem += 2 * stride;
1097 	}
1098 
1099 	free(fsd);
1100 }
1101 
write_pixel_4(uint8_t * mem,unsigned int x,unsigned int pixel)1102 static void write_pixel_4(uint8_t *mem, unsigned int x, unsigned int pixel)
1103 {
1104 	if (x & 1)
1105 		mem[x / 2] = (mem[x / 2] & 0xf0) | (pixel & 0x0f);
1106 	else
1107 		mem[x / 2] = (mem[x / 2] & 0x0f) | (pixel << 4);
1108 }
1109 
fill_smpte_c4(void * mem,unsigned int width,unsigned int height,unsigned int stride)1110 static void fill_smpte_c4(void *mem, unsigned int width, unsigned int height,
1111 			  unsigned int stride)
1112 {
1113 	unsigned int x;
1114 	unsigned int y;
1115 
1116 	for (y = 0; y < height * 6 / 9; ++y) {
1117 		for (x = 0; x < width; ++x)
1118 			write_pixel_4(mem, x, smpte_top[x * 7 / width]);
1119 		mem += stride;
1120 	}
1121 
1122 	for (; y < height * 7 / 9; ++y) {
1123 		for (x = 0; x < width; ++x)
1124 			write_pixel_4(mem, x, smpte_middle[x * 7 / width]);
1125 		mem += stride;
1126 	}
1127 
1128 	for (; y < height; ++y) {
1129 		for (x = 0; x < width * 5 / 7; ++x)
1130 			write_pixel_4(mem, x,
1131 				      smpte_bottom[x * 4 / (width * 5 / 7)]);
1132 		for (; x < width * 6 / 7; ++x)
1133 			write_pixel_4(mem, x,
1134 				      smpte_bottom[(x - width * 5 / 7) * 3 /
1135 						   (width / 7) + 4]);
1136 		for (; x < width; ++x)
1137 			write_pixel_4(mem, x, smpte_bottom[7]);
1138 		mem += stride;
1139 	}
1140 }
1141 
fill_smpte_c8(void * mem,unsigned int width,unsigned int height,unsigned int stride)1142 static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height,
1143 			  unsigned int stride)
1144 {
1145 	unsigned int x;
1146 	unsigned int y;
1147 
1148 	for (y = 0; y < height * 6 / 9; ++y) {
1149 		for (x = 0; x < width; ++x)
1150 			((uint8_t *)mem)[x] = smpte_top[x * 7 / width];
1151 		mem += stride;
1152 	}
1153 
1154 	for (; y < height * 7 / 9; ++y) {
1155 		for (x = 0; x < width; ++x)
1156 			((uint8_t *)mem)[x] = smpte_middle[x * 7 / width];
1157 		mem += stride;
1158 	}
1159 
1160 	for (; y < height; ++y) {
1161 		for (x = 0; x < width * 5 / 7; ++x)
1162 			((uint8_t *)mem)[x] =
1163 				smpte_bottom[x * 4 / (width * 5 / 7)];
1164 		for (; x < width * 6 / 7; ++x)
1165 			((uint8_t *)mem)[x] =
1166 				smpte_bottom[(x - width * 5 / 7) * 3
1167 					     / (width / 7) + 4];
1168 		for (; x < width; ++x)
1169 			((uint8_t *)mem)[x] = smpte_bottom[7];
1170 		mem += stride;
1171 	}
1172 }
1173 
util_smpte_fill_lut(unsigned int ncolors,struct drm_color_lut * lut)1174 void util_smpte_fill_lut(unsigned int ncolors, struct drm_color_lut *lut)
1175 {
1176 	if (ncolors < ARRAY_SIZE(bw_color_lut)) {
1177 		printf("Error: lut too small: %u < %zu\n", ncolors,
1178 		       ARRAY_SIZE(bw_color_lut));
1179 		return;
1180 	}
1181 	memset(lut, 0, ncolors * sizeof(struct drm_color_lut));
1182 
1183 	if (ncolors < ARRAY_SIZE(pentile_color_lut))
1184 		memcpy(lut, bw_color_lut, sizeof(bw_color_lut));
1185 	else if (ncolors < ARRAY_SIZE(smpte_color_lut))
1186 		memcpy(lut, pentile_color_lut, sizeof(pentile_color_lut));
1187 	else
1188 		memcpy(lut, smpte_color_lut, sizeof(smpte_color_lut));
1189 }
1190 
fill_smpte(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1191 static void fill_smpte(const struct util_format_info *info, void *planes[3],
1192 		       unsigned int width, unsigned int height,
1193 		       unsigned int stride)
1194 {
1195 	unsigned char *u, *v;
1196 
1197 	switch (info->format) {
1198 	case DRM_FORMAT_C1:
1199 		return fill_smpte_c1(planes[0], width, height, stride);
1200 	case DRM_FORMAT_C2:
1201 		return fill_smpte_c2(planes[0], width, height, stride);
1202 	case DRM_FORMAT_C4:
1203 		return fill_smpte_c4(planes[0], width, height, stride);
1204 	case DRM_FORMAT_C8:
1205 		return fill_smpte_c8(planes[0], width, height, stride);
1206 	case DRM_FORMAT_UYVY:
1207 	case DRM_FORMAT_VYUY:
1208 	case DRM_FORMAT_YUYV:
1209 	case DRM_FORMAT_YVYU:
1210 		return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
1211 					     height, stride);
1212 
1213 	case DRM_FORMAT_NV12:
1214 	case DRM_FORMAT_NV21:
1215 	case DRM_FORMAT_NV16:
1216 	case DRM_FORMAT_NV61:
1217 	case DRM_FORMAT_NV24:
1218 	case DRM_FORMAT_NV42:
1219 		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
1220 		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
1221 		return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
1222 					     width, height, stride);
1223 
1224 	case DRM_FORMAT_NV15:
1225 	case DRM_FORMAT_NV20:
1226 	case DRM_FORMAT_NV30:
1227 		return fill_smpte_yuv_planar_10bpp(&info->yuv, planes[0],
1228 						   planes[1], width, height,
1229 						   stride);
1230 
1231 	case DRM_FORMAT_YUV420:
1232 	case DRM_FORMAT_YUV422:
1233 	case DRM_FORMAT_YUV444:
1234 		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
1235 					     planes[2], width, height, stride);
1236 
1237 	case DRM_FORMAT_YVU420:
1238 	case DRM_FORMAT_YVU422:
1239 	case DRM_FORMAT_YVU444:
1240 		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
1241 					     planes[1], width, height, stride);
1242 
1243 	case DRM_FORMAT_ARGB4444:
1244 	case DRM_FORMAT_XRGB4444:
1245 	case DRM_FORMAT_ABGR4444:
1246 	case DRM_FORMAT_XBGR4444:
1247 	case DRM_FORMAT_RGBA4444:
1248 	case DRM_FORMAT_RGBX4444:
1249 	case DRM_FORMAT_BGRA4444:
1250 	case DRM_FORMAT_BGRX4444:
1251 	case DRM_FORMAT_RGB565:
1252 	case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
1253 	case DRM_FORMAT_BGR565:
1254 	case DRM_FORMAT_ARGB1555:
1255 	case DRM_FORMAT_XRGB1555:
1256 	case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
1257 	case DRM_FORMAT_ABGR1555:
1258 	case DRM_FORMAT_XBGR1555:
1259 	case DRM_FORMAT_RGBA5551:
1260 	case DRM_FORMAT_RGBX5551:
1261 	case DRM_FORMAT_BGRA5551:
1262 	case DRM_FORMAT_BGRX5551:
1263 		return fill_smpte_rgb16(&info->rgb, planes[0],
1264 					width, height, stride,
1265 					info->format & DRM_FORMAT_BIG_ENDIAN);
1266 
1267 	case DRM_FORMAT_BGR888:
1268 	case DRM_FORMAT_RGB888:
1269 		return fill_smpte_rgb24(&info->rgb, planes[0],
1270 					width, height, stride);
1271 	case DRM_FORMAT_ARGB8888:
1272 	case DRM_FORMAT_XRGB8888:
1273 	case DRM_FORMAT_ABGR8888:
1274 	case DRM_FORMAT_XBGR8888:
1275 	case DRM_FORMAT_RGBA8888:
1276 	case DRM_FORMAT_RGBX8888:
1277 	case DRM_FORMAT_BGRA8888:
1278 	case DRM_FORMAT_BGRX8888:
1279 	case DRM_FORMAT_ARGB2101010:
1280 	case DRM_FORMAT_XRGB2101010:
1281 	case DRM_FORMAT_ABGR2101010:
1282 	case DRM_FORMAT_XBGR2101010:
1283 	case DRM_FORMAT_RGBA1010102:
1284 	case DRM_FORMAT_RGBX1010102:
1285 	case DRM_FORMAT_BGRA1010102:
1286 	case DRM_FORMAT_BGRX1010102:
1287 		return fill_smpte_rgb32(&info->rgb, planes[0],
1288 					width, height, stride);
1289 
1290 	case DRM_FORMAT_XRGB16161616F:
1291 	case DRM_FORMAT_XBGR16161616F:
1292 	case DRM_FORMAT_ARGB16161616F:
1293 	case DRM_FORMAT_ABGR16161616F:
1294 		return fill_smpte_rgb16fp(&info->rgb, planes[0],
1295 					  width, height, stride);
1296 	}
1297 }
1298 
1299 #if HAVE_CAIRO
byteswap_buffer16(void * mem,unsigned int width,unsigned int height,unsigned int stride)1300 static void byteswap_buffer16(void *mem, unsigned int width, unsigned int height,
1301 			      unsigned int stride)
1302 {
1303 	unsigned int x, y;
1304 
1305 	for (y = 0; y < height; ++y) {
1306 		for (x = 0; x < width; ++x)
1307 			((uint16_t *)mem)[x] = swap16(((uint16_t *)mem)[x]);
1308 		mem += stride;
1309 	}
1310 }
1311 
byteswap_buffer32(void * mem,unsigned int width,unsigned int height,unsigned int stride)1312 static void byteswap_buffer32(void *mem, unsigned int width, unsigned int height,
1313 			      unsigned int stride)
1314 {
1315 	unsigned int x, y;
1316 
1317 	for (y = 0; y < height; ++y) {
1318 		for (x = 0; x < width; ++x)
1319 			((uint32_t *)mem)[x] = swap32(((uint32_t *)mem)[x]);
1320 		mem += stride;
1321 	}
1322 }
1323 #endif
1324 
make_pwetty(void * data,unsigned int width,unsigned int height,unsigned int stride,uint32_t format)1325 static void make_pwetty(void *data, unsigned int width, unsigned int height,
1326 			unsigned int stride, uint32_t format)
1327 {
1328 #if HAVE_CAIRO
1329 	cairo_surface_t *surface;
1330 	cairo_t *cr;
1331 	cairo_format_t cairo_format;
1332 	bool swap16 = false;
1333 	bool swap32 = false;
1334 
1335 	/* we can ignore the order of R,G,B channels */
1336 	switch (format) {
1337 	case DRM_FORMAT_XRGB8888:
1338 	case DRM_FORMAT_ARGB8888:
1339 	case DRM_FORMAT_XBGR8888:
1340 	case DRM_FORMAT_ABGR8888:
1341 		cairo_format = CAIRO_FORMAT_ARGB32;
1342 		break;
1343 	case DRM_FORMAT_RGB565:
1344 	case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
1345 	case DRM_FORMAT_BGR565:
1346 		cairo_format = CAIRO_FORMAT_RGB16_565;
1347 		swap16 = fb_foreign_endian(format);
1348 		break;
1349 #if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 12)
1350 	case DRM_FORMAT_ARGB2101010:
1351 	case DRM_FORMAT_XRGB2101010:
1352 	case DRM_FORMAT_ABGR2101010:
1353 	case DRM_FORMAT_XBGR2101010:
1354 		cairo_format = CAIRO_FORMAT_RGB30;
1355 		swap32 = fb_foreign_endian(format);
1356 		break;
1357 #endif
1358 	default:
1359 		return;
1360 	}
1361 
1362 	/* Cairo uses native byte order, so we may have to byteswap before... */
1363 	if (swap16)
1364 		byteswap_buffer16(data, width, height, stride);
1365 	if (swap32)
1366 		byteswap_buffer32(data, width, height, stride);
1367 
1368 	surface = cairo_image_surface_create_for_data(data,
1369 						      cairo_format,
1370 						      width, height,
1371 						      stride);
1372 	cr = cairo_create(surface);
1373 	cairo_surface_destroy(surface);
1374 
1375 	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
1376 	for (unsigned x = 0; x < width; x += 250)
1377 		for (unsigned y = 0; y < height; y += 250) {
1378 			char buf[64];
1379 
1380 			cairo_move_to(cr, x, y - 20);
1381 			cairo_line_to(cr, x, y + 20);
1382 			cairo_move_to(cr, x - 20, y);
1383 			cairo_line_to(cr, x + 20, y);
1384 			cairo_new_sub_path(cr);
1385 			cairo_arc(cr, x, y, 10, 0, M_PI * 2);
1386 			cairo_set_line_width(cr, 4);
1387 			cairo_set_source_rgb(cr, 0, 0, 0);
1388 			cairo_stroke_preserve(cr);
1389 			cairo_set_source_rgb(cr, 1, 1, 1);
1390 			cairo_set_line_width(cr, 2);
1391 			cairo_stroke(cr);
1392 
1393 			snprintf(buf, sizeof buf, "%d, %d", x, y);
1394 			cairo_move_to(cr, x + 20, y + 20);
1395 			cairo_text_path(cr, buf);
1396 			cairo_set_source_rgb(cr, 0, 0, 0);
1397 			cairo_stroke_preserve(cr);
1398 			cairo_set_source_rgb(cr, 1, 1, 1);
1399 			cairo_fill(cr);
1400 		}
1401 
1402 	cairo_destroy(cr);
1403 
1404 	/* ... and after */
1405 	if (swap16)
1406 		byteswap_buffer16(data, width, height, stride);
1407 	if (swap32)
1408 		byteswap_buffer32(data, width, height, stride);
1409 #endif
1410 }
1411 
make_tiles_yuv_color(unsigned int x,unsigned int y,unsigned int width)1412 static struct color_yuv make_tiles_yuv_color(unsigned int x, unsigned int y,
1413 					     unsigned int width)
1414 {
1415 	div_t d = div(x+y, width);
1416 	uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1417 		       + 0x000a1120 * (d.rem >> 6);
1418 	struct color_yuv color =
1419 		MAKE_YUV_601((rgb32 >> 16) & 0xff, (rgb32 >> 8) & 0xff,
1420 			     rgb32 & 0xff);
1421 	return color;
1422 }
1423 
fill_tiles_yuv_planar(const struct util_format_info * info,unsigned char * y_mem,unsigned char * u_mem,unsigned char * v_mem,unsigned int width,unsigned int height,unsigned int stride)1424 static void fill_tiles_yuv_planar(const struct util_format_info *info,
1425 				  unsigned char *y_mem, unsigned char *u_mem,
1426 				  unsigned char *v_mem, unsigned int width,
1427 				  unsigned int height, unsigned int stride)
1428 {
1429 	const struct util_yuv_info *yuv = &info->yuv;
1430 	unsigned int cs = yuv->chroma_stride;
1431 	unsigned int xsub = yuv->xsub;
1432 	unsigned int ysub = yuv->ysub;
1433 	unsigned int x;
1434 	unsigned int y;
1435 
1436 	for (y = 0; y < height; ++y) {
1437 		for (x = 0; x < width; ++x) {
1438 			struct color_yuv color =
1439 				make_tiles_yuv_color(x, y, width);
1440 
1441 			y_mem[x] = color.y;
1442 			u_mem[x/xsub*cs] = color.u;
1443 			v_mem[x/xsub*cs] = color.v;
1444 		}
1445 
1446 		y_mem += stride;
1447 		if ((y + 1) % ysub == 0) {
1448 			u_mem += stride * cs / xsub;
1449 			v_mem += stride * cs / xsub;
1450 		}
1451 	}
1452 }
1453 
fill_tiles_yuv_planar_10bpp(const struct util_format_info * info,unsigned char * y_mem,unsigned char * uv_mem,unsigned int width,unsigned int height,unsigned int stride)1454 static void fill_tiles_yuv_planar_10bpp(const struct util_format_info *info,
1455 					unsigned char *y_mem,
1456 					unsigned char *uv_mem,
1457 					unsigned int width,
1458 					unsigned int height,
1459 					unsigned int stride)
1460 {
1461 	const struct util_yuv_info *yuv = &info->yuv;
1462 	unsigned int cs = yuv->chroma_stride;
1463 	unsigned int xsub = yuv->xsub;
1464 	unsigned int ysub = yuv->ysub;
1465 	unsigned int xstep = cs * xsub;
1466 	unsigned int x;
1467 	unsigned int y;
1468 
1469 	for (y = 0; y < height; ++y) {
1470 		for (x = 0; x < width; x += 4) {
1471 			struct color_yuv a = make_tiles_yuv_color(x+0, y, width);
1472 			struct color_yuv b = make_tiles_yuv_color(x+1, y, width);
1473 			struct color_yuv c = make_tiles_yuv_color(x+2, y, width);
1474 			struct color_yuv d = make_tiles_yuv_color(x+3, y, width);
1475 
1476 			write_pixels_10bpp(&y_mem[(x * 5) / 4],
1477 				a.y << 2, b.y << 2, c.y << 2, d.y << 2);
1478 		}
1479 		y_mem += stride;
1480 	}
1481 	for (y = 0; y < height; y += ysub) {
1482 		for (x = 0; x < width; x += xstep) {
1483 			struct color_yuv a = make_tiles_yuv_color(x+0, y, width);
1484 			struct color_yuv b = make_tiles_yuv_color(x+xsub, y, width);
1485 
1486 			write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
1487 				a.u << 2, a.v << 2, b.u << 2, b.v << 2);
1488 		}
1489 		uv_mem += stride * cs / xsub;
1490 	}
1491 }
1492 
fill_tiles_yuv_packed(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1493 static void fill_tiles_yuv_packed(const struct util_format_info *info,
1494 				  void *mem, unsigned int width,
1495 				  unsigned int height, unsigned int stride)
1496 {
1497 	const struct util_yuv_info *yuv = &info->yuv;
1498 	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
1499 	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
1500 	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
1501 	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
1502 	unsigned int x;
1503 	unsigned int y;
1504 
1505 	for (y = 0; y < height; ++y) {
1506 		for (x = 0; x < width; x += 2) {
1507 			struct color_yuv color =
1508 				make_tiles_yuv_color(x, y, width);
1509 
1510 			y_mem[2*x] = color.y;
1511 			c_mem[2*x+u] = color.u;
1512 			y_mem[2*x+2] = color.y;
1513 			c_mem[2*x+v] = color.v;
1514 		}
1515 
1516 		y_mem += stride;
1517 		c_mem += stride;
1518 	}
1519 }
1520 
fill_tiles_rgb16(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride,bool fb_be)1521 static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
1522 			     unsigned int width, unsigned int height,
1523 			     unsigned int stride, bool fb_be)
1524 {
1525 	const struct util_rgb_info *rgb = &info->rgb;
1526 	void *mem_base = mem;
1527 	unsigned int x, y;
1528 
1529 	for (y = 0; y < height; ++y) {
1530 		for (x = 0; x < width; ++x) {
1531 			div_t d = div(x+y, width);
1532 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1533 				       + 0x000a1120 * (d.rem >> 6);
1534 			uint16_t color =
1535 				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
1536 					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1537 					  255);
1538 
1539 			((uint16_t *)mem)[x] = cpu_to_fb16(color);
1540 		}
1541 		mem += stride;
1542 	}
1543 
1544 	make_pwetty(mem_base, width, height, stride, info->format);
1545 }
1546 
fill_tiles_rgb24(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1547 static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
1548 			     unsigned int width, unsigned int height,
1549 			     unsigned int stride)
1550 {
1551 	const struct util_rgb_info *rgb = &info->rgb;
1552 	unsigned int x, y;
1553 
1554 	for (y = 0; y < height; ++y) {
1555 		for (x = 0; x < width; ++x) {
1556 			div_t d = div(x+y, width);
1557 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1558 				       + 0x000a1120 * (d.rem >> 6);
1559 			struct color_rgb24 color =
1560 				MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
1561 					   (rgb32 >> 8) & 0xff, rgb32 & 0xff);
1562 
1563 			((struct color_rgb24 *)mem)[x] = color;
1564 		}
1565 		mem += stride;
1566 	}
1567 }
1568 
fill_tiles_rgb32(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1569 static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
1570 			     unsigned int width, unsigned int height,
1571 			     unsigned int stride)
1572 {
1573 	const struct util_rgb_info *rgb = &info->rgb;
1574 	void *mem_base = mem;
1575 	unsigned int x, y;
1576 
1577 	for (y = 0; y < height; ++y) {
1578 		for (x = 0; x < width; ++x) {
1579 			div_t d = div(x+y, width);
1580 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1581 				       + 0x000a1120 * (d.rem >> 6);
1582 			uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
1583 			uint32_t color =
1584 				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
1585 					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1586 					  alpha);
1587 
1588 			((uint32_t *)mem)[x] = cpu_to_le32(color);
1589 		}
1590 		mem += stride;
1591 	}
1592 
1593 	make_pwetty(mem_base, width, height, stride, info->format);
1594 }
1595 
fill_tiles_rgb16fp(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1596 static void fill_tiles_rgb16fp(const struct util_format_info *info, void *mem,
1597 			       unsigned int width, unsigned int height,
1598 			       unsigned int stride)
1599 {
1600 	const struct util_rgb_info *rgb = &info->rgb;
1601 	unsigned int x, y;
1602 
1603 	/* TODO: Give this actual fp16 precision */
1604 	for (y = 0; y < height; ++y) {
1605 		for (x = 0; x < width; ++x) {
1606 			div_t d = div(x+y, width);
1607 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1608 				       + 0x000a1120 * (d.rem >> 6);
1609 			uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
1610 			uint64_t color =
1611 				MAKE_RGBA8FP16(rgb, (rgb32 >> 16) & 0xff,
1612 					       (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1613 					       alpha);
1614 
1615 			((uint64_t *)mem)[x] = color;
1616 		}
1617 		mem += stride;
1618 	}
1619 }
1620 
fill_tiles(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1621 static void fill_tiles(const struct util_format_info *info, void *planes[3],
1622 		       unsigned int width, unsigned int height,
1623 		       unsigned int stride)
1624 {
1625 	unsigned char *u, *v;
1626 
1627 	switch (info->format) {
1628 	case DRM_FORMAT_UYVY:
1629 	case DRM_FORMAT_VYUY:
1630 	case DRM_FORMAT_YUYV:
1631 	case DRM_FORMAT_YVYU:
1632 		return fill_tiles_yuv_packed(info, planes[0],
1633 					     width, height, stride);
1634 
1635 	case DRM_FORMAT_NV12:
1636 	case DRM_FORMAT_NV21:
1637 	case DRM_FORMAT_NV16:
1638 	case DRM_FORMAT_NV61:
1639 	case DRM_FORMAT_NV24:
1640 	case DRM_FORMAT_NV42:
1641 		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
1642 		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
1643 		return fill_tiles_yuv_planar(info, planes[0], u, v,
1644 					     width, height, stride);
1645 
1646 	case DRM_FORMAT_NV15:
1647 	case DRM_FORMAT_NV20:
1648 	case DRM_FORMAT_NV30:
1649 		return fill_tiles_yuv_planar_10bpp(info, planes[0], planes[1],
1650 						   width, height, stride);
1651 
1652 	case DRM_FORMAT_YUV420:
1653 	case DRM_FORMAT_YUV422:
1654 	case DRM_FORMAT_YUV444:
1655 		return fill_tiles_yuv_planar(info, planes[0], planes[1],
1656 					     planes[2], width, height, stride);
1657 
1658 	case DRM_FORMAT_YVU420:
1659 	case DRM_FORMAT_YVU422:
1660 	case DRM_FORMAT_YVU444:
1661 		return fill_tiles_yuv_planar(info, planes[0], planes[2],
1662 					     planes[1], width, height, stride);
1663 
1664 	case DRM_FORMAT_ARGB4444:
1665 	case DRM_FORMAT_XRGB4444:
1666 	case DRM_FORMAT_ABGR4444:
1667 	case DRM_FORMAT_XBGR4444:
1668 	case DRM_FORMAT_RGBA4444:
1669 	case DRM_FORMAT_RGBX4444:
1670 	case DRM_FORMAT_BGRA4444:
1671 	case DRM_FORMAT_BGRX4444:
1672 	case DRM_FORMAT_RGB565:
1673 	case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
1674 	case DRM_FORMAT_BGR565:
1675 	case DRM_FORMAT_ARGB1555:
1676 	case DRM_FORMAT_XRGB1555:
1677 	case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
1678 	case DRM_FORMAT_ABGR1555:
1679 	case DRM_FORMAT_XBGR1555:
1680 	case DRM_FORMAT_RGBA5551:
1681 	case DRM_FORMAT_RGBX5551:
1682 	case DRM_FORMAT_BGRA5551:
1683 	case DRM_FORMAT_BGRX5551:
1684 		return fill_tiles_rgb16(info, planes[0],
1685 					width, height, stride,
1686 					info->format & DRM_FORMAT_BIG_ENDIAN);
1687 
1688 	case DRM_FORMAT_BGR888:
1689 	case DRM_FORMAT_RGB888:
1690 		return fill_tiles_rgb24(info, planes[0],
1691 					width, height, stride);
1692 	case DRM_FORMAT_ARGB8888:
1693 	case DRM_FORMAT_XRGB8888:
1694 	case DRM_FORMAT_ABGR8888:
1695 	case DRM_FORMAT_XBGR8888:
1696 	case DRM_FORMAT_RGBA8888:
1697 	case DRM_FORMAT_RGBX8888:
1698 	case DRM_FORMAT_BGRA8888:
1699 	case DRM_FORMAT_BGRX8888:
1700 	case DRM_FORMAT_ARGB2101010:
1701 	case DRM_FORMAT_XRGB2101010:
1702 	case DRM_FORMAT_ABGR2101010:
1703 	case DRM_FORMAT_XBGR2101010:
1704 	case DRM_FORMAT_RGBA1010102:
1705 	case DRM_FORMAT_RGBX1010102:
1706 	case DRM_FORMAT_BGRA1010102:
1707 	case DRM_FORMAT_BGRX1010102:
1708 		return fill_tiles_rgb32(info, planes[0],
1709 					width, height, stride);
1710 
1711 	case DRM_FORMAT_XRGB16161616F:
1712 	case DRM_FORMAT_XBGR16161616F:
1713 	case DRM_FORMAT_ARGB16161616F:
1714 	case DRM_FORMAT_ABGR16161616F:
1715 		return fill_tiles_rgb16fp(info, planes[0],
1716 					  width, height, stride);
1717 	}
1718 }
1719 
fill_plain(const struct util_format_info * info,void * planes[3],unsigned int height,unsigned int stride)1720 static void fill_plain(const struct util_format_info *info, void *planes[3],
1721 		       unsigned int height,
1722 		       unsigned int stride)
1723 {
1724 	switch (info->format) {
1725 	case DRM_FORMAT_XRGB16161616F:
1726 	case DRM_FORMAT_XBGR16161616F:
1727 	case DRM_FORMAT_ARGB16161616F:
1728 	case DRM_FORMAT_ABGR16161616F:
1729 		/* 0x3838 = 0.5273 */
1730 		memset(planes[0], 0x38, stride * height);
1731 		break;
1732 	default:
1733 		memset(planes[0], 0x77, stride * height);
1734 		break;
1735 	}
1736 }
1737 
fill_gradient_rgb32(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)1738 static void fill_gradient_rgb32(const struct util_rgb_info *rgb,
1739 				void *mem,
1740 				unsigned int width, unsigned int height,
1741 				unsigned int stride)
1742 {
1743 	unsigned int i, j;
1744 
1745 	for (i = 0; i < height / 2; i++) {
1746 		uint32_t *row = mem;
1747 
1748 		for (j = 0; j < width / 2; j++) {
1749 			uint32_t value = MAKE_RGBA10(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1750 			row[2*j] = row[2*j+1] = cpu_to_le32(value);
1751 		}
1752 		mem += stride;
1753 	}
1754 
1755 	for (; i < height; i++) {
1756 		uint32_t *row = mem;
1757 
1758 		for (j = 0; j < width / 2; j++) {
1759 			uint32_t value = MAKE_RGBA10(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1760 			row[2*j] = row[2*j+1] = cpu_to_le32(value);
1761 		}
1762 		mem += stride;
1763 	}
1764 }
1765 
fill_gradient_rgb16fp(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)1766 static void fill_gradient_rgb16fp(const struct util_rgb_info *rgb,
1767 				  void *mem,
1768 				  unsigned int width, unsigned int height,
1769 				  unsigned int stride)
1770 {
1771 	unsigned int i, j;
1772 
1773 	for (i = 0; i < height / 2; i++) {
1774 		uint64_t *row = mem;
1775 
1776 		for (j = 0; j < width / 2; j++) {
1777 			uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1778 			row[2*j] = row[2*j+1] = value;
1779 		}
1780 		mem += stride;
1781 	}
1782 
1783 	for (; i < height; i++) {
1784 		uint64_t *row = mem;
1785 
1786 		for (j = 0; j < width / 2; j++) {
1787 			uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1788 			row[2*j] = row[2*j+1] = value;
1789 		}
1790 		mem += stride;
1791 	}
1792 }
1793 
1794 /* The gradient pattern creates two horizontal gray gradients, split
1795  * into two halves. The top half has 10bpc precision, the bottom half
1796  * has 8bpc precision. When using with a 10bpc fb format, there are 3
1797  * possible outcomes:
1798  *
1799  *  - Pixel data is encoded as 8bpc to the display, no dithering. This
1800  *    would lead to the top and bottom halves looking identical.
1801  *
1802  *  - Pixel data is encoded as 8bpc to the display, with dithering. This
1803  *    would lead to there being a visible difference between the two halves,
1804  *    but the top half would look a little speck-y due to the dithering.
1805  *
1806  *  - Pixel data is encoded at 10bpc+ to the display (which implies
1807  *    the display is able to show this level of depth). This should
1808  *    lead to the top half being a very clean gradient, and visibly different
1809  *    from the bottom half.
1810  *
1811  * Once we support additional fb formats, this approach could be extended
1812  * to distinguish even higher bpc precisions.
1813  *
1814  * Note that due to practical size considerations, for the screens
1815  * where this matters, the pattern actually emits stripes 2-pixels
1816  * wide for each gradient color. Otherwise the difference may be a bit
1817  * hard to notice.
1818  */
fill_gradient(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1819 static void fill_gradient(const struct util_format_info *info, void *planes[3],
1820 			  unsigned int width, unsigned int height,
1821 			  unsigned int stride)
1822 {
1823 	switch (info->format) {
1824 	case DRM_FORMAT_ARGB8888:
1825 	case DRM_FORMAT_XRGB8888:
1826 	case DRM_FORMAT_ABGR8888:
1827 	case DRM_FORMAT_XBGR8888:
1828 	case DRM_FORMAT_RGBA8888:
1829 	case DRM_FORMAT_RGBX8888:
1830 	case DRM_FORMAT_BGRA8888:
1831 	case DRM_FORMAT_BGRX8888:
1832 	case DRM_FORMAT_ARGB2101010:
1833 	case DRM_FORMAT_XRGB2101010:
1834 	case DRM_FORMAT_ABGR2101010:
1835 	case DRM_FORMAT_XBGR2101010:
1836 	case DRM_FORMAT_RGBA1010102:
1837 	case DRM_FORMAT_RGBX1010102:
1838 	case DRM_FORMAT_BGRA1010102:
1839 	case DRM_FORMAT_BGRX1010102:
1840 		return fill_gradient_rgb32(&info->rgb, planes[0],
1841 					   width, height, stride);
1842 
1843 	case DRM_FORMAT_XRGB16161616F:
1844 	case DRM_FORMAT_XBGR16161616F:
1845 	case DRM_FORMAT_ARGB16161616F:
1846 	case DRM_FORMAT_ABGR16161616F:
1847 		return fill_gradient_rgb16fp(&info->rgb, planes[0],
1848 					     width, height, stride);
1849 	}
1850 }
1851 
1852 /*
1853  * util_fill_pattern - Fill a buffer with a test pattern
1854  * @format: Pixel format
1855  * @pattern: Test pattern
1856  * @planes: Array of buffers
1857  * @width: Width in pixels
1858  * @height: Height in pixels
1859  * @stride: Line stride (pitch) in bytes
1860  *
1861  * Fill the buffers with the test pattern specified by the pattern parameter.
1862  * Supported formats vary depending on the selected pattern.
1863  */
util_fill_pattern(uint32_t format,enum util_fill_pattern pattern,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1864 void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
1865 		       void *planes[3], unsigned int width,
1866 		       unsigned int height, unsigned int stride)
1867 {
1868 	const struct util_format_info *info;
1869 
1870 	info = util_format_info_find(format);
1871 	if (info == NULL)
1872 		return;
1873 
1874 	switch (pattern) {
1875 	case UTIL_PATTERN_TILES:
1876 		return fill_tiles(info, planes, width, height, stride);
1877 
1878 	case UTIL_PATTERN_SMPTE:
1879 		return fill_smpte(info, planes, width, height, stride);
1880 
1881 	case UTIL_PATTERN_PLAIN:
1882 		return fill_plain(info, planes, height, stride);
1883 
1884 	case UTIL_PATTERN_GRADIENT:
1885 		return fill_gradient(info, planes, width, height, stride);
1886 
1887 	default:
1888 		printf("Error: unsupported test pattern %u.\n", pattern);
1889 		break;
1890 	}
1891 }
1892 
1893 static const char *pattern_names[] = {
1894 	[UTIL_PATTERN_TILES] = "tiles",
1895 	[UTIL_PATTERN_SMPTE] = "smpte",
1896 	[UTIL_PATTERN_PLAIN] = "plain",
1897 	[UTIL_PATTERN_GRADIENT] = "gradient",
1898 };
1899 
util_pattern_enum(const char * name)1900 enum util_fill_pattern util_pattern_enum(const char *name)
1901 {
1902 	unsigned int i;
1903 
1904 	for (i = 0; i < ARRAY_SIZE(pattern_names); i++)
1905 		if (!strcmp(pattern_names[i], name))
1906 			return (enum util_fill_pattern)i;
1907 
1908 	printf("Error: unsupported test pattern %s.\n", name);
1909 	return UTIL_PATTERN_SMPTE;
1910 }
1911