1 /*
2  * DRM based mode setting test program
3  * Copyright 2008 Tungsten Graphics
4  *   Jakob Bornecrantz <jakob@tungstengraphics.com>
5  * Copyright 2008 Intel Corporation
6  *   Jesse Barnes <jesse.barnes@intel.com>
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24  * IN THE SOFTWARE.
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 
31 #include <assert.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdint.h>
36 #include <string.h>
37 #include <sys/ioctl.h>
38 
39 #include "drm.h"
40 #include "drm_fourcc.h"
41 
42 #include "libdrm.h"
43 #include "xf86drm.h"
44 
45 #include "buffers.h"
46 
47 #ifdef HAVE_CAIRO
48 #include <math.h>
49 #include <cairo.h>
50 #endif
51 
52 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
53 
54 struct bo
55 {
56 	int fd;
57 	void *ptr;
58 	size_t size;
59 	size_t offset;
60 	size_t pitch;
61 	unsigned handle;
62 };
63 
64 /* -----------------------------------------------------------------------------
65  * Formats
66  */
67 
68 struct color_component {
69 	unsigned int length;
70 	unsigned int offset;
71 };
72 
73 struct rgb_info {
74 	struct color_component red;
75 	struct color_component green;
76 	struct color_component blue;
77 	struct color_component alpha;
78 };
79 
80 enum yuv_order {
81 	YUV_YCbCr = 1,
82 	YUV_YCrCb = 2,
83 	YUV_YC = 4,
84 	YUV_CY = 8,
85 };
86 
87 struct yuv_info {
88 	enum yuv_order order;
89 	unsigned int xsub;
90 	unsigned int ysub;
91 	unsigned int chroma_stride;
92 };
93 
94 struct format_info {
95 	unsigned int format;
96 	const char *name;
97 	const struct rgb_info rgb;
98 	const struct yuv_info yuv;
99 };
100 
101 #define MAKE_RGB_INFO(rl, ro, bl, bo, gl, go, al, ao) \
102 	.rgb = { { (rl), (ro) }, { (bl), (bo) }, { (gl), (go) }, { (al), (ao) } }
103 
104 #define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \
105 	.yuv = { (order), (xsub), (ysub), (chroma_stride) }
106 
107 static const struct format_info format_info[] = {
108 	/* YUV packed */
109 	{ DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) },
110 	{ DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) },
111 	{ DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) },
112 	{ DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) },
113 	/* YUV semi-planar */
114 	{ DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) },
115 	{ DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) },
116 	{ DRM_FORMAT_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) },
117 	{ DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
118 	/* YUV planar */
119 	{ DRM_FORMAT_YUV420, "YU12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 1) },
120 	{ DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
121 	/* RGB16 */
122 	{ DRM_FORMAT_ARGB4444, "AR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 4, 12) },
123 	{ DRM_FORMAT_XRGB4444, "XR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 0, 0) },
124 	{ DRM_FORMAT_ABGR4444, "AB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 4, 12) },
125 	{ DRM_FORMAT_XBGR4444, "XB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 0, 0) },
126 	{ DRM_FORMAT_RGBA4444, "RA12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 4, 0) },
127 	{ DRM_FORMAT_RGBX4444, "RX12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 0, 0) },
128 	{ DRM_FORMAT_BGRA4444, "BA12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 4, 0) },
129 	{ DRM_FORMAT_BGRX4444, "BX12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 0, 0) },
130 	{ DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) },
131 	{ DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
132 	{ DRM_FORMAT_ABGR1555, "AB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 1, 15) },
133 	{ DRM_FORMAT_XBGR1555, "XB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 0, 0) },
134 	{ DRM_FORMAT_RGBA5551, "RA15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 1, 0) },
135 	{ DRM_FORMAT_RGBX5551, "RX15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 0, 0) },
136 	{ DRM_FORMAT_BGRA5551, "BA15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 1, 0) },
137 	{ DRM_FORMAT_BGRX5551, "BX15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 0, 0) },
138 	{ DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
139 	{ DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) },
140 	/* RGB24 */
141 	{ DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
142 	{ DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
143 	/* RGB32 */
144 	{ DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
145 	{ DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
146 	{ DRM_FORMAT_ABGR8888, "AB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 8, 24) },
147 	{ DRM_FORMAT_XBGR8888, "XB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
148 	{ DRM_FORMAT_RGBA8888, "RA24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 8, 0) },
149 	{ DRM_FORMAT_RGBX8888, "RX24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 0, 0) },
150 	{ DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) },
151 	{ DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
152 	{ DRM_FORMAT_ARGB2101010, "AR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 2, 30) },
153 	{ DRM_FORMAT_XRGB2101010, "XR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 0, 0) },
154 	{ DRM_FORMAT_ABGR2101010, "AB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 2, 30) },
155 	{ DRM_FORMAT_XBGR2101010, "XB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 0, 0) },
156 	{ DRM_FORMAT_RGBA1010102, "RA30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 2, 0) },
157 	{ DRM_FORMAT_RGBX1010102, "RX30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 0, 0) },
158 	{ DRM_FORMAT_BGRA1010102, "BA30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 2, 0) },
159 	{ DRM_FORMAT_BGRX1010102, "BX30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 0, 0) },
160 };
161 
format_fourcc(const char * name)162 unsigned int format_fourcc(const char *name)
163 {
164 	unsigned int i;
165 	for (i = 0; i < ARRAY_SIZE(format_info); i++) {
166 		if (!strcmp(format_info[i].name, name))
167 			return format_info[i].format;
168 	}
169 	return 0;
170 }
171 
172 /* -----------------------------------------------------------------------------
173  * Test patterns
174  */
175 
176 struct color_rgb24 {
177 	unsigned int value:24;
178 } __attribute__((__packed__));
179 
180 struct color_yuv {
181 	unsigned char y;
182 	unsigned char u;
183 	unsigned char v;
184 };
185 
186 #define MAKE_YUV_601_Y(r, g, b) \
187 	((( 66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
188 #define MAKE_YUV_601_U(r, g, b) \
189 	(((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
190 #define MAKE_YUV_601_V(r, g, b) \
191 	(((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
192 
193 #define MAKE_YUV_601(r, g, b) \
194 	{ .y = MAKE_YUV_601_Y(r, g, b), \
195 	  .u = MAKE_YUV_601_U(r, g, b), \
196 	  .v = MAKE_YUV_601_V(r, g, b) }
197 
198 #define MAKE_RGBA(rgb, r, g, b, a) \
199 	((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \
200 	 (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \
201 	 (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \
202 	 (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset))
203 
204 #define MAKE_RGB24(rgb, r, g, b) \
205 	{ .value = MAKE_RGBA(rgb, r, g, b, 0) }
206 
207 static void
fill_smpte_yuv_planar(const struct yuv_info * yuv,unsigned char * y_mem,unsigned char * u_mem,unsigned char * v_mem,unsigned int width,unsigned int height,unsigned int stride)208 fill_smpte_yuv_planar(const struct yuv_info *yuv,
209 		      unsigned char *y_mem, unsigned char *u_mem,
210 		      unsigned char *v_mem, unsigned int width,
211 		      unsigned int height, unsigned int stride)
212 {
213 	const struct color_yuv colors_top[] = {
214 		MAKE_YUV_601(191, 192, 192),	/* grey */
215 		MAKE_YUV_601(192, 192, 0),	/* yellow */
216 		MAKE_YUV_601(0, 192, 192),	/* cyan */
217 		MAKE_YUV_601(0, 192, 0),	/* green */
218 		MAKE_YUV_601(192, 0, 192),	/* magenta */
219 		MAKE_YUV_601(192, 0, 0),	/* red */
220 		MAKE_YUV_601(0, 0, 192),	/* blue */
221 	};
222 	const struct color_yuv colors_middle[] = {
223 		MAKE_YUV_601(0, 0, 192),	/* blue */
224 		MAKE_YUV_601(19, 19, 19),	/* black */
225 		MAKE_YUV_601(192, 0, 192),	/* magenta */
226 		MAKE_YUV_601(19, 19, 19),	/* black */
227 		MAKE_YUV_601(0, 192, 192),	/* cyan */
228 		MAKE_YUV_601(19, 19, 19),	/* black */
229 		MAKE_YUV_601(192, 192, 192),	/* grey */
230 	};
231 	const struct color_yuv colors_bottom[] = {
232 		MAKE_YUV_601(0, 33, 76),	/* in-phase */
233 		MAKE_YUV_601(255, 255, 255),	/* super white */
234 		MAKE_YUV_601(50, 0, 106),	/* quadrature */
235 		MAKE_YUV_601(19, 19, 19),	/* black */
236 		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
237 		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
238 		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
239 		MAKE_YUV_601(19, 19, 19),	/* black */
240 	};
241 	unsigned int cs = yuv->chroma_stride;
242 	unsigned int xsub = yuv->xsub;
243 	unsigned int ysub = yuv->ysub;
244 	unsigned int x;
245 	unsigned int y;
246 
247 	/* Luma */
248 	for (y = 0; y < height * 6 / 9; ++y) {
249 		for (x = 0; x < width; ++x)
250 			y_mem[x] = colors_top[x * 7 / width].y;
251 		y_mem += stride;
252 	}
253 
254 	for (; y < height * 7 / 9; ++y) {
255 		for (x = 0; x < width; ++x)
256 			y_mem[x] = colors_middle[x * 7 / width].y;
257 		y_mem += stride;
258 	}
259 
260 	for (; y < height; ++y) {
261 		for (x = 0; x < width * 5 / 7; ++x)
262 			y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
263 		for (; x < width * 6 / 7; ++x)
264 			y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
265 						 / (width / 7) + 4].y;
266 		for (; x < width; ++x)
267 			y_mem[x] = colors_bottom[7].y;
268 		y_mem += stride;
269 	}
270 
271 	/* Chroma */
272 	for (y = 0; y < height / ysub * 6 / 9; ++y) {
273 		for (x = 0; x < width; x += xsub) {
274 			u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
275 			v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
276 		}
277 		u_mem += stride * cs / xsub;
278 		v_mem += stride * cs / xsub;
279 	}
280 
281 	for (; y < height / ysub * 7 / 9; ++y) {
282 		for (x = 0; x < width; x += xsub) {
283 			u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
284 			v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
285 		}
286 		u_mem += stride * cs / xsub;
287 		v_mem += stride * cs / xsub;
288 	}
289 
290 	for (; y < height / ysub; ++y) {
291 		for (x = 0; x < width * 5 / 7; x += xsub) {
292 			u_mem[x*cs/xsub] =
293 				colors_bottom[x * 4 / (width * 5 / 7)].u;
294 			v_mem[x*cs/xsub] =
295 				colors_bottom[x * 4 / (width * 5 / 7)].v;
296 		}
297 		for (; x < width * 6 / 7; x += xsub) {
298 			u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
299 							 3 / (width / 7) + 4].u;
300 			v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
301 							 3 / (width / 7) + 4].v;
302 		}
303 		for (; x < width; x += xsub) {
304 			u_mem[x*cs/xsub] = colors_bottom[7].u;
305 			v_mem[x*cs/xsub] = colors_bottom[7].v;
306 		}
307 		u_mem += stride * cs / xsub;
308 		v_mem += stride * cs / xsub;
309 	}
310 }
311 
312 static void
fill_smpte_yuv_packed(const struct yuv_info * yuv,unsigned char * mem,unsigned int width,unsigned int height,unsigned int stride)313 fill_smpte_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
314 		      unsigned int width, unsigned int height,
315 		      unsigned int stride)
316 {
317 	const struct color_yuv colors_top[] = {
318 		MAKE_YUV_601(191, 192, 192),	/* grey */
319 		MAKE_YUV_601(192, 192, 0),	/* yellow */
320 		MAKE_YUV_601(0, 192, 192),	/* cyan */
321 		MAKE_YUV_601(0, 192, 0),	/* green */
322 		MAKE_YUV_601(192, 0, 192),	/* magenta */
323 		MAKE_YUV_601(192, 0, 0),	/* red */
324 		MAKE_YUV_601(0, 0, 192),	/* blue */
325 	};
326 	const struct color_yuv colors_middle[] = {
327 		MAKE_YUV_601(0, 0, 192),	/* blue */
328 		MAKE_YUV_601(19, 19, 19),	/* black */
329 		MAKE_YUV_601(192, 0, 192),	/* magenta */
330 		MAKE_YUV_601(19, 19, 19),	/* black */
331 		MAKE_YUV_601(0, 192, 192),	/* cyan */
332 		MAKE_YUV_601(19, 19, 19),	/* black */
333 		MAKE_YUV_601(192, 192, 192),	/* grey */
334 	};
335 	const struct color_yuv colors_bottom[] = {
336 		MAKE_YUV_601(0, 33, 76),	/* in-phase */
337 		MAKE_YUV_601(255, 255, 255),	/* super white */
338 		MAKE_YUV_601(50, 0, 106),	/* quadrature */
339 		MAKE_YUV_601(19, 19, 19),	/* black */
340 		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
341 		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
342 		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
343 		MAKE_YUV_601(19, 19, 19),	/* black */
344 	};
345 	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
346 	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
347 	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
348 	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
349 	unsigned int x;
350 	unsigned int y;
351 
352 	/* Luma */
353 	for (y = 0; y < height * 6 / 9; ++y) {
354 		for (x = 0; x < width; ++x)
355 			y_mem[2*x] = colors_top[x * 7 / width].y;
356 		y_mem += stride;
357 	}
358 
359 	for (; y < height * 7 / 9; ++y) {
360 		for (x = 0; x < width; ++x)
361 			y_mem[2*x] = colors_middle[x * 7 / width].y;
362 		y_mem += stride;
363 	}
364 
365 	for (; y < height; ++y) {
366 		for (x = 0; x < width * 5 / 7; ++x)
367 			y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
368 		for (; x < width * 6 / 7; ++x)
369 			y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
370 						   / (width / 7) + 4].y;
371 		for (; x < width; ++x)
372 			y_mem[2*x] = colors_bottom[7].y;
373 		y_mem += stride;
374 	}
375 
376 	/* Chroma */
377 	for (y = 0; y < height * 6 / 9; ++y) {
378 		for (x = 0; x < width; x += 2) {
379 			c_mem[2*x+u] = colors_top[x * 7 / width].u;
380 			c_mem[2*x+v] = colors_top[x * 7 / width].v;
381 		}
382 		c_mem += stride;
383 	}
384 
385 	for (; y < height * 7 / 9; ++y) {
386 		for (x = 0; x < width; x += 2) {
387 			c_mem[2*x+u] = colors_middle[x * 7 / width].u;
388 			c_mem[2*x+v] = colors_middle[x * 7 / width].v;
389 		}
390 		c_mem += stride;
391 	}
392 
393 	for (; y < height; ++y) {
394 		for (x = 0; x < width * 5 / 7; x += 2) {
395 			c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
396 			c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
397 		}
398 		for (; x < width * 6 / 7; x += 2) {
399 			c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
400 						     3 / (width / 7) + 4].u;
401 			c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
402 						     3 / (width / 7) + 4].v;
403 		}
404 		for (; x < width; x += 2) {
405 			c_mem[2*x+u] = colors_bottom[7].u;
406 			c_mem[2*x+v] = colors_bottom[7].v;
407 		}
408 		c_mem += stride;
409 	}
410 }
411 
412 static void
fill_smpte_rgb16(const struct rgb_info * rgb,unsigned char * mem,unsigned int width,unsigned int height,unsigned int stride)413 fill_smpte_rgb16(const struct rgb_info *rgb, unsigned char *mem,
414 		 unsigned int width, unsigned int height, unsigned int stride)
415 {
416 	const uint16_t colors_top[] = {
417 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
418 		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
419 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
420 		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
421 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
422 		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
423 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
424 	};
425 	const uint16_t colors_middle[] = {
426 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
427 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
428 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
429 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
430 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
431 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
432 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
433 	};
434 	const uint16_t colors_bottom[] = {
435 		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
436 		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
437 		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
438 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
439 		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
440 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
441 		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
442 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
443 	};
444 	unsigned int x;
445 	unsigned int y;
446 
447 	for (y = 0; y < height * 6 / 9; ++y) {
448 		for (x = 0; x < width; ++x)
449 			((uint16_t *)mem)[x] = colors_top[x * 7 / width];
450 		mem += stride;
451 	}
452 
453 	for (; y < height * 7 / 9; ++y) {
454 		for (x = 0; x < width; ++x)
455 			((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
456 		mem += stride;
457 	}
458 
459 	for (; y < height; ++y) {
460 		for (x = 0; x < width * 5 / 7; ++x)
461 			((uint16_t *)mem)[x] =
462 				colors_bottom[x * 4 / (width * 5 / 7)];
463 		for (; x < width * 6 / 7; ++x)
464 			((uint16_t *)mem)[x] =
465 				colors_bottom[(x - width * 5 / 7) * 3
466 					      / (width / 7) + 4];
467 		for (; x < width; ++x)
468 			((uint16_t *)mem)[x] = colors_bottom[7];
469 		mem += stride;
470 	}
471 }
472 
473 static void
fill_smpte_rgb24(const struct rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)474 fill_smpte_rgb24(const struct rgb_info *rgb, void *mem,
475 		 unsigned int width, unsigned int height, unsigned int stride)
476 {
477 	const struct color_rgb24 colors_top[] = {
478 		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
479 		MAKE_RGB24(rgb, 192, 192, 0),	/* yellow */
480 		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
481 		MAKE_RGB24(rgb, 0, 192, 0),	/* green */
482 		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
483 		MAKE_RGB24(rgb, 192, 0, 0),	/* red */
484 		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
485 	};
486 	const struct color_rgb24 colors_middle[] = {
487 		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
488 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
489 		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
490 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
491 		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
492 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
493 		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
494 	};
495 	const struct color_rgb24 colors_bottom[] = {
496 		MAKE_RGB24(rgb, 0, 33, 76),	/* in-phase */
497 		MAKE_RGB24(rgb, 255, 255, 255),	/* super white */
498 		MAKE_RGB24(rgb, 50, 0, 106),	/* quadrature */
499 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
500 		MAKE_RGB24(rgb, 9, 9, 9),	/* 3.5% */
501 		MAKE_RGB24(rgb, 19, 19, 19),	/* 7.5% */
502 		MAKE_RGB24(rgb, 29, 29, 29),	/* 11.5% */
503 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
504 	};
505 	unsigned int x;
506 	unsigned int y;
507 
508 	for (y = 0; y < height * 6 / 9; ++y) {
509 		for (x = 0; x < width; ++x)
510 			((struct color_rgb24 *)mem)[x] =
511 				colors_top[x * 7 / width];
512 		mem += stride;
513 	}
514 
515 	for (; y < height * 7 / 9; ++y) {
516 		for (x = 0; x < width; ++x)
517 			((struct color_rgb24 *)mem)[x] =
518 				colors_middle[x * 7 / width];
519 		mem += stride;
520 	}
521 
522 	for (; y < height; ++y) {
523 		for (x = 0; x < width * 5 / 7; ++x)
524 			((struct color_rgb24 *)mem)[x] =
525 				colors_bottom[x * 4 / (width * 5 / 7)];
526 		for (; x < width * 6 / 7; ++x)
527 			((struct color_rgb24 *)mem)[x] =
528 				colors_bottom[(x - width * 5 / 7) * 3
529 					      / (width / 7) + 4];
530 		for (; x < width; ++x)
531 			((struct color_rgb24 *)mem)[x] = colors_bottom[7];
532 		mem += stride;
533 	}
534 }
535 
536 static void
fill_smpte_rgb32(const struct rgb_info * rgb,unsigned char * mem,unsigned int width,unsigned int height,unsigned int stride)537 fill_smpte_rgb32(const struct rgb_info *rgb, unsigned char *mem,
538 		 unsigned int width, unsigned int height, unsigned int stride)
539 {
540 	const uint32_t colors_top[] = {
541 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
542 		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
543 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
544 		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
545 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
546 		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
547 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
548 	};
549 	const uint32_t colors_middle[] = {
550 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
551 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
552 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
553 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
554 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
555 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
556 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
557 	};
558 	const uint32_t colors_bottom[] = {
559 		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
560 		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
561 		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
562 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
563 		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
564 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
565 		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
566 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
567 	};
568 	unsigned int x;
569 	unsigned int y;
570 
571 	for (y = 0; y < height * 6 / 9; ++y) {
572 		for (x = 0; x < width; ++x)
573 			((uint32_t *)mem)[x] = colors_top[x * 7 / width];
574 		mem += stride;
575 	}
576 
577 	for (; y < height * 7 / 9; ++y) {
578 		for (x = 0; x < width; ++x)
579 			((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
580 		mem += stride;
581 	}
582 
583 	for (; y < height; ++y) {
584 		for (x = 0; x < width * 5 / 7; ++x)
585 			((uint32_t *)mem)[x] =
586 				colors_bottom[x * 4 / (width * 5 / 7)];
587 		for (; x < width * 6 / 7; ++x)
588 			((uint32_t *)mem)[x] =
589 				colors_bottom[(x - width * 5 / 7) * 3
590 					      / (width / 7) + 4];
591 		for (; x < width; ++x)
592 			((uint32_t *)mem)[x] = colors_bottom[7];
593 		mem += stride;
594 	}
595 }
596 
597 static void
fill_smpte(const struct format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)598 fill_smpte(const struct format_info *info, void *planes[3], unsigned int width,
599 	   unsigned int height, unsigned int stride)
600 {
601 	unsigned char *u, *v;
602 
603 	switch (info->format) {
604 	case DRM_FORMAT_UYVY:
605 	case DRM_FORMAT_VYUY:
606 	case DRM_FORMAT_YUYV:
607 	case DRM_FORMAT_YVYU:
608 		return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
609 					     height, stride);
610 
611 	case DRM_FORMAT_NV12:
612 	case DRM_FORMAT_NV21:
613 	case DRM_FORMAT_NV16:
614 	case DRM_FORMAT_NV61:
615 		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
616 		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
617 		return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
618 					     width, height, stride);
619 
620 	case DRM_FORMAT_YUV420:
621 		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
622 					     planes[2], width, height, stride);
623 
624 	case DRM_FORMAT_YVU420:
625 		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
626 					     planes[1], width, height, stride);
627 
628 	case DRM_FORMAT_ARGB4444:
629 	case DRM_FORMAT_XRGB4444:
630 	case DRM_FORMAT_ABGR4444:
631 	case DRM_FORMAT_XBGR4444:
632 	case DRM_FORMAT_RGBA4444:
633 	case DRM_FORMAT_RGBX4444:
634 	case DRM_FORMAT_BGRA4444:
635 	case DRM_FORMAT_BGRX4444:
636 	case DRM_FORMAT_RGB565:
637 	case DRM_FORMAT_BGR565:
638 	case DRM_FORMAT_ARGB1555:
639 	case DRM_FORMAT_XRGB1555:
640 	case DRM_FORMAT_ABGR1555:
641 	case DRM_FORMAT_XBGR1555:
642 	case DRM_FORMAT_RGBA5551:
643 	case DRM_FORMAT_RGBX5551:
644 	case DRM_FORMAT_BGRA5551:
645 	case DRM_FORMAT_BGRX5551:
646 		return fill_smpte_rgb16(&info->rgb, planes[0],
647 					width, height, stride);
648 
649 	case DRM_FORMAT_BGR888:
650 	case DRM_FORMAT_RGB888:
651 		return fill_smpte_rgb24(&info->rgb, planes[0],
652 					width, height, stride);
653 	case DRM_FORMAT_ARGB8888:
654 	case DRM_FORMAT_XRGB8888:
655 	case DRM_FORMAT_ABGR8888:
656 	case DRM_FORMAT_XBGR8888:
657 	case DRM_FORMAT_RGBA8888:
658 	case DRM_FORMAT_RGBX8888:
659 	case DRM_FORMAT_BGRA8888:
660 	case DRM_FORMAT_BGRX8888:
661 	case DRM_FORMAT_ARGB2101010:
662 	case DRM_FORMAT_XRGB2101010:
663 	case DRM_FORMAT_ABGR2101010:
664 	case DRM_FORMAT_XBGR2101010:
665 	case DRM_FORMAT_RGBA1010102:
666 	case DRM_FORMAT_RGBX1010102:
667 	case DRM_FORMAT_BGRA1010102:
668 	case DRM_FORMAT_BGRX1010102:
669 		return fill_smpte_rgb32(&info->rgb, planes[0],
670 					width, height, stride);
671 	}
672 }
673 
674 /* swap these for big endian.. */
675 #define RED   2
676 #define GREEN 1
677 #define BLUE  0
678 
679 static void
make_pwetty(void * data,int width,int height,int stride,uint32_t format)680 make_pwetty(void *data, int width, int height, int stride, uint32_t format)
681 {
682 #ifdef HAVE_CAIRO
683 	cairo_surface_t *surface;
684 	cairo_t *cr;
685 	int x, y;
686 	cairo_format_t cairo_format;
687 
688 	/* we can ignore the order of R,G,B channels */
689 	switch (format) {
690 	case DRM_FORMAT_XRGB8888:
691 	case DRM_FORMAT_ARGB8888:
692 	case DRM_FORMAT_XBGR8888:
693 	case DRM_FORMAT_ABGR8888:
694 		cairo_format = CAIRO_FORMAT_ARGB32;
695 		break;
696 	case DRM_FORMAT_RGB565:
697 	case DRM_FORMAT_BGR565:
698 		cairo_format = CAIRO_FORMAT_RGB16_565;
699 		break;
700 	default:
701 		return;
702 	}
703 
704 	surface = cairo_image_surface_create_for_data(data,
705 						      cairo_format,
706 						      width, height,
707 						      stride);
708 	cr = cairo_create(surface);
709 	cairo_surface_destroy(surface);
710 
711 	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
712 	for (x = 0; x < width; x += 250)
713 		for (y = 0; y < height; y += 250) {
714 			char buf[64];
715 
716 			cairo_move_to(cr, x, y - 20);
717 			cairo_line_to(cr, x, y + 20);
718 			cairo_move_to(cr, x - 20, y);
719 			cairo_line_to(cr, x + 20, y);
720 			cairo_new_sub_path(cr);
721 			cairo_arc(cr, x, y, 10, 0, M_PI * 2);
722 			cairo_set_line_width(cr, 4);
723 			cairo_set_source_rgb(cr, 0, 0, 0);
724 			cairo_stroke_preserve(cr);
725 			cairo_set_source_rgb(cr, 1, 1, 1);
726 			cairo_set_line_width(cr, 2);
727 			cairo_stroke(cr);
728 
729 			snprintf(buf, sizeof buf, "%d, %d", x, y);
730 			cairo_move_to(cr, x + 20, y + 20);
731 			cairo_text_path(cr, buf);
732 			cairo_set_source_rgb(cr, 0, 0, 0);
733 			cairo_stroke_preserve(cr);
734 			cairo_set_source_rgb(cr, 1, 1, 1);
735 			cairo_fill(cr);
736 		}
737 
738 	cairo_destroy(cr);
739 #endif
740 }
741 
742 static void
fill_tiles_yuv_planar(const struct format_info * info,unsigned char * y_mem,unsigned char * u_mem,unsigned char * v_mem,unsigned int width,unsigned int height,unsigned int stride)743 fill_tiles_yuv_planar(const struct format_info *info,
744 		      unsigned char *y_mem, unsigned char *u_mem,
745 		      unsigned char *v_mem, unsigned int width,
746 		      unsigned int height, unsigned int stride)
747 {
748 	const struct yuv_info *yuv = &info->yuv;
749 	unsigned int cs = yuv->chroma_stride;
750 	unsigned int xsub = yuv->xsub;
751 	unsigned int ysub = yuv->ysub;
752 	unsigned int x;
753 	unsigned int y;
754 
755 	for (y = 0; y < height; ++y) {
756 		for (x = 0; x < width; ++x) {
757 			div_t d = div(x+y, width);
758 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
759 				       + 0x000a1120 * (d.rem >> 6);
760 			struct color_yuv color =
761 				MAKE_YUV_601((rgb32 >> 16) & 0xff,
762 					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
763 
764 			y_mem[x] = color.y;
765 			u_mem[x/xsub*cs] = color.u;
766 			v_mem[x/xsub*cs] = color.v;
767 		}
768 
769 		y_mem += stride;
770 		if ((y + 1) % ysub == 0) {
771 			u_mem += stride * cs / xsub;
772 			v_mem += stride * cs / xsub;
773 		}
774 	}
775 }
776 
777 static void
fill_tiles_yuv_packed(const struct format_info * info,unsigned char * mem,unsigned int width,unsigned int height,unsigned int stride)778 fill_tiles_yuv_packed(const struct format_info *info, unsigned char *mem,
779 		      unsigned int width, unsigned int height,
780 		      unsigned int stride)
781 {
782 	const struct yuv_info *yuv = &info->yuv;
783 	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
784 	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
785 	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
786 	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
787 	unsigned int x;
788 	unsigned int y;
789 
790 	for (y = 0; y < height; ++y) {
791 		for (x = 0; x < width; x += 2) {
792 			div_t d = div(x+y, width);
793 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
794 				       + 0x000a1120 * (d.rem >> 6);
795 			struct color_yuv color =
796 				MAKE_YUV_601((rgb32 >> 16) & 0xff,
797 					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
798 
799 			y_mem[2*x] = color.y;
800 			c_mem[2*x+u] = color.u;
801 			y_mem[2*x+2] = color.y;
802 			c_mem[2*x+v] = color.v;
803 		}
804 
805 		y_mem += stride;
806 		c_mem += stride;
807 	}
808 }
809 
810 static void
fill_tiles_rgb16(const struct format_info * info,unsigned char * mem,unsigned int width,unsigned int height,unsigned int stride)811 fill_tiles_rgb16(const struct format_info *info, unsigned char *mem,
812 		 unsigned int width, unsigned int height, unsigned int stride)
813 {
814 	const struct rgb_info *rgb = &info->rgb;
815 	unsigned char *mem_base = mem;
816 	unsigned int x, y;
817 
818 	for (y = 0; y < height; ++y) {
819 		for (x = 0; x < width; ++x) {
820 			div_t d = div(x+y, width);
821 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
822 				       + 0x000a1120 * (d.rem >> 6);
823 			uint16_t color =
824 				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
825 					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
826 					  255);
827 
828 			((uint16_t *)mem)[x] = color;
829 		}
830 		mem += stride;
831 	}
832 
833 	make_pwetty(mem_base, width, height, stride, info->format);
834 }
835 
836 static void
fill_tiles_rgb24(const struct format_info * info,unsigned char * mem,unsigned int width,unsigned int height,unsigned int stride)837 fill_tiles_rgb24(const struct format_info *info, unsigned char *mem,
838 		 unsigned int width, unsigned int height, unsigned int stride)
839 {
840 	const struct rgb_info *rgb = &info->rgb;
841 	unsigned int x, y;
842 
843 	for (y = 0; y < height; ++y) {
844 		for (x = 0; x < width; ++x) {
845 			div_t d = div(x+y, width);
846 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
847 				       + 0x000a1120 * (d.rem >> 6);
848 			struct color_rgb24 color =
849 				MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
850 					   (rgb32 >> 8) & 0xff, rgb32 & 0xff);
851 
852 			((struct color_rgb24 *)mem)[x] = color;
853 		}
854 		mem += stride;
855 	}
856 }
857 
858 static void
fill_tiles_rgb32(const struct format_info * info,unsigned char * mem,unsigned int width,unsigned int height,unsigned int stride)859 fill_tiles_rgb32(const struct format_info *info, unsigned char *mem,
860 		 unsigned int width, unsigned int height, unsigned int stride)
861 {
862 	const struct rgb_info *rgb = &info->rgb;
863 	unsigned char *mem_base = mem;
864 	unsigned int x, y;
865 
866 	for (y = 0; y < height; ++y) {
867 		for (x = 0; x < width; ++x) {
868 			div_t d = div(x+y, width);
869 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
870 				       + 0x000a1120 * (d.rem >> 6);
871 			uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
872 			uint32_t color =
873 				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
874 					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
875 					  alpha);
876 
877 			((uint32_t *)mem)[x] = color;
878 		}
879 		mem += stride;
880 	}
881 
882 	make_pwetty(mem_base, width, height, stride, info->format);
883 }
884 
885 static void
fill_tiles(const struct format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)886 fill_tiles(const struct format_info *info, void *planes[3], unsigned int width,
887 	   unsigned int height, unsigned int stride)
888 {
889 	unsigned char *u, *v;
890 
891 	switch (info->format) {
892 	case DRM_FORMAT_UYVY:
893 	case DRM_FORMAT_VYUY:
894 	case DRM_FORMAT_YUYV:
895 	case DRM_FORMAT_YVYU:
896 		return fill_tiles_yuv_packed(info, planes[0],
897 					     width, height, stride);
898 
899 	case DRM_FORMAT_NV12:
900 	case DRM_FORMAT_NV21:
901 	case DRM_FORMAT_NV16:
902 	case DRM_FORMAT_NV61:
903 		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
904 		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
905 		return fill_tiles_yuv_planar(info, planes[0], u, v,
906 					     width, height, stride);
907 
908 	case DRM_FORMAT_YUV420:
909 		return fill_tiles_yuv_planar(info, planes[0], planes[1],
910 					     planes[2], width, height, stride);
911 
912 	case DRM_FORMAT_YVU420:
913 		return fill_tiles_yuv_planar(info, planes[0], planes[2],
914 					     planes[1], width, height, stride);
915 
916 	case DRM_FORMAT_ARGB4444:
917 	case DRM_FORMAT_XRGB4444:
918 	case DRM_FORMAT_ABGR4444:
919 	case DRM_FORMAT_XBGR4444:
920 	case DRM_FORMAT_RGBA4444:
921 	case DRM_FORMAT_RGBX4444:
922 	case DRM_FORMAT_BGRA4444:
923 	case DRM_FORMAT_BGRX4444:
924 	case DRM_FORMAT_RGB565:
925 	case DRM_FORMAT_BGR565:
926 	case DRM_FORMAT_ARGB1555:
927 	case DRM_FORMAT_XRGB1555:
928 	case DRM_FORMAT_ABGR1555:
929 	case DRM_FORMAT_XBGR1555:
930 	case DRM_FORMAT_RGBA5551:
931 	case DRM_FORMAT_RGBX5551:
932 	case DRM_FORMAT_BGRA5551:
933 	case DRM_FORMAT_BGRX5551:
934 		return fill_tiles_rgb16(info, planes[0],
935 					width, height, stride);
936 
937 	case DRM_FORMAT_BGR888:
938 	case DRM_FORMAT_RGB888:
939 		return fill_tiles_rgb24(info, planes[0],
940 					width, height, stride);
941 	case DRM_FORMAT_ARGB8888:
942 	case DRM_FORMAT_XRGB8888:
943 	case DRM_FORMAT_ABGR8888:
944 	case DRM_FORMAT_XBGR8888:
945 	case DRM_FORMAT_RGBA8888:
946 	case DRM_FORMAT_RGBX8888:
947 	case DRM_FORMAT_BGRA8888:
948 	case DRM_FORMAT_BGRX8888:
949 	case DRM_FORMAT_ARGB2101010:
950 	case DRM_FORMAT_XRGB2101010:
951 	case DRM_FORMAT_ABGR2101010:
952 	case DRM_FORMAT_XBGR2101010:
953 	case DRM_FORMAT_RGBA1010102:
954 	case DRM_FORMAT_RGBX1010102:
955 	case DRM_FORMAT_BGRA1010102:
956 	case DRM_FORMAT_BGRX1010102:
957 		return fill_tiles_rgb32(info, planes[0],
958 					width, height, stride);
959 	}
960 }
961 
962 static void
fill_plain(const struct format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)963 fill_plain(const struct format_info *info, void *planes[3], unsigned int width,
964 	   unsigned int height, unsigned int stride)
965 {
966 	memset(planes[0], 0x77, stride * height);
967 }
968 
969 /*
970  * fill_pattern - Fill a buffer with a test pattern
971  * @format: Pixel format
972  * @pattern: Test pattern
973  * @buffer: Buffer memory
974  * @width: Width in pixels
975  * @height: Height in pixels
976  * @stride: Line stride (pitch) in bytes
977  *
978  * Fill the buffer with the test pattern specified by the pattern parameter.
979  * Supported formats vary depending on the selected pattern.
980  */
981 static void
fill_pattern(unsigned int format,enum fill_pattern pattern,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)982 fill_pattern(unsigned int format, enum fill_pattern pattern, void *planes[3],
983 	     unsigned int width, unsigned int height, unsigned int stride)
984 {
985 	const struct format_info *info = NULL;
986 	unsigned int i;
987 
988 	for (i = 0; i < ARRAY_SIZE(format_info); ++i) {
989 		if (format_info[i].format == format) {
990 			info = &format_info[i];
991 			break;
992 		}
993 	}
994 
995 	if (info == NULL)
996 		return;
997 
998 	switch (pattern) {
999 	case PATTERN_TILES:
1000 		return fill_tiles(info, planes, width, height, stride);
1001 
1002 	case PATTERN_SMPTE:
1003 		return fill_smpte(info, planes, width, height, stride);
1004 
1005 	case PATTERN_PLAIN:
1006 		return fill_plain(info, planes, width, height, stride);
1007 
1008 	default:
1009 		printf("Error: unsupported test pattern %u.\n", pattern);
1010 		break;
1011 	}
1012 }
1013 
1014 /* -----------------------------------------------------------------------------
1015  * Buffers management
1016  */
1017 
1018 static struct bo *
bo_create_dumb(int fd,unsigned int width,unsigned int height,unsigned int bpp)1019 bo_create_dumb(int fd, unsigned int width, unsigned int height, unsigned int bpp)
1020 {
1021 	struct drm_mode_create_dumb arg;
1022 	struct bo *bo;
1023 	int ret;
1024 
1025 	bo = malloc(sizeof(*bo));
1026 	if (bo == NULL) {
1027 		fprintf(stderr, "failed to allocate buffer object\n");
1028 		return NULL;
1029 	}
1030 
1031 	memset(&arg, 0, sizeof(arg));
1032 	arg.bpp = bpp;
1033 	arg.width = width;
1034 	arg.height = height;
1035 
1036 	ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
1037 	if (ret) {
1038 		fprintf(stderr, "failed to create dumb buffer: %s\n",
1039 			strerror(errno));
1040 		free(bo);
1041 		return NULL;
1042 	}
1043 
1044 	bo->fd = fd;
1045 	bo->handle = arg.handle;
1046 	bo->size = arg.size;
1047 	bo->pitch = arg.pitch;
1048 
1049 	return bo;
1050 }
1051 
bo_map(struct bo * bo,void ** out)1052 static int bo_map(struct bo *bo, void **out)
1053 {
1054 	struct drm_mode_map_dumb arg;
1055 	void *map;
1056 	int ret;
1057 
1058 	memset(&arg, 0, sizeof(arg));
1059 	arg.handle = bo->handle;
1060 
1061 	ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
1062 	if (ret)
1063 		return ret;
1064 
1065 	map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
1066 		       bo->fd, arg.offset);
1067 	if (map == MAP_FAILED)
1068 		return -EINVAL;
1069 
1070 	bo->ptr = map;
1071 	*out = map;
1072 
1073 	return 0;
1074 }
1075 
bo_unmap(struct bo * bo)1076 static void bo_unmap(struct bo *bo)
1077 {
1078 	if (!bo->ptr)
1079 		return;
1080 
1081 	drm_munmap(bo->ptr, bo->size);
1082 	bo->ptr = NULL;
1083 }
1084 
1085 struct bo *
bo_create(int fd,unsigned int format,unsigned int width,unsigned int height,unsigned int handles[4],unsigned int pitches[4],unsigned int offsets[4],enum fill_pattern pattern)1086 bo_create(int fd, unsigned int format,
1087 	  unsigned int width, unsigned int height,
1088 	  unsigned int handles[4], unsigned int pitches[4],
1089 	  unsigned int offsets[4], enum fill_pattern pattern)
1090 {
1091 	unsigned int virtual_height;
1092 	struct bo *bo;
1093 	unsigned int bpp;
1094 	void *planes[3] = { 0, };
1095 	void *virtual;
1096 	int ret;
1097 
1098 	switch (format) {
1099 	case DRM_FORMAT_NV12:
1100 	case DRM_FORMAT_NV21:
1101 	case DRM_FORMAT_NV16:
1102 	case DRM_FORMAT_NV61:
1103 	case DRM_FORMAT_YUV420:
1104 	case DRM_FORMAT_YVU420:
1105 		bpp = 8;
1106 		break;
1107 
1108 	case DRM_FORMAT_ARGB4444:
1109 	case DRM_FORMAT_XRGB4444:
1110 	case DRM_FORMAT_ABGR4444:
1111 	case DRM_FORMAT_XBGR4444:
1112 	case DRM_FORMAT_RGBA4444:
1113 	case DRM_FORMAT_RGBX4444:
1114 	case DRM_FORMAT_BGRA4444:
1115 	case DRM_FORMAT_BGRX4444:
1116 	case DRM_FORMAT_ARGB1555:
1117 	case DRM_FORMAT_XRGB1555:
1118 	case DRM_FORMAT_ABGR1555:
1119 	case DRM_FORMAT_XBGR1555:
1120 	case DRM_FORMAT_RGBA5551:
1121 	case DRM_FORMAT_RGBX5551:
1122 	case DRM_FORMAT_BGRA5551:
1123 	case DRM_FORMAT_BGRX5551:
1124 	case DRM_FORMAT_RGB565:
1125 	case DRM_FORMAT_BGR565:
1126 	case DRM_FORMAT_UYVY:
1127 	case DRM_FORMAT_VYUY:
1128 	case DRM_FORMAT_YUYV:
1129 	case DRM_FORMAT_YVYU:
1130 		bpp = 16;
1131 		break;
1132 
1133 	case DRM_FORMAT_BGR888:
1134 	case DRM_FORMAT_RGB888:
1135 		bpp = 24;
1136 		break;
1137 
1138 	case DRM_FORMAT_ARGB8888:
1139 	case DRM_FORMAT_XRGB8888:
1140 	case DRM_FORMAT_ABGR8888:
1141 	case DRM_FORMAT_XBGR8888:
1142 	case DRM_FORMAT_RGBA8888:
1143 	case DRM_FORMAT_RGBX8888:
1144 	case DRM_FORMAT_BGRA8888:
1145 	case DRM_FORMAT_BGRX8888:
1146 	case DRM_FORMAT_ARGB2101010:
1147 	case DRM_FORMAT_XRGB2101010:
1148 	case DRM_FORMAT_ABGR2101010:
1149 	case DRM_FORMAT_XBGR2101010:
1150 	case DRM_FORMAT_RGBA1010102:
1151 	case DRM_FORMAT_RGBX1010102:
1152 	case DRM_FORMAT_BGRA1010102:
1153 	case DRM_FORMAT_BGRX1010102:
1154 		bpp = 32;
1155 		break;
1156 
1157 	default:
1158 		fprintf(stderr, "unsupported format 0x%08x\n",  format);
1159 		return NULL;
1160 	}
1161 
1162 	switch (format) {
1163 	case DRM_FORMAT_NV12:
1164 	case DRM_FORMAT_NV21:
1165 		virtual_height = height * 3 / 2;
1166 		break;
1167 
1168 	case DRM_FORMAT_NV16:
1169 	case DRM_FORMAT_NV61:
1170 		virtual_height = height * 2;
1171 		break;
1172 
1173 	default:
1174 		virtual_height = height;
1175 		break;
1176 	}
1177 
1178 	bo = bo_create_dumb(fd, width, virtual_height, bpp);
1179 	if (!bo)
1180 		return NULL;
1181 
1182 	ret = bo_map(bo, &virtual);
1183 	if (ret) {
1184 		fprintf(stderr, "failed to map buffer: %s\n",
1185 			strerror(-errno));
1186 		bo_destroy(bo);
1187 		return NULL;
1188 	}
1189 
1190 	/* just testing a limited # of formats to test single
1191 	 * and multi-planar path.. would be nice to add more..
1192 	 */
1193 	switch (format) {
1194 	case DRM_FORMAT_UYVY:
1195 	case DRM_FORMAT_VYUY:
1196 	case DRM_FORMAT_YUYV:
1197 	case DRM_FORMAT_YVYU:
1198 		offsets[0] = 0;
1199 		handles[0] = bo->handle;
1200 		pitches[0] = bo->pitch;
1201 
1202 		planes[0] = virtual;
1203 		break;
1204 
1205 	case DRM_FORMAT_NV12:
1206 	case DRM_FORMAT_NV21:
1207 	case DRM_FORMAT_NV16:
1208 	case DRM_FORMAT_NV61:
1209 		offsets[0] = 0;
1210 		handles[0] = bo->handle;
1211 		pitches[0] = bo->pitch;
1212 		pitches[1] = pitches[0];
1213 		offsets[1] = pitches[0] * height;
1214 		handles[1] = bo->handle;
1215 
1216 		planes[0] = virtual;
1217 		planes[1] = virtual + offsets[1];
1218 		break;
1219 
1220 	case DRM_FORMAT_YUV420:
1221 	case DRM_FORMAT_YVU420:
1222 		offsets[0] = 0;
1223 		handles[0] = bo->handle;
1224 		pitches[0] = bo->pitch;
1225 		pitches[1] = pitches[0] / 2;
1226 		offsets[1] = pitches[0] * height;
1227 		handles[1] = bo->handle;
1228 		pitches[2] = pitches[1];
1229 		offsets[2] = offsets[1] + pitches[1] * height / 2;
1230 		handles[2] = bo->handle;
1231 
1232 		planes[0] = virtual;
1233 		planes[1] = virtual + offsets[1];
1234 		planes[2] = virtual + offsets[2];
1235 		break;
1236 
1237 	case DRM_FORMAT_ARGB4444:
1238 	case DRM_FORMAT_XRGB4444:
1239 	case DRM_FORMAT_ABGR4444:
1240 	case DRM_FORMAT_XBGR4444:
1241 	case DRM_FORMAT_RGBA4444:
1242 	case DRM_FORMAT_RGBX4444:
1243 	case DRM_FORMAT_BGRA4444:
1244 	case DRM_FORMAT_BGRX4444:
1245 	case DRM_FORMAT_ARGB1555:
1246 	case DRM_FORMAT_XRGB1555:
1247 	case DRM_FORMAT_ABGR1555:
1248 	case DRM_FORMAT_XBGR1555:
1249 	case DRM_FORMAT_RGBA5551:
1250 	case DRM_FORMAT_RGBX5551:
1251 	case DRM_FORMAT_BGRA5551:
1252 	case DRM_FORMAT_BGRX5551:
1253 	case DRM_FORMAT_RGB565:
1254 	case DRM_FORMAT_BGR565:
1255 	case DRM_FORMAT_BGR888:
1256 	case DRM_FORMAT_RGB888:
1257 	case DRM_FORMAT_ARGB8888:
1258 	case DRM_FORMAT_XRGB8888:
1259 	case DRM_FORMAT_ABGR8888:
1260 	case DRM_FORMAT_XBGR8888:
1261 	case DRM_FORMAT_RGBA8888:
1262 	case DRM_FORMAT_RGBX8888:
1263 	case DRM_FORMAT_BGRA8888:
1264 	case DRM_FORMAT_BGRX8888:
1265 	case DRM_FORMAT_ARGB2101010:
1266 	case DRM_FORMAT_XRGB2101010:
1267 	case DRM_FORMAT_ABGR2101010:
1268 	case DRM_FORMAT_XBGR2101010:
1269 	case DRM_FORMAT_RGBA1010102:
1270 	case DRM_FORMAT_RGBX1010102:
1271 	case DRM_FORMAT_BGRA1010102:
1272 	case DRM_FORMAT_BGRX1010102:
1273 		offsets[0] = 0;
1274 		handles[0] = bo->handle;
1275 		pitches[0] = bo->pitch;
1276 
1277 		planes[0] = virtual;
1278 		break;
1279 	}
1280 
1281 	fill_pattern(format, pattern, planes, width, height, pitches[0]);
1282 	bo_unmap(bo);
1283 
1284 	return bo;
1285 }
1286 
bo_destroy(struct bo * bo)1287 void bo_destroy(struct bo *bo)
1288 {
1289 	struct drm_mode_destroy_dumb arg;
1290 	int ret;
1291 
1292 	memset(&arg, 0, sizeof(arg));
1293 	arg.handle = bo->handle;
1294 
1295 	ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
1296 	if (ret)
1297 		fprintf(stderr, "failed to destroy dumb buffer: %s\n",
1298 			strerror(errno));
1299 
1300 	free(bo);
1301 }
1302