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