pattern.c revision 00a23bda
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#if 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#if HAVE_CAIRO
550	cairo_surface_t *surface;
551	cairo_t *cr;
552	cairo_format_t cairo_format;
553
554	/* we can ignore the order of R,G,B channels */
555	switch (format) {
556	case DRM_FORMAT_XRGB8888:
557	case DRM_FORMAT_ARGB8888:
558	case DRM_FORMAT_XBGR8888:
559	case DRM_FORMAT_ABGR8888:
560		cairo_format = CAIRO_FORMAT_ARGB32;
561		break;
562	case DRM_FORMAT_RGB565:
563	case DRM_FORMAT_BGR565:
564		cairo_format = CAIRO_FORMAT_RGB16_565;
565		break;
566	default:
567		return;
568	}
569
570	surface = cairo_image_surface_create_for_data(data,
571						      cairo_format,
572						      width, height,
573						      stride);
574	cr = cairo_create(surface);
575	cairo_surface_destroy(surface);
576
577	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
578	for (unsigned x = 0; x < width; x += 250)
579		for (unsigned y = 0; y < height; y += 250) {
580			char buf[64];
581
582			cairo_move_to(cr, x, y - 20);
583			cairo_line_to(cr, x, y + 20);
584			cairo_move_to(cr, x - 20, y);
585			cairo_line_to(cr, x + 20, y);
586			cairo_new_sub_path(cr);
587			cairo_arc(cr, x, y, 10, 0, M_PI * 2);
588			cairo_set_line_width(cr, 4);
589			cairo_set_source_rgb(cr, 0, 0, 0);
590			cairo_stroke_preserve(cr);
591			cairo_set_source_rgb(cr, 1, 1, 1);
592			cairo_set_line_width(cr, 2);
593			cairo_stroke(cr);
594
595			snprintf(buf, sizeof buf, "%d, %d", x, y);
596			cairo_move_to(cr, x + 20, y + 20);
597			cairo_text_path(cr, buf);
598			cairo_set_source_rgb(cr, 0, 0, 0);
599			cairo_stroke_preserve(cr);
600			cairo_set_source_rgb(cr, 1, 1, 1);
601			cairo_fill(cr);
602		}
603
604	cairo_destroy(cr);
605#endif
606}
607
608static void fill_tiles_yuv_planar(const struct util_format_info *info,
609				  unsigned char *y_mem, unsigned char *u_mem,
610				  unsigned char *v_mem, unsigned int width,
611				  unsigned int height, unsigned int stride)
612{
613	const struct util_yuv_info *yuv = &info->yuv;
614	unsigned int cs = yuv->chroma_stride;
615	unsigned int xsub = yuv->xsub;
616	unsigned int ysub = yuv->ysub;
617	unsigned int x;
618	unsigned int y;
619
620	for (y = 0; y < height; ++y) {
621		for (x = 0; x < width; ++x) {
622			div_t d = div(x+y, width);
623			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
624				       + 0x000a1120 * (d.rem >> 6);
625			struct color_yuv color =
626				MAKE_YUV_601((rgb32 >> 16) & 0xff,
627					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
628
629			y_mem[x] = color.y;
630			u_mem[x/xsub*cs] = color.u;
631			v_mem[x/xsub*cs] = color.v;
632		}
633
634		y_mem += stride;
635		if ((y + 1) % ysub == 0) {
636			u_mem += stride * cs / xsub;
637			v_mem += stride * cs / xsub;
638		}
639	}
640}
641
642static void fill_tiles_yuv_packed(const struct util_format_info *info,
643				  void *mem, unsigned int width,
644				  unsigned int height, unsigned int stride)
645{
646	const struct util_yuv_info *yuv = &info->yuv;
647	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
648	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
649	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
650	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
651	unsigned int x;
652	unsigned int y;
653
654	for (y = 0; y < height; ++y) {
655		for (x = 0; x < width; x += 2) {
656			div_t d = div(x+y, width);
657			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
658				       + 0x000a1120 * (d.rem >> 6);
659			struct color_yuv color =
660				MAKE_YUV_601((rgb32 >> 16) & 0xff,
661					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
662
663			y_mem[2*x] = color.y;
664			c_mem[2*x+u] = color.u;
665			y_mem[2*x+2] = color.y;
666			c_mem[2*x+v] = color.v;
667		}
668
669		y_mem += stride;
670		c_mem += stride;
671	}
672}
673
674static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
675			     unsigned int width, unsigned int height,
676			     unsigned int stride)
677{
678	const struct util_rgb_info *rgb = &info->rgb;
679	void *mem_base = mem;
680	unsigned int x, y;
681
682	for (y = 0; y < height; ++y) {
683		for (x = 0; x < width; ++x) {
684			div_t d = div(x+y, width);
685			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
686				       + 0x000a1120 * (d.rem >> 6);
687			uint16_t color =
688				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
689					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
690					  255);
691
692			((uint16_t *)mem)[x] = color;
693		}
694		mem += stride;
695	}
696
697	make_pwetty(mem_base, width, height, stride, info->format);
698}
699
700static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
701			     unsigned int width, unsigned int height,
702			     unsigned int stride)
703{
704	const struct util_rgb_info *rgb = &info->rgb;
705	unsigned int x, y;
706
707	for (y = 0; y < height; ++y) {
708		for (x = 0; x < width; ++x) {
709			div_t d = div(x+y, width);
710			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
711				       + 0x000a1120 * (d.rem >> 6);
712			struct color_rgb24 color =
713				MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
714					   (rgb32 >> 8) & 0xff, rgb32 & 0xff);
715
716			((struct color_rgb24 *)mem)[x] = color;
717		}
718		mem += stride;
719	}
720}
721
722static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
723			     unsigned int width, unsigned int height,
724			     unsigned int stride)
725{
726	const struct util_rgb_info *rgb = &info->rgb;
727	void *mem_base = mem;
728	unsigned int x, y;
729
730	for (y = 0; y < height; ++y) {
731		for (x = 0; x < width; ++x) {
732			div_t d = div(x+y, width);
733			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
734				       + 0x000a1120 * (d.rem >> 6);
735			uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
736			uint32_t color =
737				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
738					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
739					  alpha);
740
741			((uint32_t *)mem)[x] = color;
742		}
743		mem += stride;
744	}
745
746	make_pwetty(mem_base, width, height, stride, info->format);
747}
748
749static void fill_tiles(const struct util_format_info *info, void *planes[3],
750		       unsigned int width, unsigned int height,
751		       unsigned int stride)
752{
753	unsigned char *u, *v;
754
755	switch (info->format) {
756	case DRM_FORMAT_UYVY:
757	case DRM_FORMAT_VYUY:
758	case DRM_FORMAT_YUYV:
759	case DRM_FORMAT_YVYU:
760		return fill_tiles_yuv_packed(info, planes[0],
761					     width, height, stride);
762
763	case DRM_FORMAT_NV12:
764	case DRM_FORMAT_NV21:
765	case DRM_FORMAT_NV16:
766	case DRM_FORMAT_NV61:
767		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
768		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
769		return fill_tiles_yuv_planar(info, planes[0], u, v,
770					     width, height, stride);
771
772	case DRM_FORMAT_YUV420:
773		return fill_tiles_yuv_planar(info, planes[0], planes[1],
774					     planes[2], width, height, stride);
775
776	case DRM_FORMAT_YVU420:
777		return fill_tiles_yuv_planar(info, planes[0], planes[2],
778					     planes[1], width, height, stride);
779
780	case DRM_FORMAT_ARGB4444:
781	case DRM_FORMAT_XRGB4444:
782	case DRM_FORMAT_ABGR4444:
783	case DRM_FORMAT_XBGR4444:
784	case DRM_FORMAT_RGBA4444:
785	case DRM_FORMAT_RGBX4444:
786	case DRM_FORMAT_BGRA4444:
787	case DRM_FORMAT_BGRX4444:
788	case DRM_FORMAT_RGB565:
789	case DRM_FORMAT_BGR565:
790	case DRM_FORMAT_ARGB1555:
791	case DRM_FORMAT_XRGB1555:
792	case DRM_FORMAT_ABGR1555:
793	case DRM_FORMAT_XBGR1555:
794	case DRM_FORMAT_RGBA5551:
795	case DRM_FORMAT_RGBX5551:
796	case DRM_FORMAT_BGRA5551:
797	case DRM_FORMAT_BGRX5551:
798		return fill_tiles_rgb16(info, planes[0],
799					width, height, stride);
800
801	case DRM_FORMAT_BGR888:
802	case DRM_FORMAT_RGB888:
803		return fill_tiles_rgb24(info, planes[0],
804					width, height, stride);
805	case DRM_FORMAT_ARGB8888:
806	case DRM_FORMAT_XRGB8888:
807	case DRM_FORMAT_ABGR8888:
808	case DRM_FORMAT_XBGR8888:
809	case DRM_FORMAT_RGBA8888:
810	case DRM_FORMAT_RGBX8888:
811	case DRM_FORMAT_BGRA8888:
812	case DRM_FORMAT_BGRX8888:
813	case DRM_FORMAT_ARGB2101010:
814	case DRM_FORMAT_XRGB2101010:
815	case DRM_FORMAT_ABGR2101010:
816	case DRM_FORMAT_XBGR2101010:
817	case DRM_FORMAT_RGBA1010102:
818	case DRM_FORMAT_RGBX1010102:
819	case DRM_FORMAT_BGRA1010102:
820	case DRM_FORMAT_BGRX1010102:
821		return fill_tiles_rgb32(info, planes[0],
822					width, height, stride);
823	}
824}
825
826static void fill_plain(void *planes[3],
827		       unsigned int height,
828		       unsigned int stride)
829{
830	memset(planes[0], 0x77, stride * height);
831}
832
833/*
834 * util_fill_pattern - Fill a buffer with a test pattern
835 * @format: Pixel format
836 * @pattern: Test pattern
837 * @planes: Array of buffers
838 * @width: Width in pixels
839 * @height: Height in pixels
840 * @stride: Line stride (pitch) in bytes
841 *
842 * Fill the buffers with the test pattern specified by the pattern parameter.
843 * Supported formats vary depending on the selected pattern.
844 */
845void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
846		       void *planes[3], unsigned int width,
847		       unsigned int height, unsigned int stride)
848{
849	const struct util_format_info *info;
850
851	info = util_format_info_find(format);
852	if (info == NULL)
853		return;
854
855	switch (pattern) {
856	case UTIL_PATTERN_TILES:
857		return fill_tiles(info, planes, width, height, stride);
858
859	case UTIL_PATTERN_SMPTE:
860		return fill_smpte(info, planes, width, height, stride);
861
862	case UTIL_PATTERN_PLAIN:
863		return fill_plain(planes, height, stride);
864
865	default:
866		printf("Error: unsupported test pattern %u.\n", pattern);
867		break;
868	}
869}
870