Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright 2008 Tungsten Graphics
      3  *   Jakob Bornecrantz <jakob (at) tungstengraphics.com>
      4  * Copyright 2008 Intel Corporation
      5  *   Jesse Barnes <jesse.barnes (at) intel.com>
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in
     15  * all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     23  * IN THE SOFTWARE.
     24  */
     25 
     26 #ifdef HAVE_CONFIG_H
     27 #include "config.h"
     28 #endif
     29 
     30 #include <stdint.h>
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <string.h>
     34 
     35 #include <drm_fourcc.h>
     36 
     37 #ifdef HAVE_CAIRO
     38 #include <cairo.h>
     39 #include <math.h>
     40 #endif
     41 
     42 #include "format.h"
     43 #include "pattern.h"
     44 
     45 struct color_rgb24 {
     46 	unsigned int value:24;
     47 } __attribute__((__packed__));
     48 
     49 struct color_yuv {
     50 	unsigned char y;
     51 	unsigned char u;
     52 	unsigned char v;
     53 };
     54 
     55 #define MAKE_YUV_601_Y(r, g, b) \
     56 	((( 66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
     57 #define MAKE_YUV_601_U(r, g, b) \
     58 	(((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
     59 #define MAKE_YUV_601_V(r, g, b) \
     60 	(((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
     61 
     62 #define MAKE_YUV_601(r, g, b) \
     63 	{ .y = MAKE_YUV_601_Y(r, g, b), \
     64 	  .u = MAKE_YUV_601_U(r, g, b), \
     65 	  .v = MAKE_YUV_601_V(r, g, b) }
     66 
     67 #define MAKE_RGBA(rgb, r, g, b, a) \
     68 	((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \
     69 	 (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \
     70 	 (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \
     71 	 (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset))
     72 
     73 #define MAKE_RGB24(rgb, r, g, b) \
     74 	{ .value = MAKE_RGBA(rgb, r, g, b, 0) }
     75 
     76 static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv,
     77 				  unsigned char *y_mem, unsigned char *u_mem,
     78 				  unsigned char *v_mem, unsigned int width,
     79 				  unsigned int height, unsigned int stride)
     80 {
     81 	const struct color_yuv colors_top[] = {
     82 		MAKE_YUV_601(191, 192, 192),	/* grey */
     83 		MAKE_YUV_601(192, 192, 0),	/* yellow */
     84 		MAKE_YUV_601(0, 192, 192),	/* cyan */
     85 		MAKE_YUV_601(0, 192, 0),	/* green */
     86 		MAKE_YUV_601(192, 0, 192),	/* magenta */
     87 		MAKE_YUV_601(192, 0, 0),	/* red */
     88 		MAKE_YUV_601(0, 0, 192),	/* blue */
     89 	};
     90 	const struct color_yuv colors_middle[] = {
     91 		MAKE_YUV_601(0, 0, 192),	/* blue */
     92 		MAKE_YUV_601(19, 19, 19),	/* black */
     93 		MAKE_YUV_601(192, 0, 192),	/* magenta */
     94 		MAKE_YUV_601(19, 19, 19),	/* black */
     95 		MAKE_YUV_601(0, 192, 192),	/* cyan */
     96 		MAKE_YUV_601(19, 19, 19),	/* black */
     97 		MAKE_YUV_601(192, 192, 192),	/* grey */
     98 	};
     99 	const struct color_yuv colors_bottom[] = {
    100 		MAKE_YUV_601(0, 33, 76),	/* in-phase */
    101 		MAKE_YUV_601(255, 255, 255),	/* super white */
    102 		MAKE_YUV_601(50, 0, 106),	/* quadrature */
    103 		MAKE_YUV_601(19, 19, 19),	/* black */
    104 		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
    105 		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
    106 		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
    107 		MAKE_YUV_601(19, 19, 19),	/* black */
    108 	};
    109 	unsigned int cs = yuv->chroma_stride;
    110 	unsigned int xsub = yuv->xsub;
    111 	unsigned int ysub = yuv->ysub;
    112 	unsigned int x;
    113 	unsigned int y;
    114 
    115 	/* Luma */
    116 	for (y = 0; y < height * 6 / 9; ++y) {
    117 		for (x = 0; x < width; ++x)
    118 			y_mem[x] = colors_top[x * 7 / width].y;
    119 		y_mem += stride;
    120 	}
    121 
    122 	for (; y < height * 7 / 9; ++y) {
    123 		for (x = 0; x < width; ++x)
    124 			y_mem[x] = colors_middle[x * 7 / width].y;
    125 		y_mem += stride;
    126 	}
    127 
    128 	for (; y < height; ++y) {
    129 		for (x = 0; x < width * 5 / 7; ++x)
    130 			y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
    131 		for (; x < width * 6 / 7; ++x)
    132 			y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
    133 						 / (width / 7) + 4].y;
    134 		for (; x < width; ++x)
    135 			y_mem[x] = colors_bottom[7].y;
    136 		y_mem += stride;
    137 	}
    138 
    139 	/* Chroma */
    140 	for (y = 0; y < height / ysub * 6 / 9; ++y) {
    141 		for (x = 0; x < width; x += xsub) {
    142 			u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
    143 			v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
    144 		}
    145 		u_mem += stride * cs / xsub;
    146 		v_mem += stride * cs / xsub;
    147 	}
    148 
    149 	for (; y < height / ysub * 7 / 9; ++y) {
    150 		for (x = 0; x < width; x += xsub) {
    151 			u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
    152 			v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
    153 		}
    154 		u_mem += stride * cs / xsub;
    155 		v_mem += stride * cs / xsub;
    156 	}
    157 
    158 	for (; y < height / ysub; ++y) {
    159 		for (x = 0; x < width * 5 / 7; x += xsub) {
    160 			u_mem[x*cs/xsub] =
    161 				colors_bottom[x * 4 / (width * 5 / 7)].u;
    162 			v_mem[x*cs/xsub] =
    163 				colors_bottom[x * 4 / (width * 5 / 7)].v;
    164 		}
    165 		for (; x < width * 6 / 7; x += xsub) {
    166 			u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
    167 							 3 / (width / 7) + 4].u;
    168 			v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
    169 							 3 / (width / 7) + 4].v;
    170 		}
    171 		for (; x < width; x += xsub) {
    172 			u_mem[x*cs/xsub] = colors_bottom[7].u;
    173 			v_mem[x*cs/xsub] = colors_bottom[7].v;
    174 		}
    175 		u_mem += stride * cs / xsub;
    176 		v_mem += stride * cs / xsub;
    177 	}
    178 }
    179 
    180 static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem,
    181 				  unsigned int width, unsigned int height,
    182 				  unsigned int stride)
    183 {
    184 	const struct color_yuv colors_top[] = {
    185 		MAKE_YUV_601(191, 192, 192),	/* grey */
    186 		MAKE_YUV_601(192, 192, 0),	/* yellow */
    187 		MAKE_YUV_601(0, 192, 192),	/* cyan */
    188 		MAKE_YUV_601(0, 192, 0),	/* green */
    189 		MAKE_YUV_601(192, 0, 192),	/* magenta */
    190 		MAKE_YUV_601(192, 0, 0),	/* red */
    191 		MAKE_YUV_601(0, 0, 192),	/* blue */
    192 	};
    193 	const struct color_yuv colors_middle[] = {
    194 		MAKE_YUV_601(0, 0, 192),	/* blue */
    195 		MAKE_YUV_601(19, 19, 19),	/* black */
    196 		MAKE_YUV_601(192, 0, 192),	/* magenta */
    197 		MAKE_YUV_601(19, 19, 19),	/* black */
    198 		MAKE_YUV_601(0, 192, 192),	/* cyan */
    199 		MAKE_YUV_601(19, 19, 19),	/* black */
    200 		MAKE_YUV_601(192, 192, 192),	/* grey */
    201 	};
    202 	const struct color_yuv colors_bottom[] = {
    203 		MAKE_YUV_601(0, 33, 76),	/* in-phase */
    204 		MAKE_YUV_601(255, 255, 255),	/* super white */
    205 		MAKE_YUV_601(50, 0, 106),	/* quadrature */
    206 		MAKE_YUV_601(19, 19, 19),	/* black */
    207 		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
    208 		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
    209 		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
    210 		MAKE_YUV_601(19, 19, 19),	/* black */
    211 	};
    212 	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
    213 	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
    214 	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
    215 	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
    216 	unsigned int x;
    217 	unsigned int y;
    218 
    219 	/* Luma */
    220 	for (y = 0; y < height * 6 / 9; ++y) {
    221 		for (x = 0; x < width; ++x)
    222 			y_mem[2*x] = colors_top[x * 7 / width].y;
    223 		y_mem += stride;
    224 	}
    225 
    226 	for (; y < height * 7 / 9; ++y) {
    227 		for (x = 0; x < width; ++x)
    228 			y_mem[2*x] = colors_middle[x * 7 / width].y;
    229 		y_mem += stride;
    230 	}
    231 
    232 	for (; y < height; ++y) {
    233 		for (x = 0; x < width * 5 / 7; ++x)
    234 			y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
    235 		for (; x < width * 6 / 7; ++x)
    236 			y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
    237 						   / (width / 7) + 4].y;
    238 		for (; x < width; ++x)
    239 			y_mem[2*x] = colors_bottom[7].y;
    240 		y_mem += stride;
    241 	}
    242 
    243 	/* Chroma */
    244 	for (y = 0; y < height * 6 / 9; ++y) {
    245 		for (x = 0; x < width; x += 2) {
    246 			c_mem[2*x+u] = colors_top[x * 7 / width].u;
    247 			c_mem[2*x+v] = colors_top[x * 7 / width].v;
    248 		}
    249 		c_mem += stride;
    250 	}
    251 
    252 	for (; y < height * 7 / 9; ++y) {
    253 		for (x = 0; x < width; x += 2) {
    254 			c_mem[2*x+u] = colors_middle[x * 7 / width].u;
    255 			c_mem[2*x+v] = colors_middle[x * 7 / width].v;
    256 		}
    257 		c_mem += stride;
    258 	}
    259 
    260 	for (; y < height; ++y) {
    261 		for (x = 0; x < width * 5 / 7; x += 2) {
    262 			c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
    263 			c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
    264 		}
    265 		for (; x < width * 6 / 7; x += 2) {
    266 			c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
    267 						     3 / (width / 7) + 4].u;
    268 			c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
    269 						     3 / (width / 7) + 4].v;
    270 		}
    271 		for (; x < width; x += 2) {
    272 			c_mem[2*x+u] = colors_bottom[7].u;
    273 			c_mem[2*x+v] = colors_bottom[7].v;
    274 		}
    275 		c_mem += stride;
    276 	}
    277 }
    278 
    279 static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
    280 			     unsigned int width, unsigned int height,
    281 			     unsigned int stride)
    282 {
    283 	const uint16_t colors_top[] = {
    284 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
    285 		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
    286 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
    287 		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
    288 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
    289 		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
    290 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
    291 	};
    292 	const uint16_t colors_middle[] = {
    293 		MAKE_RGBA(rgb, 0, 0, 192, 127),		/* blue */
    294 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
    295 		MAKE_RGBA(rgb, 192, 0, 192, 127),	/* magenta */
    296 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
    297 		MAKE_RGBA(rgb, 0, 192, 192, 127),	/* cyan */
    298 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
    299 		MAKE_RGBA(rgb, 192, 192, 192, 127),	/* grey */
    300 	};
    301 	const uint16_t colors_bottom[] = {
    302 		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
    303 		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
    304 		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
    305 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
    306 		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
    307 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
    308 		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
    309 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
    310 	};
    311 	unsigned int x;
    312 	unsigned int y;
    313 
    314 	for (y = 0; y < height * 6 / 9; ++y) {
    315 		for (x = 0; x < width; ++x)
    316 			((uint16_t *)mem)[x] = colors_top[x * 7 / width];
    317 		mem += stride;
    318 	}
    319 
    320 	for (; y < height * 7 / 9; ++y) {
    321 		for (x = 0; x < width; ++x)
    322 			((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
    323 		mem += stride;
    324 	}
    325 
    326 	for (; y < height; ++y) {
    327 		for (x = 0; x < width * 5 / 7; ++x)
    328 			((uint16_t *)mem)[x] =
    329 				colors_bottom[x * 4 / (width * 5 / 7)];
    330 		for (; x < width * 6 / 7; ++x)
    331 			((uint16_t *)mem)[x] =
    332 				colors_bottom[(x - width * 5 / 7) * 3
    333 					      / (width / 7) + 4];
    334 		for (; x < width; ++x)
    335 			((uint16_t *)mem)[x] = colors_bottom[7];
    336 		mem += stride;
    337 	}
    338 }
    339 
    340 static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem,
    341 			     unsigned int width, unsigned int height,
    342 			     unsigned int stride)
    343 {
    344 	const struct color_rgb24 colors_top[] = {
    345 		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
    346 		MAKE_RGB24(rgb, 192, 192, 0),	/* yellow */
    347 		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
    348 		MAKE_RGB24(rgb, 0, 192, 0),	/* green */
    349 		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
    350 		MAKE_RGB24(rgb, 192, 0, 0),	/* red */
    351 		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
    352 	};
    353 	const struct color_rgb24 colors_middle[] = {
    354 		MAKE_RGB24(rgb, 0, 0, 192),	/* blue */
    355 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
    356 		MAKE_RGB24(rgb, 192, 0, 192),	/* magenta */
    357 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
    358 		MAKE_RGB24(rgb, 0, 192, 192),	/* cyan */
    359 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
    360 		MAKE_RGB24(rgb, 192, 192, 192),	/* grey */
    361 	};
    362 	const struct color_rgb24 colors_bottom[] = {
    363 		MAKE_RGB24(rgb, 0, 33, 76),	/* in-phase */
    364 		MAKE_RGB24(rgb, 255, 255, 255),	/* super white */
    365 		MAKE_RGB24(rgb, 50, 0, 106),	/* quadrature */
    366 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
    367 		MAKE_RGB24(rgb, 9, 9, 9),	/* 3.5% */
    368 		MAKE_RGB24(rgb, 19, 19, 19),	/* 7.5% */
    369 		MAKE_RGB24(rgb, 29, 29, 29),	/* 11.5% */
    370 		MAKE_RGB24(rgb, 19, 19, 19),	/* black */
    371 	};
    372 	unsigned int x;
    373 	unsigned int y;
    374 
    375 	for (y = 0; y < height * 6 / 9; ++y) {
    376 		for (x = 0; x < width; ++x)
    377 			((struct color_rgb24 *)mem)[x] =
    378 				colors_top[x * 7 / width];
    379 		mem += stride;
    380 	}
    381 
    382 	for (; y < height * 7 / 9; ++y) {
    383 		for (x = 0; x < width; ++x)
    384 			((struct color_rgb24 *)mem)[x] =
    385 				colors_middle[x * 7 / width];
    386 		mem += stride;
    387 	}
    388 
    389 	for (; y < height; ++y) {
    390 		for (x = 0; x < width * 5 / 7; ++x)
    391 			((struct color_rgb24 *)mem)[x] =
    392 				colors_bottom[x * 4 / (width * 5 / 7)];
    393 		for (; x < width * 6 / 7; ++x)
    394 			((struct color_rgb24 *)mem)[x] =
    395 				colors_bottom[(x - width * 5 / 7) * 3
    396 					      / (width / 7) + 4];
    397 		for (; x < width; ++x)
    398 			((struct color_rgb24 *)mem)[x] = colors_bottom[7];
    399 		mem += stride;
    400 	}
    401 }
    402 
    403 static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem,
    404 			     unsigned int width, unsigned int height,
    405 			     unsigned int stride)
    406 {
    407 	const uint32_t colors_top[] = {
    408 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
    409 		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
    410 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
    411 		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
    412 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
    413 		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
    414 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
    415 	};
    416 	const uint32_t colors_middle[] = {
    417 		MAKE_RGBA(rgb, 0, 0, 192, 127),		/* blue */
    418 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
    419 		MAKE_RGBA(rgb, 192, 0, 192, 127),	/* magenta */
    420 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
    421 		MAKE_RGBA(rgb, 0, 192, 192, 127),	/* cyan */
    422 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
    423 		MAKE_RGBA(rgb, 192, 192, 192, 127),	/* grey */
    424 	};
    425 	const uint32_t colors_bottom[] = {
    426 		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
    427 		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
    428 		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
    429 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
    430 		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
    431 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
    432 		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
    433 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
    434 	};
    435 	unsigned int x;
    436 	unsigned int y;
    437 
    438 	for (y = 0; y < height * 6 / 9; ++y) {
    439 		for (x = 0; x < width; ++x)
    440 			((uint32_t *)mem)[x] = colors_top[x * 7 / width];
    441 		mem += stride;
    442 	}
    443 
    444 	for (; y < height * 7 / 9; ++y) {
    445 		for (x = 0; x < width; ++x)
    446 			((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
    447 		mem += stride;
    448 	}
    449 
    450 	for (; y < height; ++y) {
    451 		for (x = 0; x < width * 5 / 7; ++x)
    452 			((uint32_t *)mem)[x] =
    453 				colors_bottom[x * 4 / (width * 5 / 7)];
    454 		for (; x < width * 6 / 7; ++x)
    455 			((uint32_t *)mem)[x] =
    456 				colors_bottom[(x - width * 5 / 7) * 3
    457 					      / (width / 7) + 4];
    458 		for (; x < width; ++x)
    459 			((uint32_t *)mem)[x] = colors_bottom[7];
    460 		mem += stride;
    461 	}
    462 }
    463 
    464 static void fill_smpte(const struct util_format_info *info, void *planes[3],
    465 		       unsigned int width, unsigned int height,
    466 		       unsigned int stride)
    467 {
    468 	unsigned char *u, *v;
    469 
    470 	switch (info->format) {
    471 	case DRM_FORMAT_UYVY:
    472 	case DRM_FORMAT_VYUY:
    473 	case DRM_FORMAT_YUYV:
    474 	case DRM_FORMAT_YVYU:
    475 		return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
    476 					     height, stride);
    477 
    478 	case DRM_FORMAT_NV12:
    479 	case DRM_FORMAT_NV21:
    480 	case DRM_FORMAT_NV16:
    481 	case DRM_FORMAT_NV61:
    482 		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
    483 		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
    484 		return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
    485 					     width, height, stride);
    486 
    487 	case DRM_FORMAT_YUV420:
    488 		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
    489 					     planes[2], width, height, stride);
    490 
    491 	case DRM_FORMAT_YVU420:
    492 		return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
    493 					     planes[1], width, height, stride);
    494 
    495 	case DRM_FORMAT_ARGB4444:
    496 	case DRM_FORMAT_XRGB4444:
    497 	case DRM_FORMAT_ABGR4444:
    498 	case DRM_FORMAT_XBGR4444:
    499 	case DRM_FORMAT_RGBA4444:
    500 	case DRM_FORMAT_RGBX4444:
    501 	case DRM_FORMAT_BGRA4444:
    502 	case DRM_FORMAT_BGRX4444:
    503 	case DRM_FORMAT_RGB565:
    504 	case DRM_FORMAT_BGR565:
    505 	case DRM_FORMAT_ARGB1555:
    506 	case DRM_FORMAT_XRGB1555:
    507 	case DRM_FORMAT_ABGR1555:
    508 	case DRM_FORMAT_XBGR1555:
    509 	case DRM_FORMAT_RGBA5551:
    510 	case DRM_FORMAT_RGBX5551:
    511 	case DRM_FORMAT_BGRA5551:
    512 	case DRM_FORMAT_BGRX5551:
    513 		return fill_smpte_rgb16(&info->rgb, planes[0],
    514 					width, height, stride);
    515 
    516 	case DRM_FORMAT_BGR888:
    517 	case DRM_FORMAT_RGB888:
    518 		return fill_smpte_rgb24(&info->rgb, planes[0],
    519 					width, height, stride);
    520 	case DRM_FORMAT_ARGB8888:
    521 	case DRM_FORMAT_XRGB8888:
    522 	case DRM_FORMAT_ABGR8888:
    523 	case DRM_FORMAT_XBGR8888:
    524 	case DRM_FORMAT_RGBA8888:
    525 	case DRM_FORMAT_RGBX8888:
    526 	case DRM_FORMAT_BGRA8888:
    527 	case DRM_FORMAT_BGRX8888:
    528 	case DRM_FORMAT_ARGB2101010:
    529 	case DRM_FORMAT_XRGB2101010:
    530 	case DRM_FORMAT_ABGR2101010:
    531 	case DRM_FORMAT_XBGR2101010:
    532 	case DRM_FORMAT_RGBA1010102:
    533 	case DRM_FORMAT_RGBX1010102:
    534 	case DRM_FORMAT_BGRA1010102:
    535 	case DRM_FORMAT_BGRX1010102:
    536 		return fill_smpte_rgb32(&info->rgb, planes[0],
    537 					width, height, stride);
    538 	}
    539 }
    540 
    541 /* swap these for big endian.. */
    542 #define RED   2
    543 #define GREEN 1
    544 #define BLUE  0
    545 
    546 static void make_pwetty(void *data, unsigned int width, unsigned int height,
    547 			unsigned int stride, uint32_t format)
    548 {
    549 #ifdef HAVE_CAIRO
    550 	cairo_surface_t *surface;
    551 	cairo_t *cr;
    552 	int x, y;
    553 	cairo_format_t cairo_format;
    554 
    555 	/* we can ignore the order of R,G,B channels */
    556 	switch (format) {
    557 	case DRM_FORMAT_XRGB8888:
    558 	case DRM_FORMAT_ARGB8888:
    559 	case DRM_FORMAT_XBGR8888:
    560 	case DRM_FORMAT_ABGR8888:
    561 		cairo_format = CAIRO_FORMAT_ARGB32;
    562 		break;
    563 	case DRM_FORMAT_RGB565:
    564 	case DRM_FORMAT_BGR565:
    565 		cairo_format = CAIRO_FORMAT_RGB16_565;
    566 		break;
    567 	default:
    568 		return;
    569 	}
    570 
    571 	surface = cairo_image_surface_create_for_data(data,
    572 						      cairo_format,
    573 						      width, height,
    574 						      stride);
    575 	cr = cairo_create(surface);
    576 	cairo_surface_destroy(surface);
    577 
    578 	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
    579 	for (x = 0; x < width; x += 250)
    580 		for (y = 0; y < height; y += 250) {
    581 			char buf[64];
    582 
    583 			cairo_move_to(cr, x, y - 20);
    584 			cairo_line_to(cr, x, y + 20);
    585 			cairo_move_to(cr, x - 20, y);
    586 			cairo_line_to(cr, x + 20, y);
    587 			cairo_new_sub_path(cr);
    588 			cairo_arc(cr, x, y, 10, 0, M_PI * 2);
    589 			cairo_set_line_width(cr, 4);
    590 			cairo_set_source_rgb(cr, 0, 0, 0);
    591 			cairo_stroke_preserve(cr);
    592 			cairo_set_source_rgb(cr, 1, 1, 1);
    593 			cairo_set_line_width(cr, 2);
    594 			cairo_stroke(cr);
    595 
    596 			snprintf(buf, sizeof buf, "%d, %d", x, y);
    597 			cairo_move_to(cr, x + 20, y + 20);
    598 			cairo_text_path(cr, buf);
    599 			cairo_set_source_rgb(cr, 0, 0, 0);
    600 			cairo_stroke_preserve(cr);
    601 			cairo_set_source_rgb(cr, 1, 1, 1);
    602 			cairo_fill(cr);
    603 		}
    604 
    605 	cairo_destroy(cr);
    606 #endif
    607 }
    608 
    609 static void fill_tiles_yuv_planar(const struct util_format_info *info,
    610 				  unsigned char *y_mem, unsigned char *u_mem,
    611 				  unsigned char *v_mem, unsigned int width,
    612 				  unsigned int height, unsigned int stride)
    613 {
    614 	const struct util_yuv_info *yuv = &info->yuv;
    615 	unsigned int cs = yuv->chroma_stride;
    616 	unsigned int xsub = yuv->xsub;
    617 	unsigned int ysub = yuv->ysub;
    618 	unsigned int x;
    619 	unsigned int y;
    620 
    621 	for (y = 0; y < height; ++y) {
    622 		for (x = 0; x < width; ++x) {
    623 			div_t d = div(x+y, width);
    624 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
    625 				       + 0x000a1120 * (d.rem >> 6);
    626 			struct color_yuv color =
    627 				MAKE_YUV_601((rgb32 >> 16) & 0xff,
    628 					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
    629 
    630 			y_mem[x] = color.y;
    631 			u_mem[x/xsub*cs] = color.u;
    632 			v_mem[x/xsub*cs] = color.v;
    633 		}
    634 
    635 		y_mem += stride;
    636 		if ((y + 1) % ysub == 0) {
    637 			u_mem += stride * cs / xsub;
    638 			v_mem += stride * cs / xsub;
    639 		}
    640 	}
    641 }
    642 
    643 static void fill_tiles_yuv_packed(const struct util_format_info *info,
    644 				  void *mem, unsigned int width,
    645 				  unsigned int height, unsigned int stride)
    646 {
    647 	const struct util_yuv_info *yuv = &info->yuv;
    648 	unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
    649 	unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
    650 	unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
    651 	unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
    652 	unsigned int x;
    653 	unsigned int y;
    654 
    655 	for (y = 0; y < height; ++y) {
    656 		for (x = 0; x < width; x += 2) {
    657 			div_t d = div(x+y, width);
    658 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
    659 				       + 0x000a1120 * (d.rem >> 6);
    660 			struct color_yuv color =
    661 				MAKE_YUV_601((rgb32 >> 16) & 0xff,
    662 					     (rgb32 >> 8) & 0xff, rgb32 & 0xff);
    663 
    664 			y_mem[2*x] = color.y;
    665 			c_mem[2*x+u] = color.u;
    666 			y_mem[2*x+2] = color.y;
    667 			c_mem[2*x+v] = color.v;
    668 		}
    669 
    670 		y_mem += stride;
    671 		c_mem += stride;
    672 	}
    673 }
    674 
    675 static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
    676 			     unsigned int width, unsigned int height,
    677 			     unsigned int stride)
    678 {
    679 	const struct util_rgb_info *rgb = &info->rgb;
    680 	void *mem_base = mem;
    681 	unsigned int x, y;
    682 
    683 	for (y = 0; y < height; ++y) {
    684 		for (x = 0; x < width; ++x) {
    685 			div_t d = div(x+y, width);
    686 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
    687 				       + 0x000a1120 * (d.rem >> 6);
    688 			uint16_t color =
    689 				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
    690 					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
    691 					  255);
    692 
    693 			((uint16_t *)mem)[x] = color;
    694 		}
    695 		mem += stride;
    696 	}
    697 
    698 	make_pwetty(mem_base, width, height, stride, info->format);
    699 }
    700 
    701 static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
    702 			     unsigned int width, unsigned int height,
    703 			     unsigned int stride)
    704 {
    705 	const struct util_rgb_info *rgb = &info->rgb;
    706 	unsigned int x, y;
    707 
    708 	for (y = 0; y < height; ++y) {
    709 		for (x = 0; x < width; ++x) {
    710 			div_t d = div(x+y, width);
    711 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
    712 				       + 0x000a1120 * (d.rem >> 6);
    713 			struct color_rgb24 color =
    714 				MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
    715 					   (rgb32 >> 8) & 0xff, rgb32 & 0xff);
    716 
    717 			((struct color_rgb24 *)mem)[x] = color;
    718 		}
    719 		mem += stride;
    720 	}
    721 }
    722 
    723 static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
    724 			     unsigned int width, unsigned int height,
    725 			     unsigned int stride)
    726 {
    727 	const struct util_rgb_info *rgb = &info->rgb;
    728 	void *mem_base = mem;
    729 	unsigned int x, y;
    730 
    731 	for (y = 0; y < height; ++y) {
    732 		for (x = 0; x < width; ++x) {
    733 			div_t d = div(x+y, width);
    734 			uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
    735 				       + 0x000a1120 * (d.rem >> 6);
    736 			uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
    737 			uint32_t color =
    738 				MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
    739 					  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
    740 					  alpha);
    741 
    742 			((uint32_t *)mem)[x] = color;
    743 		}
    744 		mem += stride;
    745 	}
    746 
    747 	make_pwetty(mem_base, width, height, stride, info->format);
    748 }
    749 
    750 static void fill_tiles(const struct util_format_info *info, void *planes[3],
    751 		       unsigned int width, unsigned int height,
    752 		       unsigned int stride)
    753 {
    754 	unsigned char *u, *v;
    755 
    756 	switch (info->format) {
    757 	case DRM_FORMAT_UYVY:
    758 	case DRM_FORMAT_VYUY:
    759 	case DRM_FORMAT_YUYV:
    760 	case DRM_FORMAT_YVYU:
    761 		return fill_tiles_yuv_packed(info, planes[0],
    762 					     width, height, stride);
    763 
    764 	case DRM_FORMAT_NV12:
    765 	case DRM_FORMAT_NV21:
    766 	case DRM_FORMAT_NV16:
    767 	case DRM_FORMAT_NV61:
    768 		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
    769 		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
    770 		return fill_tiles_yuv_planar(info, planes[0], u, v,
    771 					     width, height, stride);
    772 
    773 	case DRM_FORMAT_YUV420:
    774 		return fill_tiles_yuv_planar(info, planes[0], planes[1],
    775 					     planes[2], width, height, stride);
    776 
    777 	case DRM_FORMAT_YVU420:
    778 		return fill_tiles_yuv_planar(info, planes[0], planes[2],
    779 					     planes[1], width, height, stride);
    780 
    781 	case DRM_FORMAT_ARGB4444:
    782 	case DRM_FORMAT_XRGB4444:
    783 	case DRM_FORMAT_ABGR4444:
    784 	case DRM_FORMAT_XBGR4444:
    785 	case DRM_FORMAT_RGBA4444:
    786 	case DRM_FORMAT_RGBX4444:
    787 	case DRM_FORMAT_BGRA4444:
    788 	case DRM_FORMAT_BGRX4444:
    789 	case DRM_FORMAT_RGB565:
    790 	case DRM_FORMAT_BGR565:
    791 	case DRM_FORMAT_ARGB1555:
    792 	case DRM_FORMAT_XRGB1555:
    793 	case DRM_FORMAT_ABGR1555:
    794 	case DRM_FORMAT_XBGR1555:
    795 	case DRM_FORMAT_RGBA5551:
    796 	case DRM_FORMAT_RGBX5551:
    797 	case DRM_FORMAT_BGRA5551:
    798 	case DRM_FORMAT_BGRX5551:
    799 		return fill_tiles_rgb16(info, planes[0],
    800 					width, height, stride);
    801 
    802 	case DRM_FORMAT_BGR888:
    803 	case DRM_FORMAT_RGB888:
    804 		return fill_tiles_rgb24(info, planes[0],
    805 					width, height, stride);
    806 	case DRM_FORMAT_ARGB8888:
    807 	case DRM_FORMAT_XRGB8888:
    808 	case DRM_FORMAT_ABGR8888:
    809 	case DRM_FORMAT_XBGR8888:
    810 	case DRM_FORMAT_RGBA8888:
    811 	case DRM_FORMAT_RGBX8888:
    812 	case DRM_FORMAT_BGRA8888:
    813 	case DRM_FORMAT_BGRX8888:
    814 	case DRM_FORMAT_ARGB2101010:
    815 	case DRM_FORMAT_XRGB2101010:
    816 	case DRM_FORMAT_ABGR2101010:
    817 	case DRM_FORMAT_XBGR2101010:
    818 	case DRM_FORMAT_RGBA1010102:
    819 	case DRM_FORMAT_RGBX1010102:
    820 	case DRM_FORMAT_BGRA1010102:
    821 	case DRM_FORMAT_BGRX1010102:
    822 		return fill_tiles_rgb32(info, planes[0],
    823 					width, height, stride);
    824 	}
    825 }
    826 
    827 static void fill_plain(const struct util_format_info *info, void *planes[3],
    828 		       unsigned int width, unsigned int height,
    829 		       unsigned int stride)
    830 {
    831 	memset(planes[0], 0x77, stride * height);
    832 }
    833 
    834 /*
    835  * util_fill_pattern - Fill a buffer with a test pattern
    836  * @format: Pixel format
    837  * @pattern: Test pattern
    838  * @planes: Array of buffers
    839  * @width: Width in pixels
    840  * @height: Height in pixels
    841  * @stride: Line stride (pitch) in bytes
    842  *
    843  * Fill the buffers with the test pattern specified by the pattern parameter.
    844  * Supported formats vary depending on the selected pattern.
    845  */
    846 void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
    847 		       void *planes[3], unsigned int width,
    848 		       unsigned int height, unsigned int stride)
    849 {
    850 	const struct util_format_info *info;
    851 
    852 	info = util_format_info_find(format);
    853 	if (info == NULL)
    854 		return;
    855 
    856 	switch (pattern) {
    857 	case UTIL_PATTERN_TILES:
    858 		return fill_tiles(info, planes, width, height, stride);
    859 
    860 	case UTIL_PATTERN_SMPTE:
    861 		return fill_smpte(info, planes, width, height, stride);
    862 
    863 	case UTIL_PATTERN_PLAIN:
    864 		return fill_plain(info, planes, width, height, stride);
    865 
    866 	default:
    867 		printf("Error: unsupported test pattern %u.\n", pattern);
    868 		break;
    869 	}
    870 }
    871