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 "format.h"
39 #include "pattern.h"
40 
41 struct color_rgb24 {
42 	unsigned int value:24;
43 } __attribute__((__packed__));
44 
45 struct color_yuv {
46 	unsigned char y;
47 	unsigned char u;
48 	unsigned char v;
49 };
50 
51 #define MAKE_YUV_601_Y(r, g, b) \
52 	((( 66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
53 #define MAKE_YUV_601_U(r, g, b) \
54 	(((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
55 #define MAKE_YUV_601_V(r, g, b) \
56 	(((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
57 
58 #define MAKE_YUV_601(r, g, b) \
59 	{ .y = MAKE_YUV_601_Y(r, g, b), \
60 	  .u = MAKE_YUV_601_U(r, g, b), \
61 	  .v = MAKE_YUV_601_V(r, g, b) }
62 
63 #define MAKE_RGBA(rgb, r, g, b, a) \
64 	((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \
65 	 (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \
66 	 (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \
67 	 (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset))
68 
69 #define MAKE_RGB24(rgb, r, g, b) \
70 	{ .value = MAKE_RGBA(rgb, r, g, b, 0) }
71 
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)72 static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv,
73 				  unsigned char *y_mem, unsigned char *u_mem,
74 				  unsigned char *v_mem, unsigned int width,
75 				  unsigned int height, unsigned int stride)
76 {
77 	const struct color_yuv colors_top[] = {
78 		MAKE_YUV_601(191, 192, 192),	/* grey */
79 		MAKE_YUV_601(192, 192, 0),	/* yellow */
80 		MAKE_YUV_601(0, 192, 192),	/* cyan */
81 		MAKE_YUV_601(0, 192, 0),	/* green */
82 		MAKE_YUV_601(192, 0, 192),	/* magenta */
83 		MAKE_YUV_601(192, 0, 0),	/* red */
84 		MAKE_YUV_601(0, 0, 192),	/* blue */
85 	};
86 	const struct color_yuv colors_middle[] = {
87 		MAKE_YUV_601(0, 0, 192),	/* blue */
88 		MAKE_YUV_601(19, 19, 19),	/* black */
89 		MAKE_YUV_601(192, 0, 192),	/* magenta */
90 		MAKE_YUV_601(19, 19, 19),	/* black */
91 		MAKE_YUV_601(0, 192, 192),	/* cyan */
92 		MAKE_YUV_601(19, 19, 19),	/* black */
93 		MAKE_YUV_601(192, 192, 192),	/* grey */
94 	};
95 	const struct color_yuv colors_bottom[] = {
96 		MAKE_YUV_601(0, 33, 76),	/* in-phase */
97 		MAKE_YUV_601(255, 255, 255),	/* super white */
98 		MAKE_YUV_601(50, 0, 106),	/* quadrature */
99 		MAKE_YUV_601(19, 19, 19),	/* black */
100 		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
101 		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
102 		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
103 		MAKE_YUV_601(19, 19, 19),	/* black */
104 	};
105 	unsigned int cs = yuv->chroma_stride;
106 	unsigned int xsub = yuv->xsub;
107 	unsigned int ysub = yuv->ysub;
108 	unsigned int x;
109 	unsigned int y;
110 
111 	/* Luma */
112 	for (y = 0; y < height * 6 / 9; ++y) {
113 		for (x = 0; x < width; ++x)
114 			y_mem[x] = colors_top[x * 7 / width].y;
115 		y_mem += stride;
116 	}
117 
118 	for (; y < height * 7 / 9; ++y) {
119 		for (x = 0; x < width; ++x)
120 			y_mem[x] = colors_middle[x * 7 / width].y;
121 		y_mem += stride;
122 	}
123 
124 	for (; y < height; ++y) {
125 		for (x = 0; x < width * 5 / 7; ++x)
126 			y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
127 		for (; x < width * 6 / 7; ++x)
128 			y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
129 						 / (width / 7) + 4].y;
130 		for (; x < width; ++x)
131 			y_mem[x] = colors_bottom[7].y;
132 		y_mem += stride;
133 	}
134 
135 	/* Chroma */
136 	for (y = 0; y < height / ysub * 6 / 9; ++y) {
137 		for (x = 0; x < width; x += xsub) {
138 			u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
139 			v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
140 		}
141 		u_mem += stride * cs / xsub;
142 		v_mem += stride * cs / xsub;
143 	}
144 
145 	for (; y < height / ysub * 7 / 9; ++y) {
146 		for (x = 0; x < width; x += xsub) {
147 			u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
148 			v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
149 		}
150 		u_mem += stride * cs / xsub;
151 		v_mem += stride * cs / xsub;
152 	}
153 
154 	for (; y < height / ysub; ++y) {
155 		for (x = 0; x < width * 5 / 7; x += xsub) {
156 			u_mem[x*cs/xsub] =
157 				colors_bottom[x * 4 / (width * 5 / 7)].u;
158 			v_mem[x*cs/xsub] =
159 				colors_bottom[x * 4 / (width * 5 / 7)].v;
160 		}
161 		for (; x < width * 6 / 7; x += xsub) {
162 			u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
163 							 3 / (width / 7) + 4].u;
164 			v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
165 							 3 / (width / 7) + 4].v;
166 		}
167 		for (; x < width; x += xsub) {
168 			u_mem[x*cs/xsub] = colors_bottom[7].u;
169 			v_mem[x*cs/xsub] = colors_bottom[7].v;
170 		}
171 		u_mem += stride * cs / xsub;
172 		v_mem += stride * cs / xsub;
173 	}
174 }
175 
fill_smpte_yuv_packed(const struct util_yuv_info * yuv,void * mem,unsigned int width,unsigned int height,unsigned int stride)176 static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem,
177 				  unsigned int width, unsigned int height,
178 				  unsigned int stride)
179 {
180 	const struct color_yuv colors_top[] = {
181 		MAKE_YUV_601(191, 192, 192),	/* grey */
182 		MAKE_YUV_601(192, 192, 0),	/* yellow */
183 		MAKE_YUV_601(0, 192, 192),	/* cyan */
184 		MAKE_YUV_601(0, 192, 0),	/* green */
185 		MAKE_YUV_601(192, 0, 192),	/* magenta */
186 		MAKE_YUV_601(192, 0, 0),	/* red */
187 		MAKE_YUV_601(0, 0, 192),	/* blue */
188 	};
189 	const struct color_yuv colors_middle[] = {
190 		MAKE_YUV_601(0, 0, 192),	/* blue */
191 		MAKE_YUV_601(19, 19, 19),	/* black */
192 		MAKE_YUV_601(192, 0, 192),	/* magenta */
193 		MAKE_YUV_601(19, 19, 19),	/* black */
194 		MAKE_YUV_601(0, 192, 192),	/* cyan */
195 		MAKE_YUV_601(19, 19, 19),	/* black */
196 		MAKE_YUV_601(192, 192, 192),	/* grey */
197 	};
198 	const struct color_yuv colors_bottom[] = {
199 		MAKE_YUV_601(0, 33, 76),	/* in-phase */
200 		MAKE_YUV_601(255, 255, 255),	/* super white */
201 		MAKE_YUV_601(50, 0, 106),	/* quadrature */
202 		MAKE_YUV_601(19, 19, 19),	/* black */
203 		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
204 		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
205 		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
206 		MAKE_YUV_601(19, 19, 19),	/* black */
207 	};
208 	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
209 	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
210 	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
211 	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
212 	unsigned int x;
213 	unsigned int y;
214 
215 	/* Luma */
216 	for (y = 0; y < height * 6 / 9; ++y) {
217 		for (x = 0; x < width; ++x)
218 			y_mem[2*x] = colors_top[x * 7 / width].y;
219 		y_mem += stride;
220 	}
221 
222 	for (; y < height * 7 / 9; ++y) {
223 		for (x = 0; x < width; ++x)
224 			y_mem[2*x] = colors_middle[x * 7 / width].y;
225 		y_mem += stride;
226 	}
227 
228 	for (; y < height; ++y) {
229 		for (x = 0; x < width * 5 / 7; ++x)
230 			y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
231 		for (; x < width * 6 / 7; ++x)
232 			y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
233 						   / (width / 7) + 4].y;
234 		for (; x < width; ++x)
235 			y_mem[2*x] = colors_bottom[7].y;
236 		y_mem += stride;
237 	}
238 
239 	/* Chroma */
240 	for (y = 0; y < height * 6 / 9; ++y) {
241 		for (x = 0; x < width; x += 2) {
242 			c_mem[2*x+u] = colors_top[x * 7 / width].u;
243 			c_mem[2*x+v] = colors_top[x * 7 / width].v;
244 		}
245 		c_mem += stride;
246 	}
247 
248 	for (; y < height * 7 / 9; ++y) {
249 		for (x = 0; x < width; x += 2) {
250 			c_mem[2*x+u] = colors_middle[x * 7 / width].u;
251 			c_mem[2*x+v] = colors_middle[x * 7 / width].v;
252 		}
253 		c_mem += stride;
254 	}
255 
256 	for (; y < height; ++y) {
257 		for (x = 0; x < width * 5 / 7; x += 2) {
258 			c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
259 			c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
260 		}
261 		for (; x < width * 6 / 7; x += 2) {
262 			c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
263 						     3 / (width / 7) + 4].u;
264 			c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
265 						     3 / (width / 7) + 4].v;
266 		}
267 		for (; x < width; x += 2) {
268 			c_mem[2*x+u] = colors_bottom[7].u;
269 			c_mem[2*x+v] = colors_bottom[7].v;
270 		}
271 		c_mem += stride;
272 	}
273 }
274 
fill_smpte_rgb16(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)275 static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
276 			     unsigned int width, unsigned int height,
277 			     unsigned int stride)
278 {
279 	const uint16_t colors_top[] = {
280 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
281 		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
282 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
283 		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
284 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
285 		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
286 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
287 	};
288 	const uint16_t colors_middle[] = {
289 		MAKE_RGBA(rgb, 0, 0, 192, 127),		/* blue */
290 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
291 		MAKE_RGBA(rgb, 192, 0, 192, 127),	/* magenta */
292 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
293 		MAKE_RGBA(rgb, 0, 192, 192, 127),	/* cyan */
294 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
295 		MAKE_RGBA(rgb, 192, 192, 192, 127),	/* grey */
296 	};
297 	const uint16_t colors_bottom[] = {
298 		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
299 		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
300 		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
301 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
302 		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
303 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
304 		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
305 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
306 	};
307 	unsigned int x;
308 	unsigned int y;
309 
310 	for (y = 0; y < height * 6 / 9; ++y) {
311 		for (x = 0; x < width; ++x)
312 			((uint16_t *)mem)[x] = colors_top[x * 7 / width];
313 		mem += stride;
314 	}
315 
316 	for (; y < height * 7 / 9; ++y) {
317 		for (x = 0; x < width; ++x)
318 			((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
319 		mem += stride;
320 	}
321 
322 	for (; y < height; ++y) {
323 		for (x = 0; x < width * 5 / 7; ++x)
324 			((uint16_t *)mem)[x] =
325 				colors_bottom[x * 4 / (width * 5 / 7)];
326 		for (; x < width * 6 / 7; ++x)
327 			((uint16_t *)mem)[x] =
328 				colors_bottom[(x - width * 5 / 7) * 3
329 					      / (width / 7) + 4];
330 		for (; x < width; ++x)
331 			((uint16_t *)mem)[x] = colors_bottom[7];
332 		mem += stride;
333 	}
334 }
335 
fill_smpte_rgb24(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)336 static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem,
337 			     unsigned int width, unsigned int height,
338 			     unsigned int stride)
339 {
340 	const struct color_rgb24 colors_top[] = {
341 		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
342 		MAKE_RGB24(rgb, 192, 192, 0),	/* yellow */
343 		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
344 		MAKE_RGB24(rgb, 0, 192, 0),	/* green */
345 		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
346 		MAKE_RGB24(rgb, 192, 0, 0),	/* red */
347 		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
348 	};
349 	const struct color_rgb24 colors_middle[] = {
350 		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
351 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
352 		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
353 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
354 		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
355 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
356 		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
357 	};
358 	const struct color_rgb24 colors_bottom[] = {
359 		MAKE_RGB24(rgb, 0, 33, 76),	/* in-phase */
360 		MAKE_RGB24(rgb, 255, 255, 255),	/* super white */
361 		MAKE_RGB24(rgb, 50, 0, 106),	/* quadrature */
362 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
363 		MAKE_RGB24(rgb, 9, 9, 9),	/* 3.5% */
364 		MAKE_RGB24(rgb, 19, 19, 19),	/* 7.5% */
365 		MAKE_RGB24(rgb, 29, 29, 29),	/* 11.5% */
366 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
367 	};
368 	unsigned int x;
369 	unsigned int y;
370 
371 	for (y = 0; y < height * 6 / 9; ++y) {
372 		for (x = 0; x < width; ++x)
373 			((struct color_rgb24 *)mem)[x] =
374 				colors_top[x * 7 / width];
375 		mem += stride;
376 	}
377 
378 	for (; y < height * 7 / 9; ++y) {
379 		for (x = 0; x < width; ++x)
380 			((struct color_rgb24 *)mem)[x] =
381 				colors_middle[x * 7 / width];
382 		mem += stride;
383 	}
384 
385 	for (; y < height; ++y) {
386 		for (x = 0; x < width * 5 / 7; ++x)
387 			((struct color_rgb24 *)mem)[x] =
388 				colors_bottom[x * 4 / (width * 5 / 7)];
389 		for (; x < width * 6 / 7; ++x)
390 			((struct color_rgb24 *)mem)[x] =
391 				colors_bottom[(x - width * 5 / 7) * 3
392 					      / (width / 7) + 4];
393 		for (; x < width; ++x)
394 			((struct color_rgb24 *)mem)[x] = colors_bottom[7];
395 		mem += stride;
396 	}
397 }
398 
fill_smpte_rgb32(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)399 static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem,
400 			     unsigned int width, unsigned int height,
401 			     unsigned int stride)
402 {
403 	const uint32_t colors_top[] = {
404 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
405 		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
406 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
407 		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
408 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
409 		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
410 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
411 	};
412 	const uint32_t colors_middle[] = {
413 		MAKE_RGBA(rgb, 0, 0, 192, 127),		/* blue */
414 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
415 		MAKE_RGBA(rgb, 192, 0, 192, 127),	/* magenta */
416 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
417 		MAKE_RGBA(rgb, 0, 192, 192, 127),	/* cyan */
418 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
419 		MAKE_RGBA(rgb, 192, 192, 192, 127),	/* grey */
420 	};
421 	const uint32_t colors_bottom[] = {
422 		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
423 		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
424 		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
425 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
426 		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
427 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
428 		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
429 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
430 	};
431 	unsigned int x;
432 	unsigned int y;
433 
434 	for (y = 0; y < height * 6 / 9; ++y) {
435 		for (x = 0; x < width; ++x)
436 			((uint32_t *)mem)[x] = colors_top[x * 7 / width];
437 		mem += stride;
438 	}
439 
440 	for (; y < height * 7 / 9; ++y) {
441 		for (x = 0; x < width; ++x)
442 			((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
443 		mem += stride;
444 	}
445 
446 	for (; y < height; ++y) {
447 		for (x = 0; x < width * 5 / 7; ++x)
448 			((uint32_t *)mem)[x] =
449 				colors_bottom[x * 4 / (width * 5 / 7)];
450 		for (; x < width * 6 / 7; ++x)
451 			((uint32_t *)mem)[x] =
452 				colors_bottom[(x - width * 5 / 7) * 3
453 					      / (width / 7) + 4];
454 		for (; x < width; ++x)
455 			((uint32_t *)mem)[x] = colors_bottom[7];
456 		mem += stride;
457 	}
458 }
459 
fill_smpte(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)460 static void fill_smpte(const struct util_format_info *info, void *planes[3],
461 		       unsigned int width, unsigned int height,
462 		       unsigned int stride)
463 {
464 	unsigned char *u, *v;
465 
466 	switch (info->format) {
467 	case DRM_FORMAT_UYVY:
468 	case DRM_FORMAT_VYUY:
469 	case DRM_FORMAT_YUYV:
470 	case DRM_FORMAT_YVYU:
471 		return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
472 					     height, stride);
473 
474 	case DRM_FORMAT_NV12:
475 	case DRM_FORMAT_NV21:
476 	case DRM_FORMAT_NV16:
477 	case DRM_FORMAT_NV61:
478 		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
479 		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
480 		return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
481 					     width, height, stride);
482 
483 	case DRM_FORMAT_YUV420:
484 		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
485 					     planes[2], width, height, stride);
486 
487 	case DRM_FORMAT_YVU420:
488 		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
489 					     planes[1], width, height, stride);
490 
491 	case DRM_FORMAT_ARGB4444:
492 	case DRM_FORMAT_XRGB4444:
493 	case DRM_FORMAT_ABGR4444:
494 	case DRM_FORMAT_XBGR4444:
495 	case DRM_FORMAT_RGBA4444:
496 	case DRM_FORMAT_RGBX4444:
497 	case DRM_FORMAT_BGRA4444:
498 	case DRM_FORMAT_BGRX4444:
499 	case DRM_FORMAT_RGB565:
500 	case DRM_FORMAT_BGR565:
501 	case DRM_FORMAT_ARGB1555:
502 	case DRM_FORMAT_XRGB1555:
503 	case DRM_FORMAT_ABGR1555:
504 	case DRM_FORMAT_XBGR1555:
505 	case DRM_FORMAT_RGBA5551:
506 	case DRM_FORMAT_RGBX5551:
507 	case DRM_FORMAT_BGRA5551:
508 	case DRM_FORMAT_BGRX5551:
509 		return fill_smpte_rgb16(&info->rgb, planes[0],
510 					width, height, stride);
511 
512 	case DRM_FORMAT_BGR888:
513 	case DRM_FORMAT_RGB888:
514 		return fill_smpte_rgb24(&info->rgb, planes[0],
515 					width, height, stride);
516 	case DRM_FORMAT_ARGB8888:
517 	case DRM_FORMAT_XRGB8888:
518 	case DRM_FORMAT_ABGR8888:
519 	case DRM_FORMAT_XBGR8888:
520 	case DRM_FORMAT_RGBA8888:
521 	case DRM_FORMAT_RGBX8888:
522 	case DRM_FORMAT_BGRA8888:
523 	case DRM_FORMAT_BGRX8888:
524 	case DRM_FORMAT_ARGB2101010:
525 	case DRM_FORMAT_XRGB2101010:
526 	case DRM_FORMAT_ABGR2101010:
527 	case DRM_FORMAT_XBGR2101010:
528 	case DRM_FORMAT_RGBA1010102:
529 	case DRM_FORMAT_RGBX1010102:
530 	case DRM_FORMAT_BGRA1010102:
531 	case DRM_FORMAT_BGRX1010102:
532 		return fill_smpte_rgb32(&info->rgb, planes[0],
533 					width, height, stride);
534 	}
535 }
536 
537 /* swap these for big endian.. */
538 #define RED   2
539 #define GREEN 1
540 #define BLUE  0
541 
make_pwetty(void * data,unsigned int width,unsigned int height,unsigned int stride,uint32_t format)542 static void make_pwetty(void *data, unsigned int width, unsigned int height,
543 			unsigned int stride, uint32_t format)
544 {
545 #if HAVE_CAIRO
546 	cairo_surface_t *surface;
547 	cairo_t *cr;
548 	cairo_format_t cairo_format;
549 
550 	/* we can ignore the order of R,G,B channels */
551 	switch (format) {
552 	case DRM_FORMAT_XRGB8888:
553 	case DRM_FORMAT_ARGB8888:
554 	case DRM_FORMAT_XBGR8888:
555 	case DRM_FORMAT_ABGR8888:
556 		cairo_format = CAIRO_FORMAT_ARGB32;
557 		break;
558 	case DRM_FORMAT_RGB565:
559 	case DRM_FORMAT_BGR565:
560 		cairo_format = CAIRO_FORMAT_RGB16_565;
561 		break;
562 	default:
563 		return;
564 	}
565 
566 	surface = cairo_image_surface_create_for_data(data,
567 						      cairo_format,
568 						      width, height,
569 						      stride);
570 	cr = cairo_create(surface);
571 	cairo_surface_destroy(surface);
572 
573 	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
574 	for (unsigned x = 0; x < width; x += 250)
575 		for (unsigned y = 0; y < height; y += 250) {
576 			char buf[64];
577 
578 			cairo_move_to(cr, x, y - 20);
579 			cairo_line_to(cr, x, y + 20);
580 			cairo_move_to(cr, x - 20, y);
581 			cairo_line_to(cr, x + 20, y);
582 			cairo_new_sub_path(cr);
583 			cairo_arc(cr, x, y, 10, 0, M_PI * 2);
584 			cairo_set_line_width(cr, 4);
585 			cairo_set_source_rgb(cr, 0, 0, 0);
586 			cairo_stroke_preserve(cr);
587 			cairo_set_source_rgb(cr, 1, 1, 1);
588 			cairo_set_line_width(cr, 2);
589 			cairo_stroke(cr);
590 
591 			snprintf(buf, sizeof buf, "%d, %d", x, y);
592 			cairo_move_to(cr, x + 20, y + 20);
593 			cairo_text_path(cr, buf);
594 			cairo_set_source_rgb(cr, 0, 0, 0);
595 			cairo_stroke_preserve(cr);
596 			cairo_set_source_rgb(cr, 1, 1, 1);
597 			cairo_fill(cr);
598 		}
599 
600 	cairo_destroy(cr);
601 #endif
602 }
603 
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)604 static void fill_tiles_yuv_planar(const struct util_format_info *info,
605 				  unsigned char *y_mem, unsigned char *u_mem,
606 				  unsigned char *v_mem, unsigned int width,
607 				  unsigned int height, unsigned int stride)
608 {
609 	const struct util_yuv_info *yuv = &info->yuv;
610 	unsigned int cs = yuv->chroma_stride;
611 	unsigned int xsub = yuv->xsub;
612 	unsigned int ysub = yuv->ysub;
613 	unsigned int x;
614 	unsigned int y;
615 
616 	for (y = 0; y < height; ++y) {
617 		for (x = 0; x < width; ++x) {
618 			div_t d = div(x+y, width);
619 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
620 				       + 0x000a1120 * (d.rem >> 6);
621 			struct color_yuv color =
622 				MAKE_YUV_601((rgb32 >> 16) & 0xff,
623 					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
624 
625 			y_mem[x] = color.y;
626 			u_mem[x/xsub*cs] = color.u;
627 			v_mem[x/xsub*cs] = color.v;
628 		}
629 
630 		y_mem += stride;
631 		if ((y + 1) % ysub == 0) {
632 			u_mem += stride * cs / xsub;
633 			v_mem += stride * cs / xsub;
634 		}
635 	}
636 }
637 
fill_tiles_yuv_packed(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)638 static void fill_tiles_yuv_packed(const struct util_format_info *info,
639 				  void *mem, unsigned int width,
640 				  unsigned int height, unsigned int stride)
641 {
642 	const struct util_yuv_info *yuv = &info->yuv;
643 	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
644 	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
645 	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
646 	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
647 	unsigned int x;
648 	unsigned int y;
649 
650 	for (y = 0; y < height; ++y) {
651 		for (x = 0; x < width; x += 2) {
652 			div_t d = div(x+y, width);
653 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
654 				       + 0x000a1120 * (d.rem >> 6);
655 			struct color_yuv color =
656 				MAKE_YUV_601((rgb32 >> 16) & 0xff,
657 					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
658 
659 			y_mem[2*x] = color.y;
660 			c_mem[2*x+u] = color.u;
661 			y_mem[2*x+2] = color.y;
662 			c_mem[2*x+v] = color.v;
663 		}
664 
665 		y_mem += stride;
666 		c_mem += stride;
667 	}
668 }
669 
fill_tiles_rgb16(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)670 static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
671 			     unsigned int width, unsigned int height,
672 			     unsigned int stride)
673 {
674 	const struct util_rgb_info *rgb = &info->rgb;
675 	void *mem_base = mem;
676 	unsigned int x, y;
677 
678 	for (y = 0; y < height; ++y) {
679 		for (x = 0; x < width; ++x) {
680 			div_t d = div(x+y, width);
681 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
682 				       + 0x000a1120 * (d.rem >> 6);
683 			uint16_t color =
684 				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
685 					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
686 					  255);
687 
688 			((uint16_t *)mem)[x] = color;
689 		}
690 		mem += stride;
691 	}
692 
693 	make_pwetty(mem_base, width, height, stride, info->format);
694 }
695 
fill_tiles_rgb24(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)696 static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
697 			     unsigned int width, unsigned int height,
698 			     unsigned int stride)
699 {
700 	const struct util_rgb_info *rgb = &info->rgb;
701 	unsigned int x, y;
702 
703 	for (y = 0; y < height; ++y) {
704 		for (x = 0; x < width; ++x) {
705 			div_t d = div(x+y, width);
706 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
707 				       + 0x000a1120 * (d.rem >> 6);
708 			struct color_rgb24 color =
709 				MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
710 					   (rgb32 >> 8) & 0xff, rgb32 & 0xff);
711 
712 			((struct color_rgb24 *)mem)[x] = color;
713 		}
714 		mem += stride;
715 	}
716 }
717 
fill_tiles_rgb32(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)718 static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
719 			     unsigned int width, unsigned int height,
720 			     unsigned int stride)
721 {
722 	const struct util_rgb_info *rgb = &info->rgb;
723 	void *mem_base = mem;
724 	unsigned int x, y;
725 
726 	for (y = 0; y < height; ++y) {
727 		for (x = 0; x < width; ++x) {
728 			div_t d = div(x+y, width);
729 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
730 				       + 0x000a1120 * (d.rem >> 6);
731 			uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
732 			uint32_t color =
733 				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
734 					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
735 					  alpha);
736 
737 			((uint32_t *)mem)[x] = color;
738 		}
739 		mem += stride;
740 	}
741 
742 	make_pwetty(mem_base, width, height, stride, info->format);
743 }
744 
fill_tiles(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)745 static void fill_tiles(const struct util_format_info *info, void *planes[3],
746 		       unsigned int width, unsigned int height,
747 		       unsigned int stride)
748 {
749 	unsigned char *u, *v;
750 
751 	switch (info->format) {
752 	case DRM_FORMAT_UYVY:
753 	case DRM_FORMAT_VYUY:
754 	case DRM_FORMAT_YUYV:
755 	case DRM_FORMAT_YVYU:
756 		return fill_tiles_yuv_packed(info, planes[0],
757 					     width, height, stride);
758 
759 	case DRM_FORMAT_NV12:
760 	case DRM_FORMAT_NV21:
761 	case DRM_FORMAT_NV16:
762 	case DRM_FORMAT_NV61:
763 		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
764 		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
765 		return fill_tiles_yuv_planar(info, planes[0], u, v,
766 					     width, height, stride);
767 
768 	case DRM_FORMAT_YUV420:
769 		return fill_tiles_yuv_planar(info, planes[0], planes[1],
770 					     planes[2], width, height, stride);
771 
772 	case DRM_FORMAT_YVU420:
773 		return fill_tiles_yuv_planar(info, planes[0], planes[2],
774 					     planes[1], width, height, stride);
775 
776 	case DRM_FORMAT_ARGB4444:
777 	case DRM_FORMAT_XRGB4444:
778 	case DRM_FORMAT_ABGR4444:
779 	case DRM_FORMAT_XBGR4444:
780 	case DRM_FORMAT_RGBA4444:
781 	case DRM_FORMAT_RGBX4444:
782 	case DRM_FORMAT_BGRA4444:
783 	case DRM_FORMAT_BGRX4444:
784 	case DRM_FORMAT_RGB565:
785 	case DRM_FORMAT_BGR565:
786 	case DRM_FORMAT_ARGB1555:
787 	case DRM_FORMAT_XRGB1555:
788 	case DRM_FORMAT_ABGR1555:
789 	case DRM_FORMAT_XBGR1555:
790 	case DRM_FORMAT_RGBA5551:
791 	case DRM_FORMAT_RGBX5551:
792 	case DRM_FORMAT_BGRA5551:
793 	case DRM_FORMAT_BGRX5551:
794 		return fill_tiles_rgb16(info, planes[0],
795 					width, height, stride);
796 
797 	case DRM_FORMAT_BGR888:
798 	case DRM_FORMAT_RGB888:
799 		return fill_tiles_rgb24(info, planes[0],
800 					width, height, stride);
801 	case DRM_FORMAT_ARGB8888:
802 	case DRM_FORMAT_XRGB8888:
803 	case DRM_FORMAT_ABGR8888:
804 	case DRM_FORMAT_XBGR8888:
805 	case DRM_FORMAT_RGBA8888:
806 	case DRM_FORMAT_RGBX8888:
807 	case DRM_FORMAT_BGRA8888:
808 	case DRM_FORMAT_BGRX8888:
809 	case DRM_FORMAT_ARGB2101010:
810 	case DRM_FORMAT_XRGB2101010:
811 	case DRM_FORMAT_ABGR2101010:
812 	case DRM_FORMAT_XBGR2101010:
813 	case DRM_FORMAT_RGBA1010102:
814 	case DRM_FORMAT_RGBX1010102:
815 	case DRM_FORMAT_BGRA1010102:
816 	case DRM_FORMAT_BGRX1010102:
817 		return fill_tiles_rgb32(info, planes[0],
818 					width, height, stride);
819 	}
820 }
821 
fill_plain(void * planes[3],unsigned int height,unsigned int stride)822 static void fill_plain(void *planes[3],
823 		       unsigned int height,
824 		       unsigned int stride)
825 {
826 	memset(planes[0], 0x77, stride * height);
827 }
828 
829 /*
830  * util_fill_pattern - Fill a buffer with a test pattern
831  * @format: Pixel format
832  * @pattern: Test pattern
833  * @planes: Array of buffers
834  * @width: Width in pixels
835  * @height: Height in pixels
836  * @stride: Line stride (pitch) in bytes
837  *
838  * Fill the buffers with the test pattern specified by the pattern parameter.
839  * Supported formats vary depending on the selected pattern.
840  */
util_fill_pattern(uint32_t format,enum util_fill_pattern pattern,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)841 void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
842 		       void *planes[3], unsigned int width,
843 		       unsigned int height, unsigned int stride)
844 {
845 	const struct util_format_info *info;
846 
847 	info = util_format_info_find(format);
848 	if (info == NULL)
849 		return;
850 
851 	switch (pattern) {
852 	case UTIL_PATTERN_TILES:
853 		return fill_tiles(info, planes, width, height, stride);
854 
855 	case UTIL_PATTERN_SMPTE:
856 		return fill_smpte(info, planes, width, height, stride);
857 
858 	case UTIL_PATTERN_PLAIN:
859 		return fill_plain(planes, height, stride);
860 
861 	default:
862 		printf("Error: unsupported test pattern %u.\n", pattern);
863 		break;
864 	}
865 }
866