pattern.c revision 7cdc0497
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
41struct color_rgb24 {
42	unsigned int value:24;
43} __attribute__((__packed__));
44
45struct 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
72static 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
176static 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
275static 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
336static 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
399static 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
460static 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
542static 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
604static 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
638static 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
670static 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
696static 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
718static 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
745static 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
822static 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 */
841void 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