1 /*
2 * Copyright 2008 Tungsten Graphics
3 * Jakob Bornecrantz <[email protected]>
4 * Copyright 2008 Intel Corporation
5 * Jesse Barnes <[email protected]>
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 case DRM_FORMAT_YUV422:
1233 case DRM_FORMAT_YUV444:
1234 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
1235 planes[2], width, height, stride);
1236
1237 case DRM_FORMAT_YVU420:
1238 case DRM_FORMAT_YVU422:
1239 case DRM_FORMAT_YVU444:
1240 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
1241 planes[1], width, height, stride);
1242
1243 case DRM_FORMAT_ARGB4444:
1244 case DRM_FORMAT_XRGB4444:
1245 case DRM_FORMAT_ABGR4444:
1246 case DRM_FORMAT_XBGR4444:
1247 case DRM_FORMAT_RGBA4444:
1248 case DRM_FORMAT_RGBX4444:
1249 case DRM_FORMAT_BGRA4444:
1250 case DRM_FORMAT_BGRX4444:
1251 case DRM_FORMAT_RGB565:
1252 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
1253 case DRM_FORMAT_BGR565:
1254 case DRM_FORMAT_ARGB1555:
1255 case DRM_FORMAT_XRGB1555:
1256 case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
1257 case DRM_FORMAT_ABGR1555:
1258 case DRM_FORMAT_XBGR1555:
1259 case DRM_FORMAT_RGBA5551:
1260 case DRM_FORMAT_RGBX5551:
1261 case DRM_FORMAT_BGRA5551:
1262 case DRM_FORMAT_BGRX5551:
1263 return fill_smpte_rgb16(&info->rgb, planes[0],
1264 width, height, stride,
1265 info->format & DRM_FORMAT_BIG_ENDIAN);
1266
1267 case DRM_FORMAT_BGR888:
1268 case DRM_FORMAT_RGB888:
1269 return fill_smpte_rgb24(&info->rgb, planes[0],
1270 width, height, stride);
1271 case DRM_FORMAT_ARGB8888:
1272 case DRM_FORMAT_XRGB8888:
1273 case DRM_FORMAT_ABGR8888:
1274 case DRM_FORMAT_XBGR8888:
1275 case DRM_FORMAT_RGBA8888:
1276 case DRM_FORMAT_RGBX8888:
1277 case DRM_FORMAT_BGRA8888:
1278 case DRM_FORMAT_BGRX8888:
1279 case DRM_FORMAT_ARGB2101010:
1280 case DRM_FORMAT_XRGB2101010:
1281 case DRM_FORMAT_ABGR2101010:
1282 case DRM_FORMAT_XBGR2101010:
1283 case DRM_FORMAT_RGBA1010102:
1284 case DRM_FORMAT_RGBX1010102:
1285 case DRM_FORMAT_BGRA1010102:
1286 case DRM_FORMAT_BGRX1010102:
1287 return fill_smpte_rgb32(&info->rgb, planes[0],
1288 width, height, stride);
1289
1290 case DRM_FORMAT_XRGB16161616F:
1291 case DRM_FORMAT_XBGR16161616F:
1292 case DRM_FORMAT_ARGB16161616F:
1293 case DRM_FORMAT_ABGR16161616F:
1294 return fill_smpte_rgb16fp(&info->rgb, planes[0],
1295 width, height, stride);
1296 }
1297 }
1298
1299 #if HAVE_CAIRO
byteswap_buffer16(void * mem,unsigned int width,unsigned int height,unsigned int stride)1300 static void byteswap_buffer16(void *mem, unsigned int width, unsigned int height,
1301 unsigned int stride)
1302 {
1303 unsigned int x, y;
1304
1305 for (y = 0; y < height; ++y) {
1306 for (x = 0; x < width; ++x)
1307 ((uint16_t *)mem)[x] = swap16(((uint16_t *)mem)[x]);
1308 mem += stride;
1309 }
1310 }
1311
byteswap_buffer32(void * mem,unsigned int width,unsigned int height,unsigned int stride)1312 static void byteswap_buffer32(void *mem, unsigned int width, unsigned int height,
1313 unsigned int stride)
1314 {
1315 unsigned int x, y;
1316
1317 for (y = 0; y < height; ++y) {
1318 for (x = 0; x < width; ++x)
1319 ((uint32_t *)mem)[x] = swap32(((uint32_t *)mem)[x]);
1320 mem += stride;
1321 }
1322 }
1323 #endif
1324
make_pwetty(void * data,unsigned int width,unsigned int height,unsigned int stride,uint32_t format)1325 static void make_pwetty(void *data, unsigned int width, unsigned int height,
1326 unsigned int stride, uint32_t format)
1327 {
1328 #if HAVE_CAIRO
1329 cairo_surface_t *surface;
1330 cairo_t *cr;
1331 cairo_format_t cairo_format;
1332 bool swap16 = false;
1333 bool swap32 = false;
1334
1335 /* we can ignore the order of R,G,B channels */
1336 switch (format) {
1337 case DRM_FORMAT_XRGB8888:
1338 case DRM_FORMAT_ARGB8888:
1339 case DRM_FORMAT_XBGR8888:
1340 case DRM_FORMAT_ABGR8888:
1341 cairo_format = CAIRO_FORMAT_ARGB32;
1342 break;
1343 case DRM_FORMAT_RGB565:
1344 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
1345 case DRM_FORMAT_BGR565:
1346 cairo_format = CAIRO_FORMAT_RGB16_565;
1347 swap16 = fb_foreign_endian(format);
1348 break;
1349 #if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 12)
1350 case DRM_FORMAT_ARGB2101010:
1351 case DRM_FORMAT_XRGB2101010:
1352 case DRM_FORMAT_ABGR2101010:
1353 case DRM_FORMAT_XBGR2101010:
1354 cairo_format = CAIRO_FORMAT_RGB30;
1355 swap32 = fb_foreign_endian(format);
1356 break;
1357 #endif
1358 default:
1359 return;
1360 }
1361
1362 /* Cairo uses native byte order, so we may have to byteswap before... */
1363 if (swap16)
1364 byteswap_buffer16(data, width, height, stride);
1365 if (swap32)
1366 byteswap_buffer32(data, width, height, stride);
1367
1368 surface = cairo_image_surface_create_for_data(data,
1369 cairo_format,
1370 width, height,
1371 stride);
1372 cr = cairo_create(surface);
1373 cairo_surface_destroy(surface);
1374
1375 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
1376 for (unsigned x = 0; x < width; x += 250)
1377 for (unsigned y = 0; y < height; y += 250) {
1378 char buf[64];
1379
1380 cairo_move_to(cr, x, y - 20);
1381 cairo_line_to(cr, x, y + 20);
1382 cairo_move_to(cr, x - 20, y);
1383 cairo_line_to(cr, x + 20, y);
1384 cairo_new_sub_path(cr);
1385 cairo_arc(cr, x, y, 10, 0, M_PI * 2);
1386 cairo_set_line_width(cr, 4);
1387 cairo_set_source_rgb(cr, 0, 0, 0);
1388 cairo_stroke_preserve(cr);
1389 cairo_set_source_rgb(cr, 1, 1, 1);
1390 cairo_set_line_width(cr, 2);
1391 cairo_stroke(cr);
1392
1393 snprintf(buf, sizeof buf, "%d, %d", x, y);
1394 cairo_move_to(cr, x + 20, y + 20);
1395 cairo_text_path(cr, buf);
1396 cairo_set_source_rgb(cr, 0, 0, 0);
1397 cairo_stroke_preserve(cr);
1398 cairo_set_source_rgb(cr, 1, 1, 1);
1399 cairo_fill(cr);
1400 }
1401
1402 cairo_destroy(cr);
1403
1404 /* ... and after */
1405 if (swap16)
1406 byteswap_buffer16(data, width, height, stride);
1407 if (swap32)
1408 byteswap_buffer32(data, width, height, stride);
1409 #endif
1410 }
1411
make_tiles_yuv_color(unsigned int x,unsigned int y,unsigned int width)1412 static struct color_yuv make_tiles_yuv_color(unsigned int x, unsigned int y,
1413 unsigned int width)
1414 {
1415 div_t d = div(x+y, width);
1416 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1417 + 0x000a1120 * (d.rem >> 6);
1418 struct color_yuv color =
1419 MAKE_YUV_601((rgb32 >> 16) & 0xff, (rgb32 >> 8) & 0xff,
1420 rgb32 & 0xff);
1421 return color;
1422 }
1423
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)1424 static void fill_tiles_yuv_planar(const struct util_format_info *info,
1425 unsigned char *y_mem, unsigned char *u_mem,
1426 unsigned char *v_mem, unsigned int width,
1427 unsigned int height, unsigned int stride)
1428 {
1429 const struct util_yuv_info *yuv = &info->yuv;
1430 unsigned int cs = yuv->chroma_stride;
1431 unsigned int xsub = yuv->xsub;
1432 unsigned int ysub = yuv->ysub;
1433 unsigned int x;
1434 unsigned int y;
1435
1436 for (y = 0; y < height; ++y) {
1437 for (x = 0; x < width; ++x) {
1438 struct color_yuv color =
1439 make_tiles_yuv_color(x, y, width);
1440
1441 y_mem[x] = color.y;
1442 u_mem[x/xsub*cs] = color.u;
1443 v_mem[x/xsub*cs] = color.v;
1444 }
1445
1446 y_mem += stride;
1447 if ((y + 1) % ysub == 0) {
1448 u_mem += stride * cs / xsub;
1449 v_mem += stride * cs / xsub;
1450 }
1451 }
1452 }
1453
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)1454 static void fill_tiles_yuv_planar_10bpp(const struct util_format_info *info,
1455 unsigned char *y_mem,
1456 unsigned char *uv_mem,
1457 unsigned int width,
1458 unsigned int height,
1459 unsigned int stride)
1460 {
1461 const struct util_yuv_info *yuv = &info->yuv;
1462 unsigned int cs = yuv->chroma_stride;
1463 unsigned int xsub = yuv->xsub;
1464 unsigned int ysub = yuv->ysub;
1465 unsigned int xstep = cs * xsub;
1466 unsigned int x;
1467 unsigned int y;
1468
1469 for (y = 0; y < height; ++y) {
1470 for (x = 0; x < width; x += 4) {
1471 struct color_yuv a = make_tiles_yuv_color(x+0, y, width);
1472 struct color_yuv b = make_tiles_yuv_color(x+1, y, width);
1473 struct color_yuv c = make_tiles_yuv_color(x+2, y, width);
1474 struct color_yuv d = make_tiles_yuv_color(x+3, y, width);
1475
1476 write_pixels_10bpp(&y_mem[(x * 5) / 4],
1477 a.y << 2, b.y << 2, c.y << 2, d.y << 2);
1478 }
1479 y_mem += stride;
1480 }
1481 for (y = 0; y < height; y += ysub) {
1482 for (x = 0; x < width; x += xstep) {
1483 struct color_yuv a = make_tiles_yuv_color(x+0, y, width);
1484 struct color_yuv b = make_tiles_yuv_color(x+xsub, y, width);
1485
1486 write_pixels_10bpp(&uv_mem[(x * 5) / xstep],
1487 a.u << 2, a.v << 2, b.u << 2, b.v << 2);
1488 }
1489 uv_mem += stride * cs / xsub;
1490 }
1491 }
1492
fill_tiles_yuv_packed(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1493 static void fill_tiles_yuv_packed(const struct util_format_info *info,
1494 void *mem, unsigned int width,
1495 unsigned int height, unsigned int stride)
1496 {
1497 const struct util_yuv_info *yuv = &info->yuv;
1498 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
1499 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
1500 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
1501 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
1502 unsigned int x;
1503 unsigned int y;
1504
1505 for (y = 0; y < height; ++y) {
1506 for (x = 0; x < width; x += 2) {
1507 struct color_yuv color =
1508 make_tiles_yuv_color(x, y, width);
1509
1510 y_mem[2*x] = color.y;
1511 c_mem[2*x+u] = color.u;
1512 y_mem[2*x+2] = color.y;
1513 c_mem[2*x+v] = color.v;
1514 }
1515
1516 y_mem += stride;
1517 c_mem += stride;
1518 }
1519 }
1520
fill_tiles_rgb16(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride,bool fb_be)1521 static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
1522 unsigned int width, unsigned int height,
1523 unsigned int stride, bool fb_be)
1524 {
1525 const struct util_rgb_info *rgb = &info->rgb;
1526 void *mem_base = mem;
1527 unsigned int x, y;
1528
1529 for (y = 0; y < height; ++y) {
1530 for (x = 0; x < width; ++x) {
1531 div_t d = div(x+y, width);
1532 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1533 + 0x000a1120 * (d.rem >> 6);
1534 uint16_t color =
1535 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
1536 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1537 255);
1538
1539 ((uint16_t *)mem)[x] = cpu_to_fb16(color);
1540 }
1541 mem += stride;
1542 }
1543
1544 make_pwetty(mem_base, width, height, stride, info->format);
1545 }
1546
fill_tiles_rgb24(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1547 static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
1548 unsigned int width, unsigned int height,
1549 unsigned int stride)
1550 {
1551 const struct util_rgb_info *rgb = &info->rgb;
1552 unsigned int x, y;
1553
1554 for (y = 0; y < height; ++y) {
1555 for (x = 0; x < width; ++x) {
1556 div_t d = div(x+y, width);
1557 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1558 + 0x000a1120 * (d.rem >> 6);
1559 struct color_rgb24 color =
1560 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
1561 (rgb32 >> 8) & 0xff, rgb32 & 0xff);
1562
1563 ((struct color_rgb24 *)mem)[x] = color;
1564 }
1565 mem += stride;
1566 }
1567 }
1568
fill_tiles_rgb32(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1569 static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
1570 unsigned int width, unsigned int height,
1571 unsigned int stride)
1572 {
1573 const struct util_rgb_info *rgb = &info->rgb;
1574 void *mem_base = mem;
1575 unsigned int x, y;
1576
1577 for (y = 0; y < height; ++y) {
1578 for (x = 0; x < width; ++x) {
1579 div_t d = div(x+y, width);
1580 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1581 + 0x000a1120 * (d.rem >> 6);
1582 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
1583 uint32_t color =
1584 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
1585 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1586 alpha);
1587
1588 ((uint32_t *)mem)[x] = cpu_to_le32(color);
1589 }
1590 mem += stride;
1591 }
1592
1593 make_pwetty(mem_base, width, height, stride, info->format);
1594 }
1595
fill_tiles_rgb16fp(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)1596 static void fill_tiles_rgb16fp(const struct util_format_info *info, void *mem,
1597 unsigned int width, unsigned int height,
1598 unsigned int stride)
1599 {
1600 const struct util_rgb_info *rgb = &info->rgb;
1601 unsigned int x, y;
1602
1603 /* TODO: Give this actual fp16 precision */
1604 for (y = 0; y < height; ++y) {
1605 for (x = 0; x < width; ++x) {
1606 div_t d = div(x+y, width);
1607 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
1608 + 0x000a1120 * (d.rem >> 6);
1609 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
1610 uint64_t color =
1611 MAKE_RGBA8FP16(rgb, (rgb32 >> 16) & 0xff,
1612 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
1613 alpha);
1614
1615 ((uint64_t *)mem)[x] = color;
1616 }
1617 mem += stride;
1618 }
1619 }
1620
fill_tiles(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1621 static void fill_tiles(const struct util_format_info *info, void *planes[3],
1622 unsigned int width, unsigned int height,
1623 unsigned int stride)
1624 {
1625 unsigned char *u, *v;
1626
1627 switch (info->format) {
1628 case DRM_FORMAT_UYVY:
1629 case DRM_FORMAT_VYUY:
1630 case DRM_FORMAT_YUYV:
1631 case DRM_FORMAT_YVYU:
1632 return fill_tiles_yuv_packed(info, planes[0],
1633 width, height, stride);
1634
1635 case DRM_FORMAT_NV12:
1636 case DRM_FORMAT_NV21:
1637 case DRM_FORMAT_NV16:
1638 case DRM_FORMAT_NV61:
1639 case DRM_FORMAT_NV24:
1640 case DRM_FORMAT_NV42:
1641 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
1642 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
1643 return fill_tiles_yuv_planar(info, planes[0], u, v,
1644 width, height, stride);
1645
1646 case DRM_FORMAT_NV15:
1647 case DRM_FORMAT_NV20:
1648 case DRM_FORMAT_NV30:
1649 return fill_tiles_yuv_planar_10bpp(info, planes[0], planes[1],
1650 width, height, stride);
1651
1652 case DRM_FORMAT_YUV420:
1653 case DRM_FORMAT_YUV422:
1654 case DRM_FORMAT_YUV444:
1655 return fill_tiles_yuv_planar(info, planes[0], planes[1],
1656 planes[2], width, height, stride);
1657
1658 case DRM_FORMAT_YVU420:
1659 case DRM_FORMAT_YVU422:
1660 case DRM_FORMAT_YVU444:
1661 return fill_tiles_yuv_planar(info, planes[0], planes[2],
1662 planes[1], width, height, stride);
1663
1664 case DRM_FORMAT_ARGB4444:
1665 case DRM_FORMAT_XRGB4444:
1666 case DRM_FORMAT_ABGR4444:
1667 case DRM_FORMAT_XBGR4444:
1668 case DRM_FORMAT_RGBA4444:
1669 case DRM_FORMAT_RGBX4444:
1670 case DRM_FORMAT_BGRA4444:
1671 case DRM_FORMAT_BGRX4444:
1672 case DRM_FORMAT_RGB565:
1673 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
1674 case DRM_FORMAT_BGR565:
1675 case DRM_FORMAT_ARGB1555:
1676 case DRM_FORMAT_XRGB1555:
1677 case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
1678 case DRM_FORMAT_ABGR1555:
1679 case DRM_FORMAT_XBGR1555:
1680 case DRM_FORMAT_RGBA5551:
1681 case DRM_FORMAT_RGBX5551:
1682 case DRM_FORMAT_BGRA5551:
1683 case DRM_FORMAT_BGRX5551:
1684 return fill_tiles_rgb16(info, planes[0],
1685 width, height, stride,
1686 info->format & DRM_FORMAT_BIG_ENDIAN);
1687
1688 case DRM_FORMAT_BGR888:
1689 case DRM_FORMAT_RGB888:
1690 return fill_tiles_rgb24(info, planes[0],
1691 width, height, stride);
1692 case DRM_FORMAT_ARGB8888:
1693 case DRM_FORMAT_XRGB8888:
1694 case DRM_FORMAT_ABGR8888:
1695 case DRM_FORMAT_XBGR8888:
1696 case DRM_FORMAT_RGBA8888:
1697 case DRM_FORMAT_RGBX8888:
1698 case DRM_FORMAT_BGRA8888:
1699 case DRM_FORMAT_BGRX8888:
1700 case DRM_FORMAT_ARGB2101010:
1701 case DRM_FORMAT_XRGB2101010:
1702 case DRM_FORMAT_ABGR2101010:
1703 case DRM_FORMAT_XBGR2101010:
1704 case DRM_FORMAT_RGBA1010102:
1705 case DRM_FORMAT_RGBX1010102:
1706 case DRM_FORMAT_BGRA1010102:
1707 case DRM_FORMAT_BGRX1010102:
1708 return fill_tiles_rgb32(info, planes[0],
1709 width, height, stride);
1710
1711 case DRM_FORMAT_XRGB16161616F:
1712 case DRM_FORMAT_XBGR16161616F:
1713 case DRM_FORMAT_ARGB16161616F:
1714 case DRM_FORMAT_ABGR16161616F:
1715 return fill_tiles_rgb16fp(info, planes[0],
1716 width, height, stride);
1717 }
1718 }
1719
fill_plain(const struct util_format_info * info,void * planes[3],unsigned int height,unsigned int stride)1720 static void fill_plain(const struct util_format_info *info, void *planes[3],
1721 unsigned int height,
1722 unsigned int stride)
1723 {
1724 switch (info->format) {
1725 case DRM_FORMAT_XRGB16161616F:
1726 case DRM_FORMAT_XBGR16161616F:
1727 case DRM_FORMAT_ARGB16161616F:
1728 case DRM_FORMAT_ABGR16161616F:
1729 /* 0x3838 = 0.5273 */
1730 memset(planes[0], 0x38, stride * height);
1731 break;
1732 default:
1733 memset(planes[0], 0x77, stride * height);
1734 break;
1735 }
1736 }
1737
fill_gradient_rgb32(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)1738 static void fill_gradient_rgb32(const struct util_rgb_info *rgb,
1739 void *mem,
1740 unsigned int width, unsigned int height,
1741 unsigned int stride)
1742 {
1743 unsigned int i, j;
1744
1745 for (i = 0; i < height / 2; i++) {
1746 uint32_t *row = mem;
1747
1748 for (j = 0; j < width / 2; j++) {
1749 uint32_t value = MAKE_RGBA10(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1750 row[2*j] = row[2*j+1] = cpu_to_le32(value);
1751 }
1752 mem += stride;
1753 }
1754
1755 for (; i < height; i++) {
1756 uint32_t *row = mem;
1757
1758 for (j = 0; j < width / 2; j++) {
1759 uint32_t value = MAKE_RGBA10(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1760 row[2*j] = row[2*j+1] = cpu_to_le32(value);
1761 }
1762 mem += stride;
1763 }
1764 }
1765
fill_gradient_rgb16fp(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)1766 static void fill_gradient_rgb16fp(const struct util_rgb_info *rgb,
1767 void *mem,
1768 unsigned int width, unsigned int height,
1769 unsigned int stride)
1770 {
1771 unsigned int i, j;
1772
1773 for (i = 0; i < height / 2; i++) {
1774 uint64_t *row = mem;
1775
1776 for (j = 0; j < width / 2; j++) {
1777 uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3ff, j & 0x3ff, j & 0x3ff, 0);
1778 row[2*j] = row[2*j+1] = value;
1779 }
1780 mem += stride;
1781 }
1782
1783 for (; i < height; i++) {
1784 uint64_t *row = mem;
1785
1786 for (j = 0; j < width / 2; j++) {
1787 uint64_t value = MAKE_RGBA10FP16(rgb, j & 0x3fc, j & 0x3fc, j & 0x3fc, 0);
1788 row[2*j] = row[2*j+1] = value;
1789 }
1790 mem += stride;
1791 }
1792 }
1793
1794 /* The gradient pattern creates two horizontal gray gradients, split
1795 * into two halves. The top half has 10bpc precision, the bottom half
1796 * has 8bpc precision. When using with a 10bpc fb format, there are 3
1797 * possible outcomes:
1798 *
1799 * - Pixel data is encoded as 8bpc to the display, no dithering. This
1800 * would lead to the top and bottom halves looking identical.
1801 *
1802 * - Pixel data is encoded as 8bpc to the display, with dithering. This
1803 * would lead to there being a visible difference between the two halves,
1804 * but the top half would look a little speck-y due to the dithering.
1805 *
1806 * - Pixel data is encoded at 10bpc+ to the display (which implies
1807 * the display is able to show this level of depth). This should
1808 * lead to the top half being a very clean gradient, and visibly different
1809 * from the bottom half.
1810 *
1811 * Once we support additional fb formats, this approach could be extended
1812 * to distinguish even higher bpc precisions.
1813 *
1814 * Note that due to practical size considerations, for the screens
1815 * where this matters, the pattern actually emits stripes 2-pixels
1816 * wide for each gradient color. Otherwise the difference may be a bit
1817 * hard to notice.
1818 */
fill_gradient(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1819 static void fill_gradient(const struct util_format_info *info, void *planes[3],
1820 unsigned int width, unsigned int height,
1821 unsigned int stride)
1822 {
1823 switch (info->format) {
1824 case DRM_FORMAT_ARGB8888:
1825 case DRM_FORMAT_XRGB8888:
1826 case DRM_FORMAT_ABGR8888:
1827 case DRM_FORMAT_XBGR8888:
1828 case DRM_FORMAT_RGBA8888:
1829 case DRM_FORMAT_RGBX8888:
1830 case DRM_FORMAT_BGRA8888:
1831 case DRM_FORMAT_BGRX8888:
1832 case DRM_FORMAT_ARGB2101010:
1833 case DRM_FORMAT_XRGB2101010:
1834 case DRM_FORMAT_ABGR2101010:
1835 case DRM_FORMAT_XBGR2101010:
1836 case DRM_FORMAT_RGBA1010102:
1837 case DRM_FORMAT_RGBX1010102:
1838 case DRM_FORMAT_BGRA1010102:
1839 case DRM_FORMAT_BGRX1010102:
1840 return fill_gradient_rgb32(&info->rgb, planes[0],
1841 width, height, stride);
1842
1843 case DRM_FORMAT_XRGB16161616F:
1844 case DRM_FORMAT_XBGR16161616F:
1845 case DRM_FORMAT_ARGB16161616F:
1846 case DRM_FORMAT_ABGR16161616F:
1847 return fill_gradient_rgb16fp(&info->rgb, planes[0],
1848 width, height, stride);
1849 }
1850 }
1851
1852 /*
1853 * util_fill_pattern - Fill a buffer with a test pattern
1854 * @format: Pixel format
1855 * @pattern: Test pattern
1856 * @planes: Array of buffers
1857 * @width: Width in pixels
1858 * @height: Height in pixels
1859 * @stride: Line stride (pitch) in bytes
1860 *
1861 * Fill the buffers with the test pattern specified by the pattern parameter.
1862 * Supported formats vary depending on the selected pattern.
1863 */
util_fill_pattern(uint32_t format,enum util_fill_pattern pattern,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)1864 void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
1865 void *planes[3], unsigned int width,
1866 unsigned int height, unsigned int stride)
1867 {
1868 const struct util_format_info *info;
1869
1870 info = util_format_info_find(format);
1871 if (info == NULL)
1872 return;
1873
1874 switch (pattern) {
1875 case UTIL_PATTERN_TILES:
1876 return fill_tiles(info, planes, width, height, stride);
1877
1878 case UTIL_PATTERN_SMPTE:
1879 return fill_smpte(info, planes, width, height, stride);
1880
1881 case UTIL_PATTERN_PLAIN:
1882 return fill_plain(info, planes, height, stride);
1883
1884 case UTIL_PATTERN_GRADIENT:
1885 return fill_gradient(info, planes, width, height, stride);
1886
1887 default:
1888 printf("Error: unsupported test pattern %u.\n", pattern);
1889 break;
1890 }
1891 }
1892
1893 static const char *pattern_names[] = {
1894 [UTIL_PATTERN_TILES] = "tiles",
1895 [UTIL_PATTERN_SMPTE] = "smpte",
1896 [UTIL_PATTERN_PLAIN] = "plain",
1897 [UTIL_PATTERN_GRADIENT] = "gradient",
1898 };
1899
util_pattern_enum(const char * name)1900 enum util_fill_pattern util_pattern_enum(const char *name)
1901 {
1902 unsigned int i;
1903
1904 for (i = 0; i < ARRAY_SIZE(pattern_names); i++)
1905 if (!strcmp(pattern_names[i], name))
1906 return (enum util_fill_pattern)i;
1907
1908 printf("Error: unsupported test pattern %s.\n", name);
1909 return UTIL_PATTERN_SMPTE;
1910 }
1911