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