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