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