pattern.c revision 41687f09
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 "common.h" 39#include "format.h" 40#include "pattern.h" 41 42struct color_rgb24 { 43 unsigned int value:24; 44} __attribute__((__packed__)); 45 46struct color_yuv { 47 unsigned char y; 48 unsigned char u; 49 unsigned char v; 50}; 51 52#define MAKE_YUV_601_Y(r, g, b) \ 53 ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16) 54#define MAKE_YUV_601_U(r, g, b) \ 55 (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128) 56#define MAKE_YUV_601_V(r, g, b) \ 57 (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128) 58 59#define MAKE_YUV_601(r, g, b) \ 60 { .y = MAKE_YUV_601_Y(r, g, b), \ 61 .u = MAKE_YUV_601_U(r, g, b), \ 62 .v = MAKE_YUV_601_V(r, g, b) } 63 64/* This function takes 8-bit color values */ 65static inline uint32_t shiftcolor8(const struct util_color_component *comp, 66 uint32_t value) 67{ 68 value &= 0xff; 69 /* Fill the low bits with the high bits. */ 70 value = (value << 8) | value; 71 /* Shift down to remove unwanted low bits */ 72 value = value >> (16 - comp->length); 73 /* Shift back up to where the value should be */ 74 return value << comp->offset; 75} 76 77/* This function takes 10-bit color values */ 78static inline uint32_t shiftcolor10(const struct util_color_component *comp, 79 uint32_t value) 80{ 81 value &= 0x3ff; 82 /* Fill the low bits with the high bits. */ 83 value = (value << 6) | (value >> 4); 84 /* Shift down to remove unwanted low bits */ 85 value = value >> (16 - comp->length); 86 /* Shift back up to where the value should be */ 87 return value << comp->offset; 88} 89 90/* This function takes 16-bit color values */ 91static inline uint64_t shiftcolor16(const struct util_color_component *comp, 92 uint64_t value) 93{ 94 value &= 0xffff; 95 /* Shift down to remove unwanted low bits */ 96 value = value >> (16 - comp->length); 97 /* Shift back up to where the value should be */ 98 return value << comp->offset; 99} 100 101#define MAKE_RGBA10(rgb, r, g, b, a) \ 102 (shiftcolor10(&(rgb)->red, (r)) | \ 103 shiftcolor10(&(rgb)->green, (g)) | \ 104 shiftcolor10(&(rgb)->blue, (b)) | \ 105 shiftcolor10(&(rgb)->alpha, (a))) 106 107#define MAKE_RGBA(rgb, r, g, b, a) \ 108 (shiftcolor8(&(rgb)->red, (r)) | \ 109 shiftcolor8(&(rgb)->green, (g)) | \ 110 shiftcolor8(&(rgb)->blue, (b)) | \ 111 shiftcolor8(&(rgb)->alpha, (a))) 112 113#define MAKE_RGB24(rgb, r, g, b) \ 114 { .value = MAKE_RGBA(rgb, r, g, b, 0) } 115 116 117/** 118 * Takes a uint16_t, divides by 65536, converts the infinite-precision 119 * result to fp16 with round-to-zero. 120 * 121 * Copied from mesa:src/util/half_float.c 122 */ 123static uint16_t uint16_div_64k_to_half(uint16_t v) 124{ 125 /* Zero or subnormal. Set the mantissa to (v << 8) and return. */ 126 if (v < 4) 127 return v << 8; 128 129 /* Count the leading 0s in the uint16_t */ 130 int n = __builtin_clz(v) - 16; 131 132 /* Shift the mantissa up so bit 16 is the hidden 1 bit, 133 * mask it off, then shift back down to 10 bits 134 */ 135 int m = ( ((uint32_t)v << (n + 1)) & 0xffff ) >> 6; 136 137 /* (0{n} 1 X{15-n}) * 2^-16 138 * = 1.X * 2^(15-n-16) 139 * = 1.X * 2^(14-n - 15) 140 * which is the FP16 form with e = 14 - n 141 */ 142 int e = 14 - n; 143 144 return (e << 10) | m; 145} 146 147#define MAKE_RGBA8FP16(rgb, r, g, b, a) \ 148 (shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 8)) | \ 149 shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 8)) | \ 150 shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 8)) | \ 151 shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 8))) 152 153#define MAKE_RGBA10FP16(rgb, r, g, b, a) \ 154 (shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 6)) | \ 155 shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 6)) | \ 156 shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 6)) | \ 157 shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 6))) 158 159static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv, 160 unsigned char *y_mem, unsigned char *u_mem, 161 unsigned char *v_mem, unsigned int width, 162 unsigned int height, unsigned int stride) 163{ 164 const struct color_yuv colors_top[] = { 165 MAKE_YUV_601(191, 192, 192), /* grey */ 166 MAKE_YUV_601(192, 192, 0), /* yellow */ 167 MAKE_YUV_601(0, 192, 192), /* cyan */ 168 MAKE_YUV_601(0, 192, 0), /* green */ 169 MAKE_YUV_601(192, 0, 192), /* magenta */ 170 MAKE_YUV_601(192, 0, 0), /* red */ 171 MAKE_YUV_601(0, 0, 192), /* blue */ 172 }; 173 const struct color_yuv colors_middle[] = { 174 MAKE_YUV_601(0, 0, 192), /* blue */ 175 MAKE_YUV_601(19, 19, 19), /* black */ 176 MAKE_YUV_601(192, 0, 192), /* magenta */ 177 MAKE_YUV_601(19, 19, 19), /* black */ 178 MAKE_YUV_601(0, 192, 192), /* cyan */ 179 MAKE_YUV_601(19, 19, 19), /* black */ 180 MAKE_YUV_601(192, 192, 192), /* grey */ 181 }; 182 const struct color_yuv colors_bottom[] = { 183 MAKE_YUV_601(0, 33, 76), /* in-phase */ 184 MAKE_YUV_601(255, 255, 255), /* super white */ 185 MAKE_YUV_601(50, 0, 106), /* quadrature */ 186 MAKE_YUV_601(19, 19, 19), /* black */ 187 MAKE_YUV_601(9, 9, 9), /* 3.5% */ 188 MAKE_YUV_601(19, 19, 19), /* 7.5% */ 189 MAKE_YUV_601(29, 29, 29), /* 11.5% */ 190 MAKE_YUV_601(19, 19, 19), /* black */ 191 }; 192 unsigned int cs = yuv->chroma_stride; 193 unsigned int xsub = yuv->xsub; 194 unsigned int ysub = yuv->ysub; 195 unsigned int x; 196 unsigned int y; 197 198 /* Luma */ 199 for (y = 0; y < height * 6 / 9; ++y) { 200 for (x = 0; x < width; ++x) 201 y_mem[x] = colors_top[x * 7 / width].y; 202 y_mem += stride; 203 } 204 205 for (; y < height * 7 / 9; ++y) { 206 for (x = 0; x < width; ++x) 207 y_mem[x] = colors_middle[x * 7 / width].y; 208 y_mem += stride; 209 } 210 211 for (; y < height; ++y) { 212 for (x = 0; x < width * 5 / 7; ++x) 213 y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y; 214 for (; x < width * 6 / 7; ++x) 215 y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3 216 / (width / 7) + 4].y; 217 for (; x < width; ++x) 218 y_mem[x] = colors_bottom[7].y; 219 y_mem += stride; 220 } 221 222 /* Chroma */ 223 for (y = 0; y < height / ysub * 6 / 9; ++y) { 224 for (x = 0; x < width; x += xsub) { 225 u_mem[x*cs/xsub] = colors_top[x * 7 / width].u; 226 v_mem[x*cs/xsub] = colors_top[x * 7 / width].v; 227 } 228 u_mem += stride * cs / xsub; 229 v_mem += stride * cs / xsub; 230 } 231 232 for (; y < height / ysub * 7 / 9; ++y) { 233 for (x = 0; x < width; x += xsub) { 234 u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u; 235 v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v; 236 } 237 u_mem += stride * cs / xsub; 238 v_mem += stride * cs / xsub; 239 } 240 241 for (; y < height / ysub; ++y) { 242 for (x = 0; x < width * 5 / 7; x += xsub) { 243 u_mem[x*cs/xsub] = 244 colors_bottom[x * 4 / (width * 5 / 7)].u; 245 v_mem[x*cs/xsub] = 246 colors_bottom[x * 4 / (width * 5 / 7)].v; 247 } 248 for (; x < width * 6 / 7; x += xsub) { 249 u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * 250 3 / (width / 7) + 4].u; 251 v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * 252 3 / (width / 7) + 4].v; 253 } 254 for (; x < width; x += xsub) { 255 u_mem[x*cs/xsub] = colors_bottom[7].u; 256 v_mem[x*cs/xsub] = colors_bottom[7].v; 257 } 258 u_mem += stride * cs / xsub; 259 v_mem += stride * cs / xsub; 260 } 261} 262 263static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem, 264 unsigned int width, unsigned int height, 265 unsigned int stride) 266{ 267 const struct color_yuv colors_top[] = { 268 MAKE_YUV_601(191, 192, 192), /* grey */ 269 MAKE_YUV_601(192, 192, 0), /* yellow */ 270 MAKE_YUV_601(0, 192, 192), /* cyan */ 271 MAKE_YUV_601(0, 192, 0), /* green */ 272 MAKE_YUV_601(192, 0, 192), /* magenta */ 273 MAKE_YUV_601(192, 0, 0), /* red */ 274 MAKE_YUV_601(0, 0, 192), /* blue */ 275 }; 276 const struct color_yuv colors_middle[] = { 277 MAKE_YUV_601(0, 0, 192), /* blue */ 278 MAKE_YUV_601(19, 19, 19), /* black */ 279 MAKE_YUV_601(192, 0, 192), /* magenta */ 280 MAKE_YUV_601(19, 19, 19), /* black */ 281 MAKE_YUV_601(0, 192, 192), /* cyan */ 282 MAKE_YUV_601(19, 19, 19), /* black */ 283 MAKE_YUV_601(192, 192, 192), /* grey */ 284 }; 285 const struct color_yuv colors_bottom[] = { 286 MAKE_YUV_601(0, 33, 76), /* in-phase */ 287 MAKE_YUV_601(255, 255, 255), /* super white */ 288 MAKE_YUV_601(50, 0, 106), /* quadrature */ 289 MAKE_YUV_601(19, 19, 19), /* black */ 290 MAKE_YUV_601(9, 9, 9), /* 3.5% */ 291 MAKE_YUV_601(19, 19, 19), /* 7.5% */ 292 MAKE_YUV_601(29, 29, 29), /* 11.5% */ 293 MAKE_YUV_601(19, 19, 19), /* black */ 294 }; 295 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; 296 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; 297 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; 298 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; 299 unsigned int x; 300 unsigned int y; 301 302 /* Luma */ 303 for (y = 0; y < height * 6 / 9; ++y) { 304 for (x = 0; x < width; ++x) 305 y_mem[2*x] = colors_top[x * 7 / width].y; 306 y_mem += stride; 307 } 308 309 for (; y < height * 7 / 9; ++y) { 310 for (x = 0; x < width; ++x) 311 y_mem[2*x] = colors_middle[x * 7 / width].y; 312 y_mem += stride; 313 } 314 315 for (; y < height; ++y) { 316 for (x = 0; x < width * 5 / 7; ++x) 317 y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y; 318 for (; x < width * 6 / 7; ++x) 319 y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3 320 / (width / 7) + 4].y; 321 for (; x < width; ++x) 322 y_mem[2*x] = colors_bottom[7].y; 323 y_mem += stride; 324 } 325 326 /* Chroma */ 327 for (y = 0; y < height * 6 / 9; ++y) { 328 for (x = 0; x < width; x += 2) { 329 c_mem[2*x+u] = colors_top[x * 7 / width].u; 330 c_mem[2*x+v] = colors_top[x * 7 / width].v; 331 } 332 c_mem += stride; 333 } 334 335 for (; y < height * 7 / 9; ++y) { 336 for (x = 0; x < width; x += 2) { 337 c_mem[2*x+u] = colors_middle[x * 7 / width].u; 338 c_mem[2*x+v] = colors_middle[x * 7 / width].v; 339 } 340 c_mem += stride; 341 } 342 343 for (; y < height; ++y) { 344 for (x = 0; x < width * 5 / 7; x += 2) { 345 c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u; 346 c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v; 347 } 348 for (; x < width * 6 / 7; x += 2) { 349 c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) * 350 3 / (width / 7) + 4].u; 351 c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) * 352 3 / (width / 7) + 4].v; 353 } 354 for (; x < width; x += 2) { 355 c_mem[2*x+u] = colors_bottom[7].u; 356 c_mem[2*x+v] = colors_bottom[7].v; 357 } 358 c_mem += stride; 359 } 360} 361 362static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem, 363 unsigned int width, unsigned int height, 364 unsigned int stride) 365{ 366 const uint16_t colors_top[] = { 367 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ 368 MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ 369 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ 370 MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ 371 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ 372 MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ 373 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ 374 }; 375 const uint16_t colors_middle[] = { 376 MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ 377 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 378 MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ 379 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 380 MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ 381 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 382 MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ 383 }; 384 const uint16_t colors_bottom[] = { 385 MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ 386 MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ 387 MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ 388 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 389 MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ 390 MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ 391 MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ 392 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 393 }; 394 unsigned int x; 395 unsigned int y; 396 397 for (y = 0; y < height * 6 / 9; ++y) { 398 for (x = 0; x < width; ++x) 399 ((uint16_t *)mem)[x] = colors_top[x * 7 / width]; 400 mem += stride; 401 } 402 403 for (; y < height * 7 / 9; ++y) { 404 for (x = 0; x < width; ++x) 405 ((uint16_t *)mem)[x] = colors_middle[x * 7 / width]; 406 mem += stride; 407 } 408 409 for (; y < height; ++y) { 410 for (x = 0; x < width * 5 / 7; ++x) 411 ((uint16_t *)mem)[x] = 412 colors_bottom[x * 4 / (width * 5 / 7)]; 413 for (; x < width * 6 / 7; ++x) 414 ((uint16_t *)mem)[x] = 415 colors_bottom[(x - width * 5 / 7) * 3 416 / (width / 7) + 4]; 417 for (; x < width; ++x) 418 ((uint16_t *)mem)[x] = colors_bottom[7]; 419 mem += stride; 420 } 421} 422 423static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem, 424 unsigned int width, unsigned int height, 425 unsigned int stride) 426{ 427 const struct color_rgb24 colors_top[] = { 428 MAKE_RGB24(rgb, 192, 192, 192), /* grey */ 429 MAKE_RGB24(rgb, 192, 192, 0), /* yellow */ 430 MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ 431 MAKE_RGB24(rgb, 0, 192, 0), /* green */ 432 MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ 433 MAKE_RGB24(rgb, 192, 0, 0), /* red */ 434 MAKE_RGB24(rgb, 0, 0, 192), /* blue */ 435 }; 436 const struct color_rgb24 colors_middle[] = { 437 MAKE_RGB24(rgb, 0, 0, 192), /* blue */ 438 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 439 MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ 440 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 441 MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ 442 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 443 MAKE_RGB24(rgb, 192, 192, 192), /* grey */ 444 }; 445 const struct color_rgb24 colors_bottom[] = { 446 MAKE_RGB24(rgb, 0, 33, 76), /* in-phase */ 447 MAKE_RGB24(rgb, 255, 255, 255), /* super white */ 448 MAKE_RGB24(rgb, 50, 0, 106), /* quadrature */ 449 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 450 MAKE_RGB24(rgb, 9, 9, 9), /* 3.5% */ 451 MAKE_RGB24(rgb, 19, 19, 19), /* 7.5% */ 452 MAKE_RGB24(rgb, 29, 29, 29), /* 11.5% */ 453 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 454 }; 455 unsigned int x; 456 unsigned int y; 457 458 for (y = 0; y < height * 6 / 9; ++y) { 459 for (x = 0; x < width; ++x) 460 ((struct color_rgb24 *)mem)[x] = 461 colors_top[x * 7 / width]; 462 mem += stride; 463 } 464 465 for (; y < height * 7 / 9; ++y) { 466 for (x = 0; x < width; ++x) 467 ((struct color_rgb24 *)mem)[x] = 468 colors_middle[x * 7 / width]; 469 mem += stride; 470 } 471 472 for (; y < height; ++y) { 473 for (x = 0; x < width * 5 / 7; ++x) 474 ((struct color_rgb24 *)mem)[x] = 475 colors_bottom[x * 4 / (width * 5 / 7)]; 476 for (; x < width * 6 / 7; ++x) 477 ((struct color_rgb24 *)mem)[x] = 478 colors_bottom[(x - width * 5 / 7) * 3 479 / (width / 7) + 4]; 480 for (; x < width; ++x) 481 ((struct color_rgb24 *)mem)[x] = colors_bottom[7]; 482 mem += stride; 483 } 484} 485 486static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem, 487 unsigned int width, unsigned int height, 488 unsigned int stride) 489{ 490 const uint32_t colors_top[] = { 491 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ 492 MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ 493 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ 494 MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ 495 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ 496 MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ 497 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ 498 }; 499 const uint32_t colors_middle[] = { 500 MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ 501 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 502 MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ 503 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 504 MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ 505 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 506 MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ 507 }; 508 const uint32_t colors_bottom[] = { 509 MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ 510 MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ 511 MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ 512 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 513 MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ 514 MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ 515 MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ 516 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 517 }; 518 unsigned int x; 519 unsigned int y; 520 521 for (y = 0; y < height * 6 / 9; ++y) { 522 for (x = 0; x < width; ++x) 523 ((uint32_t *)mem)[x] = colors_top[x * 7 / width]; 524 mem += stride; 525 } 526 527 for (; y < height * 7 / 9; ++y) { 528 for (x = 0; x < width; ++x) 529 ((uint32_t *)mem)[x] = colors_middle[x * 7 / width]; 530 mem += stride; 531 } 532 533 for (; y < height; ++y) { 534 for (x = 0; x < width * 5 / 7; ++x) 535 ((uint32_t *)mem)[x] = 536 colors_bottom[x * 4 / (width * 5 / 7)]; 537 for (; x < width * 6 / 7; ++x) 538 ((uint32_t *)mem)[x] = 539 colors_bottom[(x - width * 5 / 7) * 3 540 / (width / 7) + 4]; 541 for (; x < width; ++x) 542 ((uint32_t *)mem)[x] = colors_bottom[7]; 543 mem += stride; 544 } 545} 546 547static void fill_smpte_rgb16fp(const struct util_rgb_info *rgb, void *mem, 548 unsigned int width, unsigned int height, 549 unsigned int stride) 550{ 551 const uint64_t colors_top[] = { 552 MAKE_RGBA8FP16(rgb, 192, 192, 192, 255),/* grey */ 553 MAKE_RGBA8FP16(rgb, 192, 192, 0, 255), /* yellow */ 554 MAKE_RGBA8FP16(rgb, 0, 192, 192, 255), /* cyan */ 555 MAKE_RGBA8FP16(rgb, 0, 192, 0, 255), /* green */ 556 MAKE_RGBA8FP16(rgb, 192, 0, 192, 255), /* magenta */ 557 MAKE_RGBA8FP16(rgb, 192, 0, 0, 255), /* red */ 558 MAKE_RGBA8FP16(rgb, 0, 0, 192, 255), /* blue */ 559 }; 560 const uint64_t colors_middle[] = { 561 MAKE_RGBA8FP16(rgb, 0, 0, 192, 127), /* blue */ 562 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */ 563 MAKE_RGBA8FP16(rgb, 192, 0, 192, 127), /* magenta */ 564 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */ 565 MAKE_RGBA8FP16(rgb, 0, 192, 192, 127), /* cyan */ 566 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */ 567 MAKE_RGBA8FP16(rgb, 192, 192, 192, 127),/* grey */ 568 }; 569 const uint64_t colors_bottom[] = { 570 MAKE_RGBA8FP16(rgb, 0, 33, 76, 255), /* in-phase */ 571 MAKE_RGBA8FP16(rgb, 255, 255, 255, 255),/* super white */ 572 MAKE_RGBA8FP16(rgb, 50, 0, 106, 255), /* quadrature */ 573 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* black */ 574 MAKE_RGBA8FP16(rgb, 9, 9, 9, 255), /* 3.5% */ 575 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* 7.5% */ 576 MAKE_RGBA8FP16(rgb, 29, 29, 29, 255), /* 11.5% */ 577 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* black */ 578 }; 579 unsigned int x; 580 unsigned int y; 581 582 for (y = 0; y < height * 6 / 9; ++y) { 583 for (x = 0; x < width; ++x) 584 ((uint64_t *)mem)[x] = colors_top[x * 7 / width]; 585 mem += stride; 586 } 587 588 for (; y < height * 7 / 9; ++y) { 589 for (x = 0; x < width; ++x) 590 ((uint64_t *)mem)[x] = colors_middle[x * 7 / width]; 591 mem += stride; 592 } 593 594 for (; y < height; ++y) { 595 for (x = 0; x < width * 5 / 7; ++x) 596 ((uint64_t *)mem)[x] = 597 colors_bottom[x * 4 / (width * 5 / 7)]; 598 for (; x < width * 6 / 7; ++x) 599 ((uint64_t *)mem)[x] = 600 colors_bottom[(x - width * 5 / 7) * 3 601 / (width / 7) + 4]; 602 for (; x < width; ++x) 603 ((uint64_t *)mem)[x] = colors_bottom[7]; 604 mem += stride; 605 } 606} 607 608static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height, 609 unsigned int stride) 610{ 611 unsigned int x; 612 unsigned int y; 613 614 for (y = 0; y < height * 6 / 9; ++y) { 615 for (x = 0; x < width; ++x) 616 ((uint8_t *)mem)[x] = x * 7 / width; 617 mem += stride; 618 } 619 620 for (; y < height * 7 / 9; ++y) { 621 for (x = 0; x < width; ++x) 622 ((uint8_t *)mem)[x] = 7 + (x * 7 / width); 623 mem += stride; 624 } 625 626 for (; y < height; ++y) { 627 for (x = 0; x < width * 5 / 7; ++x) 628 ((uint8_t *)mem)[x] = 629 14 + (x * 4 / (width * 5 / 7)); 630 for (; x < width * 6 / 7; ++x) 631 ((uint8_t *)mem)[x] = 632 14 + ((x - width * 5 / 7) * 3 633 / (width / 7) + 4); 634 for (; x < width; ++x) 635 ((uint8_t *)mem)[x] = 14 + 7; 636 mem += stride; 637 } 638} 639 640void util_smpte_c8_gamma(unsigned size, struct drm_color_lut *lut) 641{ 642 if (size < 7 + 7 + 8) { 643 printf("Error: gamma too small: %d < %d\n", size, 7 + 7 + 8); 644 return; 645 } 646 memset(lut, 0, size * sizeof(struct drm_color_lut)); 647 648#define FILL_COLOR(idx, r, g, b) \ 649 lut[idx].red = (r) << 8; \ 650 lut[idx].green = (g) << 8; \ 651 lut[idx].blue = (b) << 8 652 653 FILL_COLOR( 0, 192, 192, 192); /* grey */ 654 FILL_COLOR( 1, 192, 192, 0 ); /* yellow */ 655 FILL_COLOR( 2, 0, 192, 192); /* cyan */ 656 FILL_COLOR( 3, 0, 192, 0 ); /* green */ 657 FILL_COLOR( 4, 192, 0, 192); /* magenta */ 658 FILL_COLOR( 5, 192, 0, 0 ); /* red */ 659 FILL_COLOR( 6, 0, 0, 192); /* blue */ 660 661 FILL_COLOR( 7, 0, 0, 192); /* blue */ 662 FILL_COLOR( 8, 19, 19, 19 ); /* black */ 663 FILL_COLOR( 9, 192, 0, 192); /* magenta */ 664 FILL_COLOR(10, 19, 19, 19 ); /* black */ 665 FILL_COLOR(11, 0, 192, 192); /* cyan */ 666 FILL_COLOR(12, 19, 19, 19 ); /* black */ 667 FILL_COLOR(13, 192, 192, 192); /* grey */ 668 669 FILL_COLOR(14, 0, 33, 76); /* in-phase */ 670 FILL_COLOR(15, 255, 255, 255); /* super white */ 671 FILL_COLOR(16, 50, 0, 106); /* quadrature */ 672 FILL_COLOR(17, 19, 19, 19); /* black */ 673 FILL_COLOR(18, 9, 9, 9); /* 3.5% */ 674 FILL_COLOR(19, 19, 19, 19); /* 7.5% */ 675 FILL_COLOR(20, 29, 29, 29); /* 11.5% */ 676 FILL_COLOR(21, 19, 19, 19); /* black */ 677 678#undef FILL_COLOR 679} 680 681static void fill_smpte(const struct util_format_info *info, void *planes[3], 682 unsigned int width, unsigned int height, 683 unsigned int stride) 684{ 685 unsigned char *u, *v; 686 687 switch (info->format) { 688 case DRM_FORMAT_C8: 689 return fill_smpte_c8(planes[0], width, height, stride); 690 case DRM_FORMAT_UYVY: 691 case DRM_FORMAT_VYUY: 692 case DRM_FORMAT_YUYV: 693 case DRM_FORMAT_YVYU: 694 return fill_smpte_yuv_packed(&info->yuv, planes[0], width, 695 height, stride); 696 697 case DRM_FORMAT_NV12: 698 case DRM_FORMAT_NV21: 699 case DRM_FORMAT_NV16: 700 case DRM_FORMAT_NV61: 701 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; 702 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; 703 return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v, 704 width, height, stride); 705 706 case DRM_FORMAT_YUV420: 707 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], 708 planes[2], width, height, stride); 709 710 case DRM_FORMAT_YVU420: 711 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2], 712 planes[1], width, height, stride); 713 714 case DRM_FORMAT_ARGB4444: 715 case DRM_FORMAT_XRGB4444: 716 case DRM_FORMAT_ABGR4444: 717 case DRM_FORMAT_XBGR4444: 718 case DRM_FORMAT_RGBA4444: 719 case DRM_FORMAT_RGBX4444: 720 case DRM_FORMAT_BGRA4444: 721 case DRM_FORMAT_BGRX4444: 722 case DRM_FORMAT_RGB565: 723 case DRM_FORMAT_BGR565: 724 case DRM_FORMAT_ARGB1555: 725 case DRM_FORMAT_XRGB1555: 726 case DRM_FORMAT_ABGR1555: 727 case DRM_FORMAT_XBGR1555: 728 case DRM_FORMAT_RGBA5551: 729 case DRM_FORMAT_RGBX5551: 730 case DRM_FORMAT_BGRA5551: 731 case DRM_FORMAT_BGRX5551: 732 return fill_smpte_rgb16(&info->rgb, planes[0], 733 width, height, stride); 734 735 case DRM_FORMAT_BGR888: 736 case DRM_FORMAT_RGB888: 737 return fill_smpte_rgb24(&info->rgb, planes[0], 738 width, height, stride); 739 case DRM_FORMAT_ARGB8888: 740 case DRM_FORMAT_XRGB8888: 741 case DRM_FORMAT_ABGR8888: 742 case DRM_FORMAT_XBGR8888: 743 case DRM_FORMAT_RGBA8888: 744 case DRM_FORMAT_RGBX8888: 745 case DRM_FORMAT_BGRA8888: 746 case DRM_FORMAT_BGRX8888: 747 case DRM_FORMAT_ARGB2101010: 748 case DRM_FORMAT_XRGB2101010: 749 case DRM_FORMAT_ABGR2101010: 750 case DRM_FORMAT_XBGR2101010: 751 case DRM_FORMAT_RGBA1010102: 752 case DRM_FORMAT_RGBX1010102: 753 case DRM_FORMAT_BGRA1010102: 754 case DRM_FORMAT_BGRX1010102: 755 return fill_smpte_rgb32(&info->rgb, planes[0], 756 width, height, stride); 757 758 case DRM_FORMAT_XRGB16161616F: 759 case DRM_FORMAT_XBGR16161616F: 760 case DRM_FORMAT_ARGB16161616F: 761 case DRM_FORMAT_ABGR16161616F: 762 return fill_smpte_rgb16fp(&info->rgb, planes[0], 763 width, height, stride); 764 } 765} 766 767/* swap these for big endian.. */ 768#define RED 2 769#define GREEN 1 770#define BLUE 0 771 772static void make_pwetty(void *data, unsigned int width, unsigned int height, 773 unsigned int stride, uint32_t format) 774{ 775#if HAVE_CAIRO 776 cairo_surface_t *surface; 777 cairo_t *cr; 778 cairo_format_t cairo_format; 779 780 /* we can ignore the order of R,G,B channels */ 781 switch (format) { 782 case DRM_FORMAT_XRGB8888: 783 case DRM_FORMAT_ARGB8888: 784 case DRM_FORMAT_XBGR8888: 785 case DRM_FORMAT_ABGR8888: 786 cairo_format = CAIRO_FORMAT_ARGB32; 787 break; 788 case DRM_FORMAT_RGB565: 789 case DRM_FORMAT_BGR565: 790 cairo_format = CAIRO_FORMAT_RGB16_565; 791 break; 792#if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 12) 793 case DRM_FORMAT_ARGB2101010: 794 case DRM_FORMAT_XRGB2101010: 795 case DRM_FORMAT_ABGR2101010: 796 case DRM_FORMAT_XBGR2101010: 797 cairo_format = CAIRO_FORMAT_RGB30; 798 break; 799#endif 800 default: 801 return; 802 } 803 804 surface = cairo_image_surface_create_for_data(data, 805 cairo_format, 806 width, height, 807 stride); 808 cr = cairo_create(surface); 809 cairo_surface_destroy(surface); 810 811 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); 812 for (unsigned x = 0; x < width; x += 250) 813 for (unsigned y = 0; y < height; y += 250) { 814 char buf[64]; 815 816 cairo_move_to(cr, x, y - 20); 817 cairo_line_to(cr, x, y + 20); 818 cairo_move_to(cr, x - 20, y); 819 cairo_line_to(cr, x + 20, y); 820 cairo_new_sub_path(cr); 821 cairo_arc(cr, x, y, 10, 0, M_PI * 2); 822 cairo_set_line_width(cr, 4); 823 cairo_set_source_rgb(cr, 0, 0, 0); 824 cairo_stroke_preserve(cr); 825 cairo_set_source_rgb(cr, 1, 1, 1); 826 cairo_set_line_width(cr, 2); 827 cairo_stroke(cr); 828 829 snprintf(buf, sizeof buf, "%d, %d", x, y); 830 cairo_move_to(cr, x + 20, y + 20); 831 cairo_text_path(cr, buf); 832 cairo_set_source_rgb(cr, 0, 0, 0); 833 cairo_stroke_preserve(cr); 834 cairo_set_source_rgb(cr, 1, 1, 1); 835 cairo_fill(cr); 836 } 837 838 cairo_destroy(cr); 839#endif 840} 841 842static void fill_tiles_yuv_planar(const struct util_format_info *info, 843 unsigned char *y_mem, unsigned char *u_mem, 844 unsigned char *v_mem, unsigned int width, 845 unsigned int height, unsigned int stride) 846{ 847 const struct util_yuv_info *yuv = &info->yuv; 848 unsigned int cs = yuv->chroma_stride; 849 unsigned int xsub = yuv->xsub; 850 unsigned int ysub = yuv->ysub; 851 unsigned int x; 852 unsigned int y; 853 854 for (y = 0; y < height; ++y) { 855 for (x = 0; x < width; ++x) { 856 div_t d = div(x+y, width); 857 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 858 + 0x000a1120 * (d.rem >> 6); 859 struct color_yuv color = 860 MAKE_YUV_601((rgb32 >> 16) & 0xff, 861 (rgb32 >> 8) & 0xff, rgb32 & 0xff); 862 863 y_mem[x] = color.y; 864 u_mem[x/xsub*cs] = color.u; 865 v_mem[x/xsub*cs] = color.v; 866 } 867 868 y_mem += stride; 869 if ((y + 1) % ysub == 0) { 870 u_mem += stride * cs / xsub; 871 v_mem += stride * cs / xsub; 872 } 873 } 874} 875 876static void fill_tiles_yuv_packed(const struct util_format_info *info, 877 void *mem, unsigned int width, 878 unsigned int height, unsigned int stride) 879{ 880 const struct util_yuv_info *yuv = &info->yuv; 881 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; 882 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; 883 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; 884 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; 885 unsigned int x; 886 unsigned int y; 887 888 for (y = 0; y < height; ++y) { 889 for (x = 0; x < width; x += 2) { 890 div_t d = div(x+y, width); 891 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 892 + 0x000a1120 * (d.rem >> 6); 893 struct color_yuv color = 894 MAKE_YUV_601((rgb32 >> 16) & 0xff, 895 (rgb32 >> 8) & 0xff, rgb32 & 0xff); 896 897 y_mem[2*x] = color.y; 898 c_mem[2*x+u] = color.u; 899 y_mem[2*x+2] = color.y; 900 c_mem[2*x+v] = color.v; 901 } 902 903 y_mem += stride; 904 c_mem += stride; 905 } 906} 907 908static void fill_tiles_rgb16(const struct util_format_info *info, void *mem, 909 unsigned int width, unsigned int height, 910 unsigned int stride) 911{ 912 const struct util_rgb_info *rgb = &info->rgb; 913 void *mem_base = mem; 914 unsigned int x, y; 915 916 for (y = 0; y < height; ++y) { 917 for (x = 0; x < width; ++x) { 918 div_t d = div(x+y, width); 919 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 920 + 0x000a1120 * (d.rem >> 6); 921 uint16_t color = 922 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, 923 (rgb32 >> 8) & 0xff, rgb32 & 0xff, 924 255); 925 926 ((uint16_t *)mem)[x] = color; 927 } 928 mem += stride; 929 } 930 931 make_pwetty(mem_base, width, height, stride, info->format); 932} 933 934static void fill_tiles_rgb24(const struct util_format_info *info, void *mem, 935 unsigned int width, unsigned int height, 936 unsigned int stride) 937{ 938 const struct util_rgb_info *rgb = &info->rgb; 939 unsigned int x, y; 940 941 for (y = 0; y < height; ++y) { 942 for (x = 0; x < width; ++x) { 943 div_t d = div(x+y, width); 944 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 945 + 0x000a1120 * (d.rem >> 6); 946 struct color_rgb24 color = 947 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff, 948 (rgb32 >> 8) & 0xff, rgb32 & 0xff); 949 950 ((struct color_rgb24 *)mem)[x] = color; 951 } 952 mem += stride; 953 } 954} 955 956static void fill_tiles_rgb32(const struct util_format_info *info, void *mem, 957 unsigned int width, unsigned int height, 958 unsigned int stride) 959{ 960 const struct util_rgb_info *rgb = &info->rgb; 961 void *mem_base = mem; 962 unsigned int x, y; 963 964 for (y = 0; y < height; ++y) { 965 for (x = 0; x < width; ++x) { 966 div_t d = div(x+y, width); 967 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 968 + 0x000a1120 * (d.rem >> 6); 969 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255; 970 uint32_t color = 971 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, 972 (rgb32 >> 8) & 0xff, rgb32 & 0xff, 973 alpha); 974 975 ((uint32_t *)mem)[x] = color; 976 } 977 mem += stride; 978 } 979 980 make_pwetty(mem_base, width, height, stride, info->format); 981} 982 983static void fill_tiles_rgb16fp(const struct util_format_info *info, void *mem, 984 unsigned int width, unsigned int height, 985 unsigned int stride) 986{ 987 const struct util_rgb_info *rgb = &info->rgb; 988 unsigned int x, y; 989 990 /* TODO: Give this actual fp16 precision */ 991 for (y = 0; y < height; ++y) { 992 for (x = 0; x < width; ++x) { 993 div_t d = div(x+y, width); 994 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 995 + 0x000a1120 * (d.rem >> 6); 996 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255; 997 uint64_t color = 998 MAKE_RGBA8FP16(rgb, (rgb32 >> 16) & 0xff, 999 (rgb32 >> 8) & 0xff, rgb32 & 0xff, 1000 alpha); 1001 1002 ((uint64_t *)mem)[x] = color; 1003 } 1004 mem += stride; 1005 } 1006} 1007 1008static void fill_tiles(const struct util_format_info *info, void *planes[3], 1009 unsigned int width, unsigned int height, 1010 unsigned int stride) 1011{ 1012 unsigned char *u, *v; 1013 1014 switch (info->format) { 1015 case DRM_FORMAT_UYVY: 1016 case DRM_FORMAT_VYUY: 1017 case DRM_FORMAT_YUYV: 1018 case DRM_FORMAT_YVYU: 1019 return fill_tiles_yuv_packed(info, planes[0], 1020 width, height, stride); 1021 1022 case DRM_FORMAT_NV12: 1023 case DRM_FORMAT_NV21: 1024 case DRM_FORMAT_NV16: 1025 case DRM_FORMAT_NV61: 1026 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; 1027 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; 1028 return fill_tiles_yuv_planar(info, planes[0], u, v, 1029 width, height, stride); 1030 1031 case DRM_FORMAT_YUV420: 1032 return fill_tiles_yuv_planar(info, planes[0], planes[1], 1033 planes[2], width, height, stride); 1034 1035 case DRM_FORMAT_YVU420: 1036 return fill_tiles_yuv_planar(info, planes[0], planes[2], 1037 planes[1], width, height, stride); 1038 1039 case DRM_FORMAT_ARGB4444: 1040 case DRM_FORMAT_XRGB4444: 1041 case DRM_FORMAT_ABGR4444: 1042 case DRM_FORMAT_XBGR4444: 1043 case DRM_FORMAT_RGBA4444: 1044 case DRM_FORMAT_RGBX4444: 1045 case DRM_FORMAT_BGRA4444: 1046 case DRM_FORMAT_BGRX4444: 1047 case DRM_FORMAT_RGB565: 1048 case DRM_FORMAT_BGR565: 1049 case DRM_FORMAT_ARGB1555: 1050 case DRM_FORMAT_XRGB1555: 1051 case DRM_FORMAT_ABGR1555: 1052 case DRM_FORMAT_XBGR1555: 1053 case DRM_FORMAT_RGBA5551: 1054 case DRM_FORMAT_RGBX5551: 1055 case DRM_FORMAT_BGRA5551: 1056 case DRM_FORMAT_BGRX5551: 1057 return fill_tiles_rgb16(info, planes[0], 1058 width, height, stride); 1059 1060 case DRM_FORMAT_BGR888: 1061 case DRM_FORMAT_RGB888: 1062 return fill_tiles_rgb24(info, planes[0], 1063 width, height, stride); 1064 case DRM_FORMAT_ARGB8888: 1065 case DRM_FORMAT_XRGB8888: 1066 case DRM_FORMAT_ABGR8888: 1067 case DRM_FORMAT_XBGR8888: 1068 case DRM_FORMAT_RGBA8888: 1069 case DRM_FORMAT_RGBX8888: 1070 case DRM_FORMAT_BGRA8888: 1071 case DRM_FORMAT_BGRX8888: 1072 case DRM_FORMAT_ARGB2101010: 1073 case DRM_FORMAT_XRGB2101010: 1074 case DRM_FORMAT_ABGR2101010: 1075 case DRM_FORMAT_XBGR2101010: 1076 case DRM_FORMAT_RGBA1010102: 1077 case DRM_FORMAT_RGBX1010102: 1078 case DRM_FORMAT_BGRA1010102: 1079 case DRM_FORMAT_BGRX1010102: 1080 return fill_tiles_rgb32(info, planes[0], 1081 width, height, stride); 1082 1083 case DRM_FORMAT_XRGB16161616F: 1084 case DRM_FORMAT_XBGR16161616F: 1085 case DRM_FORMAT_ARGB16161616F: 1086 case DRM_FORMAT_ABGR16161616F: 1087 return fill_tiles_rgb16fp(info, planes[0], 1088 width, height, stride); 1089 } 1090} 1091 1092static void fill_plain(const struct util_format_info *info, void *planes[3], 1093 unsigned int height, 1094 unsigned int stride) 1095{ 1096 switch (info->format) { 1097 case DRM_FORMAT_XRGB16161616F: 1098 case DRM_FORMAT_XBGR16161616F: 1099 case DRM_FORMAT_ARGB16161616F: 1100 case DRM_FORMAT_ABGR16161616F: 1101 /* 0x3838 = 0.5273 */ 1102 memset(planes[0], 0x38, stride * height); 1103 break; 1104 default: 1105 memset(planes[0], 0x77, stride * height); 1106 break; 1107 } 1108} 1109 1110static void fill_gradient_rgb32(const struct util_rgb_info *rgb, 1111 void *mem, 1112 unsigned int width, unsigned int height, 1113 unsigned int stride) 1114{ 1115 unsigned int i, j; 1116 1117 for (i = 0; i < height / 2; i++) { 1118 uint32_t *row = mem; 1119 1120 for (j = 0; j < width / 2; j++) { 1121 uint32_t value = MAKE_RGBA10(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0); 1122 row[2*j] = row[2*j+1] = value; 1123 } 1124 mem += stride; 1125 } 1126 1127 for (; i < height; i++) { 1128 uint32_t *row = mem; 1129 1130 for (j = 0; j < width / 2; j++) { 1131 uint32_t value = MAKE_RGBA10(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0); 1132 row[2*j] = row[2*j+1] = value; 1133 } 1134 mem += stride; 1135 } 1136} 1137 1138static void fill_gradient_rgb16fp(const struct util_rgb_info *rgb, 1139 void *mem, 1140 unsigned int width, unsigned int height, 1141 unsigned int stride) 1142{ 1143 unsigned int i, j; 1144 1145 for (i = 0; i < height / 2; i++) { 1146 uint64_t *row = mem; 1147 1148 for (j = 0; j < width / 2; j++) { 1149 uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0); 1150 row[2*j] = row[2*j+1] = value; 1151 } 1152 mem += stride; 1153 } 1154 1155 for (; i < height; i++) { 1156 uint64_t *row = mem; 1157 1158 for (j = 0; j < width / 2; j++) { 1159 uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0); 1160 row[2*j] = row[2*j+1] = value; 1161 } 1162 mem += stride; 1163 } 1164} 1165 1166/* The gradient pattern creates two horizontal gray gradients, split 1167 * into two halves. The top half has 10bpc precision, the bottom half 1168 * has 8bpc precision. When using with a 10bpc fb format, there are 3 1169 * possible outcomes: 1170 * 1171 * - Pixel data is encoded as 8bpc to the display, no dithering. This 1172 * would lead to the top and bottom halves looking identical. 1173 * 1174 * - Pixel data is encoded as 8bpc to the display, with dithering. This 1175 * would lead to there being a visible difference between the two halves, 1176 * but the top half would look a little speck-y due to the dithering. 1177 * 1178 * - Pixel data is encoded at 10bpc+ to the display (which implies 1179 * the display is able to show this level of depth). This should 1180 * lead to the top half being a very clean gradient, and visibly different 1181 * from the bottom half. 1182 * 1183 * Once we support additional fb formats, this approach could be extended 1184 * to distinguish even higher bpc precisions. 1185 * 1186 * Note that due to practical size considerations, for the screens 1187 * where this matters, the pattern actually emits stripes 2-pixels 1188 * wide for each gradient color. Otherwise the difference may be a bit 1189 * hard to notice. 1190 */ 1191static void fill_gradient(const struct util_format_info *info, void *planes[3], 1192 unsigned int width, unsigned int height, 1193 unsigned int stride) 1194{ 1195 switch (info->format) { 1196 case DRM_FORMAT_ARGB8888: 1197 case DRM_FORMAT_XRGB8888: 1198 case DRM_FORMAT_ABGR8888: 1199 case DRM_FORMAT_XBGR8888: 1200 case DRM_FORMAT_RGBA8888: 1201 case DRM_FORMAT_RGBX8888: 1202 case DRM_FORMAT_BGRA8888: 1203 case DRM_FORMAT_BGRX8888: 1204 case DRM_FORMAT_ARGB2101010: 1205 case DRM_FORMAT_XRGB2101010: 1206 case DRM_FORMAT_ABGR2101010: 1207 case DRM_FORMAT_XBGR2101010: 1208 case DRM_FORMAT_RGBA1010102: 1209 case DRM_FORMAT_RGBX1010102: 1210 case DRM_FORMAT_BGRA1010102: 1211 case DRM_FORMAT_BGRX1010102: 1212 return fill_gradient_rgb32(&info->rgb, planes[0], 1213 width, height, stride); 1214 1215 case DRM_FORMAT_XRGB16161616F: 1216 case DRM_FORMAT_XBGR16161616F: 1217 case DRM_FORMAT_ARGB16161616F: 1218 case DRM_FORMAT_ABGR16161616F: 1219 return fill_gradient_rgb16fp(&info->rgb, planes[0], 1220 width, height, stride); 1221 } 1222} 1223 1224/* 1225 * util_fill_pattern - Fill a buffer with a test pattern 1226 * @format: Pixel format 1227 * @pattern: Test pattern 1228 * @planes: Array of buffers 1229 * @width: Width in pixels 1230 * @height: Height in pixels 1231 * @stride: Line stride (pitch) in bytes 1232 * 1233 * Fill the buffers with the test pattern specified by the pattern parameter. 1234 * Supported formats vary depending on the selected pattern. 1235 */ 1236void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern, 1237 void *planes[3], unsigned int width, 1238 unsigned int height, unsigned int stride) 1239{ 1240 const struct util_format_info *info; 1241 1242 info = util_format_info_find(format); 1243 if (info == NULL) 1244 return; 1245 1246 switch (pattern) { 1247 case UTIL_PATTERN_TILES: 1248 return fill_tiles(info, planes, width, height, stride); 1249 1250 case UTIL_PATTERN_SMPTE: 1251 return fill_smpte(info, planes, width, height, stride); 1252 1253 case UTIL_PATTERN_PLAIN: 1254 return fill_plain(info, planes, height, stride); 1255 1256 case UTIL_PATTERN_GRADIENT: 1257 return fill_gradient(info, planes, width, height, stride); 1258 1259 default: 1260 printf("Error: unsupported test pattern %u.\n", pattern); 1261 break; 1262 } 1263} 1264 1265static const char *pattern_names[] = { 1266 [UTIL_PATTERN_TILES] = "tiles", 1267 [UTIL_PATTERN_SMPTE] = "smpte", 1268 [UTIL_PATTERN_PLAIN] = "plain", 1269 [UTIL_PATTERN_GRADIENT] = "gradient", 1270}; 1271 1272enum util_fill_pattern util_pattern_enum(const char *name) 1273{ 1274 unsigned int i; 1275 1276 for (i = 0; i < ARRAY_SIZE(pattern_names); i++) 1277 if (!strcmp(pattern_names[i], name)) 1278 return (enum util_fill_pattern)i; 1279 1280 printf("Error: unsupported test pattern %s.\n", name); 1281 return UTIL_PATTERN_SMPTE; 1282} 1283