1 /*
2 * Copyright 2008 Tungsten Graphics
3 * Jakob Bornecrantz <jakob@tungstengraphics.com>
4 * Copyright 2008 Intel Corporation
5 * Jesse Barnes <jesse.barnes@intel.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * IN THE SOFTWARE.
24 */
25
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <drm_fourcc.h>
32
33 #if HAVE_CAIRO
34 #include <cairo.h>
35 #include <math.h>
36 #endif
37
38 #include "format.h"
39 #include "pattern.h"
40
41 struct color_rgb24 {
42 unsigned int value:24;
43 } __attribute__((__packed__));
44
45 struct color_yuv {
46 unsigned char y;
47 unsigned char u;
48 unsigned char v;
49 };
50
51 #define MAKE_YUV_601_Y(r, g, b) \
52 ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16)
53 #define MAKE_YUV_601_U(r, g, b) \
54 (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128)
55 #define MAKE_YUV_601_V(r, g, b) \
56 (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128)
57
58 #define MAKE_YUV_601(r, g, b) \
59 { .y = MAKE_YUV_601_Y(r, g, b), \
60 .u = MAKE_YUV_601_U(r, g, b), \
61 .v = MAKE_YUV_601_V(r, g, b) }
62
63 #define MAKE_RGBA(rgb, r, g, b, a) \
64 ((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \
65 (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \
66 (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \
67 (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset))
68
69 #define MAKE_RGB24(rgb, r, g, b) \
70 { .value = MAKE_RGBA(rgb, r, g, b, 0) }
71
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)72 static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv,
73 unsigned char *y_mem, unsigned char *u_mem,
74 unsigned char *v_mem, unsigned int width,
75 unsigned int height, unsigned int stride)
76 {
77 const struct color_yuv colors_top[] = {
78 MAKE_YUV_601(191, 192, 192), /* grey */
79 MAKE_YUV_601(192, 192, 0), /* yellow */
80 MAKE_YUV_601(0, 192, 192), /* cyan */
81 MAKE_YUV_601(0, 192, 0), /* green */
82 MAKE_YUV_601(192, 0, 192), /* magenta */
83 MAKE_YUV_601(192, 0, 0), /* red */
84 MAKE_YUV_601(0, 0, 192), /* blue */
85 };
86 const struct color_yuv colors_middle[] = {
87 MAKE_YUV_601(0, 0, 192), /* blue */
88 MAKE_YUV_601(19, 19, 19), /* black */
89 MAKE_YUV_601(192, 0, 192), /* magenta */
90 MAKE_YUV_601(19, 19, 19), /* black */
91 MAKE_YUV_601(0, 192, 192), /* cyan */
92 MAKE_YUV_601(19, 19, 19), /* black */
93 MAKE_YUV_601(192, 192, 192), /* grey */
94 };
95 const struct color_yuv colors_bottom[] = {
96 MAKE_YUV_601(0, 33, 76), /* in-phase */
97 MAKE_YUV_601(255, 255, 255), /* super white */
98 MAKE_YUV_601(50, 0, 106), /* quadrature */
99 MAKE_YUV_601(19, 19, 19), /* black */
100 MAKE_YUV_601(9, 9, 9), /* 3.5% */
101 MAKE_YUV_601(19, 19, 19), /* 7.5% */
102 MAKE_YUV_601(29, 29, 29), /* 11.5% */
103 MAKE_YUV_601(19, 19, 19), /* black */
104 };
105 unsigned int cs = yuv->chroma_stride;
106 unsigned int xsub = yuv->xsub;
107 unsigned int ysub = yuv->ysub;
108 unsigned int x;
109 unsigned int y;
110
111 /* Luma */
112 for (y = 0; y < height * 6 / 9; ++y) {
113 for (x = 0; x < width; ++x)
114 y_mem[x] = colors_top[x * 7 / width].y;
115 y_mem += stride;
116 }
117
118 for (; y < height * 7 / 9; ++y) {
119 for (x = 0; x < width; ++x)
120 y_mem[x] = colors_middle[x * 7 / width].y;
121 y_mem += stride;
122 }
123
124 for (; y < height; ++y) {
125 for (x = 0; x < width * 5 / 7; ++x)
126 y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
127 for (; x < width * 6 / 7; ++x)
128 y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
129 / (width / 7) + 4].y;
130 for (; x < width; ++x)
131 y_mem[x] = colors_bottom[7].y;
132 y_mem += stride;
133 }
134
135 /* Chroma */
136 for (y = 0; y < height / ysub * 6 / 9; ++y) {
137 for (x = 0; x < width; x += xsub) {
138 u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
139 v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
140 }
141 u_mem += stride * cs / xsub;
142 v_mem += stride * cs / xsub;
143 }
144
145 for (; y < height / ysub * 7 / 9; ++y) {
146 for (x = 0; x < width; x += xsub) {
147 u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
148 v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
149 }
150 u_mem += stride * cs / xsub;
151 v_mem += stride * cs / xsub;
152 }
153
154 for (; y < height / ysub; ++y) {
155 for (x = 0; x < width * 5 / 7; x += xsub) {
156 u_mem[x*cs/xsub] =
157 colors_bottom[x * 4 / (width * 5 / 7)].u;
158 v_mem[x*cs/xsub] =
159 colors_bottom[x * 4 / (width * 5 / 7)].v;
160 }
161 for (; x < width * 6 / 7; x += xsub) {
162 u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
163 3 / (width / 7) + 4].u;
164 v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
165 3 / (width / 7) + 4].v;
166 }
167 for (; x < width; x += xsub) {
168 u_mem[x*cs/xsub] = colors_bottom[7].u;
169 v_mem[x*cs/xsub] = colors_bottom[7].v;
170 }
171 u_mem += stride * cs / xsub;
172 v_mem += stride * cs / xsub;
173 }
174 }
175
fill_smpte_yuv_packed(const struct util_yuv_info * yuv,void * mem,unsigned int width,unsigned int height,unsigned int stride)176 static void fill_smpte_yuv_packed(const struct util_yuv_info *yuv, void *mem,
177 unsigned int width, unsigned int height,
178 unsigned int stride)
179 {
180 const struct color_yuv colors_top[] = {
181 MAKE_YUV_601(191, 192, 192), /* grey */
182 MAKE_YUV_601(192, 192, 0), /* yellow */
183 MAKE_YUV_601(0, 192, 192), /* cyan */
184 MAKE_YUV_601(0, 192, 0), /* green */
185 MAKE_YUV_601(192, 0, 192), /* magenta */
186 MAKE_YUV_601(192, 0, 0), /* red */
187 MAKE_YUV_601(0, 0, 192), /* blue */
188 };
189 const struct color_yuv colors_middle[] = {
190 MAKE_YUV_601(0, 0, 192), /* blue */
191 MAKE_YUV_601(19, 19, 19), /* black */
192 MAKE_YUV_601(192, 0, 192), /* magenta */
193 MAKE_YUV_601(19, 19, 19), /* black */
194 MAKE_YUV_601(0, 192, 192), /* cyan */
195 MAKE_YUV_601(19, 19, 19), /* black */
196 MAKE_YUV_601(192, 192, 192), /* grey */
197 };
198 const struct color_yuv colors_bottom[] = {
199 MAKE_YUV_601(0, 33, 76), /* in-phase */
200 MAKE_YUV_601(255, 255, 255), /* super white */
201 MAKE_YUV_601(50, 0, 106), /* quadrature */
202 MAKE_YUV_601(19, 19, 19), /* black */
203 MAKE_YUV_601(9, 9, 9), /* 3.5% */
204 MAKE_YUV_601(19, 19, 19), /* 7.5% */
205 MAKE_YUV_601(29, 29, 29), /* 11.5% */
206 MAKE_YUV_601(19, 19, 19), /* black */
207 };
208 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
209 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
210 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
211 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
212 unsigned int x;
213 unsigned int y;
214
215 /* Luma */
216 for (y = 0; y < height * 6 / 9; ++y) {
217 for (x = 0; x < width; ++x)
218 y_mem[2*x] = colors_top[x * 7 / width].y;
219 y_mem += stride;
220 }
221
222 for (; y < height * 7 / 9; ++y) {
223 for (x = 0; x < width; ++x)
224 y_mem[2*x] = colors_middle[x * 7 / width].y;
225 y_mem += stride;
226 }
227
228 for (; y < height; ++y) {
229 for (x = 0; x < width * 5 / 7; ++x)
230 y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
231 for (; x < width * 6 / 7; ++x)
232 y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
233 / (width / 7) + 4].y;
234 for (; x < width; ++x)
235 y_mem[2*x] = colors_bottom[7].y;
236 y_mem += stride;
237 }
238
239 /* Chroma */
240 for (y = 0; y < height * 6 / 9; ++y) {
241 for (x = 0; x < width; x += 2) {
242 c_mem[2*x+u] = colors_top[x * 7 / width].u;
243 c_mem[2*x+v] = colors_top[x * 7 / width].v;
244 }
245 c_mem += stride;
246 }
247
248 for (; y < height * 7 / 9; ++y) {
249 for (x = 0; x < width; x += 2) {
250 c_mem[2*x+u] = colors_middle[x * 7 / width].u;
251 c_mem[2*x+v] = colors_middle[x * 7 / width].v;
252 }
253 c_mem += stride;
254 }
255
256 for (; y < height; ++y) {
257 for (x = 0; x < width * 5 / 7; x += 2) {
258 c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
259 c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
260 }
261 for (; x < width * 6 / 7; x += 2) {
262 c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
263 3 / (width / 7) + 4].u;
264 c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
265 3 / (width / 7) + 4].v;
266 }
267 for (; x < width; x += 2) {
268 c_mem[2*x+u] = colors_bottom[7].u;
269 c_mem[2*x+v] = colors_bottom[7].v;
270 }
271 c_mem += stride;
272 }
273 }
274
fill_smpte_rgb16(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)275 static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
276 unsigned int width, unsigned int height,
277 unsigned int stride)
278 {
279 const uint16_t colors_top[] = {
280 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */
281 MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */
282 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */
283 MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */
284 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */
285 MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */
286 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */
287 };
288 const uint16_t colors_middle[] = {
289 MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */
290 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
291 MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */
292 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
293 MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */
294 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
295 MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */
296 };
297 const uint16_t colors_bottom[] = {
298 MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */
299 MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */
300 MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */
301 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
302 MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */
303 MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */
304 MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */
305 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
306 };
307 unsigned int x;
308 unsigned int y;
309
310 for (y = 0; y < height * 6 / 9; ++y) {
311 for (x = 0; x < width; ++x)
312 ((uint16_t *)mem)[x] = colors_top[x * 7 / width];
313 mem += stride;
314 }
315
316 for (; y < height * 7 / 9; ++y) {
317 for (x = 0; x < width; ++x)
318 ((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
319 mem += stride;
320 }
321
322 for (; y < height; ++y) {
323 for (x = 0; x < width * 5 / 7; ++x)
324 ((uint16_t *)mem)[x] =
325 colors_bottom[x * 4 / (width * 5 / 7)];
326 for (; x < width * 6 / 7; ++x)
327 ((uint16_t *)mem)[x] =
328 colors_bottom[(x - width * 5 / 7) * 3
329 / (width / 7) + 4];
330 for (; x < width; ++x)
331 ((uint16_t *)mem)[x] = colors_bottom[7];
332 mem += stride;
333 }
334 }
335
fill_smpte_rgb24(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)336 static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem,
337 unsigned int width, unsigned int height,
338 unsigned int stride)
339 {
340 const struct color_rgb24 colors_top[] = {
341 MAKE_RGB24(rgb, 192, 192, 192), /* grey */
342 MAKE_RGB24(rgb, 192, 192, 0), /* yellow */
343 MAKE_RGB24(rgb, 0, 192, 192), /* cyan */
344 MAKE_RGB24(rgb, 0, 192, 0), /* green */
345 MAKE_RGB24(rgb, 192, 0, 192), /* magenta */
346 MAKE_RGB24(rgb, 192, 0, 0), /* red */
347 MAKE_RGB24(rgb, 0, 0, 192), /* blue */
348 };
349 const struct color_rgb24 colors_middle[] = {
350 MAKE_RGB24(rgb, 0, 0, 192), /* blue */
351 MAKE_RGB24(rgb, 19, 19, 19), /* black */
352 MAKE_RGB24(rgb, 192, 0, 192), /* magenta */
353 MAKE_RGB24(rgb, 19, 19, 19), /* black */
354 MAKE_RGB24(rgb, 0, 192, 192), /* cyan */
355 MAKE_RGB24(rgb, 19, 19, 19), /* black */
356 MAKE_RGB24(rgb, 192, 192, 192), /* grey */
357 };
358 const struct color_rgb24 colors_bottom[] = {
359 MAKE_RGB24(rgb, 0, 33, 76), /* in-phase */
360 MAKE_RGB24(rgb, 255, 255, 255), /* super white */
361 MAKE_RGB24(rgb, 50, 0, 106), /* quadrature */
362 MAKE_RGB24(rgb, 19, 19, 19), /* black */
363 MAKE_RGB24(rgb, 9, 9, 9), /* 3.5% */
364 MAKE_RGB24(rgb, 19, 19, 19), /* 7.5% */
365 MAKE_RGB24(rgb, 29, 29, 29), /* 11.5% */
366 MAKE_RGB24(rgb, 19, 19, 19), /* black */
367 };
368 unsigned int x;
369 unsigned int y;
370
371 for (y = 0; y < height * 6 / 9; ++y) {
372 for (x = 0; x < width; ++x)
373 ((struct color_rgb24 *)mem)[x] =
374 colors_top[x * 7 / width];
375 mem += stride;
376 }
377
378 for (; y < height * 7 / 9; ++y) {
379 for (x = 0; x < width; ++x)
380 ((struct color_rgb24 *)mem)[x] =
381 colors_middle[x * 7 / width];
382 mem += stride;
383 }
384
385 for (; y < height; ++y) {
386 for (x = 0; x < width * 5 / 7; ++x)
387 ((struct color_rgb24 *)mem)[x] =
388 colors_bottom[x * 4 / (width * 5 / 7)];
389 for (; x < width * 6 / 7; ++x)
390 ((struct color_rgb24 *)mem)[x] =
391 colors_bottom[(x - width * 5 / 7) * 3
392 / (width / 7) + 4];
393 for (; x < width; ++x)
394 ((struct color_rgb24 *)mem)[x] = colors_bottom[7];
395 mem += stride;
396 }
397 }
398
fill_smpte_rgb32(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)399 static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem,
400 unsigned int width, unsigned int height,
401 unsigned int stride)
402 {
403 const uint32_t colors_top[] = {
404 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */
405 MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */
406 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */
407 MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */
408 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */
409 MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */
410 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */
411 };
412 const uint32_t colors_middle[] = {
413 MAKE_RGBA(rgb, 0, 0, 192, 127), /* blue */
414 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
415 MAKE_RGBA(rgb, 192, 0, 192, 127), /* magenta */
416 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
417 MAKE_RGBA(rgb, 0, 192, 192, 127), /* cyan */
418 MAKE_RGBA(rgb, 19, 19, 19, 127), /* black */
419 MAKE_RGBA(rgb, 192, 192, 192, 127), /* grey */
420 };
421 const uint32_t colors_bottom[] = {
422 MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */
423 MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */
424 MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */
425 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
426 MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */
427 MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */
428 MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */
429 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */
430 };
431 unsigned int x;
432 unsigned int y;
433
434 for (y = 0; y < height * 6 / 9; ++y) {
435 for (x = 0; x < width; ++x)
436 ((uint32_t *)mem)[x] = colors_top[x * 7 / width];
437 mem += stride;
438 }
439
440 for (; y < height * 7 / 9; ++y) {
441 for (x = 0; x < width; ++x)
442 ((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
443 mem += stride;
444 }
445
446 for (; y < height; ++y) {
447 for (x = 0; x < width * 5 / 7; ++x)
448 ((uint32_t *)mem)[x] =
449 colors_bottom[x * 4 / (width * 5 / 7)];
450 for (; x < width * 6 / 7; ++x)
451 ((uint32_t *)mem)[x] =
452 colors_bottom[(x - width * 5 / 7) * 3
453 / (width / 7) + 4];
454 for (; x < width; ++x)
455 ((uint32_t *)mem)[x] = colors_bottom[7];
456 mem += stride;
457 }
458 }
459
fill_smpte(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)460 static void fill_smpte(const struct util_format_info *info, void *planes[3],
461 unsigned int width, unsigned int height,
462 unsigned int stride)
463 {
464 unsigned char *u, *v;
465
466 switch (info->format) {
467 case DRM_FORMAT_UYVY:
468 case DRM_FORMAT_VYUY:
469 case DRM_FORMAT_YUYV:
470 case DRM_FORMAT_YVYU:
471 return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
472 height, stride);
473
474 case DRM_FORMAT_NV12:
475 case DRM_FORMAT_NV21:
476 case DRM_FORMAT_NV16:
477 case DRM_FORMAT_NV61:
478 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
479 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
480 return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
481 width, height, stride);
482
483 case DRM_FORMAT_YUV420:
484 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
485 planes[2], width, height, stride);
486
487 case DRM_FORMAT_YVU420:
488 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
489 planes[1], width, height, stride);
490
491 case DRM_FORMAT_ARGB4444:
492 case DRM_FORMAT_XRGB4444:
493 case DRM_FORMAT_ABGR4444:
494 case DRM_FORMAT_XBGR4444:
495 case DRM_FORMAT_RGBA4444:
496 case DRM_FORMAT_RGBX4444:
497 case DRM_FORMAT_BGRA4444:
498 case DRM_FORMAT_BGRX4444:
499 case DRM_FORMAT_RGB565:
500 case DRM_FORMAT_BGR565:
501 case DRM_FORMAT_ARGB1555:
502 case DRM_FORMAT_XRGB1555:
503 case DRM_FORMAT_ABGR1555:
504 case DRM_FORMAT_XBGR1555:
505 case DRM_FORMAT_RGBA5551:
506 case DRM_FORMAT_RGBX5551:
507 case DRM_FORMAT_BGRA5551:
508 case DRM_FORMAT_BGRX5551:
509 return fill_smpte_rgb16(&info->rgb, planes[0],
510 width, height, stride);
511
512 case DRM_FORMAT_BGR888:
513 case DRM_FORMAT_RGB888:
514 return fill_smpte_rgb24(&info->rgb, planes[0],
515 width, height, stride);
516 case DRM_FORMAT_ARGB8888:
517 case DRM_FORMAT_XRGB8888:
518 case DRM_FORMAT_ABGR8888:
519 case DRM_FORMAT_XBGR8888:
520 case DRM_FORMAT_RGBA8888:
521 case DRM_FORMAT_RGBX8888:
522 case DRM_FORMAT_BGRA8888:
523 case DRM_FORMAT_BGRX8888:
524 case DRM_FORMAT_ARGB2101010:
525 case DRM_FORMAT_XRGB2101010:
526 case DRM_FORMAT_ABGR2101010:
527 case DRM_FORMAT_XBGR2101010:
528 case DRM_FORMAT_RGBA1010102:
529 case DRM_FORMAT_RGBX1010102:
530 case DRM_FORMAT_BGRA1010102:
531 case DRM_FORMAT_BGRX1010102:
532 return fill_smpte_rgb32(&info->rgb, planes[0],
533 width, height, stride);
534 }
535 }
536
537 /* swap these for big endian.. */
538 #define RED 2
539 #define GREEN 1
540 #define BLUE 0
541
make_pwetty(void * data,unsigned int width,unsigned int height,unsigned int stride,uint32_t format)542 static void make_pwetty(void *data, unsigned int width, unsigned int height,
543 unsigned int stride, uint32_t format)
544 {
545 #if HAVE_CAIRO
546 cairo_surface_t *surface;
547 cairo_t *cr;
548 cairo_format_t cairo_format;
549
550 /* we can ignore the order of R,G,B channels */
551 switch (format) {
552 case DRM_FORMAT_XRGB8888:
553 case DRM_FORMAT_ARGB8888:
554 case DRM_FORMAT_XBGR8888:
555 case DRM_FORMAT_ABGR8888:
556 cairo_format = CAIRO_FORMAT_ARGB32;
557 break;
558 case DRM_FORMAT_RGB565:
559 case DRM_FORMAT_BGR565:
560 cairo_format = CAIRO_FORMAT_RGB16_565;
561 break;
562 default:
563 return;
564 }
565
566 surface = cairo_image_surface_create_for_data(data,
567 cairo_format,
568 width, height,
569 stride);
570 cr = cairo_create(surface);
571 cairo_surface_destroy(surface);
572
573 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
574 for (unsigned x = 0; x < width; x += 250)
575 for (unsigned y = 0; y < height; y += 250) {
576 char buf[64];
577
578 cairo_move_to(cr, x, y - 20);
579 cairo_line_to(cr, x, y + 20);
580 cairo_move_to(cr, x - 20, y);
581 cairo_line_to(cr, x + 20, y);
582 cairo_new_sub_path(cr);
583 cairo_arc(cr, x, y, 10, 0, M_PI * 2);
584 cairo_set_line_width(cr, 4);
585 cairo_set_source_rgb(cr, 0, 0, 0);
586 cairo_stroke_preserve(cr);
587 cairo_set_source_rgb(cr, 1, 1, 1);
588 cairo_set_line_width(cr, 2);
589 cairo_stroke(cr);
590
591 snprintf(buf, sizeof buf, "%d, %d", x, y);
592 cairo_move_to(cr, x + 20, y + 20);
593 cairo_text_path(cr, buf);
594 cairo_set_source_rgb(cr, 0, 0, 0);
595 cairo_stroke_preserve(cr);
596 cairo_set_source_rgb(cr, 1, 1, 1);
597 cairo_fill(cr);
598 }
599
600 cairo_destroy(cr);
601 #endif
602 }
603
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)604 static void fill_tiles_yuv_planar(const struct util_format_info *info,
605 unsigned char *y_mem, unsigned char *u_mem,
606 unsigned char *v_mem, unsigned int width,
607 unsigned int height, unsigned int stride)
608 {
609 const struct util_yuv_info *yuv = &info->yuv;
610 unsigned int cs = yuv->chroma_stride;
611 unsigned int xsub = yuv->xsub;
612 unsigned int ysub = yuv->ysub;
613 unsigned int x;
614 unsigned int y;
615
616 for (y = 0; y < height; ++y) {
617 for (x = 0; x < width; ++x) {
618 div_t d = div(x+y, width);
619 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
620 + 0x000a1120 * (d.rem >> 6);
621 struct color_yuv color =
622 MAKE_YUV_601((rgb32 >> 16) & 0xff,
623 (rgb32 >> 8) & 0xff, rgb32 & 0xff);
624
625 y_mem[x] = color.y;
626 u_mem[x/xsub*cs] = color.u;
627 v_mem[x/xsub*cs] = color.v;
628 }
629
630 y_mem += stride;
631 if ((y + 1) % ysub == 0) {
632 u_mem += stride * cs / xsub;
633 v_mem += stride * cs / xsub;
634 }
635 }
636 }
637
fill_tiles_yuv_packed(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)638 static void fill_tiles_yuv_packed(const struct util_format_info *info,
639 void *mem, unsigned int width,
640 unsigned int height, unsigned int stride)
641 {
642 const struct util_yuv_info *yuv = &info->yuv;
643 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
644 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
645 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
646 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
647 unsigned int x;
648 unsigned int y;
649
650 for (y = 0; y < height; ++y) {
651 for (x = 0; x < width; x += 2) {
652 div_t d = div(x+y, width);
653 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
654 + 0x000a1120 * (d.rem >> 6);
655 struct color_yuv color =
656 MAKE_YUV_601((rgb32 >> 16) & 0xff,
657 (rgb32 >> 8) & 0xff, rgb32 & 0xff);
658
659 y_mem[2*x] = color.y;
660 c_mem[2*x+u] = color.u;
661 y_mem[2*x+2] = color.y;
662 c_mem[2*x+v] = color.v;
663 }
664
665 y_mem += stride;
666 c_mem += stride;
667 }
668 }
669
fill_tiles_rgb16(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)670 static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
671 unsigned int width, unsigned int height,
672 unsigned int stride)
673 {
674 const struct util_rgb_info *rgb = &info->rgb;
675 void *mem_base = mem;
676 unsigned int x, y;
677
678 for (y = 0; y < height; ++y) {
679 for (x = 0; x < width; ++x) {
680 div_t d = div(x+y, width);
681 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
682 + 0x000a1120 * (d.rem >> 6);
683 uint16_t color =
684 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
685 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
686 255);
687
688 ((uint16_t *)mem)[x] = color;
689 }
690 mem += stride;
691 }
692
693 make_pwetty(mem_base, width, height, stride, info->format);
694 }
695
fill_tiles_rgb24(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)696 static void fill_tiles_rgb24(const struct util_format_info *info, void *mem,
697 unsigned int width, unsigned int height,
698 unsigned int stride)
699 {
700 const struct util_rgb_info *rgb = &info->rgb;
701 unsigned int x, y;
702
703 for (y = 0; y < height; ++y) {
704 for (x = 0; x < width; ++x) {
705 div_t d = div(x+y, width);
706 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
707 + 0x000a1120 * (d.rem >> 6);
708 struct color_rgb24 color =
709 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
710 (rgb32 >> 8) & 0xff, rgb32 & 0xff);
711
712 ((struct color_rgb24 *)mem)[x] = color;
713 }
714 mem += stride;
715 }
716 }
717
fill_tiles_rgb32(const struct util_format_info * info,void * mem,unsigned int width,unsigned int height,unsigned int stride)718 static void fill_tiles_rgb32(const struct util_format_info *info, void *mem,
719 unsigned int width, unsigned int height,
720 unsigned int stride)
721 {
722 const struct util_rgb_info *rgb = &info->rgb;
723 void *mem_base = mem;
724 unsigned int x, y;
725
726 for (y = 0; y < height; ++y) {
727 for (x = 0; x < width; ++x) {
728 div_t d = div(x+y, width);
729 uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
730 + 0x000a1120 * (d.rem >> 6);
731 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255;
732 uint32_t color =
733 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
734 (rgb32 >> 8) & 0xff, rgb32 & 0xff,
735 alpha);
736
737 ((uint32_t *)mem)[x] = color;
738 }
739 mem += stride;
740 }
741
742 make_pwetty(mem_base, width, height, stride, info->format);
743 }
744
fill_tiles(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)745 static void fill_tiles(const struct util_format_info *info, void *planes[3],
746 unsigned int width, unsigned int height,
747 unsigned int stride)
748 {
749 unsigned char *u, *v;
750
751 switch (info->format) {
752 case DRM_FORMAT_UYVY:
753 case DRM_FORMAT_VYUY:
754 case DRM_FORMAT_YUYV:
755 case DRM_FORMAT_YVYU:
756 return fill_tiles_yuv_packed(info, planes[0],
757 width, height, stride);
758
759 case DRM_FORMAT_NV12:
760 case DRM_FORMAT_NV21:
761 case DRM_FORMAT_NV16:
762 case DRM_FORMAT_NV61:
763 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
764 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
765 return fill_tiles_yuv_planar(info, planes[0], u, v,
766 width, height, stride);
767
768 case DRM_FORMAT_YUV420:
769 return fill_tiles_yuv_planar(info, planes[0], planes[1],
770 planes[2], width, height, stride);
771
772 case DRM_FORMAT_YVU420:
773 return fill_tiles_yuv_planar(info, planes[0], planes[2],
774 planes[1], width, height, stride);
775
776 case DRM_FORMAT_ARGB4444:
777 case DRM_FORMAT_XRGB4444:
778 case DRM_FORMAT_ABGR4444:
779 case DRM_FORMAT_XBGR4444:
780 case DRM_FORMAT_RGBA4444:
781 case DRM_FORMAT_RGBX4444:
782 case DRM_FORMAT_BGRA4444:
783 case DRM_FORMAT_BGRX4444:
784 case DRM_FORMAT_RGB565:
785 case DRM_FORMAT_BGR565:
786 case DRM_FORMAT_ARGB1555:
787 case DRM_FORMAT_XRGB1555:
788 case DRM_FORMAT_ABGR1555:
789 case DRM_FORMAT_XBGR1555:
790 case DRM_FORMAT_RGBA5551:
791 case DRM_FORMAT_RGBX5551:
792 case DRM_FORMAT_BGRA5551:
793 case DRM_FORMAT_BGRX5551:
794 return fill_tiles_rgb16(info, planes[0],
795 width, height, stride);
796
797 case DRM_FORMAT_BGR888:
798 case DRM_FORMAT_RGB888:
799 return fill_tiles_rgb24(info, planes[0],
800 width, height, stride);
801 case DRM_FORMAT_ARGB8888:
802 case DRM_FORMAT_XRGB8888:
803 case DRM_FORMAT_ABGR8888:
804 case DRM_FORMAT_XBGR8888:
805 case DRM_FORMAT_RGBA8888:
806 case DRM_FORMAT_RGBX8888:
807 case DRM_FORMAT_BGRA8888:
808 case DRM_FORMAT_BGRX8888:
809 case DRM_FORMAT_ARGB2101010:
810 case DRM_FORMAT_XRGB2101010:
811 case DRM_FORMAT_ABGR2101010:
812 case DRM_FORMAT_XBGR2101010:
813 case DRM_FORMAT_RGBA1010102:
814 case DRM_FORMAT_RGBX1010102:
815 case DRM_FORMAT_BGRA1010102:
816 case DRM_FORMAT_BGRX1010102:
817 return fill_tiles_rgb32(info, planes[0],
818 width, height, stride);
819 }
820 }
821
fill_plain(void * planes[3],unsigned int height,unsigned int stride)822 static void fill_plain(void *planes[3],
823 unsigned int height,
824 unsigned int stride)
825 {
826 memset(planes[0], 0x77, stride * height);
827 }
828
829 /*
830 * util_fill_pattern - Fill a buffer with a test pattern
831 * @format: Pixel format
832 * @pattern: Test pattern
833 * @planes: Array of buffers
834 * @width: Width in pixels
835 * @height: Height in pixels
836 * @stride: Line stride (pitch) in bytes
837 *
838 * Fill the buffers with the test pattern specified by the pattern parameter.
839 * Supported formats vary depending on the selected pattern.
840 */
util_fill_pattern(uint32_t format,enum util_fill_pattern pattern,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)841 void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern,
842 void *planes[3], unsigned int width,
843 unsigned int height, unsigned int stride)
844 {
845 const struct util_format_info *info;
846
847 info = util_format_info_find(format);
848 if (info == NULL)
849 return;
850
851 switch (pattern) {
852 case UTIL_PATTERN_TILES:
853 return fill_tiles(info, planes, width, height, stride);
854
855 case UTIL_PATTERN_SMPTE:
856 return fill_smpte(info, planes, width, height, stride);
857
858 case UTIL_PATTERN_PLAIN:
859 return fill_plain(planes, height, stride);
860
861 default:
862 printf("Error: unsupported test pattern %u.\n", pattern);
863 break;
864 }
865 }
866