2 * Copyright 2008 Tungsten Graphics
3 * Jakob Bornecrantz <jakob@tungstengraphics.com>
4 * Copyright 2008 Intel Corporation
5 * Jesse Barnes <jesse.barnes@intel.com>
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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
31 #include <drm_fourcc.h>
43 unsigned int value:24;
44 } __attribute__((__packed__));
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)
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) }
64 /* This function takes 8-bit color values */
65 static inline uint32_t shiftcolor8(const struct util_color_component *comp,
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;
77 /* This function takes 10-bit color values */
78 static inline uint32_t shiftcolor10(const struct util_color_component *comp,
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;
90 /* This function takes 16-bit color values */
91 static inline uint64_t shiftcolor16(const struct util_color_component *comp,
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;
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)))
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)))
113 #define MAKE_RGB24(rgb, r, g, b) \
114 { .value = MAKE_RGBA(rgb, r, g, b, 0) }
118 * Takes a uint16_t, divides by 65536, converts the infinite-precision
119 * result to fp16 with round-to-zero.
121 * Copied from mesa:src/util/half_float.c
123 static uint16_t uint16_div_64k_to_half(uint16_t v)
125 /* Zero or subnormal. Set the mantissa to (v << 8) and return. */
129 /* Count the leading 0s in the uint16_t */
130 int n = __builtin_clz(v) - 16;
132 /* Shift the mantissa up so bit 16 is the hidden 1 bit,
133 * mask it off, then shift back down to 10 bits
135 int m = ( ((uint32_t)v << (n + 1)) & 0xffff ) >> 6;
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
144 return (e << 10) | m;
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)))
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)))
159 static 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)
164 const struct color_yuv colors_top[] = {
165 MAKE_YUV_601(192, 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 */
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 */
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 */
192 unsigned int cs = yuv->chroma_stride;
193 unsigned int xsub = yuv->xsub;
194 unsigned int ysub = yuv->ysub;
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;
205 for (; y < height * 7 / 9; ++y) {
206 for (x = 0; x < width; ++x)
207 y_mem[x] = colors_middle[x * 7 / width].y;
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;
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;
228 u_mem += stride * cs / xsub;
229 v_mem += stride * cs / xsub;
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;
237 u_mem += stride * cs / xsub;
238 v_mem += stride * cs / xsub;
241 for (; y < height / ysub; ++y) {
242 for (x = 0; x < width * 5 / 7; x += xsub) {
244 colors_bottom[x * 4 / (width * 5 / 7)].u;
246 colors_bottom[x * 4 / (width * 5 / 7)].v;
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;
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;
258 u_mem += stride * cs / xsub;
259 v_mem += stride * cs / xsub;
263 static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem,
264 unsigned int width, unsigned int height,
267 const struct color_yuv colors_top[] = {
268 MAKE_YUV_601(192, 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 */
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 */
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 */
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;
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;
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;
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;
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;
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;
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;
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;
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;
362 static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
363 unsigned int width, unsigned int height,
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 */
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 */
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 */
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];
403 for (; y < height * 7 / 9; ++y) {
404 for (x = 0; x < width; ++x)
405 ((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
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
417 for (; x < width; ++x)
418 ((uint16_t *)mem)[x] = colors_bottom[7];
423 static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem,
424 unsigned int width, unsigned int height,
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 */
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 */
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 */
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];
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];
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
480 for (; x < width; ++x)
481 ((struct color_rgb24 *)mem)[x] = colors_bottom[7];
486 static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem,
487 unsigned int width, unsigned int height,
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 */
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 */
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 */
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];
527 for (; y < height * 7 / 9; ++y) {
528 for (x = 0; x < width; ++x)
529 ((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
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
541 for (; x < width; ++x)
542 ((uint32_t *)mem)[x] = colors_bottom[7];
547 static void fill_smpte_rgb16fp(const struct util_rgb_info *rgb, void *mem,
548 unsigned int width, unsigned int height,
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 */
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 */
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 */
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];
588 for (; y < height * 7 / 9; ++y) {
589 for (x = 0; x < width; ++x)
590 ((uint64_t *)mem)[x] = colors_middle[x * 7 / width];
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
602 for (; x < width; ++x)
603 ((uint64_t *)mem)[x] = colors_bottom[7];
617 SMPTE_COLOR_IN_PHASE,
618 SMPTE_COLOR_SUPER_WHITE,
619 SMPTE_COLOR_QUADRATURE,
624 static unsigned int smpte_top[7] = {
634 static unsigned int smpte_middle[7] = {
644 static unsigned int smpte_bottom[8] = {
645 SMPTE_COLOR_IN_PHASE,
646 SMPTE_COLOR_SUPER_WHITE,
647 SMPTE_COLOR_QUADRATURE,
655 #define EXPAND_COLOR(r, g, b) { (r) * 0x101, (g) * 0x101, (b) * 0x101 }
657 static const struct drm_color_lut bw_color_lut[] = {
658 EXPAND_COLOR( 0, 0, 0), /* black */
659 EXPAND_COLOR(255, 255, 255), /* white */
662 static const struct drm_color_lut smpte_color_lut[] = {
663 [SMPTE_COLOR_GREY] = EXPAND_COLOR(192, 192, 192),
664 [SMPTE_COLOR_YELLOW] = EXPAND_COLOR(192, 192, 0),
665 [SMPTE_COLOR_CYAN] = EXPAND_COLOR( 0, 192, 192),
666 [SMPTE_COLOR_GREEN] = EXPAND_COLOR( 0, 192, 0),
667 [SMPTE_COLOR_MAGENTA] = EXPAND_COLOR(192, 0, 192),
668 [SMPTE_COLOR_RED] = EXPAND_COLOR(192, 0, 0),
669 [SMPTE_COLOR_BLUE] = EXPAND_COLOR( 0, 0, 192),
670 [SMPTE_COLOR_BLACK] = EXPAND_COLOR( 19, 19, 19),
671 [SMPTE_COLOR_IN_PHASE] = EXPAND_COLOR( 0, 33, 76),
672 [SMPTE_COLOR_SUPER_WHITE] = EXPAND_COLOR(255, 255, 255),
673 [SMPTE_COLOR_QUADRATURE] = EXPAND_COLOR( 50, 0, 106),
674 [SMPTE_COLOR_3PC5] = EXPAND_COLOR( 9, 9, 9),
675 [SMPTE_COLOR_11PC5] = EXPAND_COLOR( 29, 29, 29),
681 * Floyd-Steinberg dithering
694 static struct fsd *fsd_alloc(unsigned int width)
696 unsigned int n = 3 * (width + 1);
697 struct fsd *fsd = malloc(sizeof(*fsd) + n * sizeof(fsd->error[0]));
702 memset(fsd->error, 0, n * sizeof(fsd->error[0]));
707 static inline int clamp(int val, int min, int max)
716 static void fsd_dither(struct fsd *fsd, struct drm_color_lut *color)
718 unsigned int i = fsd->i;
720 fsd->red = (int)color->red + (fsd->error[3 * i] + 8) / 16;
721 fsd->green = (int)color->green + (fsd->error[3 * i + 1] + 8) / 16;
722 fsd->blue = (int)color->blue + (fsd->error[3 * i + 2] + 8) / 16;
724 color->red = clamp(fsd->red, 0, 65535);
725 color->green = clamp(fsd->green, 0, 65535);
726 color->blue = clamp(fsd->blue, 0, 65535);
729 static void fsd_update(struct fsd *fsd, const struct drm_color_lut *actual)
731 int error_red = fsd->red - (int)actual->red;
732 int error_green = fsd->green - (int)actual->green;
733 int error_blue = fsd->blue - (int)actual->blue;
734 unsigned int width = fsd->width;
735 unsigned int i = fsd->i, j;
736 unsigned int n = width + 1;
738 /* Distribute errors over neighboring pixels */
739 if (fsd->x == width - 1) {
740 /* Last pixel on this scanline */
741 /* South East: initialize to zero */
742 fsd->error[3 * i] = 0;
743 fsd->error[3 * i + 1] = 0;
744 fsd->error[3 * i + 2] = 0;
746 /* East: accumulate error */
748 fsd->error[3 * j] += 7 * error_red;
749 fsd->error[3 * j + 1] += 7 * error_green;
750 fsd->error[3 * j + 2] += 7 * error_blue;
752 /* South East: initial error */
753 fsd->error[3 * i] = error_red;
754 fsd->error[3 * i + 1] = error_green;
755 fsd->error[3 * i + 2] = error_blue;
757 /* South West: accumulate error */
758 j = (i + width - 1) % n;
759 fsd->error[3 * j] += 3 * error_red;
760 fsd->error[3 * j + 1] += 3 * error_green;
761 fsd->error[3 * j + 2] += 3 * error_blue;
763 /* South: accumulate error */
765 fsd->error[3 * j] += 5 * error_red;
766 fsd->error[3 * j + 1] += 5 * error_green;
767 fsd->error[3 * j + 2] += 5 * error_blue;
769 fsd->x = (fsd->x + 1) % width;
770 fsd->i = (fsd->i + 1) % n;
773 static void write_pixel_1(uint8_t *mem, unsigned int x, unsigned int pixel)
775 unsigned int shift = 7 - (x & 7);
776 unsigned int mask = 1U << shift;
778 mem[x / 8] = (mem[x / 8] & ~mask) | ((pixel << shift) & mask);
781 static void write_color_1(struct fsd *fsd, uint8_t *mem, unsigned int x,
784 struct drm_color_lut color = smpte_color_lut[index];
787 fsd_dither(fsd, &color);
789 /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
790 if (3 * color.red + 6 * color.green + color.blue >= 10 * 32768) {
792 color.red = color.green = color.blue = 65535;
795 color.red = color.green = color.blue = 0;
798 fsd_update(fsd, &color);
800 write_pixel_1(mem, x, pixel);
803 static void fill_smpte_c1(void *mem, unsigned int width, unsigned int height,
806 struct fsd *fsd = fsd_alloc(width);
810 for (y = 0; y < height * 6 / 9; ++y) {
811 for (x = 0; x < width; ++x)
812 write_color_1(fsd, mem, x, smpte_top[x * 7 / width]);
816 for (; y < height * 7 / 9; ++y) {
817 for (x = 0; x < width; ++x)
818 write_color_1(fsd, mem, x, smpte_middle[x * 7 / width]);
822 for (; y < height; ++y) {
823 for (x = 0; x < width * 5 / 7; ++x)
824 write_color_1(fsd, mem, x,
825 smpte_bottom[x * 4 / (width * 5 / 7)]);
826 for (; x < width * 6 / 7; ++x)
827 write_color_1(fsd, mem, x,
828 smpte_bottom[(x - width * 5 / 7) * 3 /
830 for (; x < width; ++x)
831 write_color_1(fsd, mem, x, smpte_bottom[7]);
838 static void write_pixel_4(uint8_t *mem, unsigned int x, unsigned int pixel)
841 mem[x / 2] = (mem[x / 2] & 0xf0) | (pixel & 0x0f);
843 mem[x / 2] = (mem[x / 2] & 0x0f) | (pixel << 4);
846 static void fill_smpte_c4(void *mem, unsigned int width, unsigned int height,
852 for (y = 0; y < height * 6 / 9; ++y) {
853 for (x = 0; x < width; ++x)
854 write_pixel_4(mem, x, smpte_top[x * 7 / width]);
858 for (; y < height * 7 / 9; ++y) {
859 for (x = 0; x < width; ++x)
860 write_pixel_4(mem, x, smpte_middle[x * 7 / width]);
864 for (; y < height; ++y) {
865 for (x = 0; x < width * 5 / 7; ++x)
866 write_pixel_4(mem, x,
867 smpte_bottom[x * 4 / (width * 5 / 7)]);
868 for (; x < width * 6 / 7; ++x)
869 write_pixel_4(mem, x,
870 smpte_bottom[(x - width * 5 / 7) * 3 /
872 for (; x < width; ++x)
873 write_pixel_4(mem, x, smpte_bottom[7]);
878 static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height,
884 for (y = 0; y < height * 6 / 9; ++y) {
885 for (x = 0; x < width; ++x)
886 ((uint8_t *)mem)[x] = smpte_top[x * 7 / width];
890 for (; y < height * 7 / 9; ++y) {
891 for (x = 0; x < width; ++x)
892 ((uint8_t *)mem)[x] = smpte_middle[x * 7 / width];
896 for (; y < height; ++y) {
897 for (x = 0; x < width * 5 / 7; ++x)
898 ((uint8_t *)mem)[x] =
899 smpte_bottom[x * 4 / (width * 5 / 7)];
900 for (; x < width * 6 / 7; ++x)
901 ((uint8_t *)mem)[x] =
902 smpte_bottom[(x - width * 5 / 7) * 3
904 for (; x < width; ++x)
905 ((uint8_t *)mem)[x] = smpte_bottom[7];
910 void util_smpte_fill_lut(unsigned int ncolors, struct drm_color_lut *lut)
912 if (ncolors < ARRAY_SIZE(bw_color_lut)) {
913 printf("Error: lut too small: %u < %zu\n", ncolors,
914 ARRAY_SIZE(bw_color_lut));
917 memset(lut, 0, ncolors * sizeof(struct drm_color_lut));
919 if (ncolors < ARRAY_SIZE(smpte_color_lut))
920 memcpy(lut, bw_color_lut, sizeof(bw_color_lut));
922 memcpy(lut, smpte_color_lut, sizeof(smpte_color_lut));
925 static void fill_smpte(const struct util_format_info *info, void *planes[3],
926 unsigned int width, unsigned int height,
929 unsigned char *u, *v;
931 switch (info->format) {
933 return fill_smpte_c1(planes[0], width, height, stride);
935 return fill_smpte_c4(planes[0], width, height, stride);
937 return fill_smpte_c8(planes[0], width, height, stride);
938 case DRM_FORMAT_UYVY:
939 case DRM_FORMAT_VYUY:
940 case DRM_FORMAT_YUYV:
941 case DRM_FORMAT_YVYU:
942 return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
945 case DRM_FORMAT_NV12:
946 case DRM_FORMAT_NV21:
947 case DRM_FORMAT_NV16:
948 case DRM_FORMAT_NV61:
949 case DRM_FORMAT_NV24:
950 case DRM_FORMAT_NV42:
951 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
952 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
953 return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
954 width, height, stride);
956 case DRM_FORMAT_YUV420:
957 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
958 planes[2], width, height, stride);
960 case DRM_FORMAT_YVU420:
961 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
962 planes[1], width, height, stride);
964 case DRM_FORMAT_ARGB4444:
965 case DRM_FORMAT_XRGB4444:
966 case DRM_FORMAT_ABGR4444:
967 case DRM_FORMAT_XBGR4444:
968 case DRM_FORMAT_RGBA4444:
969 case DRM_FORMAT_RGBX4444:
970 case DRM_FORMAT_BGRA4444:
971 case DRM_FORMAT_BGRX4444:
972 case DRM_FORMAT_RGB565:
973 case DRM_FORMAT_BGR565:
974 case DRM_FORMAT_ARGB1555:
975 case DRM_FORMAT_XRGB1555:
976 case DRM_FORMAT_ABGR1555:
977 case DRM_FORMAT_XBGR1555:
978 case DRM_FORMAT_RGBA5551:
979 case DRM_FORMAT_RGBX5551:
980 case DRM_FORMAT_BGRA5551:
981 case DRM_FORMAT_BGRX5551:
982 return fill_smpte_rgb16(&info->rgb, planes[0],
983 width, height, stride);
985 case DRM_FORMAT_BGR888:
986 case DRM_FORMAT_RGB888:
987 return fill_smpte_rgb24(&info->rgb, planes[0],
988 width, height, stride);
989 case DRM_FORMAT_ARGB8888:
990 case DRM_FORMAT_XRGB8888:
991 case DRM_FORMAT_ABGR8888:
992 case DRM_FORMAT_XBGR8888:
993 case DRM_FORMAT_RGBA8888:
994 case DRM_FORMAT_RGBX8888:
995 case DRM_FORMAT_BGRA8888:
996 case DRM_FORMAT_BGRX8888:
997 case DRM_FORMAT_ARGB2101010:
998 case DRM_FORMAT_XRGB2101010:
999 case DRM_FORMAT_ABGR2101010:
1000 case DRM_FORMAT_XBGR2101010:
1001 case DRM_FORMAT_RGBA1010102:
1002 case DRM_FORMAT_RGBX1010102:
1003 case DRM_FORMAT_BGRA1010102:
1004 case DRM_FORMAT_BGRX1010102:
1005 return fill_smpte_rgb32(&info->rgb, planes[0],
1006 width, height, stride);
1008 case DRM_FORMAT_XRGB16161616F:
1009 case DRM_FORMAT_XBGR16161616F:
1010 case DRM_FORMAT_ARGB16161616F:
1011 case DRM_FORMAT_ABGR16161616F:
1012 return fill_smpte_rgb16fp(&info->rgb, planes[0],
1013 width, height, stride);
1017 static void make_pwetty(void *data, unsigned int width, unsigned int height,
1018 unsigned int stride, uint32_t format)
1021 cairo_surface_t *surface;
1023 cairo_format_t cairo_format;
1025 /* we can ignore the order of R,G,B channels */
1027 case DRM_FORMAT_XRGB8888:
1028 case DRM_FORMAT_ARGB8888:
1029 case DRM_FORMAT_XBGR8888:
1030 case DRM_FORMAT_ABGR8888:
1031 cairo_format = CAIRO_FORMAT_ARGB32;
1033 case DRM_FORMAT_RGB565:
1034 case DRM_FORMAT_BGR565:
1035 cairo_format = CAIRO_FORMAT_RGB16_565;
1037 #if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 12)
1038 case DRM_FORMAT_ARGB2101010:
1039 case DRM_FORMAT_XRGB2101010:
1040 case DRM_FORMAT_ABGR2101010:
1041 case DRM_FORMAT_XBGR2101010:
1042 cairo_format = CAIRO_FORMAT_RGB30;
1049 surface = cairo_image_surface_create_for_data(data,
1053 cr = cairo_create(surface);
1054 cairo_surface_destroy(surface);
1056 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
1057 for (unsigned x = 0; x < width; x += 250)
1058 for (unsigned y = 0; y < height; y += 250) {
1061 cairo_move_to(cr, x, y - 20);
1062 cairo_line_to(cr, x, y + 20);
1063 cairo_move_to(cr, x - 20, y);
1064 cairo_line_to(cr, x + 20, y);
1065 cairo_new_sub_path(cr);
1066 cairo_arc(cr, x, y, 10, 0, M_PI * 2);
1067 cairo_set_line_width(cr, 4);
1068 cairo_set_source_rgb(cr, 0, 0, 0);
1069 cairo_stroke_preserve(cr);
1070 cairo_set_source_rgb(cr, 1, 1, 1);
1071 cairo_set_line_width(cr, 2);
1074 snprintf(buf, sizeof buf, "%d, %d", x, y);
1075 cairo_move_to(cr, x + 20, y + 20);
1076 cairo_text_path(cr, buf);
1077 cairo_set_source_rgb(cr, 0, 0, 0);
1078 cairo_stroke_preserve(cr);
1079 cairo_set_source_rgb(cr, 1, 1, 1);
1087 static void fill_tiles_yuv_planar(const struct util_format_info *info,
1088 unsigned char *y_mem, unsigned char *u_mem,
1089 unsigned char *v_mem, unsigned int width,
1090 unsigned int height, unsigned int stride)
1092 const struct util_yuv_info *yuv = &info->yuv;
1093 unsigned int cs = yuv->chroma_stride;
1094 unsigned int xsub = yuv->xsub;
1095 unsigned int ysub = yuv->ysub;
1099 for (y = 0; y < height; ++y) {
1100 for (x = 0; x < width; ++x) {
1101 div_t d = div(x+y, width);
1102 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1103 + 0x000a1120 * (d.rem >> 6);
1104 struct color_yuv color =
1105 MAKE_YUV_601((rgb32 >> 16) & 0xff,
1106 (rgb32 >> 8) & 0xff, rgb32 & 0xff);
1109 u_mem[x/xsub*cs] = color.u;
1110 v_mem[x/xsub*cs] = color.v;
1114 if ((y + 1) % ysub == 0) {
1115 u_mem += stride * cs / xsub;
1116 v_mem += stride * cs / xsub;
1121 static void fill_tiles_yuv_packed(const struct util_format_info *info,
1122 void *mem, unsigned int width,
1123 unsigned int height, unsigned int stride)
1125 const struct util_yuv_info *yuv = &info->yuv;
1126 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
1127 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
1128 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
1129 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
1133 for (y = 0; y < height; ++y) {
1134 for (x = 0; x < width; x += 2) {
1135 div_t d = div(x+y, width);
1136 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1137 + 0x000a1120 * (d.rem >> 6);
1138 struct color_yuv color =
1139 MAKE_YUV_601((rgb32 >> 16) & 0xff,
1140 (rgb32 >> 8) & 0xff, rgb32 & 0xff);
1142 y_mem[2*x] = color.y;
1143 c_mem[2*x+u] = color.u;
1144 y_mem[2*x+2] = color.y;
1145 c_mem[2*x+v] = color.v;
1153 static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
1154 unsigned int width, unsigned int height,
1155 unsigned int stride)
1157 const struct util_rgb_info *rgb = &info->rgb;
1158 void *mem_base = mem;
1161 for (y = 0; y < height; ++y) {
1162 for (x = 0; x < width; ++x) {
1163 div_t d = div(x+y, width);
1164 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1165 + 0x000a1120 * (d.rem >> 6);
1167 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
1168 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1171 ((uint16_t *)mem)[x] = color;
1176 make_pwetty(mem_base, width, height, stride, info->format);
1179 static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
1180 unsigned int width, unsigned int height,
1181 unsigned int stride)
1183 const struct util_rgb_info *rgb = &info->rgb;
1186 for (y = 0; y < height; ++y) {
1187 for (x = 0; x < width; ++x) {
1188 div_t d = div(x+y, width);
1189 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1190 + 0x000a1120 * (d.rem >> 6);
1191 struct color_rgb24 color =
1192 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
1193 (rgb32 >> 8) & 0xff, rgb32 & 0xff);
1195 ((struct color_rgb24 *)mem)[x] = color;
1201 static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
1202 unsigned int width, unsigned int height,
1203 unsigned int stride)
1205 const struct util_rgb_info *rgb = &info->rgb;
1206 void *mem_base = mem;
1209 for (y = 0; y < height; ++y) {
1210 for (x = 0; x < width; ++x) {
1211 div_t d = div(x+y, width);
1212 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1213 + 0x000a1120 * (d.rem >> 6);
1214 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
1216 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
1217 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1220 ((uint32_t *)mem)[x] = color;
1225 make_pwetty(mem_base, width, height, stride, info->format);
1228 static void fill_tiles_rgb16fp(const struct util_format_info *info, void *mem,
1229 unsigned int width, unsigned int height,
1230 unsigned int stride)
1232 const struct util_rgb_info *rgb = &info->rgb;
1235 /* TODO: Give this actual fp16 precision */
1236 for (y = 0; y < height; ++y) {
1237 for (x = 0; x < width; ++x) {
1238 div_t d = div(x+y, width);
1239 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1240 + 0x000a1120 * (d.rem >> 6);
1241 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
1243 MAKE_RGBA8FP16(rgb, (rgb32 >> 16) & 0xff,
1244 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1247 ((uint64_t *)mem)[x] = color;
1253 static void fill_tiles(const struct util_format_info *info, void *planes[3],
1254 unsigned int width, unsigned int height,
1255 unsigned int stride)
1257 unsigned char *u, *v;
1259 switch (info->format) {
1260 case DRM_FORMAT_UYVY:
1261 case DRM_FORMAT_VYUY:
1262 case DRM_FORMAT_YUYV:
1263 case DRM_FORMAT_YVYU:
1264 return fill_tiles_yuv_packed(info, planes[0],
1265 width, height, stride);
1267 case DRM_FORMAT_NV12:
1268 case DRM_FORMAT_NV21:
1269 case DRM_FORMAT_NV16:
1270 case DRM_FORMAT_NV61:
1271 case DRM_FORMAT_NV24:
1272 case DRM_FORMAT_NV42:
1273 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
1274 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
1275 return fill_tiles_yuv_planar(info, planes[0], u, v,
1276 width, height, stride);
1278 case DRM_FORMAT_YUV420:
1279 return fill_tiles_yuv_planar(info, planes[0], planes[1],
1280 planes[2], width, height, stride);
1282 case DRM_FORMAT_YVU420:
1283 return fill_tiles_yuv_planar(info, planes[0], planes[2],
1284 planes[1], width, height, stride);
1286 case DRM_FORMAT_ARGB4444:
1287 case DRM_FORMAT_XRGB4444:
1288 case DRM_FORMAT_ABGR4444:
1289 case DRM_FORMAT_XBGR4444:
1290 case DRM_FORMAT_RGBA4444:
1291 case DRM_FORMAT_RGBX4444:
1292 case DRM_FORMAT_BGRA4444:
1293 case DRM_FORMAT_BGRX4444:
1294 case DRM_FORMAT_RGB565:
1295 case DRM_FORMAT_BGR565:
1296 case DRM_FORMAT_ARGB1555:
1297 case DRM_FORMAT_XRGB1555:
1298 case DRM_FORMAT_ABGR1555:
1299 case DRM_FORMAT_XBGR1555:
1300 case DRM_FORMAT_RGBA5551:
1301 case DRM_FORMAT_RGBX5551:
1302 case DRM_FORMAT_BGRA5551:
1303 case DRM_FORMAT_BGRX5551:
1304 return fill_tiles_rgb16(info, planes[0],
1305 width, height, stride);
1307 case DRM_FORMAT_BGR888:
1308 case DRM_FORMAT_RGB888:
1309 return fill_tiles_rgb24(info, planes[0],
1310 width, height, stride);
1311 case DRM_FORMAT_ARGB8888:
1312 case DRM_FORMAT_XRGB8888:
1313 case DRM_FORMAT_ABGR8888:
1314 case DRM_FORMAT_XBGR8888:
1315 case DRM_FORMAT_RGBA8888:
1316 case DRM_FORMAT_RGBX8888:
1317 case DRM_FORMAT_BGRA8888:
1318 case DRM_FORMAT_BGRX8888:
1319 case DRM_FORMAT_ARGB2101010:
1320 case DRM_FORMAT_XRGB2101010:
1321 case DRM_FORMAT_ABGR2101010:
1322 case DRM_FORMAT_XBGR2101010:
1323 case DRM_FORMAT_RGBA1010102:
1324 case DRM_FORMAT_RGBX1010102:
1325 case DRM_FORMAT_BGRA1010102:
1326 case DRM_FORMAT_BGRX1010102:
1327 return fill_tiles_rgb32(info, planes[0],
1328 width, height, stride);
1330 case DRM_FORMAT_XRGB16161616F:
1331 case DRM_FORMAT_XBGR16161616F:
1332 case DRM_FORMAT_ARGB16161616F:
1333 case DRM_FORMAT_ABGR16161616F:
1334 return fill_tiles_rgb16fp(info, planes[0],
1335 width, height, stride);
1339 static void fill_plain(const struct util_format_info *info, void *planes[3],
1340 unsigned int height,
1341 unsigned int stride)
1343 switch (info->format) {
1344 case DRM_FORMAT_XRGB16161616F:
1345 case DRM_FORMAT_XBGR16161616F:
1346 case DRM_FORMAT_ARGB16161616F:
1347 case DRM_FORMAT_ABGR16161616F:
1348 /* 0x3838 = 0.5273 */
1349 memset(planes[0], 0x38, stride * height);
1352 memset(planes[0], 0x77, stride * height);
1357 static void fill_gradient_rgb32(const struct util_rgb_info *rgb,
1359 unsigned int width, unsigned int height,
1360 unsigned int stride)
1364 for (i = 0; i < height / 2; i++) {
1365 uint32_t *row = mem;
1367 for (j = 0; j < width / 2; j++) {
1368 uint32_t value = MAKE_RGBA10(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1369 row[2*j] = row[2*j+1] = value;
1374 for (; i < height; i++) {
1375 uint32_t *row = mem;
1377 for (j = 0; j < width / 2; j++) {
1378 uint32_t value = MAKE_RGBA10(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1379 row[2*j] = row[2*j+1] = value;
1385 static void fill_gradient_rgb16fp(const struct util_rgb_info *rgb,
1387 unsigned int width, unsigned int height,
1388 unsigned int stride)
1392 for (i = 0; i < height / 2; i++) {
1393 uint64_t *row = mem;
1395 for (j = 0; j < width / 2; j++) {
1396 uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1397 row[2*j] = row[2*j+1] = value;
1402 for (; i < height; i++) {
1403 uint64_t *row = mem;
1405 for (j = 0; j < width / 2; j++) {
1406 uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1407 row[2*j] = row[2*j+1] = value;
1413 /* The gradient pattern creates two horizontal gray gradients, split
1414 * into two halves. The top half has 10bpc precision, the bottom half
1415 * has 8bpc precision. When using with a 10bpc fb format, there are 3
1416 * possible outcomes:
1418 * - Pixel data is encoded as 8bpc to the display, no dithering. This
1419 * would lead to the top and bottom halves looking identical.
1421 * - Pixel data is encoded as 8bpc to the display, with dithering. This
1422 * would lead to there being a visible difference between the two halves,
1423 * but the top half would look a little speck-y due to the dithering.
1425 * - Pixel data is encoded at 10bpc+ to the display (which implies
1426 * the display is able to show this level of depth). This should
1427 * lead to the top half being a very clean gradient, and visibly different
1428 * from the bottom half.
1430 * Once we support additional fb formats, this approach could be extended
1431 * to distinguish even higher bpc precisions.
1433 * Note that due to practical size considerations, for the screens
1434 * where this matters, the pattern actually emits stripes 2-pixels
1435 * wide for each gradient color. Otherwise the difference may be a bit
1438 static void fill_gradient(const struct util_format_info *info, void *planes[3],
1439 unsigned int width, unsigned int height,
1440 unsigned int stride)
1442 switch (info->format) {
1443 case DRM_FORMAT_ARGB8888:
1444 case DRM_FORMAT_XRGB8888:
1445 case DRM_FORMAT_ABGR8888:
1446 case DRM_FORMAT_XBGR8888:
1447 case DRM_FORMAT_RGBA8888:
1448 case DRM_FORMAT_RGBX8888:
1449 case DRM_FORMAT_BGRA8888:
1450 case DRM_FORMAT_BGRX8888:
1451 case DRM_FORMAT_ARGB2101010:
1452 case DRM_FORMAT_XRGB2101010:
1453 case DRM_FORMAT_ABGR2101010:
1454 case DRM_FORMAT_XBGR2101010:
1455 case DRM_FORMAT_RGBA1010102:
1456 case DRM_FORMAT_RGBX1010102:
1457 case DRM_FORMAT_BGRA1010102:
1458 case DRM_FORMAT_BGRX1010102:
1459 return fill_gradient_rgb32(&info->rgb, planes[0],
1460 width, height, stride);
1462 case DRM_FORMAT_XRGB16161616F:
1463 case DRM_FORMAT_XBGR16161616F:
1464 case DRM_FORMAT_ARGB16161616F:
1465 case DRM_FORMAT_ABGR16161616F:
1466 return fill_gradient_rgb16fp(&info->rgb, planes[0],
1467 width, height, stride);
1472 * util_fill_pattern - Fill a buffer with a test pattern
1473 * @format: Pixel format
1474 * @pattern: Test pattern
1475 * @planes: Array of buffers
1476 * @width: Width in pixels
1477 * @height: Height in pixels
1478 * @stride: Line stride (pitch) in bytes
1480 * Fill the buffers with the test pattern specified by the pattern parameter.
1481 * Supported formats vary depending on the selected pattern.
1483 void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
1484 void *planes[3], unsigned int width,
1485 unsigned int height, unsigned int stride)
1487 const struct util_format_info *info;
1489 info = util_format_info_find(format);
1494 case UTIL_PATTERN_TILES:
1495 return fill_tiles(info, planes, width, height, stride);
1497 case UTIL_PATTERN_SMPTE:
1498 return fill_smpte(info, planes, width, height, stride);
1500 case UTIL_PATTERN_PLAIN:
1501 return fill_plain(info, planes, height, stride);
1503 case UTIL_PATTERN_GRADIENT:
1504 return fill_gradient(info, planes, width, height, stride);
1507 printf("Error: unsupported test pattern %u.\n", pattern);
1512 static const char *pattern_names[] = {
1513 [UTIL_PATTERN_TILES] = "tiles",
1514 [UTIL_PATTERN_SMPTE] = "smpte",
1515 [UTIL_PATTERN_PLAIN] = "plain",
1516 [UTIL_PATTERN_GRADIENT] = "gradient",
1519 enum util_fill_pattern util_pattern_enum(const char *name)
1523 for (i = 0; i < ARRAY_SIZE(pattern_names); i++)
1524 if (!strcmp(pattern_names[i], name))
1525 return (enum util_fill_pattern)i;
1527 printf("Error: unsupported test pattern %s.\n", name);
1528 return UTIL_PATTERN_SMPTE;