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