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 <stdbool.h> 27 #include <stdint.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 32 #include <drm_fourcc.h> 33 34 #if HAVE_CAIRO 35 #include <cairo.h> 36 #include <math.h> 37 #endif 38 39 #include "common.h" 40 #include "format.h" 41 #include "pattern.h" 42 43 struct color_rgb24 { 44 unsigned int value:24; 45 } __attribute__((__packed__)); 46 47 struct color_yuv { 48 unsigned char y; 49 unsigned char u; 50 unsigned char v; 51 }; 52 53 #define MAKE_YUV_601_Y(r, g, b) \ 54 ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16) 55 #define MAKE_YUV_601_U(r, g, b) \ 56 (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128) 57 #define MAKE_YUV_601_V(r, g, b) \ 58 (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128) 59 60 #define MAKE_YUV_601(r, g, b) \ 61 { .y = MAKE_YUV_601_Y(r, g, b), \ 62 .u = MAKE_YUV_601_U(r, g, b), \ 63 .v = MAKE_YUV_601_V(r, g, b) } 64 65 static inline uint16_t swap16(uint16_t x) 66 { 67 return ((x & 0x00ffU) << 8) | ((x & 0xff00U) >> 8); 68 } 69 70 static inline uint32_t swap32(uint32_t x) 71 { 72 return ((x & 0x000000ffU) << 24) | 73 ((x & 0x0000ff00U) << 8) | 74 ((x & 0x00ff0000U) >> 8) | 75 ((x & 0xff000000U) >> 24); 76 } 77 78 #ifdef HAVE_BIG_ENDIAN 79 #define cpu_to_be16(x) (x) 80 #define cpu_to_le16(x) swap16(x) 81 #define cpu_to_le32(x) swap32(x) 82 #define fb_foreign_endian(format) (!((format) & DRM_FORMAT_BIG_ENDIAN)) 83 #else 84 #define cpu_to_be16(x) swap16(x) 85 #define cpu_to_le16(x) (x) 86 #define cpu_to_le32(x) (x) 87 #define fb_foreign_endian(format) ((format) & DRM_FORMAT_BIG_ENDIAN) 88 #endif 89 90 #define cpu_to_fb16(x) (fb_be ? cpu_to_be16(x) : cpu_to_le16(x)) 91 92 /* This function takes 8-bit color values */ 93 static inline uint32_t shiftcolor8(const struct util_color_component *comp, 94 uint32_t value) 95 { 96 value &= 0xff; 97 /* Fill the low bits with the high bits. */ 98 value = (value << 8) | value; 99 /* Shift down to remove unwanted low bits */ 100 value = value >> (16 - comp->length); 101 /* Shift back up to where the value should be */ 102 return value << comp->offset; 103 } 104 105 /* This function takes 10-bit color values */ 106 static inline uint32_t shiftcolor10(const struct util_color_component *comp, 107 uint32_t value) 108 { 109 value &= 0x3ff; 110 /* Fill the low bits with the high bits. */ 111 value = (value << 6) | (value >> 4); 112 /* Shift down to remove unwanted low bits */ 113 value = value >> (16 - comp->length); 114 /* Shift back up to where the value should be */ 115 return value << comp->offset; 116 } 117 118 /* This function takes 16-bit color values */ 119 static inline uint64_t shiftcolor16(const struct util_color_component *comp, 120 uint64_t value) 121 { 122 value &= 0xffff; 123 /* Shift down to remove unwanted low bits */ 124 value = value >> (16 - comp->length); 125 /* Shift back up to where the value should be */ 126 return value << comp->offset; 127 } 128 129 #define MAKE_RGBA10(rgb, r, g, b, a) \ 130 (shiftcolor10(&(rgb)->red, (r)) | \ 131 shiftcolor10(&(rgb)->green, (g)) | \ 132 shiftcolor10(&(rgb)->blue, (b)) | \ 133 shiftcolor10(&(rgb)->alpha, (a))) 134 135 #define MAKE_RGBA(rgb, r, g, b, a) \ 136 (shiftcolor8(&(rgb)->red, (r)) | \ 137 shiftcolor8(&(rgb)->green, (g)) | \ 138 shiftcolor8(&(rgb)->blue, (b)) | \ 139 shiftcolor8(&(rgb)->alpha, (a))) 140 141 #define MAKE_RGB24(rgb, r, g, b) \ 142 { .value = MAKE_RGBA(rgb, r, g, b, 0) } 143 144 145 /** 146 * Takes a uint16_t, divides by 65536, converts the infinite-precision 147 * result to fp16 with round-to-zero. 148 * 149 * Copied from mesa:src/util/half_float.c 150 */ 151 static uint16_t uint16_div_64k_to_half(uint16_t v) 152 { 153 /* Zero or subnormal. Set the mantissa to (v << 8) and return. */ 154 if (v < 4) 155 return v << 8; 156 157 /* Count the leading 0s in the uint16_t */ 158 int n = __builtin_clz(v) - 16; 159 160 /* Shift the mantissa up so bit 16 is the hidden 1 bit, 161 * mask it off, then shift back down to 10 bits 162 */ 163 int m = ( ((uint32_t)v << (n + 1)) & 0xffff ) >> 6; 164 165 /* (0{n} 1 X{15-n}) * 2^-16 166 * = 1.X * 2^(15-n-16) 167 * = 1.X * 2^(14-n - 15) 168 * which is the FP16 form with e = 14 - n 169 */ 170 int e = 14 - n; 171 172 return (e << 10) | m; 173 } 174 175 #define MAKE_RGBA8FP16(rgb, r, g, b, a) \ 176 (shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 8)) | \ 177 shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 8)) | \ 178 shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 8)) | \ 179 shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 8))) 180 181 #define MAKE_RGBA10FP16(rgb, r, g, b, a) \ 182 (shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 6)) | \ 183 shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 6)) | \ 184 shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 6)) | \ 185 shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 6))) 186 187 static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv, 188 unsigned char *y_mem, unsigned char *u_mem, 189 unsigned char *v_mem, unsigned int width, 190 unsigned int height, unsigned int stride) 191 { 192 const struct color_yuv colors_top[] = { 193 MAKE_YUV_601(192, 192, 192), /* grey */ 194 MAKE_YUV_601(192, 192, 0), /* yellow */ 195 MAKE_YUV_601(0, 192, 192), /* cyan */ 196 MAKE_YUV_601(0, 192, 0), /* green */ 197 MAKE_YUV_601(192, 0, 192), /* magenta */ 198 MAKE_YUV_601(192, 0, 0), /* red */ 199 MAKE_YUV_601(0, 0, 192), /* blue */ 200 }; 201 const struct color_yuv colors_middle[] = { 202 MAKE_YUV_601(0, 0, 192), /* blue */ 203 MAKE_YUV_601(19, 19, 19), /* black */ 204 MAKE_YUV_601(192, 0, 192), /* magenta */ 205 MAKE_YUV_601(19, 19, 19), /* black */ 206 MAKE_YUV_601(0, 192, 192), /* cyan */ 207 MAKE_YUV_601(19, 19, 19), /* black */ 208 MAKE_YUV_601(192, 192, 192), /* grey */ 209 }; 210 const struct color_yuv colors_bottom[] = { 211 MAKE_YUV_601(0, 33, 76), /* in-phase */ 212 MAKE_YUV_601(255, 255, 255), /* super white */ 213 MAKE_YUV_601(50, 0, 106), /* quadrature */ 214 MAKE_YUV_601(19, 19, 19), /* black */ 215 MAKE_YUV_601(9, 9, 9), /* 3.5% */ 216 MAKE_YUV_601(19, 19, 19), /* 7.5% */ 217 MAKE_YUV_601(29, 29, 29), /* 11.5% */ 218 MAKE_YUV_601(19, 19, 19), /* black */ 219 }; 220 unsigned int cs = yuv->chroma_stride; 221 unsigned int xsub = yuv->xsub; 222 unsigned int ysub = yuv->ysub; 223 unsigned int x; 224 unsigned int y; 225 226 /* Luma */ 227 for (y = 0; y < height * 6 / 9; ++y) { 228 for (x = 0; x < width; ++x) 229 y_mem[x] = colors_top[x * 7 / width].y; 230 y_mem += stride; 231 } 232 233 for (; y < height * 7 / 9; ++y) { 234 for (x = 0; x < width; ++x) 235 y_mem[x] = colors_middle[x * 7 / width].y; 236 y_mem += stride; 237 } 238 239 for (; y < height; ++y) { 240 for (x = 0; x < width * 5 / 7; ++x) 241 y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y; 242 for (; x < width * 6 / 7; ++x) 243 y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3 244 / (width / 7) + 4].y; 245 for (; x < width; ++x) 246 y_mem[x] = colors_bottom[7].y; 247 y_mem += stride; 248 } 249 250 /* Chroma */ 251 for (y = 0; y < height / ysub * 6 / 9; ++y) { 252 for (x = 0; x < width; x += xsub) { 253 u_mem[x*cs/xsub] = colors_top[x * 7 / width].u; 254 v_mem[x*cs/xsub] = colors_top[x * 7 / width].v; 255 } 256 u_mem += stride * cs / xsub; 257 v_mem += stride * cs / xsub; 258 } 259 260 for (; y < height / ysub * 7 / 9; ++y) { 261 for (x = 0; x < width; x += xsub) { 262 u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u; 263 v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v; 264 } 265 u_mem += stride * cs / xsub; 266 v_mem += stride * cs / xsub; 267 } 268 269 for (; y < height / ysub; ++y) { 270 for (x = 0; x < width * 5 / 7; x += xsub) { 271 u_mem[x*cs/xsub] = 272 colors_bottom[x * 4 / (width * 5 / 7)].u; 273 v_mem[x*cs/xsub] = 274 colors_bottom[x * 4 / (width * 5 / 7)].v; 275 } 276 for (; x < width * 6 / 7; x += xsub) { 277 u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * 278 3 / (width / 7) + 4].u; 279 v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * 280 3 / (width / 7) + 4].v; 281 } 282 for (; x < width; x += xsub) { 283 u_mem[x*cs/xsub] = colors_bottom[7].u; 284 v_mem[x*cs/xsub] = colors_bottom[7].v; 285 } 286 u_mem += stride * cs / xsub; 287 v_mem += stride * cs / xsub; 288 } 289 } 290 291 static void write_pixels_10bpp(unsigned char *mem, 292 unsigned short a, 293 unsigned short b, 294 unsigned short c, 295 unsigned short d) 296 { 297 mem[0] = (a & 0xff); 298 mem[1] = ((a >> 8) & 0x3) | ((b & 0x3f) << 2); 299 mem[2] = ((b >> 6) & 0xf) | ((c & 0xf) << 4); 300 mem[3] = ((c >> 4) & 0x3f) | ((d & 0x3) << 6); 301 mem[4] = ((d >> 2) & 0xff); 302 } 303 304 static void fill_smpte_yuv_planar_10bpp(const struct util_yuv_info *yuv, 305 unsigned char *y_mem, 306 unsigned char *uv_mem, 307 unsigned int width, 308 unsigned int height, 309 unsigned int stride) 310 { 311 const struct color_yuv colors_top[] = { 312 MAKE_YUV_601(192, 192, 192), /* grey */ 313 MAKE_YUV_601(192, 192, 0), /* yellow */ 314 MAKE_YUV_601(0, 192, 192), /* cyan */ 315 MAKE_YUV_601(0, 192, 0), /* green */ 316 MAKE_YUV_601(192, 0, 192), /* magenta */ 317 MAKE_YUV_601(192, 0, 0), /* red */ 318 MAKE_YUV_601(0, 0, 192), /* blue */ 319 }; 320 const struct color_yuv colors_middle[] = { 321 MAKE_YUV_601(0, 0, 192), /* blue */ 322 MAKE_YUV_601(19, 19, 19), /* black */ 323 MAKE_YUV_601(192, 0, 192), /* magenta */ 324 MAKE_YUV_601(19, 19, 19), /* black */ 325 MAKE_YUV_601(0, 192, 192), /* cyan */ 326 MAKE_YUV_601(19, 19, 19), /* black */ 327 MAKE_YUV_601(192, 192, 192), /* grey */ 328 }; 329 const struct color_yuv colors_bottom[] = { 330 MAKE_YUV_601(0, 33, 76), /* in-phase */ 331 MAKE_YUV_601(255, 255, 255), /* super white */ 332 MAKE_YUV_601(50, 0, 106), /* quadrature */ 333 MAKE_YUV_601(19, 19, 19), /* black */ 334 MAKE_YUV_601(9, 9, 9), /* 3.5% */ 335 MAKE_YUV_601(19, 19, 19), /* 7.5% */ 336 MAKE_YUV_601(29, 29, 29), /* 11.5% */ 337 MAKE_YUV_601(19, 19, 19), /* black */ 338 }; 339 unsigned int cs = yuv->chroma_stride; 340 unsigned int xsub = yuv->xsub; 341 unsigned int ysub = yuv->ysub; 342 unsigned int xstep = cs * xsub; 343 unsigned int x; 344 unsigned int y; 345 346 /* Luma */ 347 for (y = 0; y < height * 6 / 9; ++y) { 348 for (x = 0; x < width; x += 4) 349 write_pixels_10bpp(&y_mem[(x * 5) / 4], 350 colors_top[(x+0) * 7 / width].y << 2, 351 colors_top[(x+1) * 7 / width].y << 2, 352 colors_top[(x+2) * 7 / width].y << 2, 353 colors_top[(x+3) * 7 / width].y << 2); 354 y_mem += stride; 355 } 356 357 for (; y < height * 7 / 9; ++y) { 358 for (x = 0; x < width; x += 4) 359 write_pixels_10bpp(&y_mem[(x * 5) / 4], 360 colors_middle[(x+0) * 7 / width].y << 2, 361 colors_middle[(x+1) * 7 / width].y << 2, 362 colors_middle[(x+2) * 7 / width].y << 2, 363 colors_middle[(x+3) * 7 / width].y << 2); 364 y_mem += stride; 365 } 366 367 for (; y < height; ++y) { 368 for (x = 0; x < width * 5 / 7; x += 4) 369 write_pixels_10bpp(&y_mem[(x * 5) / 4], 370 colors_bottom[(x+0) * 4 / (width * 5 / 7)].y << 2, 371 colors_bottom[(x+1) * 4 / (width * 5 / 7)].y << 2, 372 colors_bottom[(x+2) * 4 / (width * 5 / 7)].y << 2, 373 colors_bottom[(x+3) * 4 / (width * 5 / 7)].y << 2); 374 for (; x < width * 6 / 7; x += 4) 375 write_pixels_10bpp(&y_mem[(x * 5) / 4], 376 colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2, 377 colors_bottom[((x+1) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2, 378 colors_bottom[((x+2) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2, 379 colors_bottom[((x+3) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2); 380 for (; x < width; x += 4) 381 write_pixels_10bpp(&y_mem[(x * 5) / 4], 382 colors_bottom[7].y << 2, 383 colors_bottom[7].y << 2, 384 colors_bottom[7].y << 2, 385 colors_bottom[7].y << 2); 386 y_mem += stride; 387 } 388 389 /* Chroma */ 390 for (y = 0; y < height * 6 / 9; y += ysub) { 391 for (x = 0; x < width; x += xstep) 392 write_pixels_10bpp(&uv_mem[(x * 5) / xstep], 393 colors_top[(x+0) * 7 / width].u << 2, 394 colors_top[(x+0) * 7 / width].v << 2, 395 colors_top[(x+xsub) * 7 / width].u << 2, 396 colors_top[(x+xsub) * 7 / width].v << 2); 397 uv_mem += stride * cs / xsub; 398 } 399 400 for (; y < height * 7 / 9; y += ysub) { 401 for (x = 0; x < width; x += xstep) 402 write_pixels_10bpp(&uv_mem[(x * 5) / xstep], 403 colors_middle[(x+0) * 7 / width].u << 2, 404 colors_middle[(x+0) * 7 / width].v << 2, 405 colors_middle[(x+xsub) * 7 / width].u << 2, 406 colors_middle[(x+xsub) * 7 / width].v << 2); 407 uv_mem += stride * cs / xsub; 408 } 409 410 for (; y < height; y += ysub) { 411 for (x = 0; x < width * 5 / 7; x += xstep) 412 write_pixels_10bpp(&uv_mem[(x * 5) / xstep], 413 colors_bottom[(x+0) * 4 / (width * 5 / 7)].u << 2, 414 colors_bottom[(x+0) * 4 / (width * 5 / 7)].v << 2, 415 colors_bottom[(x+xsub) * 4 / (width * 5 / 7)].u << 2, 416 colors_bottom[(x+xsub) * 4 / (width * 5 / 7)].v << 2); 417 for (; x < width * 6 / 7; x += xstep) 418 write_pixels_10bpp(&uv_mem[(x * 5) / xstep], 419 colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].u << 2, 420 colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].v << 2, 421 colors_bottom[((x+xsub) - width * 5 / 7) * 3 / (width / 7) + 4].u << 2, 422 colors_bottom[((x+xsub) - width * 5 / 7) * 3 / (width / 7) + 4].v << 2); 423 for (; x < width; x += xstep) 424 write_pixels_10bpp(&uv_mem[(x * 5) / xstep], 425 colors_bottom[7].u << 2, 426 colors_bottom[7].v << 2, 427 colors_bottom[7].u << 2, 428 colors_bottom[7].v << 2); 429 uv_mem += stride * cs / xsub; 430 } 431 } 432 433 static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem, 434 unsigned int width, unsigned int height, 435 unsigned int stride) 436 { 437 const struct color_yuv colors_top[] = { 438 MAKE_YUV_601(192, 192, 192), /* grey */ 439 MAKE_YUV_601(192, 192, 0), /* yellow */ 440 MAKE_YUV_601(0, 192, 192), /* cyan */ 441 MAKE_YUV_601(0, 192, 0), /* green */ 442 MAKE_YUV_601(192, 0, 192), /* magenta */ 443 MAKE_YUV_601(192, 0, 0), /* red */ 444 MAKE_YUV_601(0, 0, 192), /* blue */ 445 }; 446 const struct color_yuv colors_middle[] = { 447 MAKE_YUV_601(0, 0, 192), /* blue */ 448 MAKE_YUV_601(19, 19, 19), /* black */ 449 MAKE_YUV_601(192, 0, 192), /* magenta */ 450 MAKE_YUV_601(19, 19, 19), /* black */ 451 MAKE_YUV_601(0, 192, 192), /* cyan */ 452 MAKE_YUV_601(19, 19, 19), /* black */ 453 MAKE_YUV_601(192, 192, 192), /* grey */ 454 }; 455 const struct color_yuv colors_bottom[] = { 456 MAKE_YUV_601(0, 33, 76), /* in-phase */ 457 MAKE_YUV_601(255, 255, 255), /* super white */ 458 MAKE_YUV_601(50, 0, 106), /* quadrature */ 459 MAKE_YUV_601(19, 19, 19), /* black */ 460 MAKE_YUV_601(9, 9, 9), /* 3.5% */ 461 MAKE_YUV_601(19, 19, 19), /* 7.5% */ 462 MAKE_YUV_601(29, 29, 29), /* 11.5% */ 463 MAKE_YUV_601(19, 19, 19), /* black */ 464 }; 465 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; 466 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; 467 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; 468 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; 469 unsigned int x; 470 unsigned int y; 471 472 /* Luma */ 473 for (y = 0; y < height * 6 / 9; ++y) { 474 for (x = 0; x < width; ++x) 475 y_mem[2*x] = colors_top[x * 7 / width].y; 476 y_mem += stride; 477 } 478 479 for (; y < height * 7 / 9; ++y) { 480 for (x = 0; x < width; ++x) 481 y_mem[2*x] = colors_middle[x * 7 / width].y; 482 y_mem += stride; 483 } 484 485 for (; y < height; ++y) { 486 for (x = 0; x < width * 5 / 7; ++x) 487 y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y; 488 for (; x < width * 6 / 7; ++x) 489 y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3 490 / (width / 7) + 4].y; 491 for (; x < width; ++x) 492 y_mem[2*x] = colors_bottom[7].y; 493 y_mem += stride; 494 } 495 496 /* Chroma */ 497 for (y = 0; y < height * 6 / 9; ++y) { 498 for (x = 0; x < width; x += 2) { 499 c_mem[2*x+u] = colors_top[x * 7 / width].u; 500 c_mem[2*x+v] = colors_top[x * 7 / width].v; 501 } 502 c_mem += stride; 503 } 504 505 for (; y < height * 7 / 9; ++y) { 506 for (x = 0; x < width; x += 2) { 507 c_mem[2*x+u] = colors_middle[x * 7 / width].u; 508 c_mem[2*x+v] = colors_middle[x * 7 / width].v; 509 } 510 c_mem += stride; 511 } 512 513 for (; y < height; ++y) { 514 for (x = 0; x < width * 5 / 7; x += 2) { 515 c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u; 516 c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v; 517 } 518 for (; x < width * 6 / 7; x += 2) { 519 c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) * 520 3 / (width / 7) + 4].u; 521 c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) * 522 3 / (width / 7) + 4].v; 523 } 524 for (; x < width; x += 2) { 525 c_mem[2*x+u] = colors_bottom[7].u; 526 c_mem[2*x+v] = colors_bottom[7].v; 527 } 528 c_mem += stride; 529 } 530 } 531 532 static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem, 533 unsigned int width, unsigned int height, 534 unsigned int stride, bool fb_be) 535 { 536 const uint16_t colors_top[] = { 537 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ 538 MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ 539 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ 540 MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ 541 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ 542 MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ 543 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ 544 }; 545 const uint16_t colors_middle[] = { 546 MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ 547 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 548 MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ 549 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 550 MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ 551 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 552 MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ 553 }; 554 const uint16_t colors_bottom[] = { 555 MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ 556 MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ 557 MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ 558 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 559 MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ 560 MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ 561 MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ 562 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 563 }; 564 unsigned int x; 565 unsigned int y; 566 567 for (y = 0; y < height * 6 / 9; ++y) { 568 for (x = 0; x < width; ++x) 569 ((uint16_t *)mem)[x] = cpu_to_fb16(colors_top[x * 7 / width]); 570 mem += stride; 571 } 572 573 for (; y < height * 7 / 9; ++y) { 574 for (x = 0; x < width; ++x) 575 ((uint16_t *)mem)[x] = cpu_to_fb16(colors_middle[x * 7 / width]); 576 mem += stride; 577 } 578 579 for (; y < height; ++y) { 580 for (x = 0; x < width * 5 / 7; ++x) 581 ((uint16_t *)mem)[x] = 582 cpu_to_fb16(colors_bottom[x * 4 / (width * 5 / 7)]); 583 for (; x < width * 6 / 7; ++x) 584 ((uint16_t *)mem)[x] = 585 cpu_to_fb16(colors_bottom[(x - width * 5 / 7) * 3 586 / (width / 7) + 4]); 587 for (; x < width; ++x) 588 ((uint16_t *)mem)[x] = cpu_to_fb16(colors_bottom[7]); 589 mem += stride; 590 } 591 } 592 593 static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem, 594 unsigned int width, unsigned int height, 595 unsigned int stride) 596 { 597 const struct color_rgb24 colors_top[] = { 598 MAKE_RGB24(rgb, 192, 192, 192), /* grey */ 599 MAKE_RGB24(rgb, 192, 192, 0), /* yellow */ 600 MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ 601 MAKE_RGB24(rgb, 0, 192, 0), /* green */ 602 MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ 603 MAKE_RGB24(rgb, 192, 0, 0), /* red */ 604 MAKE_RGB24(rgb, 0, 0, 192), /* blue */ 605 }; 606 const struct color_rgb24 colors_middle[] = { 607 MAKE_RGB24(rgb, 0, 0, 192), /* blue */ 608 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 609 MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ 610 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 611 MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ 612 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 613 MAKE_RGB24(rgb, 192, 192, 192), /* grey */ 614 }; 615 const struct color_rgb24 colors_bottom[] = { 616 MAKE_RGB24(rgb, 0, 33, 76), /* in-phase */ 617 MAKE_RGB24(rgb, 255, 255, 255), /* super white */ 618 MAKE_RGB24(rgb, 50, 0, 106), /* quadrature */ 619 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 620 MAKE_RGB24(rgb, 9, 9, 9), /* 3.5% */ 621 MAKE_RGB24(rgb, 19, 19, 19), /* 7.5% */ 622 MAKE_RGB24(rgb, 29, 29, 29), /* 11.5% */ 623 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 624 }; 625 unsigned int x; 626 unsigned int y; 627 628 for (y = 0; y < height * 6 / 9; ++y) { 629 for (x = 0; x < width; ++x) 630 ((struct color_rgb24 *)mem)[x] = 631 colors_top[x * 7 / width]; 632 mem += stride; 633 } 634 635 for (; y < height * 7 / 9; ++y) { 636 for (x = 0; x < width; ++x) 637 ((struct color_rgb24 *)mem)[x] = 638 colors_middle[x * 7 / width]; 639 mem += stride; 640 } 641 642 for (; y < height; ++y) { 643 for (x = 0; x < width * 5 / 7; ++x) 644 ((struct color_rgb24 *)mem)[x] = 645 colors_bottom[x * 4 / (width * 5 / 7)]; 646 for (; x < width * 6 / 7; ++x) 647 ((struct color_rgb24 *)mem)[x] = 648 colors_bottom[(x - width * 5 / 7) * 3 649 / (width / 7) + 4]; 650 for (; x < width; ++x) 651 ((struct color_rgb24 *)mem)[x] = colors_bottom[7]; 652 mem += stride; 653 } 654 } 655 656 static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem, 657 unsigned int width, unsigned int height, 658 unsigned int stride) 659 { 660 const uint32_t colors_top[] = { 661 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ 662 MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ 663 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ 664 MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ 665 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ 666 MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ 667 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ 668 }; 669 const uint32_t colors_middle[] = { 670 MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */ 671 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 672 MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */ 673 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 674 MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */ 675 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */ 676 MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */ 677 }; 678 const uint32_t colors_bottom[] = { 679 MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ 680 MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ 681 MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ 682 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 683 MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ 684 MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ 685 MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ 686 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 687 }; 688 unsigned int x; 689 unsigned int y; 690 691 for (y = 0; y < height * 6 / 9; ++y) { 692 for (x = 0; x < width; ++x) 693 ((uint32_t *)mem)[x] = cpu_to_le32(colors_top[x * 7 / width]); 694 mem += stride; 695 } 696 697 for (; y < height * 7 / 9; ++y) { 698 for (x = 0; x < width; ++x) 699 ((uint32_t *)mem)[x] = cpu_to_le32(colors_middle[x * 7 / width]); 700 mem += stride; 701 } 702 703 for (; y < height; ++y) { 704 for (x = 0; x < width * 5 / 7; ++x) 705 ((uint32_t *)mem)[x] = 706 cpu_to_le32(colors_bottom[x * 4 / (width * 5 / 7)]); 707 for (; x < width * 6 / 7; ++x) 708 ((uint32_t *)mem)[x] = 709 cpu_to_le32(colors_bottom[(x - width * 5 / 7) * 3 710 / (width / 7) + 4]); 711 for (; x < width; ++x) 712 ((uint32_t *)mem)[x] = cpu_to_le32(colors_bottom[7]); 713 mem += stride; 714 } 715 } 716 717 static void fill_smpte_rgb16fp(const struct util_rgb_info *rgb, void *mem, 718 unsigned int width, unsigned int height, 719 unsigned int stride) 720 { 721 const uint64_t colors_top[] = { 722 MAKE_RGBA8FP16(rgb, 192, 192, 192, 255),/* grey */ 723 MAKE_RGBA8FP16(rgb, 192, 192, 0, 255), /* yellow */ 724 MAKE_RGBA8FP16(rgb, 0, 192, 192, 255), /* cyan */ 725 MAKE_RGBA8FP16(rgb, 0, 192, 0, 255), /* green */ 726 MAKE_RGBA8FP16(rgb, 192, 0, 192, 255), /* magenta */ 727 MAKE_RGBA8FP16(rgb, 192, 0, 0, 255), /* red */ 728 MAKE_RGBA8FP16(rgb, 0, 0, 192, 255), /* blue */ 729 }; 730 const uint64_t colors_middle[] = { 731 MAKE_RGBA8FP16(rgb, 0, 0, 192, 127), /* blue */ 732 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */ 733 MAKE_RGBA8FP16(rgb, 192, 0, 192, 127), /* magenta */ 734 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */ 735 MAKE_RGBA8FP16(rgb, 0, 192, 192, 127), /* cyan */ 736 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */ 737 MAKE_RGBA8FP16(rgb, 192, 192, 192, 127),/* grey */ 738 }; 739 const uint64_t colors_bottom[] = { 740 MAKE_RGBA8FP16(rgb, 0, 33, 76, 255), /* in-phase */ 741 MAKE_RGBA8FP16(rgb, 255, 255, 255, 255),/* super white */ 742 MAKE_RGBA8FP16(rgb, 50, 0, 106, 255), /* quadrature */ 743 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* black */ 744 MAKE_RGBA8FP16(rgb, 9, 9, 9, 255), /* 3.5% */ 745 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* 7.5% */ 746 MAKE_RGBA8FP16(rgb, 29, 29, 29, 255), /* 11.5% */ 747 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* black */ 748 }; 749 unsigned int x; 750 unsigned int y; 751 752 for (y = 0; y < height * 6 / 9; ++y) { 753 for (x = 0; x < width; ++x) 754 ((uint64_t *)mem)[x] = colors_top[x * 7 / width]; 755 mem += stride; 756 } 757 758 for (; y < height * 7 / 9; ++y) { 759 for (x = 0; x < width; ++x) 760 ((uint64_t *)mem)[x] = colors_middle[x * 7 / width]; 761 mem += stride; 762 } 763 764 for (; y < height; ++y) { 765 for (x = 0; x < width * 5 / 7; ++x) 766 ((uint64_t *)mem)[x] = 767 colors_bottom[x * 4 / (width * 5 / 7)]; 768 for (; x < width * 6 / 7; ++x) 769 ((uint64_t *)mem)[x] = 770 colors_bottom[(x - width * 5 / 7) * 3 771 / (width / 7) + 4]; 772 for (; x < width; ++x) 773 ((uint64_t *)mem)[x] = colors_bottom[7]; 774 mem += stride; 775 } 776 } 777 778 enum smpte_colors { 779 SMPTE_COLOR_GREY, 780 SMPTE_COLOR_YELLOW, 781 SMPTE_COLOR_CYAN, 782 SMPTE_COLOR_GREEN, 783 SMPTE_COLOR_MAGENTA, 784 SMPTE_COLOR_RED, 785 SMPTE_COLOR_BLUE, 786 SMPTE_COLOR_BLACK, 787 SMPTE_COLOR_IN_PHASE, 788 SMPTE_COLOR_SUPER_WHITE, 789 SMPTE_COLOR_QUADRATURE, 790 SMPTE_COLOR_3PC5, 791 SMPTE_COLOR_11PC5, 792 }; 793 794 static unsigned int smpte_top[7] = { 795 SMPTE_COLOR_GREY, 796 SMPTE_COLOR_YELLOW, 797 SMPTE_COLOR_CYAN, 798 SMPTE_COLOR_GREEN, 799 SMPTE_COLOR_MAGENTA, 800 SMPTE_COLOR_RED, 801 SMPTE_COLOR_BLUE, 802 }; 803 804 static unsigned int smpte_middle[7] = { 805 SMPTE_COLOR_BLUE, 806 SMPTE_COLOR_BLACK, 807 SMPTE_COLOR_MAGENTA, 808 SMPTE_COLOR_BLACK, 809 SMPTE_COLOR_CYAN, 810 SMPTE_COLOR_BLACK, 811 SMPTE_COLOR_GREY, 812 }; 813 814 static unsigned int smpte_bottom[8] = { 815 SMPTE_COLOR_IN_PHASE, 816 SMPTE_COLOR_SUPER_WHITE, 817 SMPTE_COLOR_QUADRATURE, 818 SMPTE_COLOR_BLACK, 819 SMPTE_COLOR_3PC5, 820 SMPTE_COLOR_BLACK, 821 SMPTE_COLOR_11PC5, 822 SMPTE_COLOR_BLACK, 823 }; 824 825 #define EXPAND_COLOR(r, g, b) { (r) * 0x101, (g) * 0x101, (b) * 0x101 } 826 827 static const struct drm_color_lut bw_color_lut[] = { 828 EXPAND_COLOR( 0, 0, 0), /* black */ 829 EXPAND_COLOR(255, 255, 255), /* white */ 830 }; 831 832 static const struct drm_color_lut pentile_color_lut[] = { 833 /* PenTile RG-GB */ 834 EXPAND_COLOR( 0, 0, 0), /* black */ 835 EXPAND_COLOR(255, 0, 0), /* red */ 836 EXPAND_COLOR( 0, 207, 0), /* green */ 837 EXPAND_COLOR( 0, 0, 255), /* blue */ 838 }; 839 840 static const struct drm_color_lut smpte_color_lut[] = { 841 [SMPTE_COLOR_GREY] = EXPAND_COLOR(192, 192, 192), 842 [SMPTE_COLOR_YELLOW] = EXPAND_COLOR(192, 192, 0), 843 [SMPTE_COLOR_CYAN] = EXPAND_COLOR( 0, 192, 192), 844 [SMPTE_COLOR_GREEN] = EXPAND_COLOR( 0, 192, 0), 845 [SMPTE_COLOR_MAGENTA] = EXPAND_COLOR(192, 0, 192), 846 [SMPTE_COLOR_RED] = EXPAND_COLOR(192, 0, 0), 847 [SMPTE_COLOR_BLUE] = EXPAND_COLOR( 0, 0, 192), 848 [SMPTE_COLOR_BLACK] = EXPAND_COLOR( 19, 19, 19), 849 [SMPTE_COLOR_IN_PHASE] = EXPAND_COLOR( 0, 33, 76), 850 [SMPTE_COLOR_SUPER_WHITE] = EXPAND_COLOR(255, 255, 255), 851 [SMPTE_COLOR_QUADRATURE] = EXPAND_COLOR( 50, 0, 106), 852 [SMPTE_COLOR_3PC5] = EXPAND_COLOR( 9, 9, 9), 853 [SMPTE_COLOR_11PC5] = EXPAND_COLOR( 29, 29, 29), 854 }; 855 856 #undef EXPAND_COLOR 857 858 /* 859 * Floyd-Steinberg dithering 860 */ 861 862 struct fsd { 863 unsigned int width; 864 unsigned int x; 865 unsigned int i; 866 int red; 867 int green; 868 int blue; 869 int error[]; 870 }; 871 872 static struct fsd *fsd_alloc(unsigned int width) 873 { 874 unsigned int n = 3 * (width + 1); 875 struct fsd *fsd = malloc(sizeof(*fsd) + n * sizeof(fsd->error[0])); 876 877 fsd->width = width; 878 fsd->x = 0; 879 fsd->i = 0; 880 memset(fsd->error, 0, n * sizeof(fsd->error[0])); 881 882 return fsd; 883 } 884 885 static inline int clamp(int val, int min, int max) 886 { 887 if (val < min) 888 return min; 889 if (val > max) 890 return max; 891 return val; 892 } 893 894 static void fsd_dither(struct fsd *fsd, struct drm_color_lut *color) 895 { 896 unsigned int i = fsd->i; 897 898 fsd->red = (int)color->red + (fsd->error[3 * i] + 8) / 16; 899 fsd->green = (int)color->green + (fsd->error[3 * i + 1] + 8) / 16; 900 fsd->blue = (int)color->blue + (fsd->error[3 * i + 2] + 8) / 16; 901 902 color->red = clamp(fsd->red, 0, 65535); 903 color->green = clamp(fsd->green, 0, 65535); 904 color->blue = clamp(fsd->blue, 0, 65535); 905 } 906 907 static void fsd_update(struct fsd *fsd, const struct drm_color_lut *actual) 908 { 909 int error_red = fsd->red - (int)actual->red; 910 int error_green = fsd->green - (int)actual->green; 911 int error_blue = fsd->blue - (int)actual->blue; 912 unsigned int width = fsd->width; 913 unsigned int i = fsd->i, j; 914 unsigned int n = width + 1; 915 916 /* Distribute errors over neighboring pixels */ 917 if (fsd->x == width - 1) { 918 /* Last pixel on this scanline */ 919 /* South East: initialize to zero */ 920 fsd->error[3 * i] = 0; 921 fsd->error[3 * i + 1] = 0; 922 fsd->error[3 * i + 2] = 0; 923 } else { 924 /* East: accumulate error */ 925 j = (i + 1) % n; 926 fsd->error[3 * j] += 7 * error_red; 927 fsd->error[3 * j + 1] += 7 * error_green; 928 fsd->error[3 * j + 2] += 7 * error_blue; 929 930 /* South East: initial error */ 931 fsd->error[3 * i] = error_red; 932 fsd->error[3 * i + 1] = error_green; 933 fsd->error[3 * i + 2] = error_blue; 934 } 935 /* South West: accumulate error */ 936 j = (i + width - 1) % n; 937 fsd->error[3 * j] += 3 * error_red; 938 fsd->error[3 * j + 1] += 3 * error_green; 939 fsd->error[3 * j + 2] += 3 * error_blue; 940 941 /* South: accumulate error */ 942 j = (i + width) % n; 943 fsd->error[3 * j] += 5 * error_red; 944 fsd->error[3 * j + 1] += 5 * error_green; 945 fsd->error[3 * j + 2] += 5 * error_blue; 946 947 fsd->x = (fsd->x + 1) % width; 948 fsd->i = (fsd->i + 1) % n; 949 } 950 951 static void write_pixel_1(uint8_t *mem, unsigned int x, unsigned int pixel) 952 { 953 unsigned int shift = 7 - (x & 7); 954 unsigned int mask = 1U << shift; 955 956 mem[x / 8] = (mem[x / 8] & ~mask) | ((pixel << shift) & mask); 957 } 958 959 static void write_color_1(struct fsd *fsd, uint8_t *mem, unsigned int x, 960 unsigned int index) 961 { 962 struct drm_color_lut color = smpte_color_lut[index]; 963 unsigned int pixel; 964 965 fsd_dither(fsd, &color); 966 967 /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */ 968 if (3 * color.red + 6 * color.green + color.blue >= 10 * 32768) { 969 pixel = 1; 970 color.red = color.green = color.blue = 65535; 971 } else { 972 pixel = 0; 973 color.red = color.green = color.blue = 0; 974 } 975 976 fsd_update(fsd, &color); 977 978 write_pixel_1(mem, x, pixel); 979 } 980 981 static void fill_smpte_c1(void *mem, unsigned int width, unsigned int height, 982 unsigned int stride) 983 { 984 struct fsd *fsd = fsd_alloc(width); 985 unsigned int x; 986 unsigned int y; 987 988 for (y = 0; y < height * 6 / 9; ++y) { 989 for (x = 0; x < width; ++x) 990 write_color_1(fsd, mem, x, smpte_top[x * 7 / width]); 991 mem += stride; 992 } 993 994 for (; y < height * 7 / 9; ++y) { 995 for (x = 0; x < width; ++x) 996 write_color_1(fsd, mem, x, smpte_middle[x * 7 / width]); 997 mem += stride; 998 } 999 1000 for (; y < height; ++y) { 1001 for (x = 0; x < width * 5 / 7; ++x) 1002 write_color_1(fsd, mem, x, 1003 smpte_bottom[x * 4 / (width * 5 / 7)]); 1004 for (; x < width * 6 / 7; ++x) 1005 write_color_1(fsd, mem, x, 1006 smpte_bottom[(x - width * 5 / 7) * 3 / 1007 (width / 7) + 4]); 1008 for (; x < width; ++x) 1009 write_color_1(fsd, mem, x, smpte_bottom[7]); 1010 mem += stride; 1011 } 1012 1013 free(fsd); 1014 } 1015 1016 static void write_pixel_2(uint8_t *mem, unsigned int x, unsigned int pixel) 1017 { 1018 unsigned int shift = 6 - 2 * (x & 3); 1019 unsigned int mask = 3U << shift; 1020 1021 mem[x / 4] = (mem[x / 4] & ~mask) | ((pixel << shift) & mask); 1022 } 1023 1024 static void write_color_2(struct fsd *fsd, uint8_t *mem, unsigned int stride, 1025 unsigned int x, unsigned int index) 1026 { 1027 struct drm_color_lut color = smpte_color_lut[index]; 1028 unsigned int r, g, b; 1029 1030 fsd_dither(fsd, &color); 1031 1032 if (color.red >= 32768) { 1033 r = 1; 1034 color.red = 65535; 1035 } else { 1036 r = 0; 1037 color.red = 0; 1038 } 1039 if (color.green >= 32768) { 1040 g = 2; 1041 color.green = 65535; 1042 } else { 1043 g = 0; 1044 color.green = 0; 1045 } 1046 if (color.blue >= 32768) { 1047 b = 3; 1048 color.blue = 65535; 1049 } else { 1050 b = 0; 1051 color.blue = 0; 1052 } 1053 1054 fsd_update(fsd, &color); 1055 1056 /* Use PenTile RG-GB */ 1057 write_pixel_2(mem, 2 * x, r); 1058 write_pixel_2(mem, 2 * x + 1, g); 1059 write_pixel_2(mem + stride, 2 * x, g); 1060 write_pixel_2(mem + stride, 2 * x + 1, b); 1061 } 1062 1063 static void fill_smpte_c2(void *mem, unsigned int width, unsigned int height, 1064 unsigned int stride) 1065 { 1066 struct fsd *fsd = fsd_alloc(width); 1067 unsigned int x; 1068 unsigned int y; 1069 1070 /* Half resolution for PenTile RG-GB */ 1071 width /= 2; 1072 height /= 2; 1073 1074 for (y = 0; y < height * 6 / 9; ++y) { 1075 for (x = 0; x < width; ++x) 1076 write_color_2(fsd, mem, stride, x, smpte_top[x * 7 / width]); 1077 mem += 2 * stride; 1078 } 1079 1080 for (; y < height * 7 / 9; ++y) { 1081 for (x = 0; x < width; ++x) 1082 write_color_2(fsd, mem, stride, x, smpte_middle[x * 7 / width]); 1083 mem += 2 * stride; 1084 } 1085 1086 for (; y < height; ++y) { 1087 for (x = 0; x < width * 5 / 7; ++x) 1088 write_color_2(fsd, mem, stride, x, 1089 smpte_bottom[x * 4 / (width * 5 / 7)]); 1090 for (; x < width * 6 / 7; ++x) 1091 write_color_2(fsd, mem, stride, x, 1092 smpte_bottom[(x - width * 5 / 7) * 3 / 1093 (width / 7) + 4]); 1094 for (; x < width; ++x) 1095 write_color_2(fsd, mem, stride, x, smpte_bottom[7]); 1096 mem += 2 * stride; 1097 } 1098 1099 free(fsd); 1100 } 1101 1102 static void write_pixel_4(uint8_t *mem, unsigned int x, unsigned int pixel) 1103 { 1104 if (x & 1) 1105 mem[x / 2] = (mem[x / 2] & 0xf0) | (pixel & 0x0f); 1106 else 1107 mem[x / 2] = (mem[x / 2] & 0x0f) | (pixel << 4); 1108 } 1109 1110 static void fill_smpte_c4(void *mem, unsigned int width, unsigned int height, 1111 unsigned int stride) 1112 { 1113 unsigned int x; 1114 unsigned int y; 1115 1116 for (y = 0; y < height * 6 / 9; ++y) { 1117 for (x = 0; x < width; ++x) 1118 write_pixel_4(mem, x, smpte_top[x * 7 / width]); 1119 mem += stride; 1120 } 1121 1122 for (; y < height * 7 / 9; ++y) { 1123 for (x = 0; x < width; ++x) 1124 write_pixel_4(mem, x, smpte_middle[x * 7 / width]); 1125 mem += stride; 1126 } 1127 1128 for (; y < height; ++y) { 1129 for (x = 0; x < width * 5 / 7; ++x) 1130 write_pixel_4(mem, x, 1131 smpte_bottom[x * 4 / (width * 5 / 7)]); 1132 for (; x < width * 6 / 7; ++x) 1133 write_pixel_4(mem, x, 1134 smpte_bottom[(x - width * 5 / 7) * 3 / 1135 (width / 7) + 4]); 1136 for (; x < width; ++x) 1137 write_pixel_4(mem, x, smpte_bottom[7]); 1138 mem += stride; 1139 } 1140 } 1141 1142 static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height, 1143 unsigned int stride) 1144 { 1145 unsigned int x; 1146 unsigned int y; 1147 1148 for (y = 0; y < height * 6 / 9; ++y) { 1149 for (x = 0; x < width; ++x) 1150 ((uint8_t *)mem)[x] = smpte_top[x * 7 / width]; 1151 mem += stride; 1152 } 1153 1154 for (; y < height * 7 / 9; ++y) { 1155 for (x = 0; x < width; ++x) 1156 ((uint8_t *)mem)[x] = smpte_middle[x * 7 / width]; 1157 mem += stride; 1158 } 1159 1160 for (; y < height; ++y) { 1161 for (x = 0; x < width * 5 / 7; ++x) 1162 ((uint8_t *)mem)[x] = 1163 smpte_bottom[x * 4 / (width * 5 / 7)]; 1164 for (; x < width * 6 / 7; ++x) 1165 ((uint8_t *)mem)[x] = 1166 smpte_bottom[(x - width * 5 / 7) * 3 1167 / (width / 7) + 4]; 1168 for (; x < width; ++x) 1169 ((uint8_t *)mem)[x] = smpte_bottom[7]; 1170 mem += stride; 1171 } 1172 } 1173 1174 void util_smpte_fill_lut(unsigned int ncolors, struct drm_color_lut *lut) 1175 { 1176 if (ncolors < ARRAY_SIZE(bw_color_lut)) { 1177 printf("Error: lut too small: %u < %zu\n", ncolors, 1178 ARRAY_SIZE(bw_color_lut)); 1179 return; 1180 } 1181 memset(lut, 0, ncolors * sizeof(struct drm_color_lut)); 1182 1183 if (ncolors < ARRAY_SIZE(pentile_color_lut)) 1184 memcpy(lut, bw_color_lut, sizeof(bw_color_lut)); 1185 else if (ncolors < ARRAY_SIZE(smpte_color_lut)) 1186 memcpy(lut, pentile_color_lut, sizeof(pentile_color_lut)); 1187 else 1188 memcpy(lut, smpte_color_lut, sizeof(smpte_color_lut)); 1189 } 1190 1191 static void fill_smpte(const struct util_format_info *info, void *planes[3], 1192 unsigned int width, unsigned int height, 1193 unsigned int stride) 1194 { 1195 unsigned char *u, *v; 1196 1197 switch (info->format) { 1198 case DRM_FORMAT_C1: 1199 return fill_smpte_c1(planes[0], width, height, stride); 1200 case DRM_FORMAT_C2: 1201 return fill_smpte_c2(planes[0], width, height, stride); 1202 case DRM_FORMAT_C4: 1203 return fill_smpte_c4(planes[0], width, height, stride); 1204 case DRM_FORMAT_C8: 1205 return fill_smpte_c8(planes[0], width, height, stride); 1206 case DRM_FORMAT_UYVY: 1207 case DRM_FORMAT_VYUY: 1208 case DRM_FORMAT_YUYV: 1209 case DRM_FORMAT_YVYU: 1210 return fill_smpte_yuv_packed(&info->yuv, planes[0], width, 1211 height, stride); 1212 1213 case DRM_FORMAT_NV12: 1214 case DRM_FORMAT_NV21: 1215 case DRM_FORMAT_NV16: 1216 case DRM_FORMAT_NV61: 1217 case DRM_FORMAT_NV24: 1218 case DRM_FORMAT_NV42: 1219 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; 1220 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; 1221 return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v, 1222 width, height, stride); 1223 1224 case DRM_FORMAT_NV15: 1225 case DRM_FORMAT_NV20: 1226 case DRM_FORMAT_NV30: 1227 return fill_smpte_yuv_planar_10bpp(&info->yuv, planes[0], 1228 planes[1], width, height, 1229 stride); 1230 1231 case DRM_FORMAT_YUV420: 1232 case DRM_FORMAT_YUV422: 1233 case DRM_FORMAT_YUV444: 1234 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], 1235 planes[2], width, height, stride); 1236 1237 case DRM_FORMAT_YVU420: 1238 case DRM_FORMAT_YVU422: 1239 case DRM_FORMAT_YVU444: 1240 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2], 1241 planes[1], width, height, stride); 1242 1243 case DRM_FORMAT_ARGB4444: 1244 case DRM_FORMAT_XRGB4444: 1245 case DRM_FORMAT_ABGR4444: 1246 case DRM_FORMAT_XBGR4444: 1247 case DRM_FORMAT_RGBA4444: 1248 case DRM_FORMAT_RGBX4444: 1249 case DRM_FORMAT_BGRA4444: 1250 case DRM_FORMAT_BGRX4444: 1251 case DRM_FORMAT_RGB565: 1252 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN: 1253 case DRM_FORMAT_BGR565: 1254 case DRM_FORMAT_ARGB1555: 1255 case DRM_FORMAT_XRGB1555: 1256 case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN: 1257 case DRM_FORMAT_ABGR1555: 1258 case DRM_FORMAT_XBGR1555: 1259 case DRM_FORMAT_RGBA5551: 1260 case DRM_FORMAT_RGBX5551: 1261 case DRM_FORMAT_BGRA5551: 1262 case DRM_FORMAT_BGRX5551: 1263 return fill_smpte_rgb16(&info->rgb, planes[0], 1264 width, height, stride, 1265 info->format & DRM_FORMAT_BIG_ENDIAN); 1266 1267 case DRM_FORMAT_BGR888: 1268 case DRM_FORMAT_RGB888: 1269 return fill_smpte_rgb24(&info->rgb, planes[0], 1270 width, height, stride); 1271 case DRM_FORMAT_ARGB8888: 1272 case DRM_FORMAT_XRGB8888: 1273 case DRM_FORMAT_ABGR8888: 1274 case DRM_FORMAT_XBGR8888: 1275 case DRM_FORMAT_RGBA8888: 1276 case DRM_FORMAT_RGBX8888: 1277 case DRM_FORMAT_BGRA8888: 1278 case DRM_FORMAT_BGRX8888: 1279 case DRM_FORMAT_ARGB2101010: 1280 case DRM_FORMAT_XRGB2101010: 1281 case DRM_FORMAT_ABGR2101010: 1282 case DRM_FORMAT_XBGR2101010: 1283 case DRM_FORMAT_RGBA1010102: 1284 case DRM_FORMAT_RGBX1010102: 1285 case DRM_FORMAT_BGRA1010102: 1286 case DRM_FORMAT_BGRX1010102: 1287 return fill_smpte_rgb32(&info->rgb, planes[0], 1288 width, height, stride); 1289 1290 case DRM_FORMAT_XRGB16161616F: 1291 case DRM_FORMAT_XBGR16161616F: 1292 case DRM_FORMAT_ARGB16161616F: 1293 case DRM_FORMAT_ABGR16161616F: 1294 return fill_smpte_rgb16fp(&info->rgb, planes[0], 1295 width, height, stride); 1296 } 1297 } 1298 1299 #if HAVE_CAIRO 1300 static void byteswap_buffer16(void *mem, unsigned int width, unsigned int height, 1301 unsigned int stride) 1302 { 1303 unsigned int x, y; 1304 1305 for (y = 0; y < height; ++y) { 1306 for (x = 0; x < width; ++x) 1307 ((uint16_t *)mem)[x] = swap16(((uint16_t *)mem)[x]); 1308 mem += stride; 1309 } 1310 } 1311 1312 static void byteswap_buffer32(void *mem, unsigned int width, unsigned int height, 1313 unsigned int stride) 1314 { 1315 unsigned int x, y; 1316 1317 for (y = 0; y < height; ++y) { 1318 for (x = 0; x < width; ++x) 1319 ((uint32_t *)mem)[x] = swap32(((uint32_t *)mem)[x]); 1320 mem += stride; 1321 } 1322 } 1323 #endif 1324 1325 static void make_pwetty(void *data, unsigned int width, unsigned int height, 1326 unsigned int stride, uint32_t format) 1327 { 1328 #if HAVE_CAIRO 1329 cairo_surface_t *surface; 1330 cairo_t *cr; 1331 cairo_format_t cairo_format; 1332 bool swap16 = false; 1333 bool swap32 = false; 1334 1335 /* we can ignore the order of R,G,B channels */ 1336 switch (format) { 1337 case DRM_FORMAT_XRGB8888: 1338 case DRM_FORMAT_ARGB8888: 1339 case DRM_FORMAT_XBGR8888: 1340 case DRM_FORMAT_ABGR8888: 1341 cairo_format = CAIRO_FORMAT_ARGB32; 1342 break; 1343 case DRM_FORMAT_RGB565: 1344 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN: 1345 case DRM_FORMAT_BGR565: 1346 cairo_format = CAIRO_FORMAT_RGB16_565; 1347 swap16 = fb_foreign_endian(format); 1348 break; 1349 #if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 12) 1350 case DRM_FORMAT_ARGB2101010: 1351 case DRM_FORMAT_XRGB2101010: 1352 case DRM_FORMAT_ABGR2101010: 1353 case DRM_FORMAT_XBGR2101010: 1354 cairo_format = CAIRO_FORMAT_RGB30; 1355 swap32 = fb_foreign_endian(format); 1356 break; 1357 #endif 1358 default: 1359 return; 1360 } 1361 1362 /* Cairo uses native byte order, so we may have to byteswap before... */ 1363 if (swap16) 1364 byteswap_buffer16(data, width, height, stride); 1365 if (swap32) 1366 byteswap_buffer32(data, width, height, stride); 1367 1368 surface = cairo_image_surface_create_for_data(data, 1369 cairo_format, 1370 width, height, 1371 stride); 1372 cr = cairo_create(surface); 1373 cairo_surface_destroy(surface); 1374 1375 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); 1376 for (unsigned x = 0; x < width; x += 250) 1377 for (unsigned y = 0; y < height; y += 250) { 1378 char buf[64]; 1379 1380 cairo_move_to(cr, x, y - 20); 1381 cairo_line_to(cr, x, y + 20); 1382 cairo_move_to(cr, x - 20, y); 1383 cairo_line_to(cr, x + 20, y); 1384 cairo_new_sub_path(cr); 1385 cairo_arc(cr, x, y, 10, 0, M_PI * 2); 1386 cairo_set_line_width(cr, 4); 1387 cairo_set_source_rgb(cr, 0, 0, 0); 1388 cairo_stroke_preserve(cr); 1389 cairo_set_source_rgb(cr, 1, 1, 1); 1390 cairo_set_line_width(cr, 2); 1391 cairo_stroke(cr); 1392 1393 snprintf(buf, sizeof buf, "%d, %d", x, y); 1394 cairo_move_to(cr, x + 20, y + 20); 1395 cairo_text_path(cr, buf); 1396 cairo_set_source_rgb(cr, 0, 0, 0); 1397 cairo_stroke_preserve(cr); 1398 cairo_set_source_rgb(cr, 1, 1, 1); 1399 cairo_fill(cr); 1400 } 1401 1402 cairo_destroy(cr); 1403 1404 /* ... and after */ 1405 if (swap16) 1406 byteswap_buffer16(data, width, height, stride); 1407 if (swap32) 1408 byteswap_buffer32(data, width, height, stride); 1409 #endif 1410 } 1411 1412 static struct color_yuv make_tiles_yuv_color(unsigned int x, unsigned int y, 1413 unsigned int width) 1414 { 1415 div_t d = div(x+y, width); 1416 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 1417 + 0x000a1120 * (d.rem >> 6); 1418 struct color_yuv color = 1419 MAKE_YUV_601((rgb32 >> 16) & 0xff, (rgb32 >> 8) & 0xff, 1420 rgb32 & 0xff); 1421 return color; 1422 } 1423 1424 static void fill_tiles_yuv_planar(const struct util_format_info *info, 1425 unsigned char *y_mem, unsigned char *u_mem, 1426 unsigned char *v_mem, unsigned int width, 1427 unsigned int height, unsigned int stride) 1428 { 1429 const struct util_yuv_info *yuv = &info->yuv; 1430 unsigned int cs = yuv->chroma_stride; 1431 unsigned int xsub = yuv->xsub; 1432 unsigned int ysub = yuv->ysub; 1433 unsigned int x; 1434 unsigned int y; 1435 1436 for (y = 0; y < height; ++y) { 1437 for (x = 0; x < width; ++x) { 1438 struct color_yuv color = 1439 make_tiles_yuv_color(x, y, width); 1440 1441 y_mem[x] = color.y; 1442 u_mem[x/xsub*cs] = color.u; 1443 v_mem[x/xsub*cs] = color.v; 1444 } 1445 1446 y_mem += stride; 1447 if ((y + 1) % ysub == 0) { 1448 u_mem += stride * cs / xsub; 1449 v_mem += stride * cs / xsub; 1450 } 1451 } 1452 } 1453 1454 static void fill_tiles_yuv_planar_10bpp(const struct util_format_info *info, 1455 unsigned char *y_mem, 1456 unsigned char *uv_mem, 1457 unsigned int width, 1458 unsigned int height, 1459 unsigned int stride) 1460 { 1461 const struct util_yuv_info *yuv = &info->yuv; 1462 unsigned int cs = yuv->chroma_stride; 1463 unsigned int xsub = yuv->xsub; 1464 unsigned int ysub = yuv->ysub; 1465 unsigned int xstep = cs * xsub; 1466 unsigned int x; 1467 unsigned int y; 1468 1469 for (y = 0; y < height; ++y) { 1470 for (x = 0; x < width; x += 4) { 1471 struct color_yuv a = make_tiles_yuv_color(x+0, y, width); 1472 struct color_yuv b = make_tiles_yuv_color(x+1, y, width); 1473 struct color_yuv c = make_tiles_yuv_color(x+2, y, width); 1474 struct color_yuv d = make_tiles_yuv_color(x+3, y, width); 1475 1476 write_pixels_10bpp(&y_mem[(x * 5) / 4], 1477 a.y << 2, b.y << 2, c.y << 2, d.y << 2); 1478 } 1479 y_mem += stride; 1480 } 1481 for (y = 0; y < height; y += ysub) { 1482 for (x = 0; x < width; x += xstep) { 1483 struct color_yuv a = make_tiles_yuv_color(x+0, y, width); 1484 struct color_yuv b = make_tiles_yuv_color(x+xsub, y, width); 1485 1486 write_pixels_10bpp(&uv_mem[(x * 5) / xstep], 1487 a.u << 2, a.v << 2, b.u << 2, b.v << 2); 1488 } 1489 uv_mem += stride * cs / xsub; 1490 } 1491 } 1492 1493 static void fill_tiles_yuv_packed(const struct util_format_info *info, 1494 void *mem, unsigned int width, 1495 unsigned int height, unsigned int stride) 1496 { 1497 const struct util_yuv_info *yuv = &info->yuv; 1498 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; 1499 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; 1500 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; 1501 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; 1502 unsigned int x; 1503 unsigned int y; 1504 1505 for (y = 0; y < height; ++y) { 1506 for (x = 0; x < width; x += 2) { 1507 struct color_yuv color = 1508 make_tiles_yuv_color(x, y, width); 1509 1510 y_mem[2*x] = color.y; 1511 c_mem[2*x+u] = color.u; 1512 y_mem[2*x+2] = color.y; 1513 c_mem[2*x+v] = color.v; 1514 } 1515 1516 y_mem += stride; 1517 c_mem += stride; 1518 } 1519 } 1520 1521 static void fill_tiles_rgb16(const struct util_format_info *info, void *mem, 1522 unsigned int width, unsigned int height, 1523 unsigned int stride, bool fb_be) 1524 { 1525 const struct util_rgb_info *rgb = &info->rgb; 1526 void *mem_base = mem; 1527 unsigned int x, y; 1528 1529 for (y = 0; y < height; ++y) { 1530 for (x = 0; x < width; ++x) { 1531 div_t d = div(x+y, width); 1532 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 1533 + 0x000a1120 * (d.rem >> 6); 1534 uint16_t color = 1535 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, 1536 (rgb32 >> 8) & 0xff, rgb32 & 0xff, 1537 255); 1538 1539 ((uint16_t *)mem)[x] = cpu_to_fb16(color); 1540 } 1541 mem += stride; 1542 } 1543 1544 make_pwetty(mem_base, width, height, stride, info->format); 1545 } 1546 1547 static void fill_tiles_rgb24(const struct util_format_info *info, void *mem, 1548 unsigned int width, unsigned int height, 1549 unsigned int stride) 1550 { 1551 const struct util_rgb_info *rgb = &info->rgb; 1552 unsigned int x, y; 1553 1554 for (y = 0; y < height; ++y) { 1555 for (x = 0; x < width; ++x) { 1556 div_t d = div(x+y, width); 1557 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 1558 + 0x000a1120 * (d.rem >> 6); 1559 struct color_rgb24 color = 1560 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff, 1561 (rgb32 >> 8) & 0xff, rgb32 & 0xff); 1562 1563 ((struct color_rgb24 *)mem)[x] = color; 1564 } 1565 mem += stride; 1566 } 1567 } 1568 1569 static void fill_tiles_rgb32(const struct util_format_info *info, void *mem, 1570 unsigned int width, unsigned int height, 1571 unsigned int stride) 1572 { 1573 const struct util_rgb_info *rgb = &info->rgb; 1574 void *mem_base = mem; 1575 unsigned int x, y; 1576 1577 for (y = 0; y < height; ++y) { 1578 for (x = 0; x < width; ++x) { 1579 div_t d = div(x+y, width); 1580 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 1581 + 0x000a1120 * (d.rem >> 6); 1582 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255; 1583 uint32_t color = 1584 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, 1585 (rgb32 >> 8) & 0xff, rgb32 & 0xff, 1586 alpha); 1587 1588 ((uint32_t *)mem)[x] = cpu_to_le32(color); 1589 } 1590 mem += stride; 1591 } 1592 1593 make_pwetty(mem_base, width, height, stride, info->format); 1594 } 1595 1596 static void fill_tiles_rgb16fp(const struct util_format_info *info, void *mem, 1597 unsigned int width, unsigned int height, 1598 unsigned int stride) 1599 { 1600 const struct util_rgb_info *rgb = &info->rgb; 1601 unsigned int x, y; 1602 1603 /* TODO: Give this actual fp16 precision */ 1604 for (y = 0; y < height; ++y) { 1605 for (x = 0; x < width; ++x) { 1606 div_t d = div(x+y, width); 1607 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 1608 + 0x000a1120 * (d.rem >> 6); 1609 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255; 1610 uint64_t color = 1611 MAKE_RGBA8FP16(rgb, (rgb32 >> 16) & 0xff, 1612 (rgb32 >> 8) & 0xff, rgb32 & 0xff, 1613 alpha); 1614 1615 ((uint64_t *)mem)[x] = color; 1616 } 1617 mem += stride; 1618 } 1619 } 1620 1621 static void fill_tiles(const struct util_format_info *info, void *planes[3], 1622 unsigned int width, unsigned int height, 1623 unsigned int stride) 1624 { 1625 unsigned char *u, *v; 1626 1627 switch (info->format) { 1628 case DRM_FORMAT_UYVY: 1629 case DRM_FORMAT_VYUY: 1630 case DRM_FORMAT_YUYV: 1631 case DRM_FORMAT_YVYU: 1632 return fill_tiles_yuv_packed(info, planes[0], 1633 width, height, stride); 1634 1635 case DRM_FORMAT_NV12: 1636 case DRM_FORMAT_NV21: 1637 case DRM_FORMAT_NV16: 1638 case DRM_FORMAT_NV61: 1639 case DRM_FORMAT_NV24: 1640 case DRM_FORMAT_NV42: 1641 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; 1642 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; 1643 return fill_tiles_yuv_planar(info, planes[0], u, v, 1644 width, height, stride); 1645 1646 case DRM_FORMAT_NV15: 1647 case DRM_FORMAT_NV20: 1648 case DRM_FORMAT_NV30: 1649 return fill_tiles_yuv_planar_10bpp(info, planes[0], planes[1], 1650 width, height, stride); 1651 1652 case DRM_FORMAT_YUV420: 1653 case DRM_FORMAT_YUV422: 1654 case DRM_FORMAT_YUV444: 1655 return fill_tiles_yuv_planar(info, planes[0], planes[1], 1656 planes[2], width, height, stride); 1657 1658 case DRM_FORMAT_YVU420: 1659 case DRM_FORMAT_YVU422: 1660 case DRM_FORMAT_YVU444: 1661 return fill_tiles_yuv_planar(info, planes[0], planes[2], 1662 planes[1], width, height, stride); 1663 1664 case DRM_FORMAT_ARGB4444: 1665 case DRM_FORMAT_XRGB4444: 1666 case DRM_FORMAT_ABGR4444: 1667 case DRM_FORMAT_XBGR4444: 1668 case DRM_FORMAT_RGBA4444: 1669 case DRM_FORMAT_RGBX4444: 1670 case DRM_FORMAT_BGRA4444: 1671 case DRM_FORMAT_BGRX4444: 1672 case DRM_FORMAT_RGB565: 1673 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN: 1674 case DRM_FORMAT_BGR565: 1675 case DRM_FORMAT_ARGB1555: 1676 case DRM_FORMAT_XRGB1555: 1677 case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN: 1678 case DRM_FORMAT_ABGR1555: 1679 case DRM_FORMAT_XBGR1555: 1680 case DRM_FORMAT_RGBA5551: 1681 case DRM_FORMAT_RGBX5551: 1682 case DRM_FORMAT_BGRA5551: 1683 case DRM_FORMAT_BGRX5551: 1684 return fill_tiles_rgb16(info, planes[0], 1685 width, height, stride, 1686 info->format & DRM_FORMAT_BIG_ENDIAN); 1687 1688 case DRM_FORMAT_BGR888: 1689 case DRM_FORMAT_RGB888: 1690 return fill_tiles_rgb24(info, planes[0], 1691 width, height, stride); 1692 case DRM_FORMAT_ARGB8888: 1693 case DRM_FORMAT_XRGB8888: 1694 case DRM_FORMAT_ABGR8888: 1695 case DRM_FORMAT_XBGR8888: 1696 case DRM_FORMAT_RGBA8888: 1697 case DRM_FORMAT_RGBX8888: 1698 case DRM_FORMAT_BGRA8888: 1699 case DRM_FORMAT_BGRX8888: 1700 case DRM_FORMAT_ARGB2101010: 1701 case DRM_FORMAT_XRGB2101010: 1702 case DRM_FORMAT_ABGR2101010: 1703 case DRM_FORMAT_XBGR2101010: 1704 case DRM_FORMAT_RGBA1010102: 1705 case DRM_FORMAT_RGBX1010102: 1706 case DRM_FORMAT_BGRA1010102: 1707 case DRM_FORMAT_BGRX1010102: 1708 return fill_tiles_rgb32(info, planes[0], 1709 width, height, stride); 1710 1711 case DRM_FORMAT_XRGB16161616F: 1712 case DRM_FORMAT_XBGR16161616F: 1713 case DRM_FORMAT_ARGB16161616F: 1714 case DRM_FORMAT_ABGR16161616F: 1715 return fill_tiles_rgb16fp(info, planes[0], 1716 width, height, stride); 1717 } 1718 } 1719 1720 static void fill_plain(const struct util_format_info *info, void *planes[3], 1721 unsigned int height, 1722 unsigned int stride) 1723 { 1724 switch (info->format) { 1725 case DRM_FORMAT_XRGB16161616F: 1726 case DRM_FORMAT_XBGR16161616F: 1727 case DRM_FORMAT_ARGB16161616F: 1728 case DRM_FORMAT_ABGR16161616F: 1729 /* 0x3838 = 0.5273 */ 1730 memset(planes[0], 0x38, stride * height); 1731 break; 1732 default: 1733 memset(planes[0], 0x77, stride * height); 1734 break; 1735 } 1736 } 1737 1738 static void fill_gradient_rgb32(const struct util_rgb_info *rgb, 1739 void *mem, 1740 unsigned int width, unsigned int height, 1741 unsigned int stride) 1742 { 1743 unsigned int i, j; 1744 1745 for (i = 0; i < height / 2; i++) { 1746 uint32_t *row = mem; 1747 1748 for (j = 0; j < width / 2; j++) { 1749 uint32_t value = MAKE_RGBA10(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0); 1750 row[2*j] = row[2*j+1] = cpu_to_le32(value); 1751 } 1752 mem += stride; 1753 } 1754 1755 for (; i < height; i++) { 1756 uint32_t *row = mem; 1757 1758 for (j = 0; j < width / 2; j++) { 1759 uint32_t value = MAKE_RGBA10(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0); 1760 row[2*j] = row[2*j+1] = cpu_to_le32(value); 1761 } 1762 mem += stride; 1763 } 1764 } 1765 1766 static void fill_gradient_rgb16fp(const struct util_rgb_info *rgb, 1767 void *mem, 1768 unsigned int width, unsigned int height, 1769 unsigned int stride) 1770 { 1771 unsigned int i, j; 1772 1773 for (i = 0; i < height / 2; i++) { 1774 uint64_t *row = mem; 1775 1776 for (j = 0; j < width / 2; j++) { 1777 uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0); 1778 row[2*j] = row[2*j+1] = value; 1779 } 1780 mem += stride; 1781 } 1782 1783 for (; i < height; i++) { 1784 uint64_t *row = mem; 1785 1786 for (j = 0; j < width / 2; j++) { 1787 uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0); 1788 row[2*j] = row[2*j+1] = value; 1789 } 1790 mem += stride; 1791 } 1792 } 1793 1794 /* The gradient pattern creates two horizontal gray gradients, split 1795 * into two halves. The top half has 10bpc precision, the bottom half 1796 * has 8bpc precision. When using with a 10bpc fb format, there are 3 1797 * possible outcomes: 1798 * 1799 * - Pixel data is encoded as 8bpc to the display, no dithering. This 1800 * would lead to the top and bottom halves looking identical. 1801 * 1802 * - Pixel data is encoded as 8bpc to the display, with dithering. This 1803 * would lead to there being a visible difference between the two halves, 1804 * but the top half would look a little speck-y due to the dithering. 1805 * 1806 * - Pixel data is encoded at 10bpc+ to the display (which implies 1807 * the display is able to show this level of depth). This should 1808 * lead to the top half being a very clean gradient, and visibly different 1809 * from the bottom half. 1810 * 1811 * Once we support additional fb formats, this approach could be extended 1812 * to distinguish even higher bpc precisions. 1813 * 1814 * Note that due to practical size considerations, for the screens 1815 * where this matters, the pattern actually emits stripes 2-pixels 1816 * wide for each gradient color. Otherwise the difference may be a bit 1817 * hard to notice. 1818 */ 1819 static void fill_gradient(const struct util_format_info *info, void *planes[3], 1820 unsigned int width, unsigned int height, 1821 unsigned int stride) 1822 { 1823 switch (info->format) { 1824 case DRM_FORMAT_ARGB8888: 1825 case DRM_FORMAT_XRGB8888: 1826 case DRM_FORMAT_ABGR8888: 1827 case DRM_FORMAT_XBGR8888: 1828 case DRM_FORMAT_RGBA8888: 1829 case DRM_FORMAT_RGBX8888: 1830 case DRM_FORMAT_BGRA8888: 1831 case DRM_FORMAT_BGRX8888: 1832 case DRM_FORMAT_ARGB2101010: 1833 case DRM_FORMAT_XRGB2101010: 1834 case DRM_FORMAT_ABGR2101010: 1835 case DRM_FORMAT_XBGR2101010: 1836 case DRM_FORMAT_RGBA1010102: 1837 case DRM_FORMAT_RGBX1010102: 1838 case DRM_FORMAT_BGRA1010102: 1839 case DRM_FORMAT_BGRX1010102: 1840 return fill_gradient_rgb32(&info->rgb, planes[0], 1841 width, height, stride); 1842 1843 case DRM_FORMAT_XRGB16161616F: 1844 case DRM_FORMAT_XBGR16161616F: 1845 case DRM_FORMAT_ARGB16161616F: 1846 case DRM_FORMAT_ABGR16161616F: 1847 return fill_gradient_rgb16fp(&info->rgb, planes[0], 1848 width, height, stride); 1849 } 1850 } 1851 1852 /* 1853 * util_fill_pattern - Fill a buffer with a test pattern 1854 * @format: Pixel format 1855 * @pattern: Test pattern 1856 * @planes: Array of buffers 1857 * @width: Width in pixels 1858 * @height: Height in pixels 1859 * @stride: Line stride (pitch) in bytes 1860 * 1861 * Fill the buffers with the test pattern specified by the pattern parameter. 1862 * Supported formats vary depending on the selected pattern. 1863 */ 1864 void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern, 1865 void *planes[3], unsigned int width, 1866 unsigned int height, unsigned int stride) 1867 { 1868 const struct util_format_info *info; 1869 1870 info = util_format_info_find(format); 1871 if (info == NULL) 1872 return; 1873 1874 switch (pattern) { 1875 case UTIL_PATTERN_TILES: 1876 return fill_tiles(info, planes, width, height, stride); 1877 1878 case UTIL_PATTERN_SMPTE: 1879 return fill_smpte(info, planes, width, height, stride); 1880 1881 case UTIL_PATTERN_PLAIN: 1882 return fill_plain(info, planes, height, stride); 1883 1884 case UTIL_PATTERN_GRADIENT: 1885 return fill_gradient(info, planes, width, height, stride); 1886 1887 default: 1888 printf("Error: unsupported test pattern %u.\n", pattern); 1889 break; 1890 } 1891 } 1892 1893 static const char *pattern_names[] = { 1894 [UTIL_PATTERN_TILES] = "tiles", 1895 [UTIL_PATTERN_SMPTE] = "smpte", 1896 [UTIL_PATTERN_PLAIN] = "plain", 1897 [UTIL_PATTERN_GRADIENT] = "gradient", 1898 }; 1899 1900 enum util_fill_pattern util_pattern_enum(const char *name) 1901 { 1902 unsigned int i; 1903 1904 for (i = 0; i < ARRAY_SIZE(pattern_names); i++) 1905 if (!strcmp(pattern_names[i], name)) 1906 return (enum util_fill_pattern)i; 1907 1908 printf("Error: unsupported test pattern %s.\n", name); 1909 return UTIL_PATTERN_SMPTE; 1910 } 1911