util: fix grey in YUV SMPTE patterns
[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 static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height,
609                           unsigned int stride)
610 {
611         unsigned int x;
612         unsigned int y;
613
614         for (y = 0; y < height * 6 / 9; ++y) {
615                 for (x = 0; x < width; ++x)
616                         ((uint8_t *)mem)[x] = x * 7 / width;
617                 mem += stride;
618         }
619
620         for (; y < height * 7 / 9; ++y) {
621                 for (x = 0; x < width; ++x)
622                         ((uint8_t *)mem)[x] = 7 + (x * 7 / width);
623                 mem += stride;
624         }
625
626         for (; y < height; ++y) {
627                 for (x = 0; x < width * 5 / 7; ++x)
628                         ((uint8_t *)mem)[x] =
629                                 14 + (x * 4 / (width * 5 / 7));
630                 for (; x < width * 6 / 7; ++x)
631                         ((uint8_t *)mem)[x] =
632                                 14 + ((x - width * 5 / 7) * 3
633                                               / (width / 7) + 4);
634                 for (; x < width; ++x)
635                         ((uint8_t *)mem)[x] = 14 + 7;
636                 mem += stride;
637         }
638 }
639
640 void util_smpte_c8_gamma(unsigned size, struct drm_color_lut *lut)
641 {
642         if (size < 7 + 7 + 8) {
643                 printf("Error: gamma too small: %d < %d\n", size, 7 + 7 + 8);
644                 return;
645         }
646         memset(lut, 0, size * sizeof(struct drm_color_lut));
647
648 #define FILL_COLOR(idx, r, g, b) \
649         lut[idx].red = (r) << 8; \
650         lut[idx].green = (g) << 8; \
651         lut[idx].blue = (b) << 8
652
653         FILL_COLOR( 0, 192, 192, 192);  /* grey */
654         FILL_COLOR( 1, 192, 192, 0  );  /* yellow */
655         FILL_COLOR( 2, 0,   192, 192);  /* cyan */
656         FILL_COLOR( 3, 0,   192, 0  );  /* green */
657         FILL_COLOR( 4, 192, 0,   192);  /* magenta */
658         FILL_COLOR( 5, 192, 0,   0  );  /* red */
659         FILL_COLOR( 6, 0,   0,   192);  /* blue */
660
661         FILL_COLOR( 7, 0,   0,   192);  /* blue */
662         FILL_COLOR( 8, 19,  19,  19 );  /* black */
663         FILL_COLOR( 9, 192, 0,   192);  /* magenta */
664         FILL_COLOR(10, 19,  19,  19 );  /* black */
665         FILL_COLOR(11, 0,   192, 192);  /* cyan */
666         FILL_COLOR(12, 19,  19,  19 );  /* black */
667         FILL_COLOR(13, 192, 192, 192);  /* grey */
668
669         FILL_COLOR(14, 0,   33,  76);   /* in-phase */
670         FILL_COLOR(15, 255, 255, 255);  /* super white */
671         FILL_COLOR(16, 50,  0,   106);  /* quadrature */
672         FILL_COLOR(17, 19,  19,  19);   /* black */
673         FILL_COLOR(18, 9,   9,   9);    /* 3.5% */
674         FILL_COLOR(19, 19,  19,  19);   /* 7.5% */
675         FILL_COLOR(20, 29,  29,  29);   /* 11.5% */
676         FILL_COLOR(21, 19,  19,  19);   /* black */
677
678 #undef FILL_COLOR
679 }
680
681 static void fill_smpte(const struct util_format_info *info, void *planes[3],
682                        unsigned int width, unsigned int height,
683                        unsigned int stride)
684 {
685         unsigned char *u, *v;
686
687         switch (info->format) {
688         case DRM_FORMAT_C8:
689                 return fill_smpte_c8(planes[0], width, height, stride);
690         case DRM_FORMAT_UYVY:
691         case DRM_FORMAT_VYUY:
692         case DRM_FORMAT_YUYV:
693         case DRM_FORMAT_YVYU:
694                 return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
695                                              height, stride);
696
697         case DRM_FORMAT_NV12:
698         case DRM_FORMAT_NV21:
699         case DRM_FORMAT_NV16:
700         case DRM_FORMAT_NV61:
701         case DRM_FORMAT_NV24:
702         case DRM_FORMAT_NV42:
703                 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
704                 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
705                 return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
706                                              width, height, stride);
707
708         case DRM_FORMAT_YUV420:
709                 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
710                                              planes[2], width, height, stride);
711
712         case DRM_FORMAT_YVU420:
713                 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
714                                              planes[1], width, height, stride);
715
716         case DRM_FORMAT_ARGB4444:
717         case DRM_FORMAT_XRGB4444:
718         case DRM_FORMAT_ABGR4444:
719         case DRM_FORMAT_XBGR4444:
720         case DRM_FORMAT_RGBA4444:
721         case DRM_FORMAT_RGBX4444:
722         case DRM_FORMAT_BGRA4444:
723         case DRM_FORMAT_BGRX4444:
724         case DRM_FORMAT_RGB565:
725         case DRM_FORMAT_BGR565:
726         case DRM_FORMAT_ARGB1555:
727         case DRM_FORMAT_XRGB1555:
728         case DRM_FORMAT_ABGR1555:
729         case DRM_FORMAT_XBGR1555:
730         case DRM_FORMAT_RGBA5551:
731         case DRM_FORMAT_RGBX5551:
732         case DRM_FORMAT_BGRA5551:
733         case DRM_FORMAT_BGRX5551:
734                 return fill_smpte_rgb16(&info->rgb, planes[0],
735                                         width, height, stride);
736
737         case DRM_FORMAT_BGR888:
738         case DRM_FORMAT_RGB888:
739                 return fill_smpte_rgb24(&info->rgb, planes[0],
740                                         width, height, stride);
741         case DRM_FORMAT_ARGB8888:
742         case DRM_FORMAT_XRGB8888:
743         case DRM_FORMAT_ABGR8888:
744         case DRM_FORMAT_XBGR8888:
745         case DRM_FORMAT_RGBA8888:
746         case DRM_FORMAT_RGBX8888:
747         case DRM_FORMAT_BGRA8888:
748         case DRM_FORMAT_BGRX8888:
749         case DRM_FORMAT_ARGB2101010:
750         case DRM_FORMAT_XRGB2101010:
751         case DRM_FORMAT_ABGR2101010:
752         case DRM_FORMAT_XBGR2101010:
753         case DRM_FORMAT_RGBA1010102:
754         case DRM_FORMAT_RGBX1010102:
755         case DRM_FORMAT_BGRA1010102:
756         case DRM_FORMAT_BGRX1010102:
757                 return fill_smpte_rgb32(&info->rgb, planes[0],
758                                         width, height, stride);
759
760         case DRM_FORMAT_XRGB16161616F:
761         case DRM_FORMAT_XBGR16161616F:
762         case DRM_FORMAT_ARGB16161616F:
763         case DRM_FORMAT_ABGR16161616F:
764                 return fill_smpte_rgb16fp(&info->rgb, planes[0],
765                                           width, height, stride);
766         }
767 }
768
769 /* swap these for big endian.. */
770 #define RED   2
771 #define GREEN 1
772 #define BLUE  0
773
774 static void make_pwetty(void *data, unsigned int width, unsigned int height,
775                         unsigned int stride, uint32_t format)
776 {
777 #if HAVE_CAIRO
778         cairo_surface_t *surface;
779         cairo_t *cr;
780         cairo_format_t cairo_format;
781
782         /* we can ignore the order of R,G,B channels */
783         switch (format) {
784         case DRM_FORMAT_XRGB8888:
785         case DRM_FORMAT_ARGB8888:
786         case DRM_FORMAT_XBGR8888:
787         case DRM_FORMAT_ABGR8888:
788                 cairo_format = CAIRO_FORMAT_ARGB32;
789                 break;
790         case DRM_FORMAT_RGB565:
791         case DRM_FORMAT_BGR565:
792                 cairo_format = CAIRO_FORMAT_RGB16_565;
793                 break;
794 #if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 12)
795         case DRM_FORMAT_ARGB2101010:
796         case DRM_FORMAT_XRGB2101010:
797         case DRM_FORMAT_ABGR2101010:
798         case DRM_FORMAT_XBGR2101010:
799                 cairo_format = CAIRO_FORMAT_RGB30;
800                 break;
801 #endif
802         default:
803                 return;
804         }
805
806         surface = cairo_image_surface_create_for_data(data,
807                                                       cairo_format,
808                                                       width, height,
809                                                       stride);
810         cr = cairo_create(surface);
811         cairo_surface_destroy(surface);
812
813         cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
814         for (unsigned x = 0; x < width; x += 250)
815                 for (unsigned y = 0; y < height; y += 250) {
816                         char buf[64];
817
818                         cairo_move_to(cr, x, y - 20);
819                         cairo_line_to(cr, x, y + 20);
820                         cairo_move_to(cr, x - 20, y);
821                         cairo_line_to(cr, x + 20, y);
822                         cairo_new_sub_path(cr);
823                         cairo_arc(cr, x, y, 10, 0, M_PI * 2);
824                         cairo_set_line_width(cr, 4);
825                         cairo_set_source_rgb(cr, 0, 0, 0);
826                         cairo_stroke_preserve(cr);
827                         cairo_set_source_rgb(cr, 1, 1, 1);
828                         cairo_set_line_width(cr, 2);
829                         cairo_stroke(cr);
830
831                         snprintf(buf, sizeof buf, "%d, %d", x, y);
832                         cairo_move_to(cr, x + 20, y + 20);
833                         cairo_text_path(cr, buf);
834                         cairo_set_source_rgb(cr, 0, 0, 0);
835                         cairo_stroke_preserve(cr);
836                         cairo_set_source_rgb(cr, 1, 1, 1);
837                         cairo_fill(cr);
838                 }
839
840         cairo_destroy(cr);
841 #endif
842 }
843
844 static void fill_tiles_yuv_planar(const struct util_format_info *info,
845                                   unsigned char *y_mem, unsigned char *u_mem,
846                                   unsigned char *v_mem, unsigned int width,
847                                   unsigned int height, unsigned int stride)
848 {
849         const struct util_yuv_info *yuv = &info->yuv;
850         unsigned int cs = yuv->chroma_stride;
851         unsigned int xsub = yuv->xsub;
852         unsigned int ysub = yuv->ysub;
853         unsigned int x;
854         unsigned int y;
855
856         for (y = 0; y < height; ++y) {
857                 for (x = 0; x < width; ++x) {
858                         div_t d = div(x+y, width);
859                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
860                                        + 0x000a1120 * (d.rem >> 6);
861                         struct color_yuv color =
862                                 MAKE_YUV_601((rgb32 >> 16) & 0xff,
863                                              (rgb32 >> 8) & 0xff, rgb32 & 0xff);
864
865                         y_mem[x] = color.y;
866                         u_mem[x/xsub*cs] = color.u;
867                         v_mem[x/xsub*cs] = color.v;
868                 }
869
870                 y_mem += stride;
871                 if ((y + 1) % ysub == 0) {
872                         u_mem += stride * cs / xsub;
873                         v_mem += stride * cs / xsub;
874                 }
875         }
876 }
877
878 static void fill_tiles_yuv_packed(const struct util_format_info *info,
879                                   void *mem, unsigned int width,
880                                   unsigned int height, unsigned int stride)
881 {
882         const struct util_yuv_info *yuv = &info->yuv;
883         unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
884         unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
885         unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
886         unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
887         unsigned int x;
888         unsigned int y;
889
890         for (y = 0; y < height; ++y) {
891                 for (x = 0; x < width; x += 2) {
892                         div_t d = div(x+y, width);
893                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
894                                        + 0x000a1120 * (d.rem >> 6);
895                         struct color_yuv color =
896                                 MAKE_YUV_601((rgb32 >> 16) & 0xff,
897                                              (rgb32 >> 8) & 0xff, rgb32 & 0xff);
898
899                         y_mem[2*x] = color.y;
900                         c_mem[2*x+u] = color.u;
901                         y_mem[2*x+2] = color.y;
902                         c_mem[2*x+v] = color.v;
903                 }
904
905                 y_mem += stride;
906                 c_mem += stride;
907         }
908 }
909
910 static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
911                              unsigned int width, unsigned int height,
912                              unsigned int stride)
913 {
914         const struct util_rgb_info *rgb = &info->rgb;
915         void *mem_base = mem;
916         unsigned int x, y;
917
918         for (y = 0; y < height; ++y) {
919                 for (x = 0; x < width; ++x) {
920                         div_t d = div(x+y, width);
921                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
922                                        + 0x000a1120 * (d.rem >> 6);
923                         uint16_t color =
924                                 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
925                                           (rgb32 >> 8) & 0xff, rgb32 & 0xff,
926                                           255);
927
928                         ((uint16_t *)mem)[x] = color;
929                 }
930                 mem += stride;
931         }
932
933         make_pwetty(mem_base, width, height, stride, info->format);
934 }
935
936 static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
937                              unsigned int width, unsigned int height,
938                              unsigned int stride)
939 {
940         const struct util_rgb_info *rgb = &info->rgb;
941         unsigned int x, y;
942
943         for (y = 0; y < height; ++y) {
944                 for (x = 0; x < width; ++x) {
945                         div_t d = div(x+y, width);
946                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
947                                        + 0x000a1120 * (d.rem >> 6);
948                         struct color_rgb24 color =
949                                 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
950                                            (rgb32 >> 8) & 0xff, rgb32 & 0xff);
951
952                         ((struct color_rgb24 *)mem)[x] = color;
953                 }
954                 mem += stride;
955         }
956 }
957
958 static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
959                              unsigned int width, unsigned int height,
960                              unsigned int stride)
961 {
962         const struct util_rgb_info *rgb = &info->rgb;
963         void *mem_base = mem;
964         unsigned int x, y;
965
966         for (y = 0; y < height; ++y) {
967                 for (x = 0; x < width; ++x) {
968                         div_t d = div(x+y, width);
969                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
970                                        + 0x000a1120 * (d.rem >> 6);
971                         uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
972                         uint32_t color =
973                                 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
974                                           (rgb32 >> 8) & 0xff, rgb32 & 0xff,
975                                           alpha);
976
977                         ((uint32_t *)mem)[x] = color;
978                 }
979                 mem += stride;
980         }
981
982         make_pwetty(mem_base, width, height, stride, info->format);
983 }
984
985 static void fill_tiles_rgb16fp(const struct util_format_info *info, void *mem,
986                                unsigned int width, unsigned int height,
987                                unsigned int stride)
988 {
989         const struct util_rgb_info *rgb = &info->rgb;
990         unsigned int x, y;
991
992         /* TODO: Give this actual fp16 precision */
993         for (y = 0; y < height; ++y) {
994                 for (x = 0; x < width; ++x) {
995                         div_t d = div(x+y, width);
996                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
997                                        + 0x000a1120 * (d.rem >> 6);
998                         uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
999                         uint64_t color =
1000                                 MAKE_RGBA8FP16(rgb, (rgb32 >> 16) & 0xff,
1001                                                (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1002                                                alpha);
1003
1004                         ((uint64_t *)mem)[x] = color;
1005                 }
1006                 mem += stride;
1007         }
1008 }
1009
1010 static void fill_tiles(const struct util_format_info *info, void *planes[3],
1011                        unsigned int width, unsigned int height,
1012                        unsigned int stride)
1013 {
1014         unsigned char *u, *v;
1015
1016         switch (info->format) {
1017         case DRM_FORMAT_UYVY:
1018         case DRM_FORMAT_VYUY:
1019         case DRM_FORMAT_YUYV:
1020         case DRM_FORMAT_YVYU:
1021                 return fill_tiles_yuv_packed(info, planes[0],
1022                                              width, height, stride);
1023
1024         case DRM_FORMAT_NV12:
1025         case DRM_FORMAT_NV21:
1026         case DRM_FORMAT_NV16:
1027         case DRM_FORMAT_NV61:
1028         case DRM_FORMAT_NV24:
1029         case DRM_FORMAT_NV42:
1030                 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
1031                 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
1032                 return fill_tiles_yuv_planar(info, planes[0], u, v,
1033                                              width, height, stride);
1034
1035         case DRM_FORMAT_YUV420:
1036                 return fill_tiles_yuv_planar(info, planes[0], planes[1],
1037                                              planes[2], width, height, stride);
1038
1039         case DRM_FORMAT_YVU420:
1040                 return fill_tiles_yuv_planar(info, planes[0], planes[2],
1041                                              planes[1], width, height, stride);
1042
1043         case DRM_FORMAT_ARGB4444:
1044         case DRM_FORMAT_XRGB4444:
1045         case DRM_FORMAT_ABGR4444:
1046         case DRM_FORMAT_XBGR4444:
1047         case DRM_FORMAT_RGBA4444:
1048         case DRM_FORMAT_RGBX4444:
1049         case DRM_FORMAT_BGRA4444:
1050         case DRM_FORMAT_BGRX4444:
1051         case DRM_FORMAT_RGB565:
1052         case DRM_FORMAT_BGR565:
1053         case DRM_FORMAT_ARGB1555:
1054         case DRM_FORMAT_XRGB1555:
1055         case DRM_FORMAT_ABGR1555:
1056         case DRM_FORMAT_XBGR1555:
1057         case DRM_FORMAT_RGBA5551:
1058         case DRM_FORMAT_RGBX5551:
1059         case DRM_FORMAT_BGRA5551:
1060         case DRM_FORMAT_BGRX5551:
1061                 return fill_tiles_rgb16(info, planes[0],
1062                                         width, height, stride);
1063
1064         case DRM_FORMAT_BGR888:
1065         case DRM_FORMAT_RGB888:
1066                 return fill_tiles_rgb24(info, planes[0],
1067                                         width, height, stride);
1068         case DRM_FORMAT_ARGB8888:
1069         case DRM_FORMAT_XRGB8888:
1070         case DRM_FORMAT_ABGR8888:
1071         case DRM_FORMAT_XBGR8888:
1072         case DRM_FORMAT_RGBA8888:
1073         case DRM_FORMAT_RGBX8888:
1074         case DRM_FORMAT_BGRA8888:
1075         case DRM_FORMAT_BGRX8888:
1076         case DRM_FORMAT_ARGB2101010:
1077         case DRM_FORMAT_XRGB2101010:
1078         case DRM_FORMAT_ABGR2101010:
1079         case DRM_FORMAT_XBGR2101010:
1080         case DRM_FORMAT_RGBA1010102:
1081         case DRM_FORMAT_RGBX1010102:
1082         case DRM_FORMAT_BGRA1010102:
1083         case DRM_FORMAT_BGRX1010102:
1084                 return fill_tiles_rgb32(info, planes[0],
1085                                         width, height, stride);
1086
1087         case DRM_FORMAT_XRGB16161616F:
1088         case DRM_FORMAT_XBGR16161616F:
1089         case DRM_FORMAT_ARGB16161616F:
1090         case DRM_FORMAT_ABGR16161616F:
1091                 return fill_tiles_rgb16fp(info, planes[0],
1092                                           width, height, stride);
1093         }
1094 }
1095
1096 static void fill_plain(const struct util_format_info *info, void *planes[3],
1097                        unsigned int height,
1098                        unsigned int stride)
1099 {
1100         switch (info->format) {
1101         case DRM_FORMAT_XRGB16161616F:
1102         case DRM_FORMAT_XBGR16161616F:
1103         case DRM_FORMAT_ARGB16161616F:
1104         case DRM_FORMAT_ABGR16161616F:
1105                 /* 0x3838 = 0.5273 */
1106                 memset(planes[0], 0x38, stride * height);
1107                 break;
1108         default:
1109                 memset(planes[0], 0x77, stride * height);
1110                 break;
1111         }
1112 }
1113
1114 static void fill_gradient_rgb32(const struct util_rgb_info *rgb,
1115                                 void *mem,
1116                                 unsigned int width, unsigned int height,
1117                                 unsigned int stride)
1118 {
1119         unsigned int i, j;
1120
1121         for (i = 0; i < height / 2; i++) {
1122                 uint32_t *row = mem;
1123
1124                 for (j = 0; j < width / 2; j++) {
1125                         uint32_t value = MAKE_RGBA10(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1126                         row[2*j] = row[2*j+1] = value;
1127                 }
1128                 mem += stride;
1129         }
1130
1131         for (; i < height; i++) {
1132                 uint32_t *row = mem;
1133
1134                 for (j = 0; j < width / 2; j++) {
1135                         uint32_t value = MAKE_RGBA10(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1136                         row[2*j] = row[2*j+1] = value;
1137                 }
1138                 mem += stride;
1139         }
1140 }
1141
1142 static void fill_gradient_rgb16fp(const struct util_rgb_info *rgb,
1143                                   void *mem,
1144                                   unsigned int width, unsigned int height,
1145                                   unsigned int stride)
1146 {
1147         unsigned int i, j;
1148
1149         for (i = 0; i < height / 2; i++) {
1150                 uint64_t *row = mem;
1151
1152                 for (j = 0; j < width / 2; j++) {
1153                         uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1154                         row[2*j] = row[2*j+1] = value;
1155                 }
1156                 mem += stride;
1157         }
1158
1159         for (; i < height; i++) {
1160                 uint64_t *row = mem;
1161
1162                 for (j = 0; j < width / 2; j++) {
1163                         uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1164                         row[2*j] = row[2*j+1] = value;
1165                 }
1166                 mem += stride;
1167         }
1168 }
1169
1170 /* The gradient pattern creates two horizontal gray gradients, split
1171  * into two halves. The top half has 10bpc precision, the bottom half
1172  * has 8bpc precision. When using with a 10bpc fb format, there are 3
1173  * possible outcomes:
1174  *
1175  *  - Pixel data is encoded as 8bpc to the display, no dithering. This
1176  *    would lead to the top and bottom halves looking identical.
1177  *
1178  *  - Pixel data is encoded as 8bpc to the display, with dithering. This
1179  *    would lead to there being a visible difference between the two halves,
1180  *    but the top half would look a little speck-y due to the dithering.
1181  *
1182  *  - Pixel data is encoded at 10bpc+ to the display (which implies
1183  *    the display is able to show this level of depth). This should
1184  *    lead to the top half being a very clean gradient, and visibly different
1185  *    from the bottom half.
1186  *
1187  * Once we support additional fb formats, this approach could be extended
1188  * to distinguish even higher bpc precisions.
1189  *
1190  * Note that due to practical size considerations, for the screens
1191  * where this matters, the pattern actually emits stripes 2-pixels
1192  * wide for each gradient color. Otherwise the difference may be a bit
1193  * hard to notice.
1194  */
1195 static void fill_gradient(const struct util_format_info *info, void *planes[3],
1196                           unsigned int width, unsigned int height,
1197                           unsigned int stride)
1198 {
1199         switch (info->format) {
1200         case DRM_FORMAT_ARGB8888:
1201         case DRM_FORMAT_XRGB8888:
1202         case DRM_FORMAT_ABGR8888:
1203         case DRM_FORMAT_XBGR8888:
1204         case DRM_FORMAT_RGBA8888:
1205         case DRM_FORMAT_RGBX8888:
1206         case DRM_FORMAT_BGRA8888:
1207         case DRM_FORMAT_BGRX8888:
1208         case DRM_FORMAT_ARGB2101010:
1209         case DRM_FORMAT_XRGB2101010:
1210         case DRM_FORMAT_ABGR2101010:
1211         case DRM_FORMAT_XBGR2101010:
1212         case DRM_FORMAT_RGBA1010102:
1213         case DRM_FORMAT_RGBX1010102:
1214         case DRM_FORMAT_BGRA1010102:
1215         case DRM_FORMAT_BGRX1010102:
1216                 return fill_gradient_rgb32(&info->rgb, planes[0],
1217                                            width, height, stride);
1218
1219         case DRM_FORMAT_XRGB16161616F:
1220         case DRM_FORMAT_XBGR16161616F:
1221         case DRM_FORMAT_ARGB16161616F:
1222         case DRM_FORMAT_ABGR16161616F:
1223                 return fill_gradient_rgb16fp(&info->rgb, planes[0],
1224                                              width, height, stride);
1225         }
1226 }
1227
1228 /*
1229  * util_fill_pattern - Fill a buffer with a test pattern
1230  * @format: Pixel format
1231  * @pattern: Test pattern
1232  * @planes: Array of buffers
1233  * @width: Width in pixels
1234  * @height: Height in pixels
1235  * @stride: Line stride (pitch) in bytes
1236  *
1237  * Fill the buffers with the test pattern specified by the pattern parameter.
1238  * Supported formats vary depending on the selected pattern.
1239  */
1240 void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
1241                        void *planes[3], unsigned int width,
1242                        unsigned int height, unsigned int stride)
1243 {
1244         const struct util_format_info *info;
1245
1246         info = util_format_info_find(format);
1247         if (info == NULL)
1248                 return;
1249
1250         switch (pattern) {
1251         case UTIL_PATTERN_TILES:
1252                 return fill_tiles(info, planes, width, height, stride);
1253
1254         case UTIL_PATTERN_SMPTE:
1255                 return fill_smpte(info, planes, width, height, stride);
1256
1257         case UTIL_PATTERN_PLAIN:
1258                 return fill_plain(info, planes, height, stride);
1259
1260         case UTIL_PATTERN_GRADIENT:
1261                 return fill_gradient(info, planes, width, height, stride);
1262
1263         default:
1264                 printf("Error: unsupported test pattern %u.\n", pattern);
1265                 break;
1266         }
1267 }
1268
1269 static const char *pattern_names[] = {
1270         [UTIL_PATTERN_TILES] = "tiles",
1271         [UTIL_PATTERN_SMPTE] = "smpte",
1272         [UTIL_PATTERN_PLAIN] = "plain",
1273         [UTIL_PATTERN_GRADIENT] = "gradient",
1274 };
1275
1276 enum util_fill_pattern util_pattern_enum(const char *name)
1277 {
1278         unsigned int i;
1279
1280         for (i = 0; i < ARRAY_SIZE(pattern_names); i++)
1281                 if (!strcmp(pattern_names[i], name))
1282                         return (enum util_fill_pattern)i;
1283
1284         printf("Error: unsupported test pattern %s.\n", name);
1285         return UTIL_PATTERN_SMPTE;
1286 }