util: add SMPTE pattern support for C1 format
[platform/upstream/libdrm.git] / tests / util / pattern.c
1 /*
2  * Copyright 2008 Tungsten Graphics
3  *   Jakob Bornecrantz <jakob@tungstengraphics.com>
4  * Copyright 2008 Intel Corporation
5  *   Jesse Barnes <jesse.barnes@intel.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23  * IN THE SOFTWARE.
24  */
25
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <drm_fourcc.h>
32
33 #if HAVE_CAIRO
34 #include <cairo.h>
35 #include <math.h>
36 #endif
37
38 #include "common.h"
39 #include "format.h"
40 #include "pattern.h"
41
42 struct color_rgb24 {
43         unsigned int value:24;
44 } __attribute__((__packed__));
45
46 struct color_yuv {
47         unsigned char y;
48         unsigned char u;
49         unsigned char v;
50 };
51
52 #define MAKE_YUV_601_Y(r, g, b) \
53         ((( 66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
54 #define MAKE_YUV_601_U(r, g, b) \
55         (((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
56 #define MAKE_YUV_601_V(r, g, b) \
57         (((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
58
59 #define MAKE_YUV_601(r, g, b) \
60         { .y = MAKE_YUV_601_Y(r, g, b), \
61           .u = MAKE_YUV_601_U(r, g, b), \
62           .v = MAKE_YUV_601_V(r, g, b) }
63
64 /* This function takes 8-bit color values */
65 static inline uint32_t shiftcolor8(const struct util_color_component *comp,
66                                   uint32_t value)
67 {
68         value &= 0xff;
69         /* Fill the low bits with the high bits. */
70         value = (value << 8) | value;
71         /* Shift down to remove unwanted low bits */
72         value = value >> (16 - comp->length);
73         /* Shift back up to where the value should be */
74         return value << comp->offset;
75 }
76
77 /* This function takes 10-bit color values */
78 static inline uint32_t shiftcolor10(const struct util_color_component *comp,
79                                     uint32_t value)
80 {
81         value &= 0x3ff;
82         /* Fill the low bits with the high bits. */
83         value = (value << 6) | (value >> 4);
84         /* Shift down to remove unwanted low bits */
85         value = value >> (16 - comp->length);
86         /* Shift back up to where the value should be */
87         return value << comp->offset;
88 }
89
90 /* This function takes 16-bit color values */
91 static inline uint64_t shiftcolor16(const struct util_color_component *comp,
92                                     uint64_t value)
93 {
94         value &= 0xffff;
95         /* Shift down to remove unwanted low bits */
96         value = value >> (16 - comp->length);
97         /* Shift back up to where the value should be */
98         return value << comp->offset;
99 }
100
101 #define MAKE_RGBA10(rgb, r, g, b, a) \
102         (shiftcolor10(&(rgb)->red, (r)) | \
103          shiftcolor10(&(rgb)->green, (g)) | \
104          shiftcolor10(&(rgb)->blue, (b)) | \
105          shiftcolor10(&(rgb)->alpha, (a)))
106
107 #define MAKE_RGBA(rgb, r, g, b, a) \
108         (shiftcolor8(&(rgb)->red, (r)) | \
109          shiftcolor8(&(rgb)->green, (g)) | \
110          shiftcolor8(&(rgb)->blue, (b)) | \
111          shiftcolor8(&(rgb)->alpha, (a)))
112
113 #define MAKE_RGB24(rgb, r, g, b) \
114         { .value = MAKE_RGBA(rgb, r, g, b, 0) }
115
116
117 /**
118   * Takes a uint16_t, divides by 65536, converts the infinite-precision
119   * result to fp16 with round-to-zero.
120   *
121   * Copied from mesa:src/util/half_float.c
122   */
123 static uint16_t uint16_div_64k_to_half(uint16_t v)
124 {
125         /* Zero or subnormal. Set the mantissa to (v << 8) and return. */
126         if (v < 4)
127                 return v << 8;
128
129         /* Count the leading 0s in the uint16_t */
130         int n = __builtin_clz(v) - 16;
131
132         /* Shift the mantissa up so bit 16 is the hidden 1 bit,
133          * mask it off, then shift back down to 10 bits
134          */
135         int m = ( ((uint32_t)v << (n + 1)) & 0xffff ) >> 6;
136
137         /*  (0{n} 1 X{15-n}) * 2^-16
138          * = 1.X * 2^(15-n-16)
139          * = 1.X * 2^(14-n - 15)
140          * which is the FP16 form with e = 14 - n
141          */
142         int e = 14 - n;
143
144         return (e << 10) | m;
145 }
146
147 #define MAKE_RGBA8FP16(rgb, r, g, b, a) \
148         (shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 8)) | \
149          shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 8)) | \
150          shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 8)) | \
151          shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 8)))
152
153 #define MAKE_RGBA10FP16(rgb, r, g, b, a) \
154         (shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 6)) | \
155          shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 6)) | \
156          shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 6)) | \
157          shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 6)))
158
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)
163 {
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 */
172         };
173         const struct color_yuv colors_middle[] = {
174                 MAKE_YUV_601(0, 0, 192),        /* blue */
175                 MAKE_YUV_601(19, 19, 19),       /* black */
176                 MAKE_YUV_601(192, 0, 192),      /* magenta */
177                 MAKE_YUV_601(19, 19, 19),       /* black */
178                 MAKE_YUV_601(0, 192, 192),      /* cyan */
179                 MAKE_YUV_601(19, 19, 19),       /* black */
180                 MAKE_YUV_601(192, 192, 192),    /* grey */
181         };
182         const struct color_yuv colors_bottom[] = {
183                 MAKE_YUV_601(0, 33, 76),        /* in-phase */
184                 MAKE_YUV_601(255, 255, 255),    /* super white */
185                 MAKE_YUV_601(50, 0, 106),       /* quadrature */
186                 MAKE_YUV_601(19, 19, 19),       /* black */
187                 MAKE_YUV_601(9, 9, 9),          /* 3.5% */
188                 MAKE_YUV_601(19, 19, 19),       /* 7.5% */
189                 MAKE_YUV_601(29, 29, 29),       /* 11.5% */
190                 MAKE_YUV_601(19, 19, 19),       /* black */
191         };
192         unsigned int cs = yuv->chroma_stride;
193         unsigned int xsub = yuv->xsub;
194         unsigned int ysub = yuv->ysub;
195         unsigned int x;
196         unsigned int y;
197
198         /* Luma */
199         for (y = 0; y < height * 6 / 9; ++y) {
200                 for (x = 0; x < width; ++x)
201                         y_mem[x] = colors_top[x * 7 / width].y;
202                 y_mem += stride;
203         }
204
205         for (; y < height * 7 / 9; ++y) {
206                 for (x = 0; x < width; ++x)
207                         y_mem[x] = colors_middle[x * 7 / width].y;
208                 y_mem += stride;
209         }
210
211         for (; y < height; ++y) {
212                 for (x = 0; x < width * 5 / 7; ++x)
213                         y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
214                 for (; x < width * 6 / 7; ++x)
215                         y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
216                                                  / (width / 7) + 4].y;
217                 for (; x < width; ++x)
218                         y_mem[x] = colors_bottom[7].y;
219                 y_mem += stride;
220         }
221
222         /* Chroma */
223         for (y = 0; y < height / ysub * 6 / 9; ++y) {
224                 for (x = 0; x < width; x += xsub) {
225                         u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
226                         v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
227                 }
228                 u_mem += stride * cs / xsub;
229                 v_mem += stride * cs / xsub;
230         }
231
232         for (; y < height / ysub * 7 / 9; ++y) {
233                 for (x = 0; x < width; x += xsub) {
234                         u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
235                         v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
236                 }
237                 u_mem += stride * cs / xsub;
238                 v_mem += stride * cs / xsub;
239         }
240
241         for (; y < height / ysub; ++y) {
242                 for (x = 0; x < width * 5 / 7; x += xsub) {
243                         u_mem[x*cs/xsub] =
244                                 colors_bottom[x * 4 / (width * 5 / 7)].u;
245                         v_mem[x*cs/xsub] =
246                                 colors_bottom[x * 4 / (width * 5 / 7)].v;
247                 }
248                 for (; x < width * 6 / 7; x += xsub) {
249                         u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
250                                                          3 / (width / 7) + 4].u;
251                         v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
252                                                          3 / (width / 7) + 4].v;
253                 }
254                 for (; x < width; x += xsub) {
255                         u_mem[x*cs/xsub] = colors_bottom[7].u;
256                         v_mem[x*cs/xsub] = colors_bottom[7].v;
257                 }
258                 u_mem += stride * cs / xsub;
259                 v_mem += stride * cs / xsub;
260         }
261 }
262
263 static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem,
264                                   unsigned int width, unsigned int height,
265                                   unsigned int stride)
266 {
267         const struct color_yuv colors_top[] = {
268                 MAKE_YUV_601(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 */
275         };
276         const struct color_yuv colors_middle[] = {
277                 MAKE_YUV_601(0, 0, 192),        /* blue */
278                 MAKE_YUV_601(19, 19, 19),       /* black */
279                 MAKE_YUV_601(192, 0, 192),      /* magenta */
280                 MAKE_YUV_601(19, 19, 19),       /* black */
281                 MAKE_YUV_601(0, 192, 192),      /* cyan */
282                 MAKE_YUV_601(19, 19, 19),       /* black */
283                 MAKE_YUV_601(192, 192, 192),    /* grey */
284         };
285         const struct color_yuv colors_bottom[] = {
286                 MAKE_YUV_601(0, 33, 76),        /* in-phase */
287                 MAKE_YUV_601(255, 255, 255),    /* super white */
288                 MAKE_YUV_601(50, 0, 106),       /* quadrature */
289                 MAKE_YUV_601(19, 19, 19),       /* black */
290                 MAKE_YUV_601(9, 9, 9),          /* 3.5% */
291                 MAKE_YUV_601(19, 19, 19),       /* 7.5% */
292                 MAKE_YUV_601(29, 29, 29),       /* 11.5% */
293                 MAKE_YUV_601(19, 19, 19),       /* black */
294         };
295         unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
296         unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
297         unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
298         unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
299         unsigned int x;
300         unsigned int y;
301
302         /* Luma */
303         for (y = 0; y < height * 6 / 9; ++y) {
304                 for (x = 0; x < width; ++x)
305                         y_mem[2*x] = colors_top[x * 7 / width].y;
306                 y_mem += stride;
307         }
308
309         for (; y < height * 7 / 9; ++y) {
310                 for (x = 0; x < width; ++x)
311                         y_mem[2*x] = colors_middle[x * 7 / width].y;
312                 y_mem += stride;
313         }
314
315         for (; y < height; ++y) {
316                 for (x = 0; x < width * 5 / 7; ++x)
317                         y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
318                 for (; x < width * 6 / 7; ++x)
319                         y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
320                                                    / (width / 7) + 4].y;
321                 for (; x < width; ++x)
322                         y_mem[2*x] = colors_bottom[7].y;
323                 y_mem += stride;
324         }
325
326         /* Chroma */
327         for (y = 0; y < height * 6 / 9; ++y) {
328                 for (x = 0; x < width; x += 2) {
329                         c_mem[2*x+u] = colors_top[x * 7 / width].u;
330                         c_mem[2*x+v] = colors_top[x * 7 / width].v;
331                 }
332                 c_mem += stride;
333         }
334
335         for (; y < height * 7 / 9; ++y) {
336                 for (x = 0; x < width; x += 2) {
337                         c_mem[2*x+u] = colors_middle[x * 7 / width].u;
338                         c_mem[2*x+v] = colors_middle[x * 7 / width].v;
339                 }
340                 c_mem += stride;
341         }
342
343         for (; y < height; ++y) {
344                 for (x = 0; x < width * 5 / 7; x += 2) {
345                         c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
346                         c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
347                 }
348                 for (; x < width * 6 / 7; x += 2) {
349                         c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
350                                                      3 / (width / 7) + 4].u;
351                         c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
352                                                      3 / (width / 7) + 4].v;
353                 }
354                 for (; x < width; x += 2) {
355                         c_mem[2*x+u] = colors_bottom[7].u;
356                         c_mem[2*x+v] = colors_bottom[7].v;
357                 }
358                 c_mem += stride;
359         }
360 }
361
362 static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
363                              unsigned int width, unsigned int height,
364                              unsigned int stride)
365 {
366         const uint16_t colors_top[] = {
367                 MAKE_RGBA(rgb, 192, 192, 192, 255),     /* grey */
368                 MAKE_RGBA(rgb, 192, 192, 0, 255),       /* yellow */
369                 MAKE_RGBA(rgb, 0, 192, 192, 255),       /* cyan */
370                 MAKE_RGBA(rgb, 0, 192, 0, 255),         /* green */
371                 MAKE_RGBA(rgb, 192, 0, 192, 255),       /* magenta */
372                 MAKE_RGBA(rgb, 192, 0, 0, 255),         /* red */
373                 MAKE_RGBA(rgb, 0, 0, 192, 255),         /* blue */
374         };
375         const uint16_t colors_middle[] = {
376                 MAKE_RGBA(rgb, 0, 0, 192, 127),         /* blue */
377                 MAKE_RGBA(rgb, 19, 19, 19, 127),        /* black */
378                 MAKE_RGBA(rgb, 192, 0, 192, 127),       /* magenta */
379                 MAKE_RGBA(rgb, 19, 19, 19, 127),        /* black */
380                 MAKE_RGBA(rgb, 0, 192, 192, 127),       /* cyan */
381                 MAKE_RGBA(rgb, 19, 19, 19, 127),        /* black */
382                 MAKE_RGBA(rgb, 192, 192, 192, 127),     /* grey */
383         };
384         const uint16_t colors_bottom[] = {
385                 MAKE_RGBA(rgb, 0, 33, 76, 255),         /* in-phase */
386                 MAKE_RGBA(rgb, 255, 255, 255, 255),     /* super white */
387                 MAKE_RGBA(rgb, 50, 0, 106, 255),        /* quadrature */
388                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
389                 MAKE_RGBA(rgb, 9, 9, 9, 255),           /* 3.5% */
390                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* 7.5% */
391                 MAKE_RGBA(rgb, 29, 29, 29, 255),        /* 11.5% */
392                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
393         };
394         unsigned int x;
395         unsigned int y;
396
397         for (y = 0; y < height * 6 / 9; ++y) {
398                 for (x = 0; x < width; ++x)
399                         ((uint16_t *)mem)[x] = colors_top[x * 7 / width];
400                 mem += stride;
401         }
402
403         for (; y < height * 7 / 9; ++y) {
404                 for (x = 0; x < width; ++x)
405                         ((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
406                 mem += stride;
407         }
408
409         for (; y < height; ++y) {
410                 for (x = 0; x < width * 5 / 7; ++x)
411                         ((uint16_t *)mem)[x] =
412                                 colors_bottom[x * 4 / (width * 5 / 7)];
413                 for (; x < width * 6 / 7; ++x)
414                         ((uint16_t *)mem)[x] =
415                                 colors_bottom[(x - width * 5 / 7) * 3
416                                               / (width / 7) + 4];
417                 for (; x < width; ++x)
418                         ((uint16_t *)mem)[x] = colors_bottom[7];
419                 mem += stride;
420         }
421 }
422
423 static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem,
424                              unsigned int width, unsigned int height,
425                              unsigned int stride)
426 {
427         const struct color_rgb24 colors_top[] = {
428                 MAKE_RGB24(rgb, 192, 192, 192), /* grey */
429                 MAKE_RGB24(rgb, 192, 192, 0),   /* yellow */
430                 MAKE_RGB24(rgb, 0, 192, 192),   /* cyan */
431                 MAKE_RGB24(rgb, 0, 192, 0),     /* green */
432                 MAKE_RGB24(rgb, 192, 0, 192),   /* magenta */
433                 MAKE_RGB24(rgb, 192, 0, 0),     /* red */
434                 MAKE_RGB24(rgb, 0, 0, 192),     /* blue */
435         };
436         const struct color_rgb24 colors_middle[] = {
437                 MAKE_RGB24(rgb, 0, 0, 192),     /* blue */
438                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
439                 MAKE_RGB24(rgb, 192, 0, 192),   /* magenta */
440                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
441                 MAKE_RGB24(rgb, 0, 192, 192),   /* cyan */
442                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
443                 MAKE_RGB24(rgb, 192, 192, 192), /* grey */
444         };
445         const struct color_rgb24 colors_bottom[] = {
446                 MAKE_RGB24(rgb, 0, 33, 76),     /* in-phase */
447                 MAKE_RGB24(rgb, 255, 255, 255), /* super white */
448                 MAKE_RGB24(rgb, 50, 0, 106),    /* quadrature */
449                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
450                 MAKE_RGB24(rgb, 9, 9, 9),       /* 3.5% */
451                 MAKE_RGB24(rgb, 19, 19, 19),    /* 7.5% */
452                 MAKE_RGB24(rgb, 29, 29, 29),    /* 11.5% */
453                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
454         };
455         unsigned int x;
456         unsigned int y;
457
458         for (y = 0; y < height * 6 / 9; ++y) {
459                 for (x = 0; x < width; ++x)
460                         ((struct color_rgb24 *)mem)[x] =
461                                 colors_top[x * 7 / width];
462                 mem += stride;
463         }
464
465         for (; y < height * 7 / 9; ++y) {
466                 for (x = 0; x < width; ++x)
467                         ((struct color_rgb24 *)mem)[x] =
468                                 colors_middle[x * 7 / width];
469                 mem += stride;
470         }
471
472         for (; y < height; ++y) {
473                 for (x = 0; x < width * 5 / 7; ++x)
474                         ((struct color_rgb24 *)mem)[x] =
475                                 colors_bottom[x * 4 / (width * 5 / 7)];
476                 for (; x < width * 6 / 7; ++x)
477                         ((struct color_rgb24 *)mem)[x] =
478                                 colors_bottom[(x - width * 5 / 7) * 3
479                                               / (width / 7) + 4];
480                 for (; x < width; ++x)
481                         ((struct color_rgb24 *)mem)[x] = colors_bottom[7];
482                 mem += stride;
483         }
484 }
485
486 static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem,
487                              unsigned int width, unsigned int height,
488                              unsigned int stride)
489 {
490         const uint32_t colors_top[] = {
491                 MAKE_RGBA(rgb, 192, 192, 192, 255),     /* grey */
492                 MAKE_RGBA(rgb, 192, 192, 0, 255),       /* yellow */
493                 MAKE_RGBA(rgb, 0, 192, 192, 255),       /* cyan */
494                 MAKE_RGBA(rgb, 0, 192, 0, 255),         /* green */
495                 MAKE_RGBA(rgb, 192, 0, 192, 255),       /* magenta */
496                 MAKE_RGBA(rgb, 192, 0, 0, 255),         /* red */
497                 MAKE_RGBA(rgb, 0, 0, 192, 255),         /* blue */
498         };
499         const uint32_t colors_middle[] = {
500                 MAKE_RGBA(rgb, 0, 0, 192, 127),         /* blue */
501                 MAKE_RGBA(rgb, 19, 19, 19, 127),        /* black */
502                 MAKE_RGBA(rgb, 192, 0, 192, 127),       /* magenta */
503                 MAKE_RGBA(rgb, 19, 19, 19, 127),        /* black */
504                 MAKE_RGBA(rgb, 0, 192, 192, 127),       /* cyan */
505                 MAKE_RGBA(rgb, 19, 19, 19, 127),        /* black */
506                 MAKE_RGBA(rgb, 192, 192, 192, 127),     /* grey */
507         };
508         const uint32_t colors_bottom[] = {
509                 MAKE_RGBA(rgb, 0, 33, 76, 255),         /* in-phase */
510                 MAKE_RGBA(rgb, 255, 255, 255, 255),     /* super white */
511                 MAKE_RGBA(rgb, 50, 0, 106, 255),        /* quadrature */
512                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
513                 MAKE_RGBA(rgb, 9, 9, 9, 255),           /* 3.5% */
514                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* 7.5% */
515                 MAKE_RGBA(rgb, 29, 29, 29, 255),        /* 11.5% */
516                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
517         };
518         unsigned int x;
519         unsigned int y;
520
521         for (y = 0; y < height * 6 / 9; ++y) {
522                 for (x = 0; x < width; ++x)
523                         ((uint32_t *)mem)[x] = colors_top[x * 7 / width];
524                 mem += stride;
525         }
526
527         for (; y < height * 7 / 9; ++y) {
528                 for (x = 0; x < width; ++x)
529                         ((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
530                 mem += stride;
531         }
532
533         for (; y < height; ++y) {
534                 for (x = 0; x < width * 5 / 7; ++x)
535                         ((uint32_t *)mem)[x] =
536                                 colors_bottom[x * 4 / (width * 5 / 7)];
537                 for (; x < width * 6 / 7; ++x)
538                         ((uint32_t *)mem)[x] =
539                                 colors_bottom[(x - width * 5 / 7) * 3
540                                               / (width / 7) + 4];
541                 for (; x < width; ++x)
542                         ((uint32_t *)mem)[x] = colors_bottom[7];
543                 mem += stride;
544         }
545 }
546
547 static void fill_smpte_rgb16fp(const struct util_rgb_info *rgb, void *mem,
548                                unsigned int width, unsigned int height,
549                                unsigned int stride)
550 {
551         const uint64_t colors_top[] = {
552                 MAKE_RGBA8FP16(rgb, 192, 192, 192, 255),/* grey */
553                 MAKE_RGBA8FP16(rgb, 192, 192, 0, 255),  /* yellow */
554                 MAKE_RGBA8FP16(rgb, 0, 192, 192, 255),  /* cyan */
555                 MAKE_RGBA8FP16(rgb, 0, 192, 0, 255),    /* green */
556                 MAKE_RGBA8FP16(rgb, 192, 0, 192, 255),  /* magenta */
557                 MAKE_RGBA8FP16(rgb, 192, 0, 0, 255),    /* red */
558                 MAKE_RGBA8FP16(rgb, 0, 0, 192, 255),    /* blue */
559         };
560         const uint64_t colors_middle[] = {
561                 MAKE_RGBA8FP16(rgb, 0, 0, 192, 127),    /* blue */
562                 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127),   /* black */
563                 MAKE_RGBA8FP16(rgb, 192, 0, 192, 127),  /* magenta */
564                 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127),   /* black */
565                 MAKE_RGBA8FP16(rgb, 0, 192, 192, 127),  /* cyan */
566                 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127),   /* black */
567                 MAKE_RGBA8FP16(rgb, 192, 192, 192, 127),/* grey */
568         };
569         const uint64_t colors_bottom[] = {
570                 MAKE_RGBA8FP16(rgb, 0, 33, 76, 255),    /* in-phase */
571                 MAKE_RGBA8FP16(rgb, 255, 255, 255, 255),/* super white */
572                 MAKE_RGBA8FP16(rgb, 50, 0, 106, 255),   /* quadrature */
573                 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255),   /* black */
574                 MAKE_RGBA8FP16(rgb, 9, 9, 9, 255),      /* 3.5% */
575                 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255),   /* 7.5% */
576                 MAKE_RGBA8FP16(rgb, 29, 29, 29, 255),   /* 11.5% */
577                 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255),   /* black */
578         };
579         unsigned int x;
580         unsigned int y;
581
582         for (y = 0; y < height * 6 / 9; ++y) {
583                 for (x = 0; x < width; ++x)
584                         ((uint64_t *)mem)[x] = colors_top[x * 7 / width];
585                 mem += stride;
586         }
587
588         for (; y < height * 7 / 9; ++y) {
589                 for (x = 0; x < width; ++x)
590                         ((uint64_t *)mem)[x] = colors_middle[x * 7 / width];
591                 mem += stride;
592         }
593
594         for (; y < height; ++y) {
595                 for (x = 0; x < width * 5 / 7; ++x)
596                         ((uint64_t *)mem)[x] =
597                                 colors_bottom[x * 4 / (width * 5 / 7)];
598                 for (; x < width * 6 / 7; ++x)
599                         ((uint64_t *)mem)[x] =
600                                 colors_bottom[(x - width * 5 / 7) * 3
601                                               / (width / 7) + 4];
602                 for (; x < width; ++x)
603                         ((uint64_t *)mem)[x] = colors_bottom[7];
604                 mem += stride;
605         }
606 }
607
608 enum smpte_colors {
609         SMPTE_COLOR_GREY,
610         SMPTE_COLOR_YELLOW,
611         SMPTE_COLOR_CYAN,
612         SMPTE_COLOR_GREEN,
613         SMPTE_COLOR_MAGENTA,
614         SMPTE_COLOR_RED,
615         SMPTE_COLOR_BLUE,
616         SMPTE_COLOR_BLACK,
617         SMPTE_COLOR_IN_PHASE,
618         SMPTE_COLOR_SUPER_WHITE,
619         SMPTE_COLOR_QUADRATURE,
620         SMPTE_COLOR_3PC5,
621         SMPTE_COLOR_11PC5,
622 };
623
624 static unsigned int smpte_top[7] = {
625         SMPTE_COLOR_GREY,
626         SMPTE_COLOR_YELLOW,
627         SMPTE_COLOR_CYAN,
628         SMPTE_COLOR_GREEN,
629         SMPTE_COLOR_MAGENTA,
630         SMPTE_COLOR_RED,
631         SMPTE_COLOR_BLUE,
632 };
633
634 static unsigned int smpte_middle[7] = {
635         SMPTE_COLOR_BLUE,
636         SMPTE_COLOR_BLACK,
637         SMPTE_COLOR_MAGENTA,
638         SMPTE_COLOR_BLACK,
639         SMPTE_COLOR_CYAN,
640         SMPTE_COLOR_BLACK,
641         SMPTE_COLOR_GREY,
642 };
643
644 static unsigned int smpte_bottom[8] = {
645         SMPTE_COLOR_IN_PHASE,
646         SMPTE_COLOR_SUPER_WHITE,
647         SMPTE_COLOR_QUADRATURE,
648         SMPTE_COLOR_BLACK,
649         SMPTE_COLOR_3PC5,
650         SMPTE_COLOR_BLACK,
651         SMPTE_COLOR_11PC5,
652         SMPTE_COLOR_BLACK,
653 };
654
655 #define EXPAND_COLOR(r, g, b)   { (r) * 0x101, (g) * 0x101, (b) * 0x101 }
656
657 static const struct drm_color_lut bw_color_lut[] = {
658         EXPAND_COLOR(  0,   0,   0),    /* black */
659         EXPAND_COLOR(255, 255, 255),    /* white */
660 };
661
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),
676 };
677
678 #undef EXPAND_COLOR
679
680 /*
681  * Floyd-Steinberg dithering
682  */
683
684 struct fsd {
685         unsigned int width;
686         unsigned int x;
687         unsigned int i;
688         int red;
689         int green;
690         int blue;
691         int error[];
692 };
693
694 static struct fsd *fsd_alloc(unsigned int width)
695 {
696         unsigned int n = 3 * (width + 1);
697         struct fsd *fsd = malloc(sizeof(*fsd) + n * sizeof(fsd->error[0]));
698
699         fsd->width = width;
700         fsd->x = 0;
701         fsd->i = 0;
702         memset(fsd->error, 0, n * sizeof(fsd->error[0]));
703
704         return fsd;
705 }
706
707 static inline int clamp(int val, int min, int max)
708 {
709         if (val < min)
710                 return min;
711         if (val > max)
712                 return max;
713         return val;
714 }
715
716 static void fsd_dither(struct fsd *fsd, struct drm_color_lut *color)
717 {
718         unsigned int i = fsd->i;
719
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;
723
724         color->red = clamp(fsd->red, 0, 65535);
725         color->green = clamp(fsd->green, 0, 65535);
726         color->blue = clamp(fsd->blue, 0, 65535);
727 }
728
729 static void fsd_update(struct fsd *fsd, const struct drm_color_lut *actual)
730 {
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;
737
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;
745         } else {
746                 /* East: accumulate error */
747                 j = (i + 1) % n;
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;
751
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;
756         }
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;
762
763         /* South: accumulate error */
764         j = (i + width) % n;
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;
768
769         fsd->x = (fsd->x + 1) % width;
770         fsd->i = (fsd->i + 1) % n;
771 }
772
773 static void write_pixel_1(uint8_t *mem, unsigned int x, unsigned int pixel)
774 {
775         unsigned int shift = 7 - (x & 7);
776         unsigned int mask = 1U << shift;
777
778         mem[x / 8] = (mem[x / 8] & ~mask) | ((pixel << shift) & mask);
779 }
780
781 static void write_color_1(struct fsd *fsd, uint8_t *mem, unsigned int x,
782                           unsigned int index)
783 {
784         struct drm_color_lut color = smpte_color_lut[index];
785         unsigned int pixel;
786
787         fsd_dither(fsd, &color);
788
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) {
791                 pixel = 1;
792                 color.red = color.green = color.blue = 65535;
793         } else {
794                 pixel = 0;
795                 color.red = color.green = color.blue = 0;
796         }
797
798         fsd_update(fsd, &color);
799
800         write_pixel_1(mem, x, pixel);
801 }
802
803 static void fill_smpte_c1(void *mem, unsigned int width, unsigned int height,
804                           unsigned int stride)
805 {
806         struct fsd *fsd = fsd_alloc(width);
807         unsigned int x;
808         unsigned int y;
809
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]);
813                 mem += stride;
814         }
815
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]);
819                 mem += stride;
820         }
821
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 /
829                                                    (width / 7) + 4]);
830                 for (; x < width; ++x)
831                         write_color_1(fsd, mem, x, smpte_bottom[7]);
832                 mem += stride;
833         }
834
835         free(fsd);
836 }
837
838 static void write_pixel_4(uint8_t *mem, unsigned int x, unsigned int pixel)
839 {
840         if (x & 1)
841                 mem[x / 2] = (mem[x / 2] & 0xf0) | (pixel & 0x0f);
842         else
843                 mem[x / 2] = (mem[x / 2] & 0x0f) | (pixel << 4);
844 }
845
846 static void fill_smpte_c4(void *mem, unsigned int width, unsigned int height,
847                           unsigned int stride)
848 {
849         unsigned int x;
850         unsigned int y;
851
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]);
855                 mem += stride;
856         }
857
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]);
861                 mem += stride;
862         }
863
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 /
871                                                    (width / 7) + 4]);
872                 for (; x < width; ++x)
873                         write_pixel_4(mem, x, smpte_bottom[7]);
874                 mem += stride;
875         }
876 }
877
878 static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height,
879                           unsigned int stride)
880 {
881         unsigned int x;
882         unsigned int y;
883
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];
887                 mem += stride;
888         }
889
890         for (; y < height * 7 / 9; ++y) {
891                 for (x = 0; x < width; ++x)
892                         ((uint8_t *)mem)[x] = smpte_middle[x * 7 / width];
893                 mem += stride;
894         }
895
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
903                                              / (width / 7) + 4];
904                 for (; x < width; ++x)
905                         ((uint8_t *)mem)[x] = smpte_bottom[7];
906                 mem += stride;
907         }
908 }
909
910 void util_smpte_fill_lut(unsigned int ncolors, struct drm_color_lut *lut)
911 {
912         if (ncolors < ARRAY_SIZE(bw_color_lut)) {
913                 printf("Error: lut too small: %u < %zu\n", ncolors,
914                        ARRAY_SIZE(bw_color_lut));
915                 return;
916         }
917         memset(lut, 0, ncolors * sizeof(struct drm_color_lut));
918
919         if (ncolors < ARRAY_SIZE(smpte_color_lut))
920                 memcpy(lut, bw_color_lut, sizeof(bw_color_lut));
921         else
922                 memcpy(lut, smpte_color_lut, sizeof(smpte_color_lut));
923 }
924
925 static void fill_smpte(const struct util_format_info *info, void *planes[3],
926                        unsigned int width, unsigned int height,
927                        unsigned int stride)
928 {
929         unsigned char *u, *v;
930
931         switch (info->format) {
932         case DRM_FORMAT_C1:
933                 return fill_smpte_c1(planes[0], width, height, stride);
934         case DRM_FORMAT_C4:
935                 return fill_smpte_c4(planes[0], width, height, stride);
936         case DRM_FORMAT_C8:
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,
943                                              height, stride);
944
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);
955
956         case DRM_FORMAT_YUV420:
957                 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
958                                              planes[2], width, height, stride);
959
960         case DRM_FORMAT_YVU420:
961                 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
962                                              planes[1], width, height, stride);
963
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);
984
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);
1007
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);
1014         }
1015 }
1016
1017 static void make_pwetty(void *data, unsigned int width, unsigned int height,
1018                         unsigned int stride, uint32_t format)
1019 {
1020 #if HAVE_CAIRO
1021         cairo_surface_t *surface;
1022         cairo_t *cr;
1023         cairo_format_t cairo_format;
1024
1025         /* we can ignore the order of R,G,B channels */
1026         switch (format) {
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;
1032                 break;
1033         case DRM_FORMAT_RGB565:
1034         case DRM_FORMAT_BGR565:
1035                 cairo_format = CAIRO_FORMAT_RGB16_565;
1036                 break;
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;
1043                 break;
1044 #endif
1045         default:
1046                 return;
1047         }
1048
1049         surface = cairo_image_surface_create_for_data(data,
1050                                                       cairo_format,
1051                                                       width, height,
1052                                                       stride);
1053         cr = cairo_create(surface);
1054         cairo_surface_destroy(surface);
1055
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) {
1059                         char buf[64];
1060
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);
1072                         cairo_stroke(cr);
1073
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);
1080                         cairo_fill(cr);
1081                 }
1082
1083         cairo_destroy(cr);
1084 #endif
1085 }
1086
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)
1091 {
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;
1096         unsigned int x;
1097         unsigned int y;
1098
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);
1107
1108                         y_mem[x] = color.y;
1109                         u_mem[x/xsub*cs] = color.u;
1110                         v_mem[x/xsub*cs] = color.v;
1111                 }
1112
1113                 y_mem += stride;
1114                 if ((y + 1) % ysub == 0) {
1115                         u_mem += stride * cs / xsub;
1116                         v_mem += stride * cs / xsub;
1117                 }
1118         }
1119 }
1120
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)
1124 {
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;
1130         unsigned int x;
1131         unsigned int y;
1132
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);
1141
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;
1146                 }
1147
1148                 y_mem += stride;
1149                 c_mem += stride;
1150         }
1151 }
1152
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)
1156 {
1157         const struct util_rgb_info *rgb = &info->rgb;
1158         void *mem_base = mem;
1159         unsigned int x, y;
1160
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);
1166                         uint16_t color =
1167                                 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
1168                                           (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1169                                           255);
1170
1171                         ((uint16_t *)mem)[x] = color;
1172                 }
1173                 mem += stride;
1174         }
1175
1176         make_pwetty(mem_base, width, height, stride, info->format);
1177 }
1178
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)
1182 {
1183         const struct util_rgb_info *rgb = &info->rgb;
1184         unsigned int x, y;
1185
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);
1194
1195                         ((struct color_rgb24 *)mem)[x] = color;
1196                 }
1197                 mem += stride;
1198         }
1199 }
1200
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)
1204 {
1205         const struct util_rgb_info *rgb = &info->rgb;
1206         void *mem_base = mem;
1207         unsigned int x, y;
1208
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;
1215                         uint32_t color =
1216                                 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
1217                                           (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1218                                           alpha);
1219
1220                         ((uint32_t *)mem)[x] = color;
1221                 }
1222                 mem += stride;
1223         }
1224
1225         make_pwetty(mem_base, width, height, stride, info->format);
1226 }
1227
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)
1231 {
1232         const struct util_rgb_info *rgb = &info->rgb;
1233         unsigned int x, y;
1234
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;
1242                         uint64_t color =
1243                                 MAKE_RGBA8FP16(rgb, (rgb32 >> 16) & 0xff,
1244                                                (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1245                                                alpha);
1246
1247                         ((uint64_t *)mem)[x] = color;
1248                 }
1249                 mem += stride;
1250         }
1251 }
1252
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)
1256 {
1257         unsigned char *u, *v;
1258
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);
1266
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);
1277
1278         case DRM_FORMAT_YUV420:
1279                 return fill_tiles_yuv_planar(info, planes[0], planes[1],
1280                                              planes[2], width, height, stride);
1281
1282         case DRM_FORMAT_YVU420:
1283                 return fill_tiles_yuv_planar(info, planes[0], planes[2],
1284                                              planes[1], width, height, stride);
1285
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);
1306
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);
1329
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);
1336         }
1337 }
1338
1339 static void fill_plain(const struct util_format_info *info, void *planes[3],
1340                        unsigned int height,
1341                        unsigned int stride)
1342 {
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);
1350                 break;
1351         default:
1352                 memset(planes[0], 0x77, stride * height);
1353                 break;
1354         }
1355 }
1356
1357 static void fill_gradient_rgb32(const struct util_rgb_info *rgb,
1358                                 void *mem,
1359                                 unsigned int width, unsigned int height,
1360                                 unsigned int stride)
1361 {
1362         unsigned int i, j;
1363
1364         for (i = 0; i < height / 2; i++) {
1365                 uint32_t *row = mem;
1366
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;
1370                 }
1371                 mem += stride;
1372         }
1373
1374         for (; i < height; i++) {
1375                 uint32_t *row = mem;
1376
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;
1380                 }
1381                 mem += stride;
1382         }
1383 }
1384
1385 static void fill_gradient_rgb16fp(const struct util_rgb_info *rgb,
1386                                   void *mem,
1387                                   unsigned int width, unsigned int height,
1388                                   unsigned int stride)
1389 {
1390         unsigned int i, j;
1391
1392         for (i = 0; i < height / 2; i++) {
1393                 uint64_t *row = mem;
1394
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;
1398                 }
1399                 mem += stride;
1400         }
1401
1402         for (; i < height; i++) {
1403                 uint64_t *row = mem;
1404
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;
1408                 }
1409                 mem += stride;
1410         }
1411 }
1412
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:
1417  *
1418  *  - Pixel data is encoded as 8bpc to the display, no dithering. This
1419  *    would lead to the top and bottom halves looking identical.
1420  *
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.
1424  *
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.
1429  *
1430  * Once we support additional fb formats, this approach could be extended
1431  * to distinguish even higher bpc precisions.
1432  *
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
1436  * hard to notice.
1437  */
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)
1441 {
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);
1461
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);
1468         }
1469 }
1470
1471 /*
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
1479  *
1480  * Fill the buffers with the test pattern specified by the pattern parameter.
1481  * Supported formats vary depending on the selected pattern.
1482  */
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)
1486 {
1487         const struct util_format_info *info;
1488
1489         info = util_format_info_find(format);
1490         if (info == NULL)
1491                 return;
1492
1493         switch (pattern) {
1494         case UTIL_PATTERN_TILES:
1495                 return fill_tiles(info, planes, width, height, stride);
1496
1497         case UTIL_PATTERN_SMPTE:
1498                 return fill_smpte(info, planes, width, height, stride);
1499
1500         case UTIL_PATTERN_PLAIN:
1501                 return fill_plain(info, planes, height, stride);
1502
1503         case UTIL_PATTERN_GRADIENT:
1504                 return fill_gradient(info, planes, width, height, stride);
1505
1506         default:
1507                 printf("Error: unsupported test pattern %u.\n", pattern);
1508                 break;
1509         }
1510 }
1511
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",
1517 };
1518
1519 enum util_fill_pattern util_pattern_enum(const char *name)
1520 {
1521         unsigned int i;
1522
1523         for (i = 0; i < ARRAY_SIZE(pattern_names); i++)
1524                 if (!strcmp(pattern_names[i], name))
1525                         return (enum util_fill_pattern)i;
1526
1527         printf("Error: unsupported test pattern %s.\n", name);
1528         return UTIL_PATTERN_SMPTE;
1529 }