pattern.c revision 00a23bda
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#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#if HAVE_CAIRO 38#include <cairo.h> 39#include <math.h> 40#endif 41 42#include "format.h" 43#include "pattern.h" 44 45struct color_rgb24 { 46 unsigned int value:24; 47} __attribute__((__packed__)); 48 49struct 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 76static 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 180static 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 279static 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 340static 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 403static 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 464static 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 546static void make_pwetty(void *data, unsigned int width, unsigned int height, 547 unsigned int stride, uint32_t format) 548{ 549#if HAVE_CAIRO 550 cairo_surface_t *surface; 551 cairo_t *cr; 552 cairo_format_t cairo_format; 553 554 /* we can ignore the order of R,G,B channels */ 555 switch (format) { 556 case DRM_FORMAT_XRGB8888: 557 case DRM_FORMAT_ARGB8888: 558 case DRM_FORMAT_XBGR8888: 559 case DRM_FORMAT_ABGR8888: 560 cairo_format = CAIRO_FORMAT_ARGB32; 561 break; 562 case DRM_FORMAT_RGB565: 563 case DRM_FORMAT_BGR565: 564 cairo_format = CAIRO_FORMAT_RGB16_565; 565 break; 566 default: 567 return; 568 } 569 570 surface = cairo_image_surface_create_for_data(data, 571 cairo_format, 572 width, height, 573 stride); 574 cr = cairo_create(surface); 575 cairo_surface_destroy(surface); 576 577 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); 578 for (unsigned x = 0; x < width; x += 250) 579 for (unsigned y = 0; y < height; y += 250) { 580 char buf[64]; 581 582 cairo_move_to(cr, x, y - 20); 583 cairo_line_to(cr, x, y + 20); 584 cairo_move_to(cr, x - 20, y); 585 cairo_line_to(cr, x + 20, y); 586 cairo_new_sub_path(cr); 587 cairo_arc(cr, x, y, 10, 0, M_PI * 2); 588 cairo_set_line_width(cr, 4); 589 cairo_set_source_rgb(cr, 0, 0, 0); 590 cairo_stroke_preserve(cr); 591 cairo_set_source_rgb(cr, 1, 1, 1); 592 cairo_set_line_width(cr, 2); 593 cairo_stroke(cr); 594 595 snprintf(buf, sizeof buf, "%d, %d", x, y); 596 cairo_move_to(cr, x + 20, y + 20); 597 cairo_text_path(cr, buf); 598 cairo_set_source_rgb(cr, 0, 0, 0); 599 cairo_stroke_preserve(cr); 600 cairo_set_source_rgb(cr, 1, 1, 1); 601 cairo_fill(cr); 602 } 603 604 cairo_destroy(cr); 605#endif 606} 607 608static void fill_tiles_yuv_planar(const struct util_format_info *info, 609 unsigned char *y_mem, unsigned char *u_mem, 610 unsigned char *v_mem, unsigned int width, 611 unsigned int height, unsigned int stride) 612{ 613 const struct util_yuv_info *yuv = &info->yuv; 614 unsigned int cs = yuv->chroma_stride; 615 unsigned int xsub = yuv->xsub; 616 unsigned int ysub = yuv->ysub; 617 unsigned int x; 618 unsigned int y; 619 620 for (y = 0; y < height; ++y) { 621 for (x = 0; x < width; ++x) { 622 div_t d = div(x+y, width); 623 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 624 + 0x000a1120 * (d.rem >> 6); 625 struct color_yuv color = 626 MAKE_YUV_601((rgb32 >> 16) & 0xff, 627 (rgb32 >> 8) & 0xff, rgb32 & 0xff); 628 629 y_mem[x] = color.y; 630 u_mem[x/xsub*cs] = color.u; 631 v_mem[x/xsub*cs] = color.v; 632 } 633 634 y_mem += stride; 635 if ((y + 1) % ysub == 0) { 636 u_mem += stride * cs / xsub; 637 v_mem += stride * cs / xsub; 638 } 639 } 640} 641 642static void fill_tiles_yuv_packed(const struct util_format_info *info, 643 void *mem, unsigned int width, 644 unsigned int height, unsigned int stride) 645{ 646 const struct util_yuv_info *yuv = &info->yuv; 647 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; 648 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; 649 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; 650 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; 651 unsigned int x; 652 unsigned int y; 653 654 for (y = 0; y < height; ++y) { 655 for (x = 0; x < width; x += 2) { 656 div_t d = div(x+y, width); 657 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 658 + 0x000a1120 * (d.rem >> 6); 659 struct color_yuv color = 660 MAKE_YUV_601((rgb32 >> 16) & 0xff, 661 (rgb32 >> 8) & 0xff, rgb32 & 0xff); 662 663 y_mem[2*x] = color.y; 664 c_mem[2*x+u] = color.u; 665 y_mem[2*x+2] = color.y; 666 c_mem[2*x+v] = color.v; 667 } 668 669 y_mem += stride; 670 c_mem += stride; 671 } 672} 673 674static void fill_tiles_rgb16(const struct util_format_info *info, void *mem, 675 unsigned int width, unsigned int height, 676 unsigned int stride) 677{ 678 const struct util_rgb_info *rgb = &info->rgb; 679 void *mem_base = mem; 680 unsigned int x, y; 681 682 for (y = 0; y < height; ++y) { 683 for (x = 0; x < width; ++x) { 684 div_t d = div(x+y, width); 685 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 686 + 0x000a1120 * (d.rem >> 6); 687 uint16_t color = 688 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, 689 (rgb32 >> 8) & 0xff, rgb32 & 0xff, 690 255); 691 692 ((uint16_t *)mem)[x] = color; 693 } 694 mem += stride; 695 } 696 697 make_pwetty(mem_base, width, height, stride, info->format); 698} 699 700static void fill_tiles_rgb24(const struct util_format_info *info, void *mem, 701 unsigned int width, unsigned int height, 702 unsigned int stride) 703{ 704 const struct util_rgb_info *rgb = &info->rgb; 705 unsigned int x, y; 706 707 for (y = 0; y < height; ++y) { 708 for (x = 0; x < width; ++x) { 709 div_t d = div(x+y, width); 710 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 711 + 0x000a1120 * (d.rem >> 6); 712 struct color_rgb24 color = 713 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff, 714 (rgb32 >> 8) & 0xff, rgb32 & 0xff); 715 716 ((struct color_rgb24 *)mem)[x] = color; 717 } 718 mem += stride; 719 } 720} 721 722static void fill_tiles_rgb32(const struct util_format_info *info, void *mem, 723 unsigned int width, unsigned int height, 724 unsigned int stride) 725{ 726 const struct util_rgb_info *rgb = &info->rgb; 727 void *mem_base = mem; 728 unsigned int x, y; 729 730 for (y = 0; y < height; ++y) { 731 for (x = 0; x < width; ++x) { 732 div_t d = div(x+y, width); 733 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 734 + 0x000a1120 * (d.rem >> 6); 735 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255; 736 uint32_t color = 737 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, 738 (rgb32 >> 8) & 0xff, rgb32 & 0xff, 739 alpha); 740 741 ((uint32_t *)mem)[x] = color; 742 } 743 mem += stride; 744 } 745 746 make_pwetty(mem_base, width, height, stride, info->format); 747} 748 749static void fill_tiles(const struct util_format_info *info, void *planes[3], 750 unsigned int width, unsigned int height, 751 unsigned int stride) 752{ 753 unsigned char *u, *v; 754 755 switch (info->format) { 756 case DRM_FORMAT_UYVY: 757 case DRM_FORMAT_VYUY: 758 case DRM_FORMAT_YUYV: 759 case DRM_FORMAT_YVYU: 760 return fill_tiles_yuv_packed(info, planes[0], 761 width, height, stride); 762 763 case DRM_FORMAT_NV12: 764 case DRM_FORMAT_NV21: 765 case DRM_FORMAT_NV16: 766 case DRM_FORMAT_NV61: 767 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; 768 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; 769 return fill_tiles_yuv_planar(info, planes[0], u, v, 770 width, height, stride); 771 772 case DRM_FORMAT_YUV420: 773 return fill_tiles_yuv_planar(info, planes[0], planes[1], 774 planes[2], width, height, stride); 775 776 case DRM_FORMAT_YVU420: 777 return fill_tiles_yuv_planar(info, planes[0], planes[2], 778 planes[1], width, height, stride); 779 780 case DRM_FORMAT_ARGB4444: 781 case DRM_FORMAT_XRGB4444: 782 case DRM_FORMAT_ABGR4444: 783 case DRM_FORMAT_XBGR4444: 784 case DRM_FORMAT_RGBA4444: 785 case DRM_FORMAT_RGBX4444: 786 case DRM_FORMAT_BGRA4444: 787 case DRM_FORMAT_BGRX4444: 788 case DRM_FORMAT_RGB565: 789 case DRM_FORMAT_BGR565: 790 case DRM_FORMAT_ARGB1555: 791 case DRM_FORMAT_XRGB1555: 792 case DRM_FORMAT_ABGR1555: 793 case DRM_FORMAT_XBGR1555: 794 case DRM_FORMAT_RGBA5551: 795 case DRM_FORMAT_RGBX5551: 796 case DRM_FORMAT_BGRA5551: 797 case DRM_FORMAT_BGRX5551: 798 return fill_tiles_rgb16(info, planes[0], 799 width, height, stride); 800 801 case DRM_FORMAT_BGR888: 802 case DRM_FORMAT_RGB888: 803 return fill_tiles_rgb24(info, planes[0], 804 width, height, stride); 805 case DRM_FORMAT_ARGB8888: 806 case DRM_FORMAT_XRGB8888: 807 case DRM_FORMAT_ABGR8888: 808 case DRM_FORMAT_XBGR8888: 809 case DRM_FORMAT_RGBA8888: 810 case DRM_FORMAT_RGBX8888: 811 case DRM_FORMAT_BGRA8888: 812 case DRM_FORMAT_BGRX8888: 813 case DRM_FORMAT_ARGB2101010: 814 case DRM_FORMAT_XRGB2101010: 815 case DRM_FORMAT_ABGR2101010: 816 case DRM_FORMAT_XBGR2101010: 817 case DRM_FORMAT_RGBA1010102: 818 case DRM_FORMAT_RGBX1010102: 819 case DRM_FORMAT_BGRA1010102: 820 case DRM_FORMAT_BGRX1010102: 821 return fill_tiles_rgb32(info, planes[0], 822 width, height, stride); 823 } 824} 825 826static void fill_plain(void *planes[3], 827 unsigned int height, 828 unsigned int stride) 829{ 830 memset(planes[0], 0x77, stride * height); 831} 832 833/* 834 * util_fill_pattern - Fill a buffer with a test pattern 835 * @format: Pixel format 836 * @pattern: Test pattern 837 * @planes: Array of buffers 838 * @width: Width in pixels 839 * @height: Height in pixels 840 * @stride: Line stride (pitch) in bytes 841 * 842 * Fill the buffers with the test pattern specified by the pattern parameter. 843 * Supported formats vary depending on the selected pattern. 844 */ 845void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern, 846 void *planes[3], unsigned int width, 847 unsigned int height, unsigned int stride) 848{ 849 const struct util_format_info *info; 850 851 info = util_format_info_find(format); 852 if (info == NULL) 853 return; 854 855 switch (pattern) { 856 case UTIL_PATTERN_TILES: 857 return fill_tiles(info, planes, width, height, stride); 858 859 case UTIL_PATTERN_SMPTE: 860 return fill_smpte(info, planes, width, height, stride); 861 862 case UTIL_PATTERN_PLAIN: 863 return fill_plain(planes, height, stride); 864 865 default: 866 printf("Error: unsupported test pattern %u.\n", pattern); 867 break; 868 } 869} 870