Home | History | Annotate | Download | only in modetest
      1 /*
      2  * DRM based mode setting test program
      3  * Copyright 2008 Tungsten Graphics
      4  *   Jakob Bornecrantz <jakob (at) tungstengraphics.com>
      5  * Copyright 2008 Intel Corporation
      6  *   Jesse Barnes <jesse.barnes (at) 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 
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 *
   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 
   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 
   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 *
   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 
   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