pattern.c revision 3f012e29
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
45struct color_rgb24 {
46	unsigned int value:24;
47} __attribute__((__packed__));
48
49struct 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
76static 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
180static 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
279static 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
340static 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
403static 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
464static 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
546static 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
609static 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
643static 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
675static 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
701static 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
723static 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
750static 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
827static 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 */
846void 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