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 <stdbool.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include <drm_fourcc.h>
33
34 #if HAVE_CAIRO
35 #include <cairo.h>
36 #include <math.h>
37 #endif
38
39 #include "common.h"
40 #include "format.h"
41 #include "pattern.h"
42
43 struct color_rgb24 {
44 unsigned int value:24;
45 } __attribute__((__packed__));
46
47 struct color_yuv {
48 unsigned char y;
49 unsigned char u;
50 unsigned char v;
51 };
52
53 #define MAKE_YUV_601_Y(r, g, b) \
54 ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16)
55 #define MAKE_YUV_601_U(r, g, b) \
56 (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128)
57 #define MAKE_YUV_601_V(r, g, b) \
58 (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128)
59
60 #define MAKE_YUV_601(r, g, b) \
61 { .y = MAKE_YUV_601_Y(r, g, b), \
62 .u = MAKE_YUV_601_U(r, g, b), \
63 .v = MAKE_YUV_601_V(r, g, b) }
64
swap16(uint16_t x)65 static inline uint16_t swap16(uint16_t x)
66 {
67 return ((x & 0x00ffU) << 8) | ((x & 0xff00U) >> 8);
68 }
69
swap32(uint32_t x)70 static inline uint32_t swap32(uint32_t x)
71 {
72 return ((x & 0x000000ffU) << 24) |
73 ((x & 0x0000ff00U) << 8) |
74 ((x & 0x00ff0000U) >> 8) |
75 ((x & 0xff000000U) >> 24);
76 }
77
78 #ifdef HAVE_BIG_ENDIAN
79 #define cpu_to_be16(x) (x)
80 #define cpu_to_le16(x) swap16(x)
81 #define cpu_to_le32(x) swap32(x)
82 #define fb_foreign_endian(format) (!((format) & DRM_FORMAT_BIG_ENDIAN))
83 #else
84 #define cpu_to_be16(x) swap16(x)
85 #define cpu_to_le16(x) (x)
86 #define cpu_to_le32(x) (x)
87 #define fb_foreign_endian(format) ((format) & DRM_FORMAT_BIG_ENDIAN)
88 #endif
89
90 #define cpu_to_fb16(x) (fb_be ? cpu_to_be16(x) : cpu_to_le16(x))
91
92 /* This function takes 8-bit color values */
shiftcolor8(const struct util_color_component * comp,uint32_t value)93 static inline uint32_t shiftcolor8(const struct util_color_component *comp,
94 uint32_t value)
95 {
96 value &= 0xff;
97 /* Fill the low bits with the high bits. */
98 value = (value << 8) | value;
99 /* Shift down to remove unwanted low bits */
100 value = value >> (16 - comp->length);
101 /* Shift back up to where the value should be */
102 return value << comp->offset;
103 }
104
105 /* This function takes 10-bit color values */
shiftcolor10(const struct util_color_component * comp,uint32_t value)106 static inline uint32_t shiftcolor10(const struct util_color_component *comp,
107 uint32_t value)
108 {
109 value &= 0x3ff;
110 /* Fill the low bits with the high bits. */
111 value = (value << 6) | (value >> 4);
112 /* Shift down to remove unwanted low bits */
113 value = value >> (16 - comp->length);
114 /* Shift back up to where the value should be */
115 return value << comp->offset;
116 }
117
118 /* This function takes 16-bit color values */
shiftcolor16(const struct util_color_component * comp,uint64_t value)119 static inline uint64_t shiftcolor16(const struct util_color_component *comp,
120 uint64_t value)
121 {
122 value &= 0xffff;
123 /* Shift down to remove unwanted low bits */
124 value = value >> (16 - comp->length);
125 /* Shift back up to where the value should be */
126 return value << comp->offset;
127 }
128
129 #define MAKE_RGBA10(rgb, r, g, b, a) \
130 (shiftcolor10(&(rgb)->red, (r)) | \
131 shiftcolor10(&(rgb)->green, (g)) | \
132 shiftcolor10(&(rgb)->blue, (b)) | \
133 shiftcolor10(&(rgb)->alpha, (a)))
134
135 #define MAKE_RGBA(rgb, r, g, b, a) \
136 (shiftcolor8(&(rgb)->red, (r)) | \
137 shiftcolor8(&(rgb)->green, (g)) | \
138 shiftcolor8(&(rgb)->blue, (b)) | \
139 shiftcolor8(&(rgb)->alpha, (a)))
140
141 #define MAKE_RGB24(rgb, r, g, b) \
142 { .value = MAKE_RGBA(rgb, r, g, b, 0) }
143
144
145 /**
146 * Takes a uint16_t, divides by 65536, converts the infinite-precision
147 * result to fp16 with round-to-zero.
148 *
149 * Copied from mesa:src/util/half_float.c
150 */
uint16_div_64k_to_half(uint16_t v)151 static uint16_t uint16_div_64k_to_half(uint16_t v)
152 {
153 /* Zero or subnormal. Set the mantissa to (v << 8) and return. */
154 if (v < 4)
155 return v << 8;
156
157 /* Count the leading 0s in the uint16_t */
158 int n = __builtin_clz(v) - 16;
159
160 /* Shift the mantissa up so bit 16 is the hidden 1 bit,
161 * mask it off, then shift back down to 10 bits
162 */
163 int m = ( ((uint32_t)v << (n + 1)) & 0xffff ) >> 6;
164
165 /* (0{n} 1 X{15-n}) * 2^-16
166 * = 1.X * 2^(15-n-16)
167 * = 1.X * 2^(14-n - 15)
168 * which is the FP16 form with e = 14 - n
169 */
170 int e = 14 - n;
171
172 return (e << 10) | m;
173 }
174
175 #define MAKE_RGBA8FP16(rgb, r, g, b, a) \
176 (shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 8)) | \
177 shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 8)) | \
178 shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 8)) | \
179 shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 8)))
180
181 #define MAKE_RGBA10FP16(rgb, r, g, b, a) \
182 (shiftcolor16(&(rgb)->red, uint16_div_64k_to_half((r) << 6)) | \
183 shiftcolor16(&(rgb)->green, uint16_div_64k_to_half((g) << 6)) | \
184 shiftcolor16(&(rgb)->blue, uint16_div_64k_to_half((b) << 6)) | \
185 shiftcolor16(&(rgb)->alpha, uint16_div_64k_to_half((a) << 6)))
186
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)187 static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv,
188 unsigned char *y_mem, unsigned char *u_mem,
189 unsigned char *v_mem, unsigned int width,
190 unsigned int height, unsigned int stride)
191 {
192 const struct color_yuv colors_top[] = {
193 MAKE_YUV_601(192, 192, 192), /* grey */
194 MAKE_YUV_601(192, 192, 0), /* yellow */
195 MAKE_YUV_601(0, 192, 192), /* cyan */
196 MAKE_YUV_601(0, 192, 0), /* green */
197 MAKE_YUV_601(192, 0, 192), /* magenta */
198 MAKE_YUV_601(192, 0, 0), /* red */
199 MAKE_YUV_601(0, 0, 192), /* blue */
200 };
201 const struct color_yuv colors_middle[] = {
202 MAKE_YUV_601(0, 0, 192), /* blue */
203 MAKE_YUV_601(19, 19, 19), /* black */
204 MAKE_YUV_601(192, 0, 192), /* magenta */
205 MAKE_YUV_601(19, 19, 19), /* black */
206 MAKE_YUV_601(0, 192, 192), /* cyan */
207 MAKE_YUV_601(19, 19, 19), /* black */
208 MAKE_YUV_601(192, 192, 192), /* grey */
209 };
210 const struct color_yuv colors_bottom[] = {
211 MAKE_YUV_601(0, 33, 76), /* in-phase */
212 MAKE_YUV_601(255, 255, 255), /* super white */
213 MAKE_YUV_601(50, 0, 106), /* quadrature */
214 MAKE_YUV_601(19, 19, 19), /* black */
215 MAKE_YUV_601(9, 9, 9), /* 3.5% */
216 MAKE_YUV_601(19, 19, 19), /* 7.5% */
217 MAKE_YUV_601(29, 29, 29), /* 11.5% */
218 MAKE_YUV_601(19, 19, 19), /* black */
219 };
220 unsigned int cs = yuv->chroma_stride;
221 unsigned int xsub = yuv->xsub;
222 unsigned int ysub = yuv->ysub;
223 unsigned int x;
224 unsigned int y;
225
226 /* Luma */
227 for (y = 0; y < height * 6 / 9; ++y) {
228 for (x = 0; x < width; ++x)
229 y_mem[x] = colors_top[x * 7 / width].y;
230 y_mem += stride;
231 }
232
233 for (; y < height * 7 / 9; ++y) {
234 for (x = 0; x < width; ++x)
235 y_mem[x] = colors_middle[x * 7 / width].y;
236 y_mem += stride;
237 }
238
239 for (; y < height; ++y) {
240 for (x = 0; x < width * 5 / 7; ++x)
241 y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
242 for (; x < width * 6 / 7; ++x)
243 y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
244 / (width / 7) + 4].y;
245 for (; x < width; ++x)
246 y_mem[x] = colors_bottom[7].y;
247 y_mem += stride;
248 }
249
250 /* Chroma */
251 for (y = 0; y < height / ysub * 6 / 9; ++y) {
252 for (x = 0; x < width; x += xsub) {
253 u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
254 v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
255 }
256 u_mem += stride * cs / xsub;
257 v_mem += stride * cs / xsub;
258 }
259
260 for (; y < height / ysub * 7 / 9; ++y) {
261 for (x = 0; x < width; x += xsub) {
262 u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
263 v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
264 }
265 u_mem += stride * cs / xsub;
266 v_mem += stride * cs / xsub;
267 }
268
269 for (; y < height / ysub; ++y) {
270 for (x = 0; x < width * 5 / 7; x += xsub) {
271 u_mem[x*cs/xsub] =
272 colors_bottom[x * 4 / (width * 5 / 7)].u;
273 v_mem[x*cs/xsub] =
274 colors_bottom[x * 4 / (width * 5 / 7)].v;
275 }
276 for (; x < width * 6 / 7; x += xsub) {
277 u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
278 3 / (width / 7) + 4].u;
279 v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
280 3 / (width / 7) + 4].v;
281 }
282 for (; x < width; x += xsub) {
283 u_mem[x*cs/xsub] = colors_bottom[7].u;
284 v_mem[x*cs/xsub] = colors_bottom[7].v;
285 }
286 u_mem += stride * cs / xsub;
287 v_mem += stride * cs / xsub;
288 }
289 }
290
write_pixels_10bpp(unsigned char * mem,unsigned short a,unsigned short b,unsigned short c,unsigned short d)291 static void write_pixels_10bpp(unsigned char *mem,
292 unsigned short a,
293 unsigned short b,
294 unsigned short c,
295 unsigned short d)
296 {
297 mem[0] = (a & 0xff);
298 mem[1] = ((a >> 8) & 0x3) | ((b & 0x3f) << 2);
299 mem[2] = ((b >> 6) & 0xf) | ((c & 0xf) << 4);
300 mem[3] = ((c >> 4) & 0x3f) | ((d & 0x3) << 6);
301 mem[4] = ((d >> 2) & 0xff);
302 }
303
fill_smpte_yuv_planar_10bpp(const struct util_yuv_info * yuv,unsigned char * y_mem,unsigned char * uv_mem,unsigned int width,unsigned int height,unsigned int stride)304 static void fill_smpte_yuv_planar_10bpp(const struct util_yuv_info *yuv,
305 unsigned char *y_mem,
306 unsigned char *uv_mem,
307 unsigned int width,
308 unsigned int height,
309 unsigned int stride)
310 {
311 const struct color_yuv colors_top[] = {
312 MAKE_YUV_601(192, 192, 192), /* grey */
313 MAKE_YUV_601(192, 192, 0), /* yellow */
314 MAKE_YUV_601(0, 192, 192), /* cyan */
315 MAKE_YUV_601(0, 192, 0), /* green */
316 MAKE_YUV_601(192, 0, 192), /* magenta */
317 MAKE_YUV_601(192, 0, 0), /* red */
318 MAKE_YUV_601(0, 0, 192), /* blue */
319 };
320 const struct color_yuv colors_middle[] = {
321 MAKE_YUV_601(0, 0, 192), /* blue */
322 MAKE_YUV_601(19, 19, 19), /* black */
323 MAKE_YUV_601(192, 0, 192), /* magenta */
324 MAKE_YUV_601(19, 19, 19), /* black */
325 MAKE_YUV_601(0, 192, 192), /* cyan */
326 MAKE_YUV_601(19, 19, 19), /* black */
327 MAKE_YUV_601(192, 192, 192), /* grey */
328 };
329 const struct color_yuv colors_bottom[] = {
330 MAKE_YUV_601(0, 33, 76), /* in-phase */
331 MAKE_YUV_601(255, 255, 255), /* super white */
332 MAKE_YUV_601(50, 0, 106), /* quadrature */
333 MAKE_YUV_601(19, 19, 19), /* black */
334 MAKE_YUV_601(9, 9, 9), /* 3.5% */
335 MAKE_YUV_601(19, 19, 19), /* 7.5% */
336 MAKE_YUV_601(29, 29, 29), /* 11.5% */
337 MAKE_YUV_601(19, 19, 19), /* black */
338 };
339 unsigned int cs = yuv->chroma_stride;
340 unsigned int xsub = yuv->xsub;
341 unsigned int ysub = yuv->ysub;
342 unsigned int xstep = cs * xsub;
343 unsigned int x;
344 unsigned int y;
345
346 /* Luma */
347 for (y = 0; y < height * 6 / 9; ++y) {
348 for (x = 0; x < width; x += 4)
349 write_pixels_10bpp(&y_mem[(x * 5) / 4],
350 colors_top[(x+0) * 7 / width].y << 2,
351 colors_top[(x+1) * 7 / width].y << 2,
352 colors_top[(x+2) * 7 / width].y << 2,
353 colors_top[(x+3) * 7 / width].y << 2);
354 y_mem += stride;
355 }
356
357 for (; y < height * 7 / 9; ++y) {
358 for (x = 0; x < width; x += 4)
359 write_pixels_10bpp(&y_mem[(x * 5) / 4],
360 colors_middle[(x+0) * 7 / width].y << 2,
361 colors_middle[(x+1) * 7 / width].y << 2,
362 colors_middle[(x+2) * 7 / width].y << 2,
363 colors_middle[(x+3) * 7 / width].y << 2);
364 y_mem += stride;
365 }
366
367 for (; y < height; ++y) {
368 for (x = 0; x < width * 5 / 7; x += 4)
369 write_pixels_10bpp(&y_mem[(x * 5) / 4],
370 colors_bottom[(x+0) * 4 / (width * 5 / 7)].y << 2,
371 colors_bottom[(x+1) * 4 / (width * 5 / 7)].y << 2,
372 colors_bottom[(x+2) * 4 / (width * 5 / 7)].y << 2,
373 colors_bottom[(x+3) * 4 / (width * 5 / 7)].y << 2);
374 for (; x < width * 6 / 7; x += 4)
375 write_pixels_10bpp(&y_mem[(x * 5) / 4],
376 colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2,
377 colors_bottom[((x+1) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2,
378 colors_bottom[((x+2) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2,
379 colors_bottom[((x+3) - width * 5 / 7) * 3 / (width / 7) + 4].y << 2);
380 for (; x < width; x += 4)
381 write_pixels_10bpp(&y_mem[(x * 5) / 4],
382 colors_bottom[7].y << 2,
383 colors_bottom[7].y << 2,
384 colors_bottom[7].y << 2,
385 colors_bottom[7].y << 2);
386 y_mem += stride;
387 }
388
389 /* Chroma */
390 for (y = 0; y < height * 6 / 9; y += ysub) {
391 for (x = 0; x < width; x += xstep)
392 write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
393 colors_top[(x+0) * 7 / width].u << 2,
394 colors_top[(x+0) * 7 / width].v << 2,
395 colors_top[(x+xsub) * 7 / width].u << 2,
396 colors_top[(x+xsub) * 7 / width].v << 2);
397 uv_mem += stride * cs / xsub;
398 }
399
400 for (; y < height * 7 / 9; y += ysub) {
401 for (x = 0; x < width; x += xstep)
402 write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
403 colors_middle[(x+0) * 7 / width].u << 2,
404 colors_middle[(x+0) * 7 / width].v << 2,
405 colors_middle[(x+xsub) * 7 / width].u << 2,
406 colors_middle[(x+xsub) * 7 / width].v << 2);
407 uv_mem += stride * cs / xsub;
408 }
409
410 for (; y < height; y += ysub) {
411 for (x = 0; x < width * 5 / 7; x += xstep)
412 write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
413 colors_bottom[(x+0) * 4 / (width * 5 / 7)].u << 2,
414 colors_bottom[(x+0) * 4 / (width * 5 / 7)].v << 2,
415 colors_bottom[(x+xsub) * 4 / (width * 5 / 7)].u << 2,
416 colors_bottom[(x+xsub) * 4 / (width * 5 / 7)].v << 2);
417 for (; x < width * 6 / 7; x += xstep)
418 write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
419 colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].u << 2,
420 colors_bottom[((x+0) - width * 5 / 7) * 3 / (width / 7) + 4].v << 2,
421 colors_bottom[((x+xsub) - width * 5 / 7) * 3 / (width / 7) + 4].u << 2,
422 colors_bottom[((x+xsub) - width * 5 / 7) * 3 / (width / 7) + 4].v << 2);
423 for (; x < width; x += xstep)
424 write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
425 colors_bottom[7].u << 2,
426 colors_bottom[7].v << 2,
427 colors_bottom[7].u << 2,
428 colors_bottom[7].v << 2);
429 uv_mem += stride * cs / xsub;
430 }
431 }
432
fill_smpte_yuv_packed(const struct util_yuv_info * yuv,void * mem,unsigned int width,unsigned int height,unsigned int stride)433 static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem,
434 unsigned int width, unsigned int height,
435 unsigned int stride)
436 {
437 const struct color_yuv colors_top[] = {
438 MAKE_YUV_601(192, 192, 192), /* grey */
439 MAKE_YUV_601(192, 192, 0), /* yellow */
440 MAKE_YUV_601(0, 192, 192), /* cyan */
441 MAKE_YUV_601(0, 192, 0), /* green */
442 MAKE_YUV_601(192, 0, 192), /* magenta */
443 MAKE_YUV_601(192, 0, 0), /* red */
444 MAKE_YUV_601(0, 0, 192), /* blue */
445 };
446 const struct color_yuv colors_middle[] = {
447 MAKE_YUV_601(0, 0, 192), /* blue */
448 MAKE_YUV_601(19, 19, 19), /* black */
449 MAKE_YUV_601(192, 0, 192), /* magenta */
450 MAKE_YUV_601(19, 19, 19), /* black */
451 MAKE_YUV_601(0, 192, 192), /* cyan */
452 MAKE_YUV_601(19, 19, 19), /* black */
453 MAKE_YUV_601(192, 192, 192), /* grey */
454 };
455 const struct color_yuv colors_bottom[] = {
456 MAKE_YUV_601(0, 33, 76), /* in-phase */
457 MAKE_YUV_601(255, 255, 255), /* super white */
458 MAKE_YUV_601(50, 0, 106), /* quadrature */
459 MAKE_YUV_601(19, 19, 19), /* black */
460 MAKE_YUV_601(9, 9, 9), /* 3.5% */
461 MAKE_YUV_601(19, 19, 19), /* 7.5% */
462 MAKE_YUV_601(29, 29, 29), /* 11.5% */
463 MAKE_YUV_601(19, 19, 19), /* black */
464 };
465 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
466 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
467 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
468 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
469 unsigned int x;
470 unsigned int y;
471
472 /* Luma */
473 for (y = 0; y < height * 6 / 9; ++y) {
474 for (x = 0; x < width; ++x)
475 y_mem[2*x] = colors_top[x * 7 / width].y;
476 y_mem += stride;
477 }
478
479 for (; y < height * 7 / 9; ++y) {
480 for (x = 0; x < width; ++x)
481 y_mem[2*x] = colors_middle[x * 7 / width].y;
482 y_mem += stride;
483 }
484
485 for (; y < height; ++y) {
486 for (x = 0; x < width * 5 / 7; ++x)
487 y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
488 for (; x < width * 6 / 7; ++x)
489 y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
490 / (width / 7) + 4].y;
491 for (; x < width; ++x)
492 y_mem[2*x] = colors_bottom[7].y;
493 y_mem += stride;
494 }
495
496 /* Chroma */
497 for (y = 0; y < height * 6 / 9; ++y) {
498 for (x = 0; x < width; x += 2) {
499 c_mem[2*x+u] = colors_top[x * 7 / width].u;
500 c_mem[2*x+v] = colors_top[x * 7 / width].v;
501 }
502 c_mem += stride;
503 }
504
505 for (; y < height * 7 / 9; ++y) {
506 for (x = 0; x < width; x += 2) {
507 c_mem[2*x+u] = colors_middle[x * 7 / width].u;
508 c_mem[2*x+v] = colors_middle[x * 7 / width].v;
509 }
510 c_mem += stride;
511 }
512
513 for (; y < height; ++y) {
514 for (x = 0; x < width * 5 / 7; x += 2) {
515 c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
516 c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
517 }
518 for (; x < width * 6 / 7; x += 2) {
519 c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
520 3 / (width / 7) + 4].u;
521 c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
522 3 / (width / 7) + 4].v;
523 }
524 for (; x < width; x += 2) {
525 c_mem[2*x+u] = colors_bottom[7].u;
526 c_mem[2*x+v] = colors_bottom[7].v;
527 }
528 c_mem += stride;
529 }
530 }
531
fill_smpte_rgb16(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride,bool fb_be)532 static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
533 unsigned int width, unsigned int height,
534 unsigned int stride, bool fb_be)
535 {
536 const uint16_t colors_top[] = {
537 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */
538 MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */
539 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */
540 MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */
541 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */
542 MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */
543 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */
544 };
545 const uint16_t colors_middle[] = {
546 MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */
547 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
548 MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */
549 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
550 MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */
551 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
552 MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */
553 };
554 const uint16_t colors_bottom[] = {
555 MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */
556 MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */
557 MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */
558 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
559 MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */
560 MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */
561 MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */
562 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
563 };
564 unsigned int x;
565 unsigned int y;
566
567 for (y = 0; y < height * 6 / 9; ++y) {
568 for (x = 0; x < width; ++x)
569 ((uint16_t *)mem)[x] = cpu_to_fb16(colors_top[x * 7 / width]);
570 mem += stride;
571 }
572
573 for (; y < height * 7 / 9; ++y) {
574 for (x = 0; x < width; ++x)
575 ((uint16_t *)mem)[x] = cpu_to_fb16(colors_middle[x * 7 / width]);
576 mem += stride;
577 }
578
579 for (; y < height; ++y) {
580 for (x = 0; x < width * 5 / 7; ++x)
581 ((uint16_t *)mem)[x] =
582 cpu_to_fb16(colors_bottom[x * 4 / (width * 5 / 7)]);
583 for (; x < width * 6 / 7; ++x)
584 ((uint16_t *)mem)[x] =
585 cpu_to_fb16(colors_bottom[(x - width * 5 / 7) * 3
586 / (width / 7) + 4]);
587 for (; x < width; ++x)
588 ((uint16_t *)mem)[x] = cpu_to_fb16(colors_bottom[7]);
589 mem += stride;
590 }
591 }
592
fill_smpte_rgb24(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)593 static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem,
594 unsigned int width, unsigned int height,
595 unsigned int stride)
596 {
597 const struct color_rgb24 colors_top[] = {
598 MAKE_RGB24(rgb, 192, 192, 192), /* grey */
599 MAKE_RGB24(rgb, 192, 192, 0), /* yellow */
600 MAKE_RGB24(rgb, 0, 192, 192), /* cyan */
601 MAKE_RGB24(rgb, 0, 192, 0), /* green */
602 MAKE_RGB24(rgb, 192, 0, 192), /* magenta */
603 MAKE_RGB24(rgb, 192, 0, 0), /* red */
604 MAKE_RGB24(rgb, 0, 0, 192), /* blue */
605 };
606 const struct color_rgb24 colors_middle[] = {
607 MAKE_RGB24(rgb, 0, 0, 192), /* blue */
608 MAKE_RGB24(rgb, 19, 19, 19), /* black */
609 MAKE_RGB24(rgb, 192, 0, 192), /* magenta */
610 MAKE_RGB24(rgb, 19, 19, 19), /* black */
611 MAKE_RGB24(rgb, 0, 192, 192), /* cyan */
612 MAKE_RGB24(rgb, 19, 19, 19), /* black */
613 MAKE_RGB24(rgb, 192, 192, 192), /* grey */
614 };
615 const struct color_rgb24 colors_bottom[] = {
616 MAKE_RGB24(rgb, 0, 33, 76), /* in-phase */
617 MAKE_RGB24(rgb, 255, 255, 255), /* super white */
618 MAKE_RGB24(rgb, 50, 0, 106), /* quadrature */
619 MAKE_RGB24(rgb, 19, 19, 19), /* black */
620 MAKE_RGB24(rgb, 9, 9, 9), /* 3.5% */
621 MAKE_RGB24(rgb, 19, 19, 19), /* 7.5% */
622 MAKE_RGB24(rgb, 29, 29, 29), /* 11.5% */
623 MAKE_RGB24(rgb, 19, 19, 19), /* black */
624 };
625 unsigned int x;
626 unsigned int y;
627
628 for (y = 0; y < height * 6 / 9; ++y) {
629 for (x = 0; x < width; ++x)
630 ((struct color_rgb24 *)mem)[x] =
631 colors_top[x * 7 / width];
632 mem += stride;
633 }
634
635 for (; y < height * 7 / 9; ++y) {
636 for (x = 0; x < width; ++x)
637 ((struct color_rgb24 *)mem)[x] =
638 colors_middle[x * 7 / width];
639 mem += stride;
640 }
641
642 for (; y < height; ++y) {
643 for (x = 0; x < width * 5 / 7; ++x)
644 ((struct color_rgb24 *)mem)[x] =
645 colors_bottom[x * 4 / (width * 5 / 7)];
646 for (; x < width * 6 / 7; ++x)
647 ((struct color_rgb24 *)mem)[x] =
648 colors_bottom[(x - width * 5 / 7) * 3
649 / (width / 7) + 4];
650 for (; x < width; ++x)
651 ((struct color_rgb24 *)mem)[x] = colors_bottom[7];
652 mem += stride;
653 }
654 }
655
fill_smpte_rgb32(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)656 static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem,
657 unsigned int width, unsigned int height,
658 unsigned int stride)
659 {
660 const uint32_t colors_top[] = {
661 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */
662 MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */
663 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */
664 MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */
665 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */
666 MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */
667 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */
668 };
669 const uint32_t colors_middle[] = {
670 MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */
671 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
672 MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */
673 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
674 MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */
675 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
676 MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */
677 };
678 const uint32_t colors_bottom[] = {
679 MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */
680 MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */
681 MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */
682 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
683 MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */
684 MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */
685 MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */
686 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
687 };
688 unsigned int x;
689 unsigned int y;
690
691 for (y = 0; y < height * 6 / 9; ++y) {
692 for (x = 0; x < width; ++x)
693 ((uint32_t *)mem)[x] = cpu_to_le32(colors_top[x * 7 / width]);
694 mem += stride;
695 }
696
697 for (; y < height * 7 / 9; ++y) {
698 for (x = 0; x < width; ++x)
699 ((uint32_t *)mem)[x] = cpu_to_le32(colors_middle[x * 7 / width]);
700 mem += stride;
701 }
702
703 for (; y < height; ++y) {
704 for (x = 0; x < width * 5 / 7; ++x)
705 ((uint32_t *)mem)[x] =
706 cpu_to_le32(colors_bottom[x * 4 / (width * 5 / 7)]);
707 for (; x < width * 6 / 7; ++x)
708 ((uint32_t *)mem)[x] =
709 cpu_to_le32(colors_bottom[(x - width * 5 / 7) * 3
710 / (width / 7) + 4]);
711 for (; x < width; ++x)
712 ((uint32_t *)mem)[x] = cpu_to_le32(colors_bottom[7]);
713 mem += stride;
714 }
715 }
716
fill_smpte_rgb16fp(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)717 static void fill_smpte_rgb16fp(const struct util_rgb_info *rgb, void *mem,
718 unsigned int width, unsigned int height,
719 unsigned int stride)
720 {
721 const uint64_t colors_top[] = {
722 MAKE_RGBA8FP16(rgb, 192, 192, 192, 255),/* grey */
723 MAKE_RGBA8FP16(rgb, 192, 192, 0, 255), /* yellow */
724 MAKE_RGBA8FP16(rgb, 0, 192, 192, 255), /* cyan */
725 MAKE_RGBA8FP16(rgb, 0, 192, 0, 255), /* green */
726 MAKE_RGBA8FP16(rgb, 192, 0, 192, 255), /* magenta */
727 MAKE_RGBA8FP16(rgb, 192, 0, 0, 255), /* red */
728 MAKE_RGBA8FP16(rgb, 0, 0, 192, 255), /* blue */
729 };
730 const uint64_t colors_middle[] = {
731 MAKE_RGBA8FP16(rgb, 0, 0, 192, 127), /* blue */
732 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */
733 MAKE_RGBA8FP16(rgb, 192, 0, 192, 127), /* magenta */
734 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */
735 MAKE_RGBA8FP16(rgb, 0, 192, 192, 127), /* cyan */
736 MAKE_RGBA8FP16(rgb, 19, 19, 19, 127), /* black */
737 MAKE_RGBA8FP16(rgb, 192, 192, 192, 127),/* grey */
738 };
739 const uint64_t colors_bottom[] = {
740 MAKE_RGBA8FP16(rgb, 0, 33, 76, 255), /* in-phase */
741 MAKE_RGBA8FP16(rgb, 255, 255, 255, 255),/* super white */
742 MAKE_RGBA8FP16(rgb, 50, 0, 106, 255), /* quadrature */
743 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* black */
744 MAKE_RGBA8FP16(rgb, 9, 9, 9, 255), /* 3.5% */
745 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* 7.5% */
746 MAKE_RGBA8FP16(rgb, 29, 29, 29, 255), /* 11.5% */
747 MAKE_RGBA8FP16(rgb, 19, 19, 19, 255), /* black */
748 };
749 unsigned int x;
750 unsigned int y;
751
752 for (y = 0; y < height * 6 / 9; ++y) {
753 for (x = 0; x < width; ++x)
754 ((uint64_t *)mem)[x] = colors_top[x * 7 / width];
755 mem += stride;
756 }
757
758 for (; y < height * 7 / 9; ++y) {
759 for (x = 0; x < width; ++x)
760 ((uint64_t *)mem)[x] = colors_middle[x * 7 / width];
761 mem += stride;
762 }
763
764 for (; y < height; ++y) {
765 for (x = 0; x < width * 5 / 7; ++x)
766 ((uint64_t *)mem)[x] =
767 colors_bottom[x * 4 / (width * 5 / 7)];
768 for (; x < width * 6 / 7; ++x)
769 ((uint64_t *)mem)[x] =
770 colors_bottom[(x - width * 5 / 7) * 3
771 / (width / 7) + 4];
772 for (; x < width; ++x)
773 ((uint64_t *)mem)[x] = colors_bottom[7];
774 mem += stride;
775 }
776 }
777
778 enum smpte_colors {
779 SMPTE_COLOR_GREY,
780 SMPTE_COLOR_YELLOW,
781 SMPTE_COLOR_CYAN,
782 SMPTE_COLOR_GREEN,
783 SMPTE_COLOR_MAGENTA,
784 SMPTE_COLOR_RED,
785 SMPTE_COLOR_BLUE,
786 SMPTE_COLOR_BLACK,
787 SMPTE_COLOR_IN_PHASE,
788 SMPTE_COLOR_SUPER_WHITE,
789 SMPTE_COLOR_QUADRATURE,
790 SMPTE_COLOR_3PC5,
791 SMPTE_COLOR_11PC5,
792 };
793
794 static unsigned int smpte_top[7] = {
795 SMPTE_COLOR_GREY,
796 SMPTE_COLOR_YELLOW,
797 SMPTE_COLOR_CYAN,
798 SMPTE_COLOR_GREEN,
799 SMPTE_COLOR_MAGENTA,
800 SMPTE_COLOR_RED,
801 SMPTE_COLOR_BLUE,
802 };
803
804 static unsigned int smpte_middle[7] = {
805 SMPTE_COLOR_BLUE,
806 SMPTE_COLOR_BLACK,
807 SMPTE_COLOR_MAGENTA,
808 SMPTE_COLOR_BLACK,
809 SMPTE_COLOR_CYAN,
810 SMPTE_COLOR_BLACK,
811 SMPTE_COLOR_GREY,
812 };
813
814 static unsigned int smpte_bottom[8] = {
815 SMPTE_COLOR_IN_PHASE,
816 SMPTE_COLOR_SUPER_WHITE,
817 SMPTE_COLOR_QUADRATURE,
818 SMPTE_COLOR_BLACK,
819 SMPTE_COLOR_3PC5,
820 SMPTE_COLOR_BLACK,
821 SMPTE_COLOR_11PC5,
822 SMPTE_COLOR_BLACK,
823 };
824
825 #define EXPAND_COLOR(r, g, b) { (r) * 0x101, (g) * 0x101, (b) * 0x101 }
826
827 static const struct drm_color_lut bw_color_lut[] = {
828 EXPAND_COLOR( 0, 0, 0), /* black */
829 EXPAND_COLOR(255, 255, 255), /* white */
830 };
831
832 static const struct drm_color_lut pentile_color_lut[] = {
833 /* PenTile RG-GB */
834 EXPAND_COLOR( 0, 0, 0), /* black */
835 EXPAND_COLOR(255, 0, 0), /* red */
836 EXPAND_COLOR( 0, 207, 0), /* green */
837 EXPAND_COLOR( 0, 0, 255), /* blue */
838 };
839
840 static const struct drm_color_lut smpte_color_lut[] = {
841 [SMPTE_COLOR_GREY] = EXPAND_COLOR(192, 192, 192),
842 [SMPTE_COLOR_YELLOW] = EXPAND_COLOR(192, 192, 0),
843 [SMPTE_COLOR_CYAN] = EXPAND_COLOR( 0, 192, 192),
844 [SMPTE_COLOR_GREEN] = EXPAND_COLOR( 0, 192, 0),
845 [SMPTE_COLOR_MAGENTA] = EXPAND_COLOR(192, 0, 192),
846 [SMPTE_COLOR_RED] = EXPAND_COLOR(192, 0, 0),
847 [SMPTE_COLOR_BLUE] = EXPAND_COLOR( 0, 0, 192),
848 [SMPTE_COLOR_BLACK] = EXPAND_COLOR( 19, 19, 19),
849 [SMPTE_COLOR_IN_PHASE] = EXPAND_COLOR( 0, 33, 76),
850 [SMPTE_COLOR_SUPER_WHITE] = EXPAND_COLOR(255, 255, 255),
851 [SMPTE_COLOR_QUADRATURE] = EXPAND_COLOR( 50, 0, 106),
852 [SMPTE_COLOR_3PC5] = EXPAND_COLOR( 9, 9, 9),
853 [SMPTE_COLOR_11PC5] = EXPAND_COLOR( 29, 29, 29),
854 };
855
856 #undef EXPAND_COLOR
857
858 /*
859 * Floyd-Steinberg dithering
860 */
861
862 struct fsd {
863 unsigned int width;
864 unsigned int x;
865 unsigned int i;
866 int red;
867 int green;
868 int blue;
869 int error[];
870 };
871
fsd_alloc(unsigned int width)872 static struct fsd *fsd_alloc(unsigned int width)
873 {
874 unsigned int n = 3 * (width + 1);
875 struct fsd *fsd = malloc(sizeof(*fsd) + n * sizeof(fsd->error[0]));
876
877 fsd->width = width;
878 fsd->x = 0;
879 fsd->i = 0;
880 memset(fsd->error, 0, n * sizeof(fsd->error[0]));
881
882 return fsd;
883 }
884
clamp(int val,int min,int max)885 static inline int clamp(int val, int min, int max)
886 {
887 if (val < min)
888 return min;
889 if (val > max)
890 return max;
891 return val;
892 }
893
fsd_dither(struct fsd * fsd,struct drm_color_lut * color)894 static void fsd_dither(struct fsd *fsd, struct drm_color_lut *color)
895 {
896 unsigned int i = fsd->i;
897
898 fsd->red = (int)color->red + (fsd->error[3 * i] + 8) / 16;
899 fsd->green = (int)color->green + (fsd->error[3 * i + 1] + 8) / 16;
900 fsd->blue = (int)color->blue + (fsd->error[3 * i + 2] + 8) / 16;
901
902 color->red = clamp(fsd->red, 0, 65535);
903 color->green = clamp(fsd->green, 0, 65535);
904 color->blue = clamp(fsd->blue, 0, 65535);
905 }
906
fsd_update(struct fsd * fsd,const struct drm_color_lut * actual)907 static void fsd_update(struct fsd *fsd, const struct drm_color_lut *actual)
908 {
909 int error_red = fsd->red - (int)actual->red;
910 int error_green = fsd->green - (int)actual->green;
911 int error_blue = fsd->blue - (int)actual->blue;
912 unsigned int width = fsd->width;
913 unsigned int i = fsd->i, j;
914 unsigned int n = width + 1;
915
916 /* Distribute errors over neighboring pixels */
917 if (fsd->x == width - 1) {
918 /* Last pixel on this scanline */
919 /* South East: initialize to zero */
920 fsd->error[3 * i] = 0;
921 fsd->error[3 * i + 1] = 0;
922 fsd->error[3 * i + 2] = 0;
923 } else {
924 /* East: accumulate error */
925 j = (i + 1) % n;
926 fsd->error[3 * j] += 7 * error_red;
927 fsd->error[3 * j + 1] += 7 * error_green;
928 fsd->error[3 * j + 2] += 7 * error_blue;
929
930 /* South East: initial error */
931 fsd->error[3 * i] = error_red;
932 fsd->error[3 * i + 1] = error_green;
933 fsd->error[3 * i + 2] = error_blue;
934 }
935 /* South West: accumulate error */
936 j = (i + width - 1) % n;
937 fsd->error[3 * j] += 3 * error_red;
938 fsd->error[3 * j + 1] += 3 * error_green;
939 fsd->error[3 * j + 2] += 3 * error_blue;
940
941 /* South: accumulate error */
942 j = (i + width) % n;
943 fsd->error[3 * j] += 5 * error_red;
944 fsd->error[3 * j + 1] += 5 * error_green;
945 fsd->error[3 * j + 2] += 5 * error_blue;
946
947 fsd->x = (fsd->x + 1) % width;
948 fsd->i = (fsd->i + 1) % n;
949 }
950
write_pixel_1(uint8_t * mem,unsigned int x,unsigned int pixel)951 static void write_pixel_1(uint8_t *mem, unsigned int x, unsigned int pixel)
952 {
953 unsigned int shift = 7 - (x & 7);
954 unsigned int mask = 1U << shift;
955
956 mem[x / 8] = (mem[x / 8] & ~mask) | ((pixel << shift) & mask);
957 }
958
write_color_1(struct fsd * fsd,uint8_t * mem,unsigned int x,unsigned int index)959 static void write_color_1(struct fsd *fsd, uint8_t *mem, unsigned int x,
960 unsigned int index)
961 {
962 struct drm_color_lut color = smpte_color_lut[index];
963 unsigned int pixel;
964
965 fsd_dither(fsd, &color);
966
967 /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
968 if (3 * color.red + 6 * color.green + color.blue >= 10 * 32768) {
969 pixel = 1;
970 color.red = color.green = color.blue = 65535;
971 } else {
972 pixel = 0;
973 color.red = color.green = color.blue = 0;
974 }
975
976 fsd_update(fsd, &color);
977
978 write_pixel_1(mem, x, pixel);
979 }
980
fill_smpte_c1(void * mem,unsigned int width,unsigned int height,unsigned int stride)981 static void fill_smpte_c1(void *mem, unsigned int width, unsigned int height,
982 unsigned int stride)
983 {
984 struct fsd *fsd = fsd_alloc(width);
985 unsigned int x;
986 unsigned int y;
987
988 for (y = 0; y < height * 6 / 9; ++y) {
989 for (x = 0; x < width; ++x)
990 write_color_1(fsd, mem, x, smpte_top[x * 7 / width]);
991 mem += stride;
992 }
993
994 for (; y < height * 7 / 9; ++y) {
995 for (x = 0; x < width; ++x)
996 write_color_1(fsd, mem, x, smpte_middle[x * 7 / width]);
997 mem += stride;
998 }
999
1000 for (; y < height; ++y) {
1001 for (x = 0; x < width * 5 / 7; ++x)
1002 write_color_1(fsd, mem, x,
1003 smpte_bottom[x * 4 / (width * 5 / 7)]);
1004 for (; x < width * 6 / 7; ++x)
1005 write_color_1(fsd, mem, x,
1006 smpte_bottom[(x - width * 5 / 7) * 3 /
1007 (width / 7) + 4]);
1008 for (; x < width; ++x)
1009 write_color_1(fsd, mem, x, smpte_bottom[7]);
1010 mem += stride;
1011 }
1012
1013 free(fsd);
1014 }
1015
write_pixel_2(uint8_t * mem,unsigned int x,unsigned int pixel)1016 static void write_pixel_2(uint8_t *mem, unsigned int x, unsigned int pixel)
1017 {
1018 unsigned int shift = 6 - 2 * (x & 3);
1019 unsigned int mask = 3U << shift;
1020
1021 mem[x / 4] = (mem[x / 4] & ~mask) | ((pixel << shift) & mask);
1022 }
1023
write_color_2(struct fsd * fsd,uint8_t * mem,unsigned int stride,unsigned int x,unsigned int index)1024 static void write_color_2(struct fsd *fsd, uint8_t *mem, unsigned int stride,
1025 unsigned int x, unsigned int index)
1026 {
1027 struct drm_color_lut color = smpte_color_lut[index];
1028 unsigned int r, g, b;
1029
1030 fsd_dither(fsd, &color);
1031
1032 if (color.red >= 32768) {
1033 r = 1;
1034 color.red = 65535;
1035 } else {
1036 r = 0;
1037 color.red = 0;
1038 }
1039 if (color.green >= 32768) {
1040 g = 2;
1041 color.green = 65535;
1042 } else {
1043 g = 0;
1044 color.green = 0;
1045 }
1046 if (color.blue >= 32768) {
1047 b = 3;
1048 color.blue = 65535;
1049 } else {
1050 b = 0;
1051 color.blue = 0;
1052 }
1053
1054 fsd_update(fsd, &color);
1055
1056 /* Use PenTile RG-GB */
1057 write_pixel_2(mem, 2 * x, r);
1058 write_pixel_2(mem, 2 * x + 1, g);
1059 write_pixel_2(mem + stride, 2 * x, g);
1060 write_pixel_2(mem + stride, 2 * x + 1, b);
1061 }
1062
fill_smpte_c2(void * mem,unsigned int width,unsigned int height,unsigned int stride)1063 static void fill_smpte_c2(void *mem, unsigned int width, unsigned int height,
1064 unsigned int stride)
1065 {
1066 struct fsd *fsd = fsd_alloc(width);
1067 unsigned int x;
1068 unsigned int y;
1069
1070 /* Half resolution for PenTile RG-GB */
1071 width /= 2;
1072 height /= 2;
1073
1074 for (y = 0; y < height * 6 / 9; ++y) {
1075 for (x = 0; x < width; ++x)
1076 write_color_2(fsd, mem, stride, x, smpte_top[x * 7 / width]);
1077 mem += 2 * stride;
1078 }
1079
1080 for (; y < height * 7 / 9; ++y) {
1081 for (x = 0; x < width; ++x)
1082 write_color_2(fsd, mem, stride, x, smpte_middle[x * 7 / width]);
1083 mem += 2 * stride;
1084 }
1085
1086 for (; y < height; ++y) {
1087 for (x = 0; x < width * 5 / 7; ++x)
1088 write_color_2(fsd, mem, stride, x,
1089 smpte_bottom[x * 4 / (width * 5 / 7)]);
1090 for (; x < width * 6 / 7; ++x)
1091 write_color_2(fsd, mem, stride, x,
1092 smpte_bottom[(x - width * 5 / 7) * 3 /
1093 (width / 7) + 4]);
1094 for (; x < width; ++x)
1095 write_color_2(fsd, mem, stride, x, smpte_bottom[7]);
1096 mem += 2 * stride;
1097 }
1098
1099 free(fsd);
1100 }
1101
write_pixel_4(uint8_t * mem,unsigned int x,unsigned int pixel)1102 static void write_pixel_4(uint8_t *mem, unsigned int x, unsigned int pixel)
1103 {
1104 if (x & 1)
1105 mem[x / 2] = (mem[x / 2] & 0xf0) | (pixel & 0x0f);
1106 else
1107 mem[x / 2] = (mem[x / 2] & 0x0f) | (pixel << 4);
1108 }
1109
fill_smpte_c4(void * mem,unsigned int width,unsigned int height,unsigned int stride)1110 static void fill_smpte_c4(void *mem, unsigned int width, unsigned int height,
1111 unsigned int stride)
1112 {
1113 unsigned int x;
1114 unsigned int y;
1115
1116 for (y = 0; y < height * 6 / 9; ++y) {
1117 for (x = 0; x < width; ++x)
1118 write_pixel_4(mem, x, smpte_top[x * 7 / width]);
1119 mem += stride;
1120 }
1121
1122 for (; y < height * 7 / 9; ++y) {
1123 for (x = 0; x < width; ++x)
1124 write_pixel_4(mem, x, smpte_middle[x * 7 / width]);
1125 mem += stride;
1126 }
1127
1128 for (; y < height; ++y) {
1129 for (x = 0; x < width * 5 / 7; ++x)
1130 write_pixel_4(mem, x,
1131 smpte_bottom[x * 4 / (width * 5 / 7)]);
1132 for (; x < width * 6 / 7; ++x)
1133 write_pixel_4(mem, x,
1134 smpte_bottom[(x - width * 5 / 7) * 3 /
1135 (width / 7) + 4]);
1136 for (; x < width; ++x)
1137 write_pixel_4(mem, x, smpte_bottom[7]);
1138 mem += stride;
1139 }
1140 }
1141
fill_smpte_c8(void * mem,unsigned int width,unsigned int height,unsigned int stride)1142 static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height,
1143 unsigned int stride)
1144 {
1145 unsigned int x;
1146 unsigned int y;
1147
1148 for (y = 0; y < height * 6 / 9; ++y) {
1149 for (x = 0; x < width; ++x)
1150 ((uint8_t *)mem)[x] = smpte_top[x * 7 / width];
1151 mem += stride;
1152 }
1153
1154 for (; y < height * 7 / 9; ++y) {
1155 for (x = 0; x < width; ++x)
1156 ((uint8_t *)mem)[x] = smpte_middle[x * 7 / width];
1157 mem += stride;
1158 }
1159
1160 for (; y < height; ++y) {
1161 for (x = 0; x < width * 5 / 7; ++x)
1162 ((uint8_t *)mem)[x] =
1163 smpte_bottom[x * 4 / (width * 5 / 7)];
1164 for (; x < width * 6 / 7; ++x)
1165 ((uint8_t *)mem)[x] =
1166 smpte_bottom[(x - width * 5 / 7) * 3
1167 / (width / 7) + 4];
1168 for (; x < width; ++x)
1169 ((uint8_t *)mem)[x] = smpte_bottom[7];
1170 mem += stride;
1171 }
1172 }
1173
util_smpte_fill_lut(unsigned int ncolors,struct drm_color_lut * lut)1174 void util_smpte_fill_lut(unsigned int ncolors, struct drm_color_lut *lut)
1175 {
1176 if (ncolors < ARRAY_SIZE(bw_color_lut)) {
1177 printf("Error: lut too small: %u < %zu\n", ncolors,
1178 ARRAY_SIZE(bw_color_lut));
1179 return;
1180 }
1181 memset(lut, 0, ncolors * sizeof(struct drm_color_lut));
1182
1183 if (ncolors < ARRAY_SIZE(pentile_color_lut))
1184 memcpy(lut, bw_color_lut, sizeof(bw_color_lut));
1185 else if (ncolors < ARRAY_SIZE(smpte_color_lut))
1186 memcpy(lut, pentile_color_lut, sizeof(pentile_color_lut));
1187 else
1188 memcpy(lut, smpte_color_lut, sizeof(smpte_color_lut));
1189 }
1190
fill_smpte(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1191 static void fill_smpte(const struct util_format_info *info, void *planes[3],
1192 unsigned int width, unsigned int height,
1193 unsigned int stride)
1194 {
1195 unsigned char *u, *v;
1196
1197 switch (info->format) {
1198 case DRM_FORMAT_C1:
1199 return fill_smpte_c1(planes[0], width, height, stride);
1200 case DRM_FORMAT_C2:
1201 return fill_smpte_c2(planes[0], width, height, stride);
1202 case DRM_FORMAT_C4:
1203 return fill_smpte_c4(planes[0], width, height, stride);
1204 case DRM_FORMAT_C8:
1205 return fill_smpte_c8(planes[0], width, height, stride);
1206 case DRM_FORMAT_UYVY:
1207 case DRM_FORMAT_VYUY:
1208 case DRM_FORMAT_YUYV:
1209 case DRM_FORMAT_YVYU:
1210 return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
1211 height, stride);
1212
1213 case DRM_FORMAT_NV12:
1214 case DRM_FORMAT_NV21:
1215 case DRM_FORMAT_NV16:
1216 case DRM_FORMAT_NV61:
1217 case DRM_FORMAT_NV24:
1218 case DRM_FORMAT_NV42:
1219 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
1220 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
1221 return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
1222 width, height, stride);
1223
1224 case DRM_FORMAT_NV15:
1225 case DRM_FORMAT_NV20:
1226 case DRM_FORMAT_NV30:
1227 return fill_smpte_yuv_planar_10bpp(&info->yuv, planes[0],
1228 planes[1], width, height,
1229 stride);
1230
1231 case DRM_FORMAT_YUV420:
1232 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
1233 planes[2], width, height, stride);
1234
1235 case DRM_FORMAT_YVU420:
1236 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
1237 planes[1], width, height, stride);
1238
1239 case DRM_FORMAT_ARGB4444:
1240 case DRM_FORMAT_XRGB4444:
1241 case DRM_FORMAT_ABGR4444:
1242 case DRM_FORMAT_XBGR4444:
1243 case DRM_FORMAT_RGBA4444:
1244 case DRM_FORMAT_RGBX4444:
1245 case DRM_FORMAT_BGRA4444:
1246 case DRM_FORMAT_BGRX4444:
1247 case DRM_FORMAT_RGB565:
1248 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
1249 case DRM_FORMAT_BGR565:
1250 case DRM_FORMAT_ARGB1555:
1251 case DRM_FORMAT_XRGB1555:
1252 case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
1253 case DRM_FORMAT_ABGR1555:
1254 case DRM_FORMAT_XBGR1555:
1255 case DRM_FORMAT_RGBA5551:
1256 case DRM_FORMAT_RGBX5551:
1257 case DRM_FORMAT_BGRA5551:
1258 case DRM_FORMAT_BGRX5551:
1259 return fill_smpte_rgb16(&info->rgb, planes[0],
1260 width, height, stride,
1261 info->format & DRM_FORMAT_BIG_ENDIAN);
1262
1263 case DRM_FORMAT_BGR888:
1264 case DRM_FORMAT_RGB888:
1265 return fill_smpte_rgb24(&info->rgb, planes[0],
1266 width, height, stride);
1267 case DRM_FORMAT_ARGB8888:
1268 case DRM_FORMAT_XRGB8888:
1269 case DRM_FORMAT_ABGR8888:
1270 case DRM_FORMAT_XBGR8888:
1271 case DRM_FORMAT_RGBA8888:
1272 case DRM_FORMAT_RGBX8888:
1273 case DRM_FORMAT_BGRA8888:
1274 case DRM_FORMAT_BGRX8888:
1275 case DRM_FORMAT_ARGB2101010:
1276 case DRM_FORMAT_XRGB2101010:
1277 case DRM_FORMAT_ABGR2101010:
1278 case DRM_FORMAT_XBGR2101010:
1279 case DRM_FORMAT_RGBA1010102:
1280 case DRM_FORMAT_RGBX1010102:
1281 case DRM_FORMAT_BGRA1010102:
1282 case DRM_FORMAT_BGRX1010102:
1283 return fill_smpte_rgb32(&info->rgb, planes[0],
1284 width, height, stride);
1285
1286 case DRM_FORMAT_XRGB16161616F:
1287 case DRM_FORMAT_XBGR16161616F:
1288 case DRM_FORMAT_ARGB16161616F:
1289 case DRM_FORMAT_ABGR16161616F:
1290 return fill_smpte_rgb16fp(&info->rgb, planes[0],
1291 width, height, stride);
1292 }
1293 }
1294
1295 #if HAVE_CAIRO
byteswap_buffer16(void * mem,unsigned int width,unsigned int height,unsigned int stride)1296 static void byteswap_buffer16(void *mem, unsigned int width, unsigned int height,
1297 unsigned int stride)
1298 {
1299 unsigned int x, y;
1300
1301 for (y = 0; y < height; ++y) {
1302 for (x = 0; x < width; ++x)
1303 ((uint16_t *)mem)[x] = swap16(((uint16_t *)mem)[x]);
1304 mem += stride;
1305 }
1306 }
1307
byteswap_buffer32(void * mem,unsigned int width,unsigned int height,unsigned int stride)1308 static void byteswap_buffer32(void *mem, unsigned int width, unsigned int height,
1309 unsigned int stride)
1310 {
1311 unsigned int x, y;
1312
1313 for (y = 0; y < height; ++y) {
1314 for (x = 0; x < width; ++x)
1315 ((uint32_t *)mem)[x] = swap32(((uint32_t *)mem)[x]);
1316 mem += stride;
1317 }
1318 }
1319 #endif
1320
make_pwetty(void * data,unsigned int width,unsigned int height,unsigned int stride,uint32_t format)1321 static void make_pwetty(void *data, unsigned int width, unsigned int height,
1322 unsigned int stride, uint32_t format)
1323 {
1324 #if HAVE_CAIRO
1325 cairo_surface_t *surface;
1326 cairo_t *cr;
1327 cairo_format_t cairo_format;
1328 bool swap16 = false;
1329 bool swap32 = false;
1330
1331 /* we can ignore the order of R,G,B channels */
1332 switch (format) {
1333 case DRM_FORMAT_XRGB8888:
1334 case DRM_FORMAT_ARGB8888:
1335 case DRM_FORMAT_XBGR8888:
1336 case DRM_FORMAT_ABGR8888:
1337 cairo_format = CAIRO_FORMAT_ARGB32;
1338 break;
1339 case DRM_FORMAT_RGB565:
1340 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
1341 case DRM_FORMAT_BGR565:
1342 cairo_format = CAIRO_FORMAT_RGB16_565;
1343 swap16 = fb_foreign_endian(format);
1344 break;
1345 #if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 12)
1346 case DRM_FORMAT_ARGB2101010:
1347 case DRM_FORMAT_XRGB2101010:
1348 case DRM_FORMAT_ABGR2101010:
1349 case DRM_FORMAT_XBGR2101010:
1350 cairo_format = CAIRO_FORMAT_RGB30;
1351 swap32 = fb_foreign_endian(format);
1352 break;
1353 #endif
1354 default:
1355 return;
1356 }
1357
1358 /* Cairo uses native byte order, so we may have to byteswap before... */
1359 if (swap16)
1360 byteswap_buffer16(data, width, height, stride);
1361 if (swap32)
1362 byteswap_buffer32(data, width, height, stride);
1363
1364 surface = cairo_image_surface_create_for_data(data,
1365 cairo_format,
1366 width, height,
1367 stride);
1368 cr = cairo_create(surface);
1369 cairo_surface_destroy(surface);
1370
1371 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
1372 for (unsigned x = 0; x < width; x += 250)
1373 for (unsigned y = 0; y < height; y += 250) {
1374 char buf[64];
1375
1376 cairo_move_to(cr, x, y - 20);
1377 cairo_line_to(cr, x, y + 20);
1378 cairo_move_to(cr, x - 20, y);
1379 cairo_line_to(cr, x + 20, y);
1380 cairo_new_sub_path(cr);
1381 cairo_arc(cr, x, y, 10, 0, M_PI * 2);
1382 cairo_set_line_width(cr, 4);
1383 cairo_set_source_rgb(cr, 0, 0, 0);
1384 cairo_stroke_preserve(cr);
1385 cairo_set_source_rgb(cr, 1, 1, 1);
1386 cairo_set_line_width(cr, 2);
1387 cairo_stroke(cr);
1388
1389 snprintf(buf, sizeof buf, "%d, %d", x, y);
1390 cairo_move_to(cr, x + 20, y + 20);
1391 cairo_text_path(cr, buf);
1392 cairo_set_source_rgb(cr, 0, 0, 0);
1393 cairo_stroke_preserve(cr);
1394 cairo_set_source_rgb(cr, 1, 1, 1);
1395 cairo_fill(cr);
1396 }
1397
1398 cairo_destroy(cr);
1399
1400 /* ... and after */
1401 if (swap16)
1402 byteswap_buffer16(data, width, height, stride);
1403 if (swap32)
1404 byteswap_buffer32(data, width, height, stride);
1405 #endif
1406 }
1407
make_tiles_yuv_color(unsigned int x,unsigned int y,unsigned int width)1408 static struct color_yuv make_tiles_yuv_color(unsigned int x, unsigned int y,
1409 unsigned int width)
1410 {
1411 div_t d = div(x+y, width);
1412 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1413 + 0x000a1120 * (d.rem >> 6);
1414 struct color_yuv color =
1415 MAKE_YUV_601((rgb32 >> 16) & 0xff, (rgb32 >> 8) & 0xff,
1416 rgb32 & 0xff);
1417 return color;
1418 }
1419
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)1420 static void fill_tiles_yuv_planar(const struct util_format_info *info,
1421 unsigned char *y_mem, unsigned char *u_mem,
1422 unsigned char *v_mem, unsigned int width,
1423 unsigned int height, unsigned int stride)
1424 {
1425 const struct util_yuv_info *yuv = &info->yuv;
1426 unsigned int cs = yuv->chroma_stride;
1427 unsigned int xsub = yuv->xsub;
1428 unsigned int ysub = yuv->ysub;
1429 unsigned int x;
1430 unsigned int y;
1431
1432 for (y = 0; y < height; ++y) {
1433 for (x = 0; x < width; ++x) {
1434 struct color_yuv color =
1435 make_tiles_yuv_color(x, y, width);
1436
1437 y_mem[x] = color.y;
1438 u_mem[x/xsub*cs] = color.u;
1439 v_mem[x/xsub*cs] = color.v;
1440 }
1441
1442 y_mem += stride;
1443 if ((y + 1) % ysub == 0) {
1444 u_mem += stride * cs / xsub;
1445 v_mem += stride * cs / xsub;
1446 }
1447 }
1448 }
1449
fill_tiles_yuv_planar_10bpp(const struct util_format_info * info,unsigned char * y_mem,unsigned char * uv_mem,unsigned int width,unsigned int height,unsigned int stride)1450 static void fill_tiles_yuv_planar_10bpp(const struct util_format_info *info,
1451 unsigned char *y_mem,
1452 unsigned char *uv_mem,
1453 unsigned int width,
1454 unsigned int height,
1455 unsigned int stride)
1456 {
1457 const struct util_yuv_info *yuv = &info->yuv;
1458 unsigned int cs = yuv->chroma_stride;
1459 unsigned int xsub = yuv->xsub;
1460 unsigned int ysub = yuv->ysub;
1461 unsigned int xstep = cs * xsub;
1462 unsigned int x;
1463 unsigned int y;
1464
1465 for (y = 0; y < height; ++y) {
1466 for (x = 0; x < width; x += 4) {
1467 struct color_yuv a = make_tiles_yuv_color(x+0, y, width);
1468 struct color_yuv b = make_tiles_yuv_color(x+1, y, width);
1469 struct color_yuv c = make_tiles_yuv_color(x+2, y, width);
1470 struct color_yuv d = make_tiles_yuv_color(x+3, y, width);
1471
1472 write_pixels_10bpp(&y_mem[(x * 5) / 4],
1473 a.y << 2, b.y << 2, c.y << 2, d.y << 2);
1474 }
1475 y_mem += stride;
1476 }
1477 for (y = 0; y < height; y += ysub) {
1478 for (x = 0; x < width; x += xstep) {
1479 struct color_yuv a = make_tiles_yuv_color(x+0, y, width);
1480 struct color_yuv b = make_tiles_yuv_color(x+xsub, y, width);
1481
1482 write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
1483 a.u << 2, a.v << 2, b.u << 2, b.v << 2);
1484 }
1485 uv_mem += stride * cs / xsub;
1486 }
1487 }
1488
fill_tiles_yuv_packed(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1489 static void fill_tiles_yuv_packed(const struct util_format_info *info,
1490 void *mem, unsigned int width,
1491 unsigned int height, unsigned int stride)
1492 {
1493 const struct util_yuv_info *yuv = &info->yuv;
1494 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
1495 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
1496 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
1497 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
1498 unsigned int x;
1499 unsigned int y;
1500
1501 for (y = 0; y < height; ++y) {
1502 for (x = 0; x < width; x += 2) {
1503 struct color_yuv color =
1504 make_tiles_yuv_color(x, y, width);
1505
1506 y_mem[2*x] = color.y;
1507 c_mem[2*x+u] = color.u;
1508 y_mem[2*x+2] = color.y;
1509 c_mem[2*x+v] = color.v;
1510 }
1511
1512 y_mem += stride;
1513 c_mem += stride;
1514 }
1515 }
1516
fill_tiles_rgb16(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride,bool fb_be)1517 static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
1518 unsigned int width, unsigned int height,
1519 unsigned int stride, bool fb_be)
1520 {
1521 const struct util_rgb_info *rgb = &info->rgb;
1522 void *mem_base = mem;
1523 unsigned int x, y;
1524
1525 for (y = 0; y < height; ++y) {
1526 for (x = 0; x < width; ++x) {
1527 div_t d = div(x+y, width);
1528 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1529 + 0x000a1120 * (d.rem >> 6);
1530 uint16_t color =
1531 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
1532 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1533 255);
1534
1535 ((uint16_t *)mem)[x] = cpu_to_fb16(color);
1536 }
1537 mem += stride;
1538 }
1539
1540 make_pwetty(mem_base, width, height, stride, info->format);
1541 }
1542
fill_tiles_rgb24(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1543 static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
1544 unsigned int width, unsigned int height,
1545 unsigned int stride)
1546 {
1547 const struct util_rgb_info *rgb = &info->rgb;
1548 unsigned int x, y;
1549
1550 for (y = 0; y < height; ++y) {
1551 for (x = 0; x < width; ++x) {
1552 div_t d = div(x+y, width);
1553 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1554 + 0x000a1120 * (d.rem >> 6);
1555 struct color_rgb24 color =
1556 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
1557 (rgb32 >> 8) & 0xff, rgb32 & 0xff);
1558
1559 ((struct color_rgb24 *)mem)[x] = color;
1560 }
1561 mem += stride;
1562 }
1563 }
1564
fill_tiles_rgb32(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1565 static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
1566 unsigned int width, unsigned int height,
1567 unsigned int stride)
1568 {
1569 const struct util_rgb_info *rgb = &info->rgb;
1570 void *mem_base = mem;
1571 unsigned int x, y;
1572
1573 for (y = 0; y < height; ++y) {
1574 for (x = 0; x < width; ++x) {
1575 div_t d = div(x+y, width);
1576 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1577 + 0x000a1120 * (d.rem >> 6);
1578 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
1579 uint32_t color =
1580 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
1581 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1582 alpha);
1583
1584 ((uint32_t *)mem)[x] = cpu_to_le32(color);
1585 }
1586 mem += stride;
1587 }
1588
1589 make_pwetty(mem_base, width, height, stride, info->format);
1590 }
1591
fill_tiles_rgb16fp(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1592 static void fill_tiles_rgb16fp(const struct util_format_info *info, void *mem,
1593 unsigned int width, unsigned int height,
1594 unsigned int stride)
1595 {
1596 const struct util_rgb_info *rgb = &info->rgb;
1597 unsigned int x, y;
1598
1599 /* TODO: Give this actual fp16 precision */
1600 for (y = 0; y < height; ++y) {
1601 for (x = 0; x < width; ++x) {
1602 div_t d = div(x+y, width);
1603 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1604 + 0x000a1120 * (d.rem >> 6);
1605 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
1606 uint64_t color =
1607 MAKE_RGBA8FP16(rgb, (rgb32 >> 16) & 0xff,
1608 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1609 alpha);
1610
1611 ((uint64_t *)mem)[x] = color;
1612 }
1613 mem += stride;
1614 }
1615 }
1616
fill_tiles(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1617 static void fill_tiles(const struct util_format_info *info, void *planes[3],
1618 unsigned int width, unsigned int height,
1619 unsigned int stride)
1620 {
1621 unsigned char *u, *v;
1622
1623 switch (info->format) {
1624 case DRM_FORMAT_UYVY:
1625 case DRM_FORMAT_VYUY:
1626 case DRM_FORMAT_YUYV:
1627 case DRM_FORMAT_YVYU:
1628 return fill_tiles_yuv_packed(info, planes[0],
1629 width, height, stride);
1630
1631 case DRM_FORMAT_NV12:
1632 case DRM_FORMAT_NV21:
1633 case DRM_FORMAT_NV16:
1634 case DRM_FORMAT_NV61:
1635 case DRM_FORMAT_NV24:
1636 case DRM_FORMAT_NV42:
1637 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
1638 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
1639 return fill_tiles_yuv_planar(info, planes[0], u, v,
1640 width, height, stride);
1641
1642 case DRM_FORMAT_NV15:
1643 case DRM_FORMAT_NV20:
1644 case DRM_FORMAT_NV30:
1645 return fill_tiles_yuv_planar_10bpp(info, planes[0], planes[1],
1646 width, height, stride);
1647
1648 case DRM_FORMAT_YUV420:
1649 return fill_tiles_yuv_planar(info, planes[0], planes[1],
1650 planes[2], width, height, stride);
1651
1652 case DRM_FORMAT_YVU420:
1653 return fill_tiles_yuv_planar(info, planes[0], planes[2],
1654 planes[1], width, height, stride);
1655
1656 case DRM_FORMAT_ARGB4444:
1657 case DRM_FORMAT_XRGB4444:
1658 case DRM_FORMAT_ABGR4444:
1659 case DRM_FORMAT_XBGR4444:
1660 case DRM_FORMAT_RGBA4444:
1661 case DRM_FORMAT_RGBX4444:
1662 case DRM_FORMAT_BGRA4444:
1663 case DRM_FORMAT_BGRX4444:
1664 case DRM_FORMAT_RGB565:
1665 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
1666 case DRM_FORMAT_BGR565:
1667 case DRM_FORMAT_ARGB1555:
1668 case DRM_FORMAT_XRGB1555:
1669 case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
1670 case DRM_FORMAT_ABGR1555:
1671 case DRM_FORMAT_XBGR1555:
1672 case DRM_FORMAT_RGBA5551:
1673 case DRM_FORMAT_RGBX5551:
1674 case DRM_FORMAT_BGRA5551:
1675 case DRM_FORMAT_BGRX5551:
1676 return fill_tiles_rgb16(info, planes[0],
1677 width, height, stride,
1678 info->format & DRM_FORMAT_BIG_ENDIAN);
1679
1680 case DRM_FORMAT_BGR888:
1681 case DRM_FORMAT_RGB888:
1682 return fill_tiles_rgb24(info, planes[0],
1683 width, height, stride);
1684 case DRM_FORMAT_ARGB8888:
1685 case DRM_FORMAT_XRGB8888:
1686 case DRM_FORMAT_ABGR8888:
1687 case DRM_FORMAT_XBGR8888:
1688 case DRM_FORMAT_RGBA8888:
1689 case DRM_FORMAT_RGBX8888:
1690 case DRM_FORMAT_BGRA8888:
1691 case DRM_FORMAT_BGRX8888:
1692 case DRM_FORMAT_ARGB2101010:
1693 case DRM_FORMAT_XRGB2101010:
1694 case DRM_FORMAT_ABGR2101010:
1695 case DRM_FORMAT_XBGR2101010:
1696 case DRM_FORMAT_RGBA1010102:
1697 case DRM_FORMAT_RGBX1010102:
1698 case DRM_FORMAT_BGRA1010102:
1699 case DRM_FORMAT_BGRX1010102:
1700 return fill_tiles_rgb32(info, planes[0],
1701 width, height, stride);
1702
1703 case DRM_FORMAT_XRGB16161616F:
1704 case DRM_FORMAT_XBGR16161616F:
1705 case DRM_FORMAT_ARGB16161616F:
1706 case DRM_FORMAT_ABGR16161616F:
1707 return fill_tiles_rgb16fp(info, planes[0],
1708 width, height, stride);
1709 }
1710 }
1711
fill_plain(const struct util_format_info * info,void * planes[3],unsigned int height,unsigned int stride)1712 static void fill_plain(const struct util_format_info *info, void *planes[3],
1713 unsigned int height,
1714 unsigned int stride)
1715 {
1716 switch (info->format) {
1717 case DRM_FORMAT_XRGB16161616F:
1718 case DRM_FORMAT_XBGR16161616F:
1719 case DRM_FORMAT_ARGB16161616F:
1720 case DRM_FORMAT_ABGR16161616F:
1721 /* 0x3838 = 0.5273 */
1722 memset(planes[0], 0x38, stride * height);
1723 break;
1724 default:
1725 memset(planes[0], 0x77, stride * height);
1726 break;
1727 }
1728 }
1729
fill_gradient_rgb32(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)1730 static void fill_gradient_rgb32(const struct util_rgb_info *rgb,
1731 void *mem,
1732 unsigned int width, unsigned int height,
1733 unsigned int stride)
1734 {
1735 unsigned int i, j;
1736
1737 for (i = 0; i < height / 2; i++) {
1738 uint32_t *row = mem;
1739
1740 for (j = 0; j < width / 2; j++) {
1741 uint32_t value = MAKE_RGBA10(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1742 row[2*j] = row[2*j+1] = cpu_to_le32(value);
1743 }
1744 mem += stride;
1745 }
1746
1747 for (; i < height; i++) {
1748 uint32_t *row = mem;
1749
1750 for (j = 0; j < width / 2; j++) {
1751 uint32_t value = MAKE_RGBA10(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1752 row[2*j] = row[2*j+1] = cpu_to_le32(value);
1753 }
1754 mem += stride;
1755 }
1756 }
1757
fill_gradient_rgb16fp(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)1758 static void fill_gradient_rgb16fp(const struct util_rgb_info *rgb,
1759 void *mem,
1760 unsigned int width, unsigned int height,
1761 unsigned int stride)
1762 {
1763 unsigned int i, j;
1764
1765 for (i = 0; i < height / 2; i++) {
1766 uint64_t *row = mem;
1767
1768 for (j = 0; j < width / 2; j++) {
1769 uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1770 row[2*j] = row[2*j+1] = value;
1771 }
1772 mem += stride;
1773 }
1774
1775 for (; i < height; i++) {
1776 uint64_t *row = mem;
1777
1778 for (j = 0; j < width / 2; j++) {
1779 uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1780 row[2*j] = row[2*j+1] = value;
1781 }
1782 mem += stride;
1783 }
1784 }
1785
1786 /* The gradient pattern creates two horizontal gray gradients, split
1787 * into two halves. The top half has 10bpc precision, the bottom half
1788 * has 8bpc precision. When using with a 10bpc fb format, there are 3
1789 * possible outcomes:
1790 *
1791 * - Pixel data is encoded as 8bpc to the display, no dithering. This
1792 * would lead to the top and bottom halves looking identical.
1793 *
1794 * - Pixel data is encoded as 8bpc to the display, with dithering. This
1795 * would lead to there being a visible difference between the two halves,
1796 * but the top half would look a little speck-y due to the dithering.
1797 *
1798 * - Pixel data is encoded at 10bpc+ to the display (which implies
1799 * the display is able to show this level of depth). This should
1800 * lead to the top half being a very clean gradient, and visibly different
1801 * from the bottom half.
1802 *
1803 * Once we support additional fb formats, this approach could be extended
1804 * to distinguish even higher bpc precisions.
1805 *
1806 * Note that due to practical size considerations, for the screens
1807 * where this matters, the pattern actually emits stripes 2-pixels
1808 * wide for each gradient color. Otherwise the difference may be a bit
1809 * hard to notice.
1810 */
fill_gradient(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1811 static void fill_gradient(const struct util_format_info *info, void *planes[3],
1812 unsigned int width, unsigned int height,
1813 unsigned int stride)
1814 {
1815 switch (info->format) {
1816 case DRM_FORMAT_ARGB8888:
1817 case DRM_FORMAT_XRGB8888:
1818 case DRM_FORMAT_ABGR8888:
1819 case DRM_FORMAT_XBGR8888:
1820 case DRM_FORMAT_RGBA8888:
1821 case DRM_FORMAT_RGBX8888:
1822 case DRM_FORMAT_BGRA8888:
1823 case DRM_FORMAT_BGRX8888:
1824 case DRM_FORMAT_ARGB2101010:
1825 case DRM_FORMAT_XRGB2101010:
1826 case DRM_FORMAT_ABGR2101010:
1827 case DRM_FORMAT_XBGR2101010:
1828 case DRM_FORMAT_RGBA1010102:
1829 case DRM_FORMAT_RGBX1010102:
1830 case DRM_FORMAT_BGRA1010102:
1831 case DRM_FORMAT_BGRX1010102:
1832 return fill_gradient_rgb32(&info->rgb, planes[0],
1833 width, height, stride);
1834
1835 case DRM_FORMAT_XRGB16161616F:
1836 case DRM_FORMAT_XBGR16161616F:
1837 case DRM_FORMAT_ARGB16161616F:
1838 case DRM_FORMAT_ABGR16161616F:
1839 return fill_gradient_rgb16fp(&info->rgb, planes[0],
1840 width, height, stride);
1841 }
1842 }
1843
1844 /*
1845 * util_fill_pattern - Fill a buffer with a test pattern
1846 * @format: Pixel format
1847 * @pattern: Test pattern
1848 * @planes: Array of buffers
1849 * @width: Width in pixels
1850 * @height: Height in pixels
1851 * @stride: Line stride (pitch) in bytes
1852 *
1853 * Fill the buffers with the test pattern specified by the pattern parameter.
1854 * Supported formats vary depending on the selected pattern.
1855 */
util_fill_pattern(uint32_t format,enum util_fill_pattern pattern,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1856 void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
1857 void *planes[3], unsigned int width,
1858 unsigned int height, unsigned int stride)
1859 {
1860 const struct util_format_info *info;
1861
1862 info = util_format_info_find(format);
1863 if (info == NULL)
1864 return;
1865
1866 switch (pattern) {
1867 case UTIL_PATTERN_TILES:
1868 return fill_tiles(info, planes, width, height, stride);
1869
1870 case UTIL_PATTERN_SMPTE:
1871 return fill_smpte(info, planes, width, height, stride);
1872
1873 case UTIL_PATTERN_PLAIN:
1874 return fill_plain(info, planes, height, stride);
1875
1876 case UTIL_PATTERN_GRADIENT:
1877 return fill_gradient(info, planes, width, height, stride);
1878
1879 default:
1880 printf("Error: unsupported test pattern %u.\n", pattern);
1881 break;
1882 }
1883 }
1884
1885 static const char *pattern_names[] = {
1886 [UTIL_PATTERN_TILES] = "tiles",
1887 [UTIL_PATTERN_SMPTE] = "smpte",
1888 [UTIL_PATTERN_PLAIN] = "plain",
1889 [UTIL_PATTERN_GRADIENT] = "gradient",
1890 };
1891
util_pattern_enum(const char * name)1892 enum util_fill_pattern util_pattern_enum(const char *name)
1893 {
1894 unsigned int i;
1895
1896 for (i = 0; i < ARRAY_SIZE(pattern_names); i++)
1897 if (!strcmp(pattern_names[i], name))
1898 return (enum util_fill_pattern)i;
1899
1900 printf("Error: unsupported test pattern %s.\n", name);
1901 return UTIL_PATTERN_SMPTE;
1902 }
1903