pattern.c revision 41687f09
1/*
2 * Copyright 2008 Tungsten Graphics
3 *   Jakob Bornecrantz <jakob@tungstengraphics.com>
4 * Copyright 2008 Intel Corporation
5 *   Jesse Barnes <jesse.barnes@intel.com>
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 <stdint.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include <drm_fourcc.h>
32
33#if HAVE_CAIRO
34#include <cairo.h>
35#include <math.h>
36#endif
37
38#include "common.h"
39#include "format.h"
40#include "pattern.h"
41
42struct color_rgb24 {
43	unsigned int value:24;
44} __attribute__((__packed__));
45
46struct color_yuv {
47	unsigned char y;
48	unsigned char u;
49	unsigned char v;
50};
51
52#define MAKE_YUV_601_Y(r, g, b) \
53	((( 66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
54#define MAKE_YUV_601_U(r, g, b) \
55	(((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
56#define MAKE_YUV_601_V(r, g, b) \
57	(((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
58
59#define MAKE_YUV_601(r, g, b) \
60	{ .y = MAKE_YUV_601_Y(r, g, b), \
61	  .u = MAKE_YUV_601_U(r, g, b), \
62	  .v = MAKE_YUV_601_V(r, g, b) }
63
64/* This function takes 8-bit color values */
65static inline uint32_t shiftcolor8(const struct util_color_component *comp,
66				  uint32_t value)
67{
68	value &= 0xff;
69	/* Fill the low bits with the high bits. */
70	value = (value << 8) | value;
71	/* Shift down to remove unwanted low bits */
72	value = value >> (16 - comp->length);
73	/* Shift back up to where the value should be */
74	return value << comp->offset;
75}
76
77/* This function takes 10-bit color values */
78static inline uint32_t shiftcolor10(const struct util_color_component *comp,
79				    uint32_t value)
80{
81	value &= 0x3ff;
82	/* Fill the low bits with the high bits. */
83	value = (value << 6) | (value >> 4);
84	/* Shift down to remove unwanted low bits */
85	value = value >> (16 - comp->length);
86	/* Shift back up to where the value should be */
87	return value << comp->offset;
88}
89
90/* This function takes 16-bit color values */
91static inline uint64_t shiftcolor16(const struct util_color_component *comp,
92				    uint64_t value)
93{
94	value &= 0xffff;
95	/* Shift down to remove unwanted low bits */
96	value = value >> (16 - comp->length);
97	/* Shift back up to where the value should be */
98	return value << comp->offset;
99}
100
101#define MAKE_RGBA10(rgb, r, g, b, a) \
102	(shiftcolor10(&(rgb)->red, (r)) | \
103	 shiftcolor10(&(rgb)->green, (g)) | \
104	 shiftcolor10(&(rgb)->blue, (b)) | \
105	 shiftcolor10(&(rgb)->alpha, (a)))
106
107#define MAKE_RGBA(rgb, r, g, b, a) \
108	(shiftcolor8(&(rgb)->red, (r)) | \
109	 shiftcolor8(&(rgb)->green, (g)) | \
110	 shiftcolor8(&(rgb)->blue, (b)) | \
111	 shiftcolor8(&(rgb)->alpha, (a)))
112
113#define MAKE_RGB24(rgb, r, g, b) \
114	{ .value = MAKE_RGBA(rgb, r, g, b, 0) }
115
116
117/**
118  * Takes a uint16_t, divides by 65536, converts the infinite-precision
119  * result to fp16 with round-to-zero.
120  *
121  * Copied from mesa:src/util/half_float.c
122  */
123static uint16_t uint16_div_64k_to_half(uint16_t v)
124{
125	/* Zero or subnormal. Set the mantissa to (v << 8) and return. */
126	if (v < 4)
127		return v << 8;
128
129	/* Count the leading 0s in the uint16_t */
130	int n = __builtin_clz(v) - 16;
131
132	/* Shift the mantissa up so bit 16 is the hidden 1 bit,
133	 * mask it off, then shift back down to 10 bits
134	 */
135	int m = ( ((uint32_t)v << (n + 1)) & 0xffff ) >> 6;
136
137	/*  (0{n} 1 X{15-n}) * 2^-16
138	 * = 1.X * 2^(15-n-16)
139	 * = 1.X * 2^(14-n - 15)
140	 * which is the FP16 form with e = 14 - n
141	 */
142	int e = 14 - n;
143
144	return (e << 10) | m;
145}
146
147#define MAKE_RGBA8FP16(rgb, r, g, b, a) \
148	(shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 8)) | \
149	 shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 8)) | \
150	 shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 8)) | \
151	 shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 8)))
152
153#define MAKE_RGBA10FP16(rgb, r, g, b, a) \
154	(shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 6)) | \
155	 shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 6)) | \
156	 shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 6)) | \
157	 shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 6)))
158
159static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv,
160				  unsigned char *y_mem, unsigned char *u_mem,
161				  unsigned char *v_mem, unsigned int width,
162				  unsigned int height, unsigned int stride)
163{
164	const struct color_yuv colors_top[] = {
165		MAKE_YUV_601(191, 192, 192),	/* grey */
166		MAKE_YUV_601(192, 192, 0),	/* yellow */
167		MAKE_YUV_601(0, 192, 192),	/* cyan */
168		MAKE_YUV_601(0, 192, 0),	/* green */
169		MAKE_YUV_601(192, 0, 192),	/* magenta */
170		MAKE_YUV_601(192, 0, 0),	/* red */
171		MAKE_YUV_601(0, 0, 192),	/* blue */
172	};
173	const struct color_yuv colors_middle[] = {
174		MAKE_YUV_601(0, 0, 192),	/* blue */
175		MAKE_YUV_601(19, 19, 19),	/* black */
176		MAKE_YUV_601(192, 0, 192),	/* magenta */
177		MAKE_YUV_601(19, 19, 19),	/* black */
178		MAKE_YUV_601(0, 192, 192),	/* cyan */
179		MAKE_YUV_601(19, 19, 19),	/* black */
180		MAKE_YUV_601(192, 192, 192),	/* grey */
181	};
182	const struct color_yuv colors_bottom[] = {
183		MAKE_YUV_601(0, 33, 76),	/* in-phase */
184		MAKE_YUV_601(255, 255, 255),	/* super white */
185		MAKE_YUV_601(50, 0, 106),	/* quadrature */
186		MAKE_YUV_601(19, 19, 19),	/* black */
187		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
188		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
189		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
190		MAKE_YUV_601(19, 19, 19),	/* black */
191	};
192	unsigned int cs = yuv->chroma_stride;
193	unsigned int xsub = yuv->xsub;
194	unsigned int ysub = yuv->ysub;
195	unsigned int x;
196	unsigned int y;
197
198	/* Luma */
199	for (y = 0; y < height * 6 / 9; ++y) {
200		for (x = 0; x < width; ++x)
201			y_mem[x] = colors_top[x * 7 / width].y;
202		y_mem += stride;
203	}
204
205	for (; y < height * 7 / 9; ++y) {
206		for (x = 0; x < width; ++x)
207			y_mem[x] = colors_middle[x * 7 / width].y;
208		y_mem += stride;
209	}
210
211	for (; y < height; ++y) {
212		for (x = 0; x < width * 5 / 7; ++x)
213			y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
214		for (; x < width * 6 / 7; ++x)
215			y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
216						 / (width / 7) + 4].y;
217		for (; x < width; ++x)
218			y_mem[x] = colors_bottom[7].y;
219		y_mem += stride;
220	}
221
222	/* Chroma */
223	for (y = 0; y < height / ysub * 6 / 9; ++y) {
224		for (x = 0; x < width; x += xsub) {
225			u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
226			v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
227		}
228		u_mem += stride * cs / xsub;
229		v_mem += stride * cs / xsub;
230	}
231
232	for (; y < height / ysub * 7 / 9; ++y) {
233		for (x = 0; x < width; x += xsub) {
234			u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
235			v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
236		}
237		u_mem += stride * cs / xsub;
238		v_mem += stride * cs / xsub;
239	}
240
241	for (; y < height / ysub; ++y) {
242		for (x = 0; x < width * 5 / 7; x += xsub) {
243			u_mem[x*cs/xsub] =
244				colors_bottom[x * 4 / (width * 5 / 7)].u;
245			v_mem[x*cs/xsub] =
246				colors_bottom[x * 4 / (width * 5 / 7)].v;
247		}
248		for (; x < width * 6 / 7; x += xsub) {
249			u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
250							 3 / (width / 7) + 4].u;
251			v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
252							 3 / (width / 7) + 4].v;
253		}
254		for (; x < width; x += xsub) {
255			u_mem[x*cs/xsub] = colors_bottom[7].u;
256			v_mem[x*cs/xsub] = colors_bottom[7].v;
257		}
258		u_mem += stride * cs / xsub;
259		v_mem += stride * cs / xsub;
260	}
261}
262
263static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem,
264				  unsigned int width, unsigned int height,
265				  unsigned int stride)
266{
267	const struct color_yuv colors_top[] = {
268		MAKE_YUV_601(191, 192, 192),	/* grey */
269		MAKE_YUV_601(192, 192, 0),	/* yellow */
270		MAKE_YUV_601(0, 192, 192),	/* cyan */
271		MAKE_YUV_601(0, 192, 0),	/* green */
272		MAKE_YUV_601(192, 0, 192),	/* magenta */
273		MAKE_YUV_601(192, 0, 0),	/* red */
274		MAKE_YUV_601(0, 0, 192),	/* blue */
275	};
276	const struct color_yuv colors_middle[] = {
277		MAKE_YUV_601(0, 0, 192),	/* blue */
278		MAKE_YUV_601(19, 19, 19),	/* black */
279		MAKE_YUV_601(192, 0, 192),	/* magenta */
280		MAKE_YUV_601(19, 19, 19),	/* black */
281		MAKE_YUV_601(0, 192, 192),	/* cyan */
282		MAKE_YUV_601(19, 19, 19),	/* black */
283		MAKE_YUV_601(192, 192, 192),	/* grey */
284	};
285	const struct color_yuv colors_bottom[] = {
286		MAKE_YUV_601(0, 33, 76),	/* in-phase */
287		MAKE_YUV_601(255, 255, 255),	/* super white */
288		MAKE_YUV_601(50, 0, 106),	/* quadrature */
289		MAKE_YUV_601(19, 19, 19),	/* black */
290		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
291		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
292		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
293		MAKE_YUV_601(19, 19, 19),	/* black */
294	};
295	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
296	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
297	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
298	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
299	unsigned int x;
300	unsigned int y;
301
302	/* Luma */
303	for (y = 0; y < height * 6 / 9; ++y) {
304		for (x = 0; x < width; ++x)
305			y_mem[2*x] = colors_top[x * 7 / width].y;
306		y_mem += stride;
307	}
308
309	for (; y < height * 7 / 9; ++y) {
310		for (x = 0; x < width; ++x)
311			y_mem[2*x] = colors_middle[x * 7 / width].y;
312		y_mem += stride;
313	}
314
315	for (; y < height; ++y) {
316		for (x = 0; x < width * 5 / 7; ++x)
317			y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
318		for (; x < width * 6 / 7; ++x)
319			y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
320						   / (width / 7) + 4].y;
321		for (; x < width; ++x)
322			y_mem[2*x] = colors_bottom[7].y;
323		y_mem += stride;
324	}
325
326	/* Chroma */
327	for (y = 0; y < height * 6 / 9; ++y) {
328		for (x = 0; x < width; x += 2) {
329			c_mem[2*x+u] = colors_top[x * 7 / width].u;
330			c_mem[2*x+v] = colors_top[x * 7 / width].v;
331		}
332		c_mem += stride;
333	}
334
335	for (; y < height * 7 / 9; ++y) {
336		for (x = 0; x < width; x += 2) {
337			c_mem[2*x+u] = colors_middle[x * 7 / width].u;
338			c_mem[2*x+v] = colors_middle[x * 7 / width].v;
339		}
340		c_mem += stride;
341	}
342
343	for (; y < height; ++y) {
344		for (x = 0; x < width * 5 / 7; x += 2) {
345			c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
346			c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
347		}
348		for (; x < width * 6 / 7; x += 2) {
349			c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
350						     3 / (width / 7) + 4].u;
351			c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
352						     3 / (width / 7) + 4].v;
353		}
354		for (; x < width; x += 2) {
355			c_mem[2*x+u] = colors_bottom[7].u;
356			c_mem[2*x+v] = colors_bottom[7].v;
357		}
358		c_mem += stride;
359	}
360}
361
362static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
363			     unsigned int width, unsigned int height,
364			     unsigned int stride)
365{
366	const uint16_t colors_top[] = {
367		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
368		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
369		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
370		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
371		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
372		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
373		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
374	};
375	const uint16_t colors_middle[] = {
376		MAKE_RGBA(rgb, 0, 0, 192, 127),		/* blue */
377		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
378		MAKE_RGBA(rgb, 192, 0, 192, 127),	/* magenta */
379		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
380		MAKE_RGBA(rgb, 0, 192, 192, 127),	/* cyan */
381		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
382		MAKE_RGBA(rgb, 192, 192, 192, 127),	/* grey */
383	};
384	const uint16_t colors_bottom[] = {
385		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
386		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
387		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
388		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
389		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
390		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
391		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
392		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
393	};
394	unsigned int x;
395	unsigned int y;
396
397	for (y = 0; y < height * 6 / 9; ++y) {
398		for (x = 0; x < width; ++x)
399			((uint16_t *)mem)[x] = colors_top[x * 7 / width];
400		mem += stride;
401	}
402
403	for (; y < height * 7 / 9; ++y) {
404		for (x = 0; x < width; ++x)
405			((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
406		mem += stride;
407	}
408
409	for (; y < height; ++y) {
410		for (x = 0; x < width * 5 / 7; ++x)
411			((uint16_t *)mem)[x] =
412				colors_bottom[x * 4 / (width * 5 / 7)];
413		for (; x < width * 6 / 7; ++x)
414			((uint16_t *)mem)[x] =
415				colors_bottom[(x - width * 5 / 7) * 3
416					      / (width / 7) + 4];
417		for (; x < width; ++x)
418			((uint16_t *)mem)[x] = colors_bottom[7];
419		mem += stride;
420	}
421}
422
423static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem,
424			     unsigned int width, unsigned int height,
425			     unsigned int stride)
426{
427	const struct color_rgb24 colors_top[] = {
428		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
429		MAKE_RGB24(rgb, 192, 192, 0),	/* yellow */
430		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
431		MAKE_RGB24(rgb, 0, 192, 0),	/* green */
432		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
433		MAKE_RGB24(rgb, 192, 0, 0),	/* red */
434		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
435	};
436	const struct color_rgb24 colors_middle[] = {
437		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
438		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
439		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
440		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
441		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
442		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
443		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
444	};
445	const struct color_rgb24 colors_bottom[] = {
446		MAKE_RGB24(rgb, 0, 33, 76),	/* in-phase */
447		MAKE_RGB24(rgb, 255, 255, 255),	/* super white */
448		MAKE_RGB24(rgb, 50, 0, 106),	/* quadrature */
449		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
450		MAKE_RGB24(rgb, 9, 9, 9),	/* 3.5% */
451		MAKE_RGB24(rgb, 19, 19, 19),	/* 7.5% */
452		MAKE_RGB24(rgb, 29, 29, 29),	/* 11.5% */
453		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
454	};
455	unsigned int x;
456	unsigned int y;
457
458	for (y = 0; y < height * 6 / 9; ++y) {
459		for (x = 0; x < width; ++x)
460			((struct color_rgb24 *)mem)[x] =
461				colors_top[x * 7 / width];
462		mem += stride;
463	}
464
465	for (; y < height * 7 / 9; ++y) {
466		for (x = 0; x < width; ++x)
467			((struct color_rgb24 *)mem)[x] =
468				colors_middle[x * 7 / width];
469		mem += stride;
470	}
471
472	for (; y < height; ++y) {
473		for (x = 0; x < width * 5 / 7; ++x)
474			((struct color_rgb24 *)mem)[x] =
475				colors_bottom[x * 4 / (width * 5 / 7)];
476		for (; x < width * 6 / 7; ++x)
477			((struct color_rgb24 *)mem)[x] =
478				colors_bottom[(x - width * 5 / 7) * 3
479					      / (width / 7) + 4];
480		for (; x < width; ++x)
481			((struct color_rgb24 *)mem)[x] = colors_bottom[7];
482		mem += stride;
483	}
484}
485
486static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem,
487			     unsigned int width, unsigned int height,
488			     unsigned int stride)
489{
490	const uint32_t colors_top[] = {
491		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
492		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
493		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
494		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
495		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
496		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
497		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
498	};
499	const uint32_t colors_middle[] = {
500		MAKE_RGBA(rgb, 0, 0, 192, 127),		/* blue */
501		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
502		MAKE_RGBA(rgb, 192, 0, 192, 127),	/* magenta */
503		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
504		MAKE_RGBA(rgb, 0, 192, 192, 127),	/* cyan */
505		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
506		MAKE_RGBA(rgb, 192, 192, 192, 127),	/* grey */
507	};
508	const uint32_t colors_bottom[] = {
509		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
510		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
511		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
512		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
513		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
514		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
515		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
516		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
517	};
518	unsigned int x;
519	unsigned int y;
520
521	for (y = 0; y < height * 6 / 9; ++y) {
522		for (x = 0; x < width; ++x)
523			((uint32_t *)mem)[x] = colors_top[x * 7 / width];
524		mem += stride;
525	}
526
527	for (; y < height * 7 / 9; ++y) {
528		for (x = 0; x < width; ++x)
529			((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
530		mem += stride;
531	}
532
533	for (; y < height; ++y) {
534		for (x = 0; x < width * 5 / 7; ++x)
535			((uint32_t *)mem)[x] =
536				colors_bottom[x * 4 / (width * 5 / 7)];
537		for (; x < width * 6 / 7; ++x)
538			((uint32_t *)mem)[x] =
539				colors_bottom[(x - width * 5 / 7) * 3
540					      / (width / 7) + 4];
541		for (; x < width; ++x)
542			((uint32_t *)mem)[x] = colors_bottom[7];
543		mem += stride;
544	}
545}
546
547static void fill_smpte_rgb16fp(const struct util_rgb_info *rgb, void *mem,
548			       unsigned int width, unsigned int height,
549			       unsigned int stride)
550{
551	const uint64_t colors_top[] = {
552		MAKE_RGBA8FP16(rgb, 192, 192, 192, 255),/* grey */
553		MAKE_RGBA8FP16(rgb, 192, 192, 0, 255),	/* yellow */
554		MAKE_RGBA8FP16(rgb, 0, 192, 192, 255),	/* cyan */
555		MAKE_RGBA8FP16(rgb, 0, 192, 0, 255),	/* green */
556		MAKE_RGBA8FP16(rgb, 192, 0, 192, 255),	/* magenta */
557		MAKE_RGBA8FP16(rgb, 192, 0, 0, 255),	/* red */
558		MAKE_RGBA8FP16(rgb, 0, 0, 192, 255),	/* blue */
559	};
560	const uint64_t colors_middle[] = {
561		MAKE_RGBA8FP16(rgb, 0, 0, 192, 127),	/* blue */
562		MAKE_RGBA8FP16(rgb, 19, 19, 19, 127),	/* black */
563		MAKE_RGBA8FP16(rgb, 192, 0, 192, 127),	/* magenta */
564		MAKE_RGBA8FP16(rgb, 19, 19, 19, 127),	/* black */
565		MAKE_RGBA8FP16(rgb, 0, 192, 192, 127),	/* cyan */
566		MAKE_RGBA8FP16(rgb, 19, 19, 19, 127),	/* black */
567		MAKE_RGBA8FP16(rgb, 192, 192, 192, 127),/* grey */
568	};
569	const uint64_t colors_bottom[] = {
570		MAKE_RGBA8FP16(rgb, 0, 33, 76, 255),	/* in-phase */
571		MAKE_RGBA8FP16(rgb, 255, 255, 255, 255),/* super white */
572		MAKE_RGBA8FP16(rgb, 50, 0, 106, 255),	/* quadrature */
573		MAKE_RGBA8FP16(rgb, 19, 19, 19, 255),	/* black */
574		MAKE_RGBA8FP16(rgb, 9, 9, 9, 255),	/* 3.5% */
575		MAKE_RGBA8FP16(rgb, 19, 19, 19, 255),	/* 7.5% */
576		MAKE_RGBA8FP16(rgb, 29, 29, 29, 255),	/* 11.5% */
577		MAKE_RGBA8FP16(rgb, 19, 19, 19, 255),	/* black */
578	};
579	unsigned int x;
580	unsigned int y;
581
582	for (y = 0; y < height * 6 / 9; ++y) {
583		for (x = 0; x < width; ++x)
584			((uint64_t *)mem)[x] = colors_top[x * 7 / width];
585		mem += stride;
586	}
587
588	for (; y < height * 7 / 9; ++y) {
589		for (x = 0; x < width; ++x)
590			((uint64_t *)mem)[x] = colors_middle[x * 7 / width];
591		mem += stride;
592	}
593
594	for (; y < height; ++y) {
595		for (x = 0; x < width * 5 / 7; ++x)
596			((uint64_t *)mem)[x] =
597				colors_bottom[x * 4 / (width * 5 / 7)];
598		for (; x < width * 6 / 7; ++x)
599			((uint64_t *)mem)[x] =
600				colors_bottom[(x - width * 5 / 7) * 3
601					      / (width / 7) + 4];
602		for (; x < width; ++x)
603			((uint64_t *)mem)[x] = colors_bottom[7];
604		mem += stride;
605	}
606}
607
608static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height,
609			  unsigned int stride)
610{
611	unsigned int x;
612	unsigned int y;
613
614	for (y = 0; y < height * 6 / 9; ++y) {
615		for (x = 0; x < width; ++x)
616			((uint8_t *)mem)[x] = x * 7 / width;
617		mem += stride;
618	}
619
620	for (; y < height * 7 / 9; ++y) {
621		for (x = 0; x < width; ++x)
622			((uint8_t *)mem)[x] = 7 + (x * 7 / width);
623		mem += stride;
624	}
625
626	for (; y < height; ++y) {
627		for (x = 0; x < width * 5 / 7; ++x)
628			((uint8_t *)mem)[x] =
629				14 + (x * 4 / (width * 5 / 7));
630		for (; x < width * 6 / 7; ++x)
631			((uint8_t *)mem)[x] =
632				14 + ((x - width * 5 / 7) * 3
633					      / (width / 7) + 4);
634		for (; x < width; ++x)
635			((uint8_t *)mem)[x] = 14 + 7;
636		mem += stride;
637	}
638}
639
640void util_smpte_c8_gamma(unsigned size, struct drm_color_lut *lut)
641{
642	if (size < 7 + 7 + 8) {
643		printf("Error: gamma too small: %d < %d\n", size, 7 + 7 + 8);
644		return;
645	}
646	memset(lut, 0, size * sizeof(struct drm_color_lut));
647
648#define FILL_COLOR(idx, r, g, b) \
649	lut[idx].red = (r) << 8; \
650	lut[idx].green = (g) << 8; \
651	lut[idx].blue = (b) << 8
652
653	FILL_COLOR( 0, 192, 192, 192);	/* grey */
654	FILL_COLOR( 1, 192, 192, 0  );	/* yellow */
655	FILL_COLOR( 2, 0,   192, 192);	/* cyan */
656	FILL_COLOR( 3, 0,   192, 0  );	/* green */
657	FILL_COLOR( 4, 192, 0,   192);	/* magenta */
658	FILL_COLOR( 5, 192, 0,   0  );	/* red */
659	FILL_COLOR( 6, 0,   0,   192);	/* blue */
660
661	FILL_COLOR( 7, 0,   0,   192);	/* blue */
662	FILL_COLOR( 8, 19,  19,  19 );	/* black */
663	FILL_COLOR( 9, 192, 0,   192);	/* magenta */
664	FILL_COLOR(10, 19,  19,  19 );	/* black */
665	FILL_COLOR(11, 0,   192, 192);	/* cyan */
666	FILL_COLOR(12, 19,  19,  19 );	/* black */
667	FILL_COLOR(13, 192, 192, 192);	/* grey */
668
669	FILL_COLOR(14, 0,   33,  76);	/* in-phase */
670	FILL_COLOR(15, 255, 255, 255);	/* super white */
671	FILL_COLOR(16, 50,  0,   106);	/* quadrature */
672	FILL_COLOR(17, 19,  19,  19);	/* black */
673	FILL_COLOR(18, 9,   9,   9);	/* 3.5% */
674	FILL_COLOR(19, 19,  19,  19);	/* 7.5% */
675	FILL_COLOR(20, 29,  29,  29);	/* 11.5% */
676	FILL_COLOR(21, 19,  19,  19);	/* black */
677
678#undef FILL_COLOR
679}
680
681static void fill_smpte(const struct util_format_info *info, void *planes[3],
682		       unsigned int width, unsigned int height,
683		       unsigned int stride)
684{
685	unsigned char *u, *v;
686
687	switch (info->format) {
688	case DRM_FORMAT_C8:
689		return fill_smpte_c8(planes[0], width, height, stride);
690	case DRM_FORMAT_UYVY:
691	case DRM_FORMAT_VYUY:
692	case DRM_FORMAT_YUYV:
693	case DRM_FORMAT_YVYU:
694		return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
695					     height, stride);
696
697	case DRM_FORMAT_NV12:
698	case DRM_FORMAT_NV21:
699	case DRM_FORMAT_NV16:
700	case DRM_FORMAT_NV61:
701		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
702		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
703		return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
704					     width, height, stride);
705
706	case DRM_FORMAT_YUV420:
707		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
708					     planes[2], width, height, stride);
709
710	case DRM_FORMAT_YVU420:
711		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
712					     planes[1], width, height, stride);
713
714	case DRM_FORMAT_ARGB4444:
715	case DRM_FORMAT_XRGB4444:
716	case DRM_FORMAT_ABGR4444:
717	case DRM_FORMAT_XBGR4444:
718	case DRM_FORMAT_RGBA4444:
719	case DRM_FORMAT_RGBX4444:
720	case DRM_FORMAT_BGRA4444:
721	case DRM_FORMAT_BGRX4444:
722	case DRM_FORMAT_RGB565:
723	case DRM_FORMAT_BGR565:
724	case DRM_FORMAT_ARGB1555:
725	case DRM_FORMAT_XRGB1555:
726	case DRM_FORMAT_ABGR1555:
727	case DRM_FORMAT_XBGR1555:
728	case DRM_FORMAT_RGBA5551:
729	case DRM_FORMAT_RGBX5551:
730	case DRM_FORMAT_BGRA5551:
731	case DRM_FORMAT_BGRX5551:
732		return fill_smpte_rgb16(&info->rgb, planes[0],
733					width, height, stride);
734
735	case DRM_FORMAT_BGR888:
736	case DRM_FORMAT_RGB888:
737		return fill_smpte_rgb24(&info->rgb, planes[0],
738					width, height, stride);
739	case DRM_FORMAT_ARGB8888:
740	case DRM_FORMAT_XRGB8888:
741	case DRM_FORMAT_ABGR8888:
742	case DRM_FORMAT_XBGR8888:
743	case DRM_FORMAT_RGBA8888:
744	case DRM_FORMAT_RGBX8888:
745	case DRM_FORMAT_BGRA8888:
746	case DRM_FORMAT_BGRX8888:
747	case DRM_FORMAT_ARGB2101010:
748	case DRM_FORMAT_XRGB2101010:
749	case DRM_FORMAT_ABGR2101010:
750	case DRM_FORMAT_XBGR2101010:
751	case DRM_FORMAT_RGBA1010102:
752	case DRM_FORMAT_RGBX1010102:
753	case DRM_FORMAT_BGRA1010102:
754	case DRM_FORMAT_BGRX1010102:
755		return fill_smpte_rgb32(&info->rgb, planes[0],
756					width, height, stride);
757
758	case DRM_FORMAT_XRGB16161616F:
759	case DRM_FORMAT_XBGR16161616F:
760	case DRM_FORMAT_ARGB16161616F:
761	case DRM_FORMAT_ABGR16161616F:
762		return fill_smpte_rgb16fp(&info->rgb, planes[0],
763					  width, height, stride);
764	}
765}
766
767/* swap these for big endian.. */
768#define RED   2
769#define GREEN 1
770#define BLUE  0
771
772static void make_pwetty(void *data, unsigned int width, unsigned int height,
773			unsigned int stride, uint32_t format)
774{
775#if HAVE_CAIRO
776	cairo_surface_t *surface;
777	cairo_t *cr;
778	cairo_format_t cairo_format;
779
780	/* we can ignore the order of R,G,B channels */
781	switch (format) {
782	case DRM_FORMAT_XRGB8888:
783	case DRM_FORMAT_ARGB8888:
784	case DRM_FORMAT_XBGR8888:
785	case DRM_FORMAT_ABGR8888:
786		cairo_format = CAIRO_FORMAT_ARGB32;
787		break;
788	case DRM_FORMAT_RGB565:
789	case DRM_FORMAT_BGR565:
790		cairo_format = CAIRO_FORMAT_RGB16_565;
791		break;
792#if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 12)
793	case DRM_FORMAT_ARGB2101010:
794	case DRM_FORMAT_XRGB2101010:
795	case DRM_FORMAT_ABGR2101010:
796	case DRM_FORMAT_XBGR2101010:
797		cairo_format = CAIRO_FORMAT_RGB30;
798		break;
799#endif
800	default:
801		return;
802	}
803
804	surface = cairo_image_surface_create_for_data(data,
805						      cairo_format,
806						      width, height,
807						      stride);
808	cr = cairo_create(surface);
809	cairo_surface_destroy(surface);
810
811	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
812	for (unsigned x = 0; x < width; x += 250)
813		for (unsigned y = 0; y < height; y += 250) {
814			char buf[64];
815
816			cairo_move_to(cr, x, y - 20);
817			cairo_line_to(cr, x, y + 20);
818			cairo_move_to(cr, x - 20, y);
819			cairo_line_to(cr, x + 20, y);
820			cairo_new_sub_path(cr);
821			cairo_arc(cr, x, y, 10, 0, M_PI * 2);
822			cairo_set_line_width(cr, 4);
823			cairo_set_source_rgb(cr, 0, 0, 0);
824			cairo_stroke_preserve(cr);
825			cairo_set_source_rgb(cr, 1, 1, 1);
826			cairo_set_line_width(cr, 2);
827			cairo_stroke(cr);
828
829			snprintf(buf, sizeof buf, "%d, %d", x, y);
830			cairo_move_to(cr, x + 20, y + 20);
831			cairo_text_path(cr, buf);
832			cairo_set_source_rgb(cr, 0, 0, 0);
833			cairo_stroke_preserve(cr);
834			cairo_set_source_rgb(cr, 1, 1, 1);
835			cairo_fill(cr);
836		}
837
838	cairo_destroy(cr);
839#endif
840}
841
842static void fill_tiles_yuv_planar(const struct util_format_info *info,
843				  unsigned char *y_mem, unsigned char *u_mem,
844				  unsigned char *v_mem, unsigned int width,
845				  unsigned int height, unsigned int stride)
846{
847	const struct util_yuv_info *yuv = &info->yuv;
848	unsigned int cs = yuv->chroma_stride;
849	unsigned int xsub = yuv->xsub;
850	unsigned int ysub = yuv->ysub;
851	unsigned int x;
852	unsigned int y;
853
854	for (y = 0; y < height; ++y) {
855		for (x = 0; x < width; ++x) {
856			div_t d = div(x+y, width);
857			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
858				       + 0x000a1120 * (d.rem >> 6);
859			struct color_yuv color =
860				MAKE_YUV_601((rgb32 >> 16) & 0xff,
861					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
862
863			y_mem[x] = color.y;
864			u_mem[x/xsub*cs] = color.u;
865			v_mem[x/xsub*cs] = color.v;
866		}
867
868		y_mem += stride;
869		if ((y + 1) % ysub == 0) {
870			u_mem += stride * cs / xsub;
871			v_mem += stride * cs / xsub;
872		}
873	}
874}
875
876static void fill_tiles_yuv_packed(const struct util_format_info *info,
877				  void *mem, unsigned int width,
878				  unsigned int height, unsigned int stride)
879{
880	const struct util_yuv_info *yuv = &info->yuv;
881	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
882	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
883	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
884	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
885	unsigned int x;
886	unsigned int y;
887
888	for (y = 0; y < height; ++y) {
889		for (x = 0; x < width; x += 2) {
890			div_t d = div(x+y, width);
891			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
892				       + 0x000a1120 * (d.rem >> 6);
893			struct color_yuv color =
894				MAKE_YUV_601((rgb32 >> 16) & 0xff,
895					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
896
897			y_mem[2*x] = color.y;
898			c_mem[2*x+u] = color.u;
899			y_mem[2*x+2] = color.y;
900			c_mem[2*x+v] = color.v;
901		}
902
903		y_mem += stride;
904		c_mem += stride;
905	}
906}
907
908static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
909			     unsigned int width, unsigned int height,
910			     unsigned int stride)
911{
912	const struct util_rgb_info *rgb = &info->rgb;
913	void *mem_base = mem;
914	unsigned int x, y;
915
916	for (y = 0; y < height; ++y) {
917		for (x = 0; x < width; ++x) {
918			div_t d = div(x+y, width);
919			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
920				       + 0x000a1120 * (d.rem >> 6);
921			uint16_t color =
922				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
923					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
924					  255);
925
926			((uint16_t *)mem)[x] = color;
927		}
928		mem += stride;
929	}
930
931	make_pwetty(mem_base, width, height, stride, info->format);
932}
933
934static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
935			     unsigned int width, unsigned int height,
936			     unsigned int stride)
937{
938	const struct util_rgb_info *rgb = &info->rgb;
939	unsigned int x, y;
940
941	for (y = 0; y < height; ++y) {
942		for (x = 0; x < width; ++x) {
943			div_t d = div(x+y, width);
944			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
945				       + 0x000a1120 * (d.rem >> 6);
946			struct color_rgb24 color =
947				MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
948					   (rgb32 >> 8) & 0xff, rgb32 & 0xff);
949
950			((struct color_rgb24 *)mem)[x] = color;
951		}
952		mem += stride;
953	}
954}
955
956static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
957			     unsigned int width, unsigned int height,
958			     unsigned int stride)
959{
960	const struct util_rgb_info *rgb = &info->rgb;
961	void *mem_base = mem;
962	unsigned int x, y;
963
964	for (y = 0; y < height; ++y) {
965		for (x = 0; x < width; ++x) {
966			div_t d = div(x+y, width);
967			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
968				       + 0x000a1120 * (d.rem >> 6);
969			uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
970			uint32_t color =
971				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
972					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
973					  alpha);
974
975			((uint32_t *)mem)[x] = color;
976		}
977		mem += stride;
978	}
979
980	make_pwetty(mem_base, width, height, stride, info->format);
981}
982
983static void fill_tiles_rgb16fp(const struct util_format_info *info, void *mem,
984			       unsigned int width, unsigned int height,
985			       unsigned int stride)
986{
987	const struct util_rgb_info *rgb = &info->rgb;
988	unsigned int x, y;
989
990	/* TODO: Give this actual fp16 precision */
991	for (y = 0; y < height; ++y) {
992		for (x = 0; x < width; ++x) {
993			div_t d = div(x+y, width);
994			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
995				       + 0x000a1120 * (d.rem >> 6);
996			uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
997			uint64_t color =
998				MAKE_RGBA8FP16(rgb, (rgb32 >> 16) & 0xff,
999					       (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1000					       alpha);
1001
1002			((uint64_t *)mem)[x] = color;
1003		}
1004		mem += stride;
1005	}
1006}
1007
1008static void fill_tiles(const struct util_format_info *info, void *planes[3],
1009		       unsigned int width, unsigned int height,
1010		       unsigned int stride)
1011{
1012	unsigned char *u, *v;
1013
1014	switch (info->format) {
1015	case DRM_FORMAT_UYVY:
1016	case DRM_FORMAT_VYUY:
1017	case DRM_FORMAT_YUYV:
1018	case DRM_FORMAT_YVYU:
1019		return fill_tiles_yuv_packed(info, planes[0],
1020					     width, height, stride);
1021
1022	case DRM_FORMAT_NV12:
1023	case DRM_FORMAT_NV21:
1024	case DRM_FORMAT_NV16:
1025	case DRM_FORMAT_NV61:
1026		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
1027		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
1028		return fill_tiles_yuv_planar(info, planes[0], u, v,
1029					     width, height, stride);
1030
1031	case DRM_FORMAT_YUV420:
1032		return fill_tiles_yuv_planar(info, planes[0], planes[1],
1033					     planes[2], width, height, stride);
1034
1035	case DRM_FORMAT_YVU420:
1036		return fill_tiles_yuv_planar(info, planes[0], planes[2],
1037					     planes[1], width, height, stride);
1038
1039	case DRM_FORMAT_ARGB4444:
1040	case DRM_FORMAT_XRGB4444:
1041	case DRM_FORMAT_ABGR4444:
1042	case DRM_FORMAT_XBGR4444:
1043	case DRM_FORMAT_RGBA4444:
1044	case DRM_FORMAT_RGBX4444:
1045	case DRM_FORMAT_BGRA4444:
1046	case DRM_FORMAT_BGRX4444:
1047	case DRM_FORMAT_RGB565:
1048	case DRM_FORMAT_BGR565:
1049	case DRM_FORMAT_ARGB1555:
1050	case DRM_FORMAT_XRGB1555:
1051	case DRM_FORMAT_ABGR1555:
1052	case DRM_FORMAT_XBGR1555:
1053	case DRM_FORMAT_RGBA5551:
1054	case DRM_FORMAT_RGBX5551:
1055	case DRM_FORMAT_BGRA5551:
1056	case DRM_FORMAT_BGRX5551:
1057		return fill_tiles_rgb16(info, planes[0],
1058					width, height, stride);
1059
1060	case DRM_FORMAT_BGR888:
1061	case DRM_FORMAT_RGB888:
1062		return fill_tiles_rgb24(info, planes[0],
1063					width, height, stride);
1064	case DRM_FORMAT_ARGB8888:
1065	case DRM_FORMAT_XRGB8888:
1066	case DRM_FORMAT_ABGR8888:
1067	case DRM_FORMAT_XBGR8888:
1068	case DRM_FORMAT_RGBA8888:
1069	case DRM_FORMAT_RGBX8888:
1070	case DRM_FORMAT_BGRA8888:
1071	case DRM_FORMAT_BGRX8888:
1072	case DRM_FORMAT_ARGB2101010:
1073	case DRM_FORMAT_XRGB2101010:
1074	case DRM_FORMAT_ABGR2101010:
1075	case DRM_FORMAT_XBGR2101010:
1076	case DRM_FORMAT_RGBA1010102:
1077	case DRM_FORMAT_RGBX1010102:
1078	case DRM_FORMAT_BGRA1010102:
1079	case DRM_FORMAT_BGRX1010102:
1080		return fill_tiles_rgb32(info, planes[0],
1081					width, height, stride);
1082
1083	case DRM_FORMAT_XRGB16161616F:
1084	case DRM_FORMAT_XBGR16161616F:
1085	case DRM_FORMAT_ARGB16161616F:
1086	case DRM_FORMAT_ABGR16161616F:
1087		return fill_tiles_rgb16fp(info, planes[0],
1088					  width, height, stride);
1089	}
1090}
1091
1092static void fill_plain(const struct util_format_info *info, void *planes[3],
1093		       unsigned int height,
1094		       unsigned int stride)
1095{
1096	switch (info->format) {
1097	case DRM_FORMAT_XRGB16161616F:
1098	case DRM_FORMAT_XBGR16161616F:
1099	case DRM_FORMAT_ARGB16161616F:
1100	case DRM_FORMAT_ABGR16161616F:
1101		/* 0x3838 = 0.5273 */
1102		memset(planes[0], 0x38, stride * height);
1103		break;
1104	default:
1105		memset(planes[0], 0x77, stride * height);
1106		break;
1107	}
1108}
1109
1110static void fill_gradient_rgb32(const struct util_rgb_info *rgb,
1111				void *mem,
1112				unsigned int width, unsigned int height,
1113				unsigned int stride)
1114{
1115	unsigned int i, j;
1116
1117	for (i = 0; i < height / 2; i++) {
1118		uint32_t *row = mem;
1119
1120		for (j = 0; j < width / 2; j++) {
1121			uint32_t value = MAKE_RGBA10(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1122			row[2*j] = row[2*j+1] = value;
1123		}
1124		mem += stride;
1125	}
1126
1127	for (; i < height; i++) {
1128		uint32_t *row = mem;
1129
1130		for (j = 0; j < width / 2; j++) {
1131			uint32_t value = MAKE_RGBA10(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1132			row[2*j] = row[2*j+1] = value;
1133		}
1134		mem += stride;
1135	}
1136}
1137
1138static void fill_gradient_rgb16fp(const struct util_rgb_info *rgb,
1139				  void *mem,
1140				  unsigned int width, unsigned int height,
1141				  unsigned int stride)
1142{
1143	unsigned int i, j;
1144
1145	for (i = 0; i < height / 2; i++) {
1146		uint64_t *row = mem;
1147
1148		for (j = 0; j < width / 2; j++) {
1149			uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1150			row[2*j] = row[2*j+1] = value;
1151		}
1152		mem += stride;
1153	}
1154
1155	for (; i < height; i++) {
1156		uint64_t *row = mem;
1157
1158		for (j = 0; j < width / 2; j++) {
1159			uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1160			row[2*j] = row[2*j+1] = value;
1161		}
1162		mem += stride;
1163	}
1164}
1165
1166/* The gradient pattern creates two horizontal gray gradients, split
1167 * into two halves. The top half has 10bpc precision, the bottom half
1168 * has 8bpc precision. When using with a 10bpc fb format, there are 3
1169 * possible outcomes:
1170 *
1171 *  - Pixel data is encoded as 8bpc to the display, no dithering. This
1172 *    would lead to the top and bottom halves looking identical.
1173 *
1174 *  - Pixel data is encoded as 8bpc to the display, with dithering. This
1175 *    would lead to there being a visible difference between the two halves,
1176 *    but the top half would look a little speck-y due to the dithering.
1177 *
1178 *  - Pixel data is encoded at 10bpc+ to the display (which implies
1179 *    the display is able to show this level of depth). This should
1180 *    lead to the top half being a very clean gradient, and visibly different
1181 *    from the bottom half.
1182 *
1183 * Once we support additional fb formats, this approach could be extended
1184 * to distinguish even higher bpc precisions.
1185 *
1186 * Note that due to practical size considerations, for the screens
1187 * where this matters, the pattern actually emits stripes 2-pixels
1188 * wide for each gradient color. Otherwise the difference may be a bit
1189 * hard to notice.
1190 */
1191static void fill_gradient(const struct util_format_info *info, void *planes[3],
1192			  unsigned int width, unsigned int height,
1193			  unsigned int stride)
1194{
1195	switch (info->format) {
1196	case DRM_FORMAT_ARGB8888:
1197	case DRM_FORMAT_XRGB8888:
1198	case DRM_FORMAT_ABGR8888:
1199	case DRM_FORMAT_XBGR8888:
1200	case DRM_FORMAT_RGBA8888:
1201	case DRM_FORMAT_RGBX8888:
1202	case DRM_FORMAT_BGRA8888:
1203	case DRM_FORMAT_BGRX8888:
1204	case DRM_FORMAT_ARGB2101010:
1205	case DRM_FORMAT_XRGB2101010:
1206	case DRM_FORMAT_ABGR2101010:
1207	case DRM_FORMAT_XBGR2101010:
1208	case DRM_FORMAT_RGBA1010102:
1209	case DRM_FORMAT_RGBX1010102:
1210	case DRM_FORMAT_BGRA1010102:
1211	case DRM_FORMAT_BGRX1010102:
1212		return fill_gradient_rgb32(&info->rgb, planes[0],
1213					   width, height, stride);
1214
1215	case DRM_FORMAT_XRGB16161616F:
1216	case DRM_FORMAT_XBGR16161616F:
1217	case DRM_FORMAT_ARGB16161616F:
1218	case DRM_FORMAT_ABGR16161616F:
1219		return fill_gradient_rgb16fp(&info->rgb, planes[0],
1220					     width, height, stride);
1221	}
1222}
1223
1224/*
1225 * util_fill_pattern - Fill a buffer with a test pattern
1226 * @format: Pixel format
1227 * @pattern: Test pattern
1228 * @planes: Array of buffers
1229 * @width: Width in pixels
1230 * @height: Height in pixels
1231 * @stride: Line stride (pitch) in bytes
1232 *
1233 * Fill the buffers with the test pattern specified by the pattern parameter.
1234 * Supported formats vary depending on the selected pattern.
1235 */
1236void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
1237		       void *planes[3], unsigned int width,
1238		       unsigned int height, unsigned int stride)
1239{
1240	const struct util_format_info *info;
1241
1242	info = util_format_info_find(format);
1243	if (info == NULL)
1244		return;
1245
1246	switch (pattern) {
1247	case UTIL_PATTERN_TILES:
1248		return fill_tiles(info, planes, width, height, stride);
1249
1250	case UTIL_PATTERN_SMPTE:
1251		return fill_smpte(info, planes, width, height, stride);
1252
1253	case UTIL_PATTERN_PLAIN:
1254		return fill_plain(info, planes, height, stride);
1255
1256	case UTIL_PATTERN_GRADIENT:
1257		return fill_gradient(info, planes, width, height, stride);
1258
1259	default:
1260		printf("Error: unsupported test pattern %u.\n", pattern);
1261		break;
1262	}
1263}
1264
1265static const char *pattern_names[] = {
1266	[UTIL_PATTERN_TILES] = "tiles",
1267	[UTIL_PATTERN_SMPTE] = "smpte",
1268	[UTIL_PATTERN_PLAIN] = "plain",
1269	[UTIL_PATTERN_GRADIENT] = "gradient",
1270};
1271
1272enum util_fill_pattern util_pattern_enum(const char *name)
1273{
1274	unsigned int i;
1275
1276	for (i = 0; i < ARRAY_SIZE(pattern_names); i++)
1277		if (!strcmp(pattern_names[i], name))
1278			return (enum util_fill_pattern)i;
1279
1280	printf("Error: unsupported test pattern %s.\n", name);
1281	return UTIL_PATTERN_SMPTE;
1282}
1283