]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/libdrm.git/blob - tests/modetest/buffers.c
modeset: Split buffer allocation to a separate file
[glsdk/libdrm.git] / tests / modetest / buffers.c
1 /*
2  * DRM based mode setting test program
3  * Copyright 2008 Tungsten Graphics
4  *   Jakob Bornecrantz <jakob@tungstengraphics.com>
5  * Copyright 2008 Intel Corporation
6  *   Jesse Barnes <jesse.barnes@intel.com>
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24  * IN THE SOFTWARE.
25  */
27 #include "config.h"
29 #include <assert.h>
30 #include <errno.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdint.h>
34 #include <string.h>
36 #include "drm_fourcc.h"
37 #include "libkms.h"
39 #include "buffers.h"
41 #ifdef HAVE_CAIRO
42 #include <math.h>
43 #include <cairo.h>
44 #endif
46 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
48 /* -----------------------------------------------------------------------------
49  * Formats
50  */
52 struct color_component {
53         unsigned int length;
54         unsigned int offset;
55 };
57 struct rgb_info {
58         struct color_component red;
59         struct color_component green;
60         struct color_component blue;
61         struct color_component alpha;
62 };
64 enum yuv_order {
65         YUV_YCbCr = 1,
66         YUV_YCrCb = 2,
67         YUV_YC = 4,
68         YUV_CY = 8,
69 };
71 struct yuv_info {
72         enum yuv_order order;
73         unsigned int xsub;
74         unsigned int ysub;
75         unsigned int chroma_stride;
76 };
78 struct format_info {
79         unsigned int format;
80         const char *name;
81         const struct rgb_info rgb;
82         const struct yuv_info yuv;
83 };
85 #define MAKE_RGB_INFO(rl, ro, bl, bo, gl, go, al, ao) \
86         .rgb = { { (rl), (ro) }, { (bl), (bo) }, { (gl), (go) }, { (al), (ao) } }
88 #define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \
89         .yuv = { (order), (xsub), (ysub), (chroma_stride) }
91 static const struct format_info format_info[] = {
92         /* YUV packed */
93         { DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) },
94         { DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) },
95         { DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) },
96         { DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) },
97         /* YUV semi-planar */
98         { DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) },
99         { DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) },
100         { DRM_FORMAT_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) },
101         { DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
102         /* YUV planar */
103         { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
104         /* RGB16 */
105         { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) },
106         { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
107         { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
108         /* RGB24 */
109         { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
110         { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
111         /* RGB32 */
112         { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
113         { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) },
114         { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
115         { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
116 };
118 unsigned int format_fourcc(const char *name)
120         unsigned int i;
121         for (i = 0; i < ARRAY_SIZE(format_info); i++) {
122                 if (!strcmp(format_info[i].name, name))
123                         return format_info[i].format;
124         }
125         return 0;
128 /* -----------------------------------------------------------------------------
129  * Test patterns
130  */
132 struct color_rgb24 {
133         unsigned int value:24;
134 } __attribute__((__packed__));
136 struct color_yuv {
137         unsigned char y;
138         unsigned char u;
139         unsigned char v;
140 };
142 #define MAKE_YUV_601_Y(r, g, b) \
143         ((( 66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
144 #define MAKE_YUV_601_U(r, g, b) \
145         (((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
146 #define MAKE_YUV_601_V(r, g, b) \
147         (((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
149 #define MAKE_YUV_601(r, g, b) \
150         { .y = MAKE_YUV_601_Y(r, g, b), \
151           .u = MAKE_YUV_601_U(r, g, b), \
152           .v = MAKE_YUV_601_V(r, g, b) }
154 #define MAKE_RGBA(rgb, r, g, b, a) \
155         ((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \
156          (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \
157          (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \
158          (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset))
160 #define MAKE_RGB24(rgb, r, g, b) \
161         { .value = MAKE_RGBA(rgb, r, g, b, 0) }
163 static void
164 fill_smpte_yuv_planar(const struct yuv_info *yuv,
165                       unsigned char *y_mem, unsigned char *u_mem,
166                       unsigned char *v_mem, unsigned int width,
167                       unsigned int height, unsigned int stride)
169         const struct color_yuv colors_top[] = {
170                 MAKE_YUV_601(191, 192, 192),    /* grey */
171                 MAKE_YUV_601(192, 192, 0),      /* yellow */
172                 MAKE_YUV_601(0, 192, 192),      /* cyan */
173                 MAKE_YUV_601(0, 192, 0),        /* green */
174                 MAKE_YUV_601(192, 0, 192),      /* magenta */
175                 MAKE_YUV_601(192, 0, 0),        /* red */
176                 MAKE_YUV_601(0, 0, 192),        /* blue */
177         };
178         const struct color_yuv colors_middle[] = {
179                 MAKE_YUV_601(0, 0, 192),        /* blue */
180                 MAKE_YUV_601(19, 19, 19),       /* black */
181                 MAKE_YUV_601(192, 0, 192),      /* magenta */
182                 MAKE_YUV_601(19, 19, 19),       /* black */
183                 MAKE_YUV_601(0, 192, 192),      /* cyan */
184                 MAKE_YUV_601(19, 19, 19),       /* black */
185                 MAKE_YUV_601(192, 192, 192),    /* grey */
186         };
187         const struct color_yuv colors_bottom[] = {
188                 MAKE_YUV_601(0, 33, 76),        /* in-phase */
189                 MAKE_YUV_601(255, 255, 255),    /* super white */
190                 MAKE_YUV_601(50, 0, 106),       /* quadrature */
191                 MAKE_YUV_601(19, 19, 19),       /* black */
192                 MAKE_YUV_601(9, 9, 9),          /* 3.5% */
193                 MAKE_YUV_601(19, 19, 19),       /* 7.5% */
194                 MAKE_YUV_601(29, 29, 29),       /* 11.5% */
195                 MAKE_YUV_601(19, 19, 19),       /* black */
196         };
197         unsigned int cs = yuv->chroma_stride;
198         unsigned int xsub = yuv->xsub;
199         unsigned int ysub = yuv->ysub;
200         unsigned int x;
201         unsigned int y;
203         /* Luma */
204         for (y = 0; y < height * 6 / 9; ++y) {
205                 for (x = 0; x < width; ++x)
206                         y_mem[x] = colors_top[x * 7 / width].y;
207                 y_mem += stride;
208         }
210         for (; y < height * 7 / 9; ++y) {
211                 for (x = 0; x < width; ++x)
212                         y_mem[x] = colors_middle[x * 7 / width].y;
213                 y_mem += stride;
214         }
216         for (; y < height; ++y) {
217                 for (x = 0; x < width * 5 / 7; ++x)
218                         y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
219                 for (; x < width * 6 / 7; ++x)
220                         y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
221                                                  / (width / 7) + 4].y;
222                 for (; x < width; ++x)
223                         y_mem[x] = colors_bottom[7].y;
224                 y_mem += stride;
225         }
227         /* Chroma */
228         for (y = 0; y < height / ysub * 6 / 9; ++y) {
229                 for (x = 0; x < width; x += xsub) {
230                         u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
231                         v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
232                 }
233                 u_mem += stride * cs / xsub;
234                 v_mem += stride * cs / xsub;
235         }
237         for (; y < height / ysub * 7 / 9; ++y) {
238                 for (x = 0; x < width; x += xsub) {
239                         u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
240                         v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
241                 }
242                 u_mem += stride * cs / xsub;
243                 v_mem += stride * cs / xsub;
244         }
246         for (; y < height / ysub; ++y) {
247                 for (x = 0; x < width * 5 / 7; x += xsub) {
248                         u_mem[x*cs/xsub] =
249                                 colors_bottom[x * 4 / (width * 5 / 7)].u;
250                         v_mem[x*cs/xsub] =
251                                 colors_bottom[x * 4 / (width * 5 / 7)].v;
252                 }
253                 for (; x < width * 6 / 7; x += xsub) {
254                         u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
255                                                          3 / (width / 7) + 4].u;
256                         v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
257                                                          3 / (width / 7) + 4].v;
258                 }
259                 for (; x < width; x += xsub) {
260                         u_mem[x*cs/xsub] = colors_bottom[7].u;
261                         v_mem[x*cs/xsub] = colors_bottom[7].v;
262                 }
263                 u_mem += stride * cs / xsub;
264                 v_mem += stride * cs / xsub;
265         }
268 static void
269 fill_smpte_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
270                       unsigned int width, unsigned int height,
271                       unsigned int stride)
273         const struct color_yuv colors_top[] = {
274                 MAKE_YUV_601(191, 192, 192),    /* grey */
275                 MAKE_YUV_601(192, 192, 0),      /* yellow */
276                 MAKE_YUV_601(0, 192, 192),      /* cyan */
277                 MAKE_YUV_601(0, 192, 0),        /* green */
278                 MAKE_YUV_601(192, 0, 192),      /* magenta */
279                 MAKE_YUV_601(192, 0, 0),        /* red */
280                 MAKE_YUV_601(0, 0, 192),        /* blue */
281         };
282         const struct color_yuv colors_middle[] = {
283                 MAKE_YUV_601(0, 0, 192),        /* blue */
284                 MAKE_YUV_601(19, 19, 19),       /* black */
285                 MAKE_YUV_601(192, 0, 192),      /* magenta */
286                 MAKE_YUV_601(19, 19, 19),       /* black */
287                 MAKE_YUV_601(0, 192, 192),      /* cyan */
288                 MAKE_YUV_601(19, 19, 19),       /* black */
289                 MAKE_YUV_601(192, 192, 192),    /* grey */
290         };
291         const struct color_yuv colors_bottom[] = {
292                 MAKE_YUV_601(0, 33, 76),        /* in-phase */
293                 MAKE_YUV_601(255, 255, 255),    /* super white */
294                 MAKE_YUV_601(50, 0, 106),       /* quadrature */
295                 MAKE_YUV_601(19, 19, 19),       /* black */
296                 MAKE_YUV_601(9, 9, 9),          /* 3.5% */
297                 MAKE_YUV_601(19, 19, 19),       /* 7.5% */
298                 MAKE_YUV_601(29, 29, 29),       /* 11.5% */
299                 MAKE_YUV_601(19, 19, 19),       /* black */
300         };
301         unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
302         unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
303         unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
304         unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
305         unsigned int x;
306         unsigned int y;
308         /* Luma */
309         for (y = 0; y < height * 6 / 9; ++y) {
310                 for (x = 0; x < width; ++x)
311                         y_mem[2*x] = colors_top[x * 7 / width].y;
312                 y_mem += stride * 2;
313         }
315         for (; y < height * 7 / 9; ++y) {
316                 for (x = 0; x < width; ++x)
317                         y_mem[2*x] = colors_middle[x * 7 / width].y;
318                 y_mem += stride * 2;
319         }
321         for (; y < height; ++y) {
322                 for (x = 0; x < width * 5 / 7; ++x)
323                         y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
324                 for (; x < width * 6 / 7; ++x)
325                         y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
326                                                    / (width / 7) + 4].y;
327                 for (; x < width; ++x)
328                         y_mem[2*x] = colors_bottom[7].y;
329                 y_mem += stride * 2;
330         }
332         /* Chroma */
333         for (y = 0; y < height * 6 / 9; ++y) {
334                 for (x = 0; x < width; x += 2) {
335                         c_mem[2*x+u] = colors_top[x * 7 / width].u;
336                         c_mem[2*x+v] = colors_top[x * 7 / width].v;
337                 }
338                 c_mem += stride * 2;
339         }
341         for (; y < height * 7 / 9; ++y) {
342                 for (x = 0; x < width; x += 2) {
343                         c_mem[2*x+u] = colors_middle[x * 7 / width].u;
344                         c_mem[2*x+v] = colors_middle[x * 7 / width].v;
345                 }
346                 c_mem += stride * 2;
347         }
349         for (; y < height; ++y) {
350                 for (x = 0; x < width * 5 / 7; x += 2) {
351                         c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
352                         c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
353                 }
354                 for (; x < width * 6 / 7; x += 2) {
355                         c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
356                                                      3 / (width / 7) + 4].u;
357                         c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
358                                                      3 / (width / 7) + 4].v;
359                 }
360                 for (; x < width; x += 2) {
361                         c_mem[2*x+u] = colors_bottom[7].u;
362                         c_mem[2*x+v] = colors_bottom[7].v;
363                 }
364                 c_mem += stride * 2;
365         }
368 static void
369 fill_smpte_rgb16(const struct rgb_info *rgb, unsigned char *mem,
370                  unsigned int width, unsigned int height, unsigned int stride)
372         const uint16_t colors_top[] = {
373                 MAKE_RGBA(rgb, 192, 192, 192, 255),     /* grey */
374                 MAKE_RGBA(rgb, 192, 192, 0, 255),       /* yellow */
375                 MAKE_RGBA(rgb, 0, 192, 192, 255),       /* cyan */
376                 MAKE_RGBA(rgb, 0, 192, 0, 255),         /* green */
377                 MAKE_RGBA(rgb, 192, 0, 192, 255),       /* magenta */
378                 MAKE_RGBA(rgb, 192, 0, 0, 255),         /* red */
379                 MAKE_RGBA(rgb, 0, 0, 192, 255),         /* blue */
380         };
381         const uint16_t colors_middle[] = {
382                 MAKE_RGBA(rgb, 0, 0, 192, 255),         /* blue */
383                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
384                 MAKE_RGBA(rgb, 192, 0, 192, 255),       /* magenta */
385                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
386                 MAKE_RGBA(rgb, 0, 192, 192, 255),       /* cyan */
387                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
388                 MAKE_RGBA(rgb, 192, 192, 192, 255),     /* grey */
389         };
390         const uint16_t colors_bottom[] = {
391                 MAKE_RGBA(rgb, 0, 33, 76, 255),         /* in-phase */
392                 MAKE_RGBA(rgb, 255, 255, 255, 255),     /* super white */
393                 MAKE_RGBA(rgb, 50, 0, 106, 255),        /* quadrature */
394                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
395                 MAKE_RGBA(rgb, 9, 9, 9, 255),           /* 3.5% */
396                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* 7.5% */
397                 MAKE_RGBA(rgb, 29, 29, 29, 255),        /* 11.5% */
398                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
399         };
400         unsigned int x;
401         unsigned int y;
403         for (y = 0; y < height * 6 / 9; ++y) {
404                 for (x = 0; x < width; ++x)
405                         ((uint16_t *)mem)[x] = colors_top[x * 7 / width];
406                 mem += stride;
407         }
409         for (; y < height * 7 / 9; ++y) {
410                 for (x = 0; x < width; ++x)
411                         ((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
412                 mem += stride;
413         }
415         for (; y < height; ++y) {
416                 for (x = 0; x < width * 5 / 7; ++x)
417                         ((uint16_t *)mem)[x] =
418                                 colors_bottom[x * 4 / (width * 5 / 7)];
419                 for (; x < width * 6 / 7; ++x)
420                         ((uint16_t *)mem)[x] =
421                                 colors_bottom[(x - width * 5 / 7) * 3
422                                               / (width / 7) + 4];
423                 for (; x < width; ++x)
424                         ((uint16_t *)mem)[x] = colors_bottom[7];
425                 mem += stride;
426         }
429 static void
430 fill_smpte_rgb24(const struct rgb_info *rgb, void *mem,
431                  unsigned int width, unsigned int height, unsigned int stride)
433         const struct color_rgb24 colors_top[] = {
434                 MAKE_RGB24(rgb, 192, 192, 192), /* grey */
435                 MAKE_RGB24(rgb, 192, 192, 0),   /* yellow */
436                 MAKE_RGB24(rgb, 0, 192, 192),   /* cyan */
437                 MAKE_RGB24(rgb, 0, 192, 0),     /* green */
438                 MAKE_RGB24(rgb, 192, 0, 192),   /* magenta */
439                 MAKE_RGB24(rgb, 192, 0, 0),     /* red */
440                 MAKE_RGB24(rgb, 0, 0, 192),     /* blue */
441         };
442         const struct color_rgb24 colors_middle[] = {
443                 MAKE_RGB24(rgb, 0, 0, 192),     /* blue */
444                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
445                 MAKE_RGB24(rgb, 192, 0, 192),   /* magenta */
446                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
447                 MAKE_RGB24(rgb, 0, 192, 192),   /* cyan */
448                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
449                 MAKE_RGB24(rgb, 192, 192, 192), /* grey */
450         };
451         const struct color_rgb24 colors_bottom[] = {
452                 MAKE_RGB24(rgb, 0, 33, 76),     /* in-phase */
453                 MAKE_RGB24(rgb, 255, 255, 255), /* super white */
454                 MAKE_RGB24(rgb, 50, 0, 106),    /* quadrature */
455                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
456                 MAKE_RGB24(rgb, 9, 9, 9),       /* 3.5% */
457                 MAKE_RGB24(rgb, 19, 19, 19),    /* 7.5% */
458                 MAKE_RGB24(rgb, 29, 29, 29),    /* 11.5% */
459                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
460         };
461         unsigned int x;
462         unsigned int y;
464         for (y = 0; y < height * 6 / 9; ++y) {
465                 for (x = 0; x < width; ++x)
466                         ((struct color_rgb24 *)mem)[x] =
467                                 colors_top[x * 7 / width];
468                 mem += stride;
469         }
471         for (; y < height * 7 / 9; ++y) {
472                 for (x = 0; x < width; ++x)
473                         ((struct color_rgb24 *)mem)[x] =
474                                 colors_middle[x * 7 / width];
475                 mem += stride;
476         }
478         for (; y < height; ++y) {
479                 for (x = 0; x < width * 5 / 7; ++x)
480                         ((struct color_rgb24 *)mem)[x] =
481                                 colors_bottom[x * 4 / (width * 5 / 7)];
482                 for (; x < width * 6 / 7; ++x)
483                         ((struct color_rgb24 *)mem)[x] =
484                                 colors_bottom[(x - width * 5 / 7) * 3
485                                               / (width / 7) + 4];
486                 for (; x < width; ++x)
487                         ((struct color_rgb24 *)mem)[x] = colors_bottom[7];
488                 mem += stride;
489         }
492 static void
493 fill_smpte_rgb32(const struct rgb_info *rgb, unsigned char *mem,
494                  unsigned int width, unsigned int height, unsigned int stride)
496         const uint32_t colors_top[] = {
497                 MAKE_RGBA(rgb, 192, 192, 192, 255),     /* grey */
498                 MAKE_RGBA(rgb, 192, 192, 0, 255),       /* yellow */
499                 MAKE_RGBA(rgb, 0, 192, 192, 255),       /* cyan */
500                 MAKE_RGBA(rgb, 0, 192, 0, 255),         /* green */
501                 MAKE_RGBA(rgb, 192, 0, 192, 255),       /* magenta */
502                 MAKE_RGBA(rgb, 192, 0, 0, 255),         /* red */
503                 MAKE_RGBA(rgb, 0, 0, 192, 255),         /* blue */
504         };
505         const uint32_t colors_middle[] = {
506                 MAKE_RGBA(rgb, 0, 0, 192, 255),         /* blue */
507                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
508                 MAKE_RGBA(rgb, 192, 0, 192, 255),       /* magenta */
509                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
510                 MAKE_RGBA(rgb, 0, 192, 192, 255),       /* cyan */
511                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
512                 MAKE_RGBA(rgb, 192, 192, 192, 255),     /* grey */
513         };
514         const uint32_t colors_bottom[] = {
515                 MAKE_RGBA(rgb, 0, 33, 76, 255),         /* in-phase */
516                 MAKE_RGBA(rgb, 255, 255, 255, 255),     /* super white */
517                 MAKE_RGBA(rgb, 50, 0, 106, 255),        /* quadrature */
518                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
519                 MAKE_RGBA(rgb, 9, 9, 9, 255),           /* 3.5% */
520                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* 7.5% */
521                 MAKE_RGBA(rgb, 29, 29, 29, 255),        /* 11.5% */
522                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
523         };
524         unsigned int x;
525         unsigned int y;
527         for (y = 0; y < height * 6 / 9; ++y) {
528                 for (x = 0; x < width; ++x)
529                         ((uint32_t *)mem)[x] = colors_top[x * 7 / width];
530                 mem += stride;
531         }
533         for (; y < height * 7 / 9; ++y) {
534                 for (x = 0; x < width; ++x)
535                         ((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
536                 mem += stride;
537         }
539         for (; y < height; ++y) {
540                 for (x = 0; x < width * 5 / 7; ++x)
541                         ((uint32_t *)mem)[x] =
542                                 colors_bottom[x * 4 / (width * 5 / 7)];
543                 for (; x < width * 6 / 7; ++x)
544                         ((uint32_t *)mem)[x] =
545                                 colors_bottom[(x - width * 5 / 7) * 3
546                                               / (width / 7) + 4];
547                 for (; x < width; ++x)
548                         ((uint32_t *)mem)[x] = colors_bottom[7];
549                 mem += stride;
550         }
553 static void
554 fill_smpte(const struct format_info *info, void *planes[3], unsigned int width,
555            unsigned int height, unsigned int stride)
557         unsigned char *u, *v;
559         switch (info->format) {
560         case DRM_FORMAT_UYVY:
561         case DRM_FORMAT_VYUY:
562         case DRM_FORMAT_YUYV:
563         case DRM_FORMAT_YVYU:
564                 return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
565                                              height, stride);
567         case DRM_FORMAT_NV12:
568         case DRM_FORMAT_NV21:
569         case DRM_FORMAT_NV16:
570         case DRM_FORMAT_NV61:
571                 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
572                 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
573                 return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
574                                              width, height, stride);
576         case DRM_FORMAT_YVU420:
577                 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
578                                              planes[2], width, height, stride);
580         case DRM_FORMAT_RGB565:
581         case DRM_FORMAT_ARGB1555:
582         case DRM_FORMAT_XRGB1555:
583                 return fill_smpte_rgb16(&info->rgb, planes[0],
584                                         width, height, stride);
585         case DRM_FORMAT_BGR888:
586         case DRM_FORMAT_RGB888:
587                 return fill_smpte_rgb24(&info->rgb, planes[0],
588                                         width, height, stride);
589         case DRM_FORMAT_ARGB8888:
590         case DRM_FORMAT_BGRA8888:
591         case DRM_FORMAT_XRGB8888:
592         case DRM_FORMAT_BGRX8888:
593                 return fill_smpte_rgb32(&info->rgb, planes[0],
594                                         width, height, stride);
595         }
598 /* swap these for big endian.. */
599 #define RED   2
600 #define GREEN 1
601 #define BLUE  0
603 static void
604 make_pwetty(void *data, int width, int height, int stride)
606 #ifdef HAVE_CAIRO
607         cairo_surface_t *surface;
608         cairo_t *cr;
609         int x, y;
611         surface = cairo_image_surface_create_for_data(data,
612                                                       CAIRO_FORMAT_ARGB32,
613                                                       width, height,
614                                                       stride);
615         cr = cairo_create(surface);
616         cairo_surface_destroy(surface);
618         cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
619         for (x = 0; x < width; x += 250)
620                 for (y = 0; y < height; y += 250) {
621                         char buf[64];
623                         cairo_move_to(cr, x, y - 20);
624                         cairo_line_to(cr, x, y + 20);
625                         cairo_move_to(cr, x - 20, y);
626                         cairo_line_to(cr, x + 20, y);
627                         cairo_new_sub_path(cr);
628                         cairo_arc(cr, x, y, 10, 0, M_PI * 2);
629                         cairo_set_line_width(cr, 4);
630                         cairo_set_source_rgb(cr, 0, 0, 0);
631                         cairo_stroke_preserve(cr);
632                         cairo_set_source_rgb(cr, 1, 1, 1);
633                         cairo_set_line_width(cr, 2);
634                         cairo_stroke(cr);
636                         snprintf(buf, sizeof buf, "%d, %d", x, y);
637                         cairo_move_to(cr, x + 20, y + 20);
638                         cairo_text_path(cr, buf);
639                         cairo_set_source_rgb(cr, 0, 0, 0);
640                         cairo_stroke_preserve(cr);
641                         cairo_set_source_rgb(cr, 1, 1, 1);
642                         cairo_fill(cr);
643                 }
645         cairo_destroy(cr);
646 #endif
649 static void
650 fill_tiles_yuv_planar(const struct yuv_info *yuv,
651                       unsigned char *y_mem, unsigned char *u_mem,
652                       unsigned char *v_mem, unsigned int width,
653                       unsigned int height, unsigned int stride)
655         unsigned int cs = yuv->chroma_stride;
656         unsigned int xsub = yuv->xsub;
657         unsigned int ysub = yuv->ysub;
658         unsigned int x;
659         unsigned int y;
661         for (y = 0; y < height; ++y) {
662                 for (x = 0; x < width; ++x) {
663                         div_t d = div(x+y, width);
664                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
665                                        + 0x000a1120 * (d.rem >> 6);
666                         struct color_yuv color =
667                                 MAKE_YUV_601((rgb32 >> 16) & 0xff,
668                                              (rgb32 >> 8) & 0xff, rgb32 & 0xff);
670                         y_mem[x] = color.y;
671                         u_mem[x/xsub*cs] = color.u;
672                         v_mem[x/xsub*cs] = color.v;
673                 }
675                 y_mem += stride;
676                 if ((y + 1) % ysub == 0) {
677                         u_mem += stride * cs / xsub;
678                         v_mem += stride * cs / xsub;
679                 }
680         }
683 static void
684 fill_tiles_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
685                       unsigned int width, unsigned int height,
686                       unsigned int stride)
688         unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
689         unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
690         unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
691         unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
692         unsigned int x;
693         unsigned int y;
695         for (y = 0; y < height; ++y) {
696                 for (x = 0; x < width; x += 2) {
697                         div_t d = div(x+y, width);
698                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
699                                        + 0x000a1120 * (d.rem >> 6);
700                         struct color_yuv color =
701                                 MAKE_YUV_601((rgb32 >> 16) & 0xff,
702                                              (rgb32 >> 8) & 0xff, rgb32 & 0xff);
704                         y_mem[2*x] = color.y;
705                         c_mem[2*x+u] = color.u;
706                         y_mem[2*x+2] = color.y;
707                         c_mem[2*x+v] = color.v;
708                 }
710                 y_mem += stride;
711                 c_mem += stride;
712         }
715 static void
716 fill_tiles_rgb16(const struct rgb_info *rgb, unsigned char *mem,
717                  unsigned int width, unsigned int height, unsigned int stride)
719         unsigned int x, y;
721         for (y = 0; y < height; ++y) {
722                 for (x = 0; x < width; ++x) {
723                         div_t d = div(x+y, width);
724                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
725                                        + 0x000a1120 * (d.rem >> 6);
726                         uint16_t color =
727                                 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
728                                           (rgb32 >> 8) & 0xff, rgb32 & 0xff,
729                                           255);
731                         ((uint16_t *)mem)[x] = color;
732                 }
733                 mem += stride;
734         }
737 static void
738 fill_tiles_rgb24(const struct rgb_info *rgb, unsigned char *mem,
739                  unsigned int width, unsigned int height, unsigned int stride)
741         unsigned int x, y;
743         for (y = 0; y < height; ++y) {
744                 for (x = 0; x < width; ++x) {
745                         div_t d = div(x+y, width);
746                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
747                                        + 0x000a1120 * (d.rem >> 6);
748                         struct color_rgb24 color =
749                                 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
750                                            (rgb32 >> 8) & 0xff, rgb32 & 0xff);
752                         ((struct color_rgb24 *)mem)[x] = color;
753                 }
754                 mem += stride;
755         }
758 static void
759 fill_tiles_rgb32(const struct rgb_info *rgb, unsigned char *mem,
760                  unsigned int width, unsigned int height, unsigned int stride)
762         unsigned char *mem_base = mem;
763         unsigned int x, y;
765         for (y = 0; y < height; ++y) {
766                 for (x = 0; x < width; ++x) {
767                         div_t d = div(x+y, width);
768                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
769                                        + 0x000a1120 * (d.rem >> 6);
770                         uint32_t color =
771                                 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
772                                           (rgb32 >> 8) & 0xff, rgb32 & 0xff,
773                                           255);
775                         ((uint32_t *)mem)[x] = color;
776                 }
777                 mem += stride;
778         }
780         make_pwetty(mem_base, width, height, stride);
783 static void
784 fill_tiles(const struct format_info *info, void *planes[3], unsigned int width,
785            unsigned int height, unsigned int stride)
787         unsigned char *u, *v;
789         switch (info->format) {
790         case DRM_FORMAT_UYVY:
791         case DRM_FORMAT_VYUY:
792         case DRM_FORMAT_YUYV:
793         case DRM_FORMAT_YVYU:
794                 return fill_tiles_yuv_packed(&info->yuv, planes[0],
795                                              width, height, stride);
797         case DRM_FORMAT_NV12:
798         case DRM_FORMAT_NV21:
799         case DRM_FORMAT_NV16:
800         case DRM_FORMAT_NV61:
801                 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
802                 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
803                 return fill_tiles_yuv_planar(&info->yuv, planes[0], u, v,
804                                              width, height, stride);
806         case DRM_FORMAT_YVU420:
807                 return fill_tiles_yuv_planar(&info->yuv, planes[0], planes[1],
808                                              planes[2], width, height, stride);
810         case DRM_FORMAT_RGB565:
811         case DRM_FORMAT_ARGB1555:
812         case DRM_FORMAT_XRGB1555:
813                 return fill_tiles_rgb16(&info->rgb, planes[0],
814                                         width, height, stride);
815         case DRM_FORMAT_BGR888:
816         case DRM_FORMAT_RGB888:
817                 return fill_tiles_rgb24(&info->rgb, planes[0],
818                                         width, height, stride);
819         case DRM_FORMAT_ARGB8888:
820         case DRM_FORMAT_BGRA8888:
821         case DRM_FORMAT_XRGB8888:
822         case DRM_FORMAT_BGRX8888:
823                 return fill_tiles_rgb32(&info->rgb, planes[0],
824                                         width, height, stride);
825         }
828 static void
829 fill_plain(const struct format_info *info, void *planes[3], unsigned int width,
830            unsigned int height, unsigned int stride)
832         memset(planes[0], 0x77, stride * height);
835 /*
836  * fill_pattern - Fill a buffer with a test pattern
837  * @format: Pixel format
838  * @pattern: Test pattern
839  * @buffer: Buffer memory
840  * @width: Width in pixels
841  * @height: Height in pixels
842  * @stride: Line stride (pitch) in bytes
843  *
844  * Fill the buffer with the test pattern specified by the pattern parameter.
845  * Supported formats vary depending on the selected pattern.
846  */
847 static void
848 fill_pattern(unsigned int format, enum fill_pattern pattern, void *planes[3],
849              unsigned int width, unsigned int height, unsigned int stride)
851         const struct format_info *info = NULL;
852         unsigned int i;
854         for (i = 0; i < ARRAY_SIZE(format_info); ++i) {
855                 if (format_info[i].format == format) {
856                         info = &format_info[i];
857                         break;
858                 }
859         }
861         if (info == NULL)
862                 return;
864         switch (pattern) {
865         case PATTERN_TILES:
866                 return fill_tiles(info, planes, width, height, stride);
868         case PATTERN_SMPTE:
869                 return fill_smpte(info, planes, width, height, stride);
871         case PATTERN_PLAIN:
872                 return fill_plain(info, planes, width, height, stride);
874         default:
875                 printf("Error: unsupported test pattern %u.\n", pattern);
876                 break;
877         }
880 /* -----------------------------------------------------------------------------
881  * Buffers management
882  */
884 static struct kms_bo *
885 allocate_buffer(struct kms_driver *kms,
886                 int width, int height, int *stride)
888         struct kms_bo *bo;
889         unsigned bo_attribs[] = {
890                 KMS_WIDTH,   0,
891                 KMS_HEIGHT,  0,
892                 KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
893                 KMS_TERMINATE_PROP_LIST
894         };
895         int ret;
897         bo_attribs[1] = width;
898         bo_attribs[3] = height;
900         ret = kms_bo_create(kms, bo_attribs, &bo);
901         if (ret) {
902                 fprintf(stderr, "failed to alloc buffer: %s\n",
903                         strerror(-ret));
904                 return NULL;
905         }
907         ret = kms_bo_get_prop(bo, KMS_PITCH, stride);
908         if (ret) {
909                 fprintf(stderr, "failed to retreive buffer stride: %s\n",
910                         strerror(-ret));
911                 kms_bo_destroy(&bo);
912                 return NULL;
913         }
915         return bo;
918 struct kms_bo *
919 create_test_buffer(struct kms_driver *kms, unsigned int format,
920                    int width, int height, int handles[4],
921                    int pitches[4], int offsets[4], enum fill_pattern pattern)
923         struct kms_bo *bo;
924         int ret, stride;
925         void *planes[3];
926         void *virtual;
928         bo = allocate_buffer(kms, width, height, &pitches[0]);
929         if (!bo)
930                 return NULL;
932         ret = kms_bo_map(bo, &virtual);
933         if (ret) {
934                 fprintf(stderr, "failed to map buffer: %s\n",
935                         strerror(-ret));
936                 kms_bo_destroy(&bo);
937                 return NULL;
938         }
940         /* just testing a limited # of formats to test single
941          * and multi-planar path.. would be nice to add more..
942          */
943         switch (format) {
944         case DRM_FORMAT_UYVY:
945         case DRM_FORMAT_VYUY:
946         case DRM_FORMAT_YUYV:
947         case DRM_FORMAT_YVYU:
948                 pitches[0] = width * 2;
949                 offsets[0] = 0;
950                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
952                 planes[0] = virtual;
953                 break;
955         case DRM_FORMAT_NV12:
956         case DRM_FORMAT_NV21:
957         case DRM_FORMAT_NV16:
958         case DRM_FORMAT_NV61:
959                 pitches[0] = width;
960                 offsets[0] = 0;
961                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
962                 pitches[1] = width;
963                 offsets[1] = width * height;
964                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
966                 planes[0] = virtual;
967                 planes[1] = virtual + offsets[1];
968                 break;
970         case DRM_FORMAT_YVU420:
971                 pitches[0] = width;
972                 offsets[0] = 0;
973                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
974                 pitches[1] = width / 2;
975                 offsets[1] = width * height;
976                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
977                 pitches[2] = width / 2;
978                 offsets[2] = offsets[1] + (width * height) / 4;
979                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]);
981                 planes[0] = virtual;
982                 planes[1] = virtual + offsets[1];
983                 planes[2] = virtual + offsets[2];
984                 break;
986         case DRM_FORMAT_RGB565:
987         case DRM_FORMAT_ARGB1555:
988         case DRM_FORMAT_XRGB1555:
989                 pitches[0] = width * 2;
990                 offsets[0] = 0;
991                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
993                 planes[0] = virtual;
994                 break;
996         case DRM_FORMAT_BGR888:
997         case DRM_FORMAT_RGB888:
998                 pitches[0] = width * 3;
999                 offsets[0] = 0;
1000                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
1002                 planes[0] = virtual;
1003                 break;
1005         case DRM_FORMAT_ARGB8888:
1006         case DRM_FORMAT_BGRA8888:
1007         case DRM_FORMAT_XRGB8888:
1008         case DRM_FORMAT_BGRX8888:
1009                 pitches[0] = width * 4;
1010                 offsets[0] = 0;
1011                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
1013                 planes[0] = virtual;
1014                 break;
1015         }
1017         fill_pattern(format, pattern, planes, width, height, pitches[0]);
1018         kms_bo_unmap(bo);
1020         return bo;