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