OSDN Git Service

modetest: Fix warnings
[android-x86/external-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  */
26
27 #include "config.h"
28
29 #include <assert.h>
30 #include <errno.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdint.h>
34 #include <string.h>
35
36 #include "drm_fourcc.h"
37 #include "libkms.h"
38
39 #include "buffers.h"
40
41 #ifdef HAVE_CAIRO
42 #include <math.h>
43 #include <cairo.h>
44 #endif
45
46 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
47
48 /* -----------------------------------------------------------------------------
49  * Formats
50  */
51
52 struct color_component {
53         unsigned int length;
54         unsigned int offset;
55 };
56
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 };
63
64 enum yuv_order {
65         YUV_YCbCr = 1,
66         YUV_YCrCb = 2,
67         YUV_YC = 4,
68         YUV_CY = 8,
69 };
70
71 struct yuv_info {
72         enum yuv_order order;
73         unsigned int xsub;
74         unsigned int ysub;
75         unsigned int chroma_stride;
76 };
77
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 };
84
85 #define MAKE_RGB_INFO(rl, ro, bl, bo, gl, go, al, ao) \
86         .rgb = { { (rl), (ro) }, { (bl), (bo) }, { (gl), (go) }, { (al), (ao) } }
87
88 #define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \
89         .yuv = { (order), (xsub), (ysub), (chroma_stride) }
90
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_YUV420, "YU12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 1) },
104         { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) },
105         /* RGB16 */
106         { DRM_FORMAT_ARGB4444, "AR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 4, 12) },
107         { DRM_FORMAT_XRGB4444, "XR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 0, 0) },
108         { DRM_FORMAT_ABGR4444, "AB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 4, 12) },
109         { DRM_FORMAT_XBGR4444, "XB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 0, 0) },
110         { DRM_FORMAT_RGBA4444, "RA12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 4, 0) },
111         { DRM_FORMAT_RGBX4444, "RX12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 0, 0) },
112         { DRM_FORMAT_BGRA4444, "BA12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 4, 0) },
113         { DRM_FORMAT_BGRX4444, "BX12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 0, 0) },
114         { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) },
115         { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
116         { DRM_FORMAT_ABGR1555, "AB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 1, 15) },
117         { DRM_FORMAT_XBGR1555, "XB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 0, 0) },
118         { DRM_FORMAT_RGBA5551, "RA15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 1, 0) },
119         { DRM_FORMAT_RGBX5551, "RX15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 0, 0) },
120         { DRM_FORMAT_BGRA5551, "BA15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 1, 0) },
121         { DRM_FORMAT_BGRX5551, "BX15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 0, 0) },
122         { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
123         { DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) },
124         /* RGB24 */
125         { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
126         { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
127         /* RGB32 */
128         { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
129         { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
130         { DRM_FORMAT_ABGR8888, "AB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 8, 24) },
131         { DRM_FORMAT_XBGR8888, "XB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
132         { DRM_FORMAT_RGBA8888, "RA24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 8, 0) },
133         { DRM_FORMAT_RGBX8888, "RX24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 0, 0) },
134         { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) },
135         { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
136         { DRM_FORMAT_ARGB2101010, "AR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 2, 30) },
137         { DRM_FORMAT_XRGB2101010, "XR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 0, 0) },
138         { DRM_FORMAT_ABGR2101010, "AB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 2, 30) },
139         { DRM_FORMAT_XBGR2101010, "XB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 0, 0) },
140         { DRM_FORMAT_RGBA1010102, "RA30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 2, 0) },
141         { DRM_FORMAT_RGBX1010102, "RX30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 0, 0) },
142         { DRM_FORMAT_BGRA1010102, "BA30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 2, 0) },
143         { DRM_FORMAT_BGRX1010102, "BX30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 0, 0) },
144 };
145
146 unsigned int format_fourcc(const char *name)
147 {
148         unsigned int i;
149         for (i = 0; i < ARRAY_SIZE(format_info); i++) {
150                 if (!strcmp(format_info[i].name, name))
151                         return format_info[i].format;
152         }
153         return 0;
154 }
155
156 /* -----------------------------------------------------------------------------
157  * Test patterns
158  */
159
160 struct color_rgb24 {
161         unsigned int value:24;
162 } __attribute__((__packed__));
163
164 struct color_yuv {
165         unsigned char y;
166         unsigned char u;
167         unsigned char v;
168 };
169
170 #define MAKE_YUV_601_Y(r, g, b) \
171         ((( 66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
172 #define MAKE_YUV_601_U(r, g, b) \
173         (((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
174 #define MAKE_YUV_601_V(r, g, b) \
175         (((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
176
177 #define MAKE_YUV_601(r, g, b) \
178         { .y = MAKE_YUV_601_Y(r, g, b), \
179           .u = MAKE_YUV_601_U(r, g, b), \
180           .v = MAKE_YUV_601_V(r, g, b) }
181
182 #define MAKE_RGBA(rgb, r, g, b, a) \
183         ((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \
184          (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \
185          (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \
186          (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset))
187
188 #define MAKE_RGB24(rgb, r, g, b) \
189         { .value = MAKE_RGBA(rgb, r, g, b, 0) }
190
191 static void
192 fill_smpte_yuv_planar(const struct yuv_info *yuv,
193                       unsigned char *y_mem, unsigned char *u_mem,
194                       unsigned char *v_mem, unsigned int width,
195                       unsigned int height, unsigned int stride)
196 {
197         const struct color_yuv colors_top[] = {
198                 MAKE_YUV_601(191, 192, 192),    /* grey */
199                 MAKE_YUV_601(192, 192, 0),      /* yellow */
200                 MAKE_YUV_601(0, 192, 192),      /* cyan */
201                 MAKE_YUV_601(0, 192, 0),        /* green */
202                 MAKE_YUV_601(192, 0, 192),      /* magenta */
203                 MAKE_YUV_601(192, 0, 0),        /* red */
204                 MAKE_YUV_601(0, 0, 192),        /* blue */
205         };
206         const struct color_yuv colors_middle[] = {
207                 MAKE_YUV_601(0, 0, 192),        /* blue */
208                 MAKE_YUV_601(19, 19, 19),       /* black */
209                 MAKE_YUV_601(192, 0, 192),      /* magenta */
210                 MAKE_YUV_601(19, 19, 19),       /* black */
211                 MAKE_YUV_601(0, 192, 192),      /* cyan */
212                 MAKE_YUV_601(19, 19, 19),       /* black */
213                 MAKE_YUV_601(192, 192, 192),    /* grey */
214         };
215         const struct color_yuv colors_bottom[] = {
216                 MAKE_YUV_601(0, 33, 76),        /* in-phase */
217                 MAKE_YUV_601(255, 255, 255),    /* super white */
218                 MAKE_YUV_601(50, 0, 106),       /* quadrature */
219                 MAKE_YUV_601(19, 19, 19),       /* black */
220                 MAKE_YUV_601(9, 9, 9),          /* 3.5% */
221                 MAKE_YUV_601(19, 19, 19),       /* 7.5% */
222                 MAKE_YUV_601(29, 29, 29),       /* 11.5% */
223                 MAKE_YUV_601(19, 19, 19),       /* black */
224         };
225         unsigned int cs = yuv->chroma_stride;
226         unsigned int xsub = yuv->xsub;
227         unsigned int ysub = yuv->ysub;
228         unsigned int x;
229         unsigned int y;
230
231         /* Luma */
232         for (y = 0; y < height * 6 / 9; ++y) {
233                 for (x = 0; x < width; ++x)
234                         y_mem[x] = colors_top[x * 7 / width].y;
235                 y_mem += stride;
236         }
237
238         for (; y < height * 7 / 9; ++y) {
239                 for (x = 0; x < width; ++x)
240                         y_mem[x] = colors_middle[x * 7 / width].y;
241                 y_mem += stride;
242         }
243
244         for (; y < height; ++y) {
245                 for (x = 0; x < width * 5 / 7; ++x)
246                         y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
247                 for (; x < width * 6 / 7; ++x)
248                         y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3
249                                                  / (width / 7) + 4].y;
250                 for (; x < width; ++x)
251                         y_mem[x] = colors_bottom[7].y;
252                 y_mem += stride;
253         }
254
255         /* Chroma */
256         for (y = 0; y < height / ysub * 6 / 9; ++y) {
257                 for (x = 0; x < width; x += xsub) {
258                         u_mem[x*cs/xsub] = colors_top[x * 7 / width].u;
259                         v_mem[x*cs/xsub] = colors_top[x * 7 / width].v;
260                 }
261                 u_mem += stride * cs / xsub;
262                 v_mem += stride * cs / xsub;
263         }
264
265         for (; y < height / ysub * 7 / 9; ++y) {
266                 for (x = 0; x < width; x += xsub) {
267                         u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u;
268                         v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v;
269                 }
270                 u_mem += stride * cs / xsub;
271                 v_mem += stride * cs / xsub;
272         }
273
274         for (; y < height / ysub; ++y) {
275                 for (x = 0; x < width * 5 / 7; x += xsub) {
276                         u_mem[x*cs/xsub] =
277                                 colors_bottom[x * 4 / (width * 5 / 7)].u;
278                         v_mem[x*cs/xsub] =
279                                 colors_bottom[x * 4 / (width * 5 / 7)].v;
280                 }
281                 for (; x < width * 6 / 7; x += xsub) {
282                         u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
283                                                          3 / (width / 7) + 4].u;
284                         v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) *
285                                                          3 / (width / 7) + 4].v;
286                 }
287                 for (; x < width; x += xsub) {
288                         u_mem[x*cs/xsub] = colors_bottom[7].u;
289                         v_mem[x*cs/xsub] = colors_bottom[7].v;
290                 }
291                 u_mem += stride * cs / xsub;
292                 v_mem += stride * cs / xsub;
293         }
294 }
295
296 static void
297 fill_smpte_yuv_packed(const struct yuv_info *yuv, unsigned char *mem,
298                       unsigned int width, unsigned int height,
299                       unsigned int stride)
300 {
301         const struct color_yuv colors_top[] = {
302                 MAKE_YUV_601(191, 192, 192),    /* grey */
303                 MAKE_YUV_601(192, 192, 0),      /* yellow */
304                 MAKE_YUV_601(0, 192, 192),      /* cyan */
305                 MAKE_YUV_601(0, 192, 0),        /* green */
306                 MAKE_YUV_601(192, 0, 192),      /* magenta */
307                 MAKE_YUV_601(192, 0, 0),        /* red */
308                 MAKE_YUV_601(0, 0, 192),        /* blue */
309         };
310         const struct color_yuv colors_middle[] = {
311                 MAKE_YUV_601(0, 0, 192),        /* blue */
312                 MAKE_YUV_601(19, 19, 19),       /* black */
313                 MAKE_YUV_601(192, 0, 192),      /* magenta */
314                 MAKE_YUV_601(19, 19, 19),       /* black */
315                 MAKE_YUV_601(0, 192, 192),      /* cyan */
316                 MAKE_YUV_601(19, 19, 19),       /* black */
317                 MAKE_YUV_601(192, 192, 192),    /* grey */
318         };
319         const struct color_yuv colors_bottom[] = {
320                 MAKE_YUV_601(0, 33, 76),        /* in-phase */
321                 MAKE_YUV_601(255, 255, 255),    /* super white */
322                 MAKE_YUV_601(50, 0, 106),       /* quadrature */
323                 MAKE_YUV_601(19, 19, 19),       /* black */
324                 MAKE_YUV_601(9, 9, 9),          /* 3.5% */
325                 MAKE_YUV_601(19, 19, 19),       /* 7.5% */
326                 MAKE_YUV_601(29, 29, 29),       /* 11.5% */
327                 MAKE_YUV_601(19, 19, 19),       /* black */
328         };
329         unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
330         unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
331         unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
332         unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
333         unsigned int x;
334         unsigned int y;
335
336         /* Luma */
337         for (y = 0; y < height * 6 / 9; ++y) {
338                 for (x = 0; x < width; ++x)
339                         y_mem[2*x] = colors_top[x * 7 / width].y;
340                 y_mem += stride * 2;
341         }
342
343         for (; y < height * 7 / 9; ++y) {
344                 for (x = 0; x < width; ++x)
345                         y_mem[2*x] = colors_middle[x * 7 / width].y;
346                 y_mem += stride * 2;
347         }
348
349         for (; y < height; ++y) {
350                 for (x = 0; x < width * 5 / 7; ++x)
351                         y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
352                 for (; x < width * 6 / 7; ++x)
353                         y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3
354                                                    / (width / 7) + 4].y;
355                 for (; x < width; ++x)
356                         y_mem[2*x] = colors_bottom[7].y;
357                 y_mem += stride * 2;
358         }
359
360         /* Chroma */
361         for (y = 0; y < height * 6 / 9; ++y) {
362                 for (x = 0; x < width; x += 2) {
363                         c_mem[2*x+u] = colors_top[x * 7 / width].u;
364                         c_mem[2*x+v] = colors_top[x * 7 / width].v;
365                 }
366                 c_mem += stride * 2;
367         }
368
369         for (; y < height * 7 / 9; ++y) {
370                 for (x = 0; x < width; x += 2) {
371                         c_mem[2*x+u] = colors_middle[x * 7 / width].u;
372                         c_mem[2*x+v] = colors_middle[x * 7 / width].v;
373                 }
374                 c_mem += stride * 2;
375         }
376
377         for (; y < height; ++y) {
378                 for (x = 0; x < width * 5 / 7; x += 2) {
379                         c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u;
380                         c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v;
381                 }
382                 for (; x < width * 6 / 7; x += 2) {
383                         c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) *
384                                                      3 / (width / 7) + 4].u;
385                         c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) *
386                                                      3 / (width / 7) + 4].v;
387                 }
388                 for (; x < width; x += 2) {
389                         c_mem[2*x+u] = colors_bottom[7].u;
390                         c_mem[2*x+v] = colors_bottom[7].v;
391                 }
392                 c_mem += stride * 2;
393         }
394 }
395
396 static void
397 fill_smpte_rgb16(const struct rgb_info *rgb, unsigned char *mem,
398                  unsigned int width, unsigned int height, unsigned int stride)
399 {
400         const uint16_t colors_top[] = {
401                 MAKE_RGBA(rgb, 192, 192, 192, 255),     /* grey */
402                 MAKE_RGBA(rgb, 192, 192, 0, 255),       /* yellow */
403                 MAKE_RGBA(rgb, 0, 192, 192, 255),       /* cyan */
404                 MAKE_RGBA(rgb, 0, 192, 0, 255),         /* green */
405                 MAKE_RGBA(rgb, 192, 0, 192, 255),       /* magenta */
406                 MAKE_RGBA(rgb, 192, 0, 0, 255),         /* red */
407                 MAKE_RGBA(rgb, 0, 0, 192, 255),         /* blue */
408         };
409         const uint16_t colors_middle[] = {
410                 MAKE_RGBA(rgb, 0, 0, 192, 255),         /* blue */
411                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
412                 MAKE_RGBA(rgb, 192, 0, 192, 255),       /* magenta */
413                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
414                 MAKE_RGBA(rgb, 0, 192, 192, 255),       /* cyan */
415                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
416                 MAKE_RGBA(rgb, 192, 192, 192, 255),     /* grey */
417         };
418         const uint16_t colors_bottom[] = {
419                 MAKE_RGBA(rgb, 0, 33, 76, 255),         /* in-phase */
420                 MAKE_RGBA(rgb, 255, 255, 255, 255),     /* super white */
421                 MAKE_RGBA(rgb, 50, 0, 106, 255),        /* quadrature */
422                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
423                 MAKE_RGBA(rgb, 9, 9, 9, 255),           /* 3.5% */
424                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* 7.5% */
425                 MAKE_RGBA(rgb, 29, 29, 29, 255),        /* 11.5% */
426                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
427         };
428         unsigned int x;
429         unsigned int y;
430
431         for (y = 0; y < height * 6 / 9; ++y) {
432                 for (x = 0; x < width; ++x)
433                         ((uint16_t *)mem)[x] = colors_top[x * 7 / width];
434                 mem += stride;
435         }
436
437         for (; y < height * 7 / 9; ++y) {
438                 for (x = 0; x < width; ++x)
439                         ((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
440                 mem += stride;
441         }
442
443         for (; y < height; ++y) {
444                 for (x = 0; x < width * 5 / 7; ++x)
445                         ((uint16_t *)mem)[x] =
446                                 colors_bottom[x * 4 / (width * 5 / 7)];
447                 for (; x < width * 6 / 7; ++x)
448                         ((uint16_t *)mem)[x] =
449                                 colors_bottom[(x - width * 5 / 7) * 3
450                                               / (width / 7) + 4];
451                 for (; x < width; ++x)
452                         ((uint16_t *)mem)[x] = colors_bottom[7];
453                 mem += stride;
454         }
455 }
456
457 static void
458 fill_smpte_rgb24(const struct rgb_info *rgb, void *mem,
459                  unsigned int width, unsigned int height, unsigned int stride)
460 {
461         const struct color_rgb24 colors_top[] = {
462                 MAKE_RGB24(rgb, 192, 192, 192), /* grey */
463                 MAKE_RGB24(rgb, 192, 192, 0),   /* yellow */
464                 MAKE_RGB24(rgb, 0, 192, 192),   /* cyan */
465                 MAKE_RGB24(rgb, 0, 192, 0),     /* green */
466                 MAKE_RGB24(rgb, 192, 0, 192),   /* magenta */
467                 MAKE_RGB24(rgb, 192, 0, 0),     /* red */
468                 MAKE_RGB24(rgb, 0, 0, 192),     /* blue */
469         };
470         const struct color_rgb24 colors_middle[] = {
471                 MAKE_RGB24(rgb, 0, 0, 192),     /* blue */
472                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
473                 MAKE_RGB24(rgb, 192, 0, 192),   /* magenta */
474                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
475                 MAKE_RGB24(rgb, 0, 192, 192),   /* cyan */
476                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
477                 MAKE_RGB24(rgb, 192, 192, 192), /* grey */
478         };
479         const struct color_rgb24 colors_bottom[] = {
480                 MAKE_RGB24(rgb, 0, 33, 76),     /* in-phase */
481                 MAKE_RGB24(rgb, 255, 255, 255), /* super white */
482                 MAKE_RGB24(rgb, 50, 0, 106),    /* quadrature */
483                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
484                 MAKE_RGB24(rgb, 9, 9, 9),       /* 3.5% */
485                 MAKE_RGB24(rgb, 19, 19, 19),    /* 7.5% */
486                 MAKE_RGB24(rgb, 29, 29, 29),    /* 11.5% */
487                 MAKE_RGB24(rgb, 19, 19, 19),    /* black */
488         };
489         unsigned int x;
490         unsigned int y;
491
492         for (y = 0; y < height * 6 / 9; ++y) {
493                 for (x = 0; x < width; ++x)
494                         ((struct color_rgb24 *)mem)[x] =
495                                 colors_top[x * 7 / width];
496                 mem += stride;
497         }
498
499         for (; y < height * 7 / 9; ++y) {
500                 for (x = 0; x < width; ++x)
501                         ((struct color_rgb24 *)mem)[x] =
502                                 colors_middle[x * 7 / width];
503                 mem += stride;
504         }
505
506         for (; y < height; ++y) {
507                 for (x = 0; x < width * 5 / 7; ++x)
508                         ((struct color_rgb24 *)mem)[x] =
509                                 colors_bottom[x * 4 / (width * 5 / 7)];
510                 for (; x < width * 6 / 7; ++x)
511                         ((struct color_rgb24 *)mem)[x] =
512                                 colors_bottom[(x - width * 5 / 7) * 3
513                                               / (width / 7) + 4];
514                 for (; x < width; ++x)
515                         ((struct color_rgb24 *)mem)[x] = colors_bottom[7];
516                 mem += stride;
517         }
518 }
519
520 static void
521 fill_smpte_rgb32(const struct rgb_info *rgb, unsigned char *mem,
522                  unsigned int width, unsigned int height, unsigned int stride)
523 {
524         const uint32_t colors_top[] = {
525                 MAKE_RGBA(rgb, 192, 192, 192, 255),     /* grey */
526                 MAKE_RGBA(rgb, 192, 192, 0, 255),       /* yellow */
527                 MAKE_RGBA(rgb, 0, 192, 192, 255),       /* cyan */
528                 MAKE_RGBA(rgb, 0, 192, 0, 255),         /* green */
529                 MAKE_RGBA(rgb, 192, 0, 192, 255),       /* magenta */
530                 MAKE_RGBA(rgb, 192, 0, 0, 255),         /* red */
531                 MAKE_RGBA(rgb, 0, 0, 192, 255),         /* blue */
532         };
533         const uint32_t colors_middle[] = {
534                 MAKE_RGBA(rgb, 0, 0, 192, 255),         /* blue */
535                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
536                 MAKE_RGBA(rgb, 192, 0, 192, 255),       /* magenta */
537                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
538                 MAKE_RGBA(rgb, 0, 192, 192, 255),       /* cyan */
539                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
540                 MAKE_RGBA(rgb, 192, 192, 192, 255),     /* grey */
541         };
542         const uint32_t colors_bottom[] = {
543                 MAKE_RGBA(rgb, 0, 33, 76, 255),         /* in-phase */
544                 MAKE_RGBA(rgb, 255, 255, 255, 255),     /* super white */
545                 MAKE_RGBA(rgb, 50, 0, 106, 255),        /* quadrature */
546                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
547                 MAKE_RGBA(rgb, 9, 9, 9, 255),           /* 3.5% */
548                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* 7.5% */
549                 MAKE_RGBA(rgb, 29, 29, 29, 255),        /* 11.5% */
550                 MAKE_RGBA(rgb, 19, 19, 19, 255),        /* black */
551         };
552         unsigned int x;
553         unsigned int y;
554
555         for (y = 0; y < height * 6 / 9; ++y) {
556                 for (x = 0; x < width; ++x)
557                         ((uint32_t *)mem)[x] = colors_top[x * 7 / width];
558                 mem += stride;
559         }
560
561         for (; y < height * 7 / 9; ++y) {
562                 for (x = 0; x < width; ++x)
563                         ((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
564                 mem += stride;
565         }
566
567         for (; y < height; ++y) {
568                 for (x = 0; x < width * 5 / 7; ++x)
569                         ((uint32_t *)mem)[x] =
570                                 colors_bottom[x * 4 / (width * 5 / 7)];
571                 for (; x < width * 6 / 7; ++x)
572                         ((uint32_t *)mem)[x] =
573                                 colors_bottom[(x - width * 5 / 7) * 3
574                                               / (width / 7) + 4];
575                 for (; x < width; ++x)
576                         ((uint32_t *)mem)[x] = colors_bottom[7];
577                 mem += stride;
578         }
579 }
580
581 static void
582 fill_smpte(const struct format_info *info, void *planes[3], unsigned int width,
583            unsigned int height, unsigned int stride)
584 {
585         unsigned char *u, *v;
586
587         switch (info->format) {
588         case DRM_FORMAT_UYVY:
589         case DRM_FORMAT_VYUY:
590         case DRM_FORMAT_YUYV:
591         case DRM_FORMAT_YVYU:
592                 return fill_smpte_yuv_packed(&info->yuv, planes[0], width,
593                                              height, stride);
594
595         case DRM_FORMAT_NV12:
596         case DRM_FORMAT_NV21:
597         case DRM_FORMAT_NV16:
598         case DRM_FORMAT_NV61:
599                 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
600                 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
601                 return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
602                                              width, height, stride);
603
604         case DRM_FORMAT_YUV420:
605                 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1],
606                                              planes[2], width, height, stride);
607
608         case DRM_FORMAT_YVU420:
609                 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2],
610                                              planes[1], width, height, stride);
611
612         case DRM_FORMAT_ARGB4444:
613         case DRM_FORMAT_XRGB4444:
614         case DRM_FORMAT_ABGR4444:
615         case DRM_FORMAT_XBGR4444:
616         case DRM_FORMAT_RGBA4444:
617         case DRM_FORMAT_RGBX4444:
618         case DRM_FORMAT_BGRA4444:
619         case DRM_FORMAT_BGRX4444:
620         case DRM_FORMAT_RGB565:
621         case DRM_FORMAT_BGR565:
622         case DRM_FORMAT_ARGB1555:
623         case DRM_FORMAT_XRGB1555:
624         case DRM_FORMAT_ABGR1555:
625         case DRM_FORMAT_XBGR1555:
626         case DRM_FORMAT_RGBA5551:
627         case DRM_FORMAT_RGBX5551:
628         case DRM_FORMAT_BGRA5551:
629         case DRM_FORMAT_BGRX5551:
630                 return fill_smpte_rgb16(&info->rgb, planes[0],
631                                         width, height, stride);
632
633         case DRM_FORMAT_BGR888:
634         case DRM_FORMAT_RGB888:
635                 return fill_smpte_rgb24(&info->rgb, planes[0],
636                                         width, height, stride);
637         case DRM_FORMAT_ARGB8888:
638         case DRM_FORMAT_XRGB8888:
639         case DRM_FORMAT_ABGR8888:
640         case DRM_FORMAT_XBGR8888:
641         case DRM_FORMAT_RGBA8888:
642         case DRM_FORMAT_RGBX8888:
643         case DRM_FORMAT_BGRA8888:
644         case DRM_FORMAT_BGRX8888:
645         case DRM_FORMAT_ARGB2101010:
646         case DRM_FORMAT_XRGB2101010:
647         case DRM_FORMAT_ABGR2101010:
648         case DRM_FORMAT_XBGR2101010:
649         case DRM_FORMAT_RGBA1010102:
650         case DRM_FORMAT_RGBX1010102:
651         case DRM_FORMAT_BGRA1010102:
652         case DRM_FORMAT_BGRX1010102:
653                 return fill_smpte_rgb32(&info->rgb, planes[0],
654                                         width, height, stride);
655         }
656 }
657
658 /* swap these for big endian.. */
659 #define RED   2
660 #define GREEN 1
661 #define BLUE  0
662
663 static void
664 make_pwetty(void *data, int width, int height, int stride, uint32_t format)
665 {
666 #ifdef HAVE_CAIRO
667         cairo_surface_t *surface;
668         cairo_t *cr;
669         int x, y;
670         cairo_format_t cairo_format;
671
672         /* we can ignore the order of R,G,B channels */
673         switch (format) {
674         case DRM_FORMAT_XRGB8888:
675         case DRM_FORMAT_ARGB8888:
676         case DRM_FORMAT_XBGR8888:
677         case DRM_FORMAT_ABGR8888:
678                 cairo_format = CAIRO_FORMAT_ARGB32;
679                 break;
680         case DRM_FORMAT_RGB565:
681         case DRM_FORMAT_BGR565:
682                 cairo_format = CAIRO_FORMAT_RGB16_565;
683                 break;
684         default:
685                 return;
686         }
687
688         surface = cairo_image_surface_create_for_data(data,
689                                                       cairo_format,
690                                                       width, height,
691                                                       stride);
692         cr = cairo_create(surface);
693         cairo_surface_destroy(surface);
694
695         cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
696         for (x = 0; x < width; x += 250)
697                 for (y = 0; y < height; y += 250) {
698                         char buf[64];
699
700                         cairo_move_to(cr, x, y - 20);
701                         cairo_line_to(cr, x, y + 20);
702                         cairo_move_to(cr, x - 20, y);
703                         cairo_line_to(cr, x + 20, y);
704                         cairo_new_sub_path(cr);
705                         cairo_arc(cr, x, y, 10, 0, M_PI * 2);
706                         cairo_set_line_width(cr, 4);
707                         cairo_set_source_rgb(cr, 0, 0, 0);
708                         cairo_stroke_preserve(cr);
709                         cairo_set_source_rgb(cr, 1, 1, 1);
710                         cairo_set_line_width(cr, 2);
711                         cairo_stroke(cr);
712
713                         snprintf(buf, sizeof buf, "%d, %d", x, y);
714                         cairo_move_to(cr, x + 20, y + 20);
715                         cairo_text_path(cr, buf);
716                         cairo_set_source_rgb(cr, 0, 0, 0);
717                         cairo_stroke_preserve(cr);
718                         cairo_set_source_rgb(cr, 1, 1, 1);
719                         cairo_fill(cr);
720                 }
721
722         cairo_destroy(cr);
723 #endif
724 }
725
726 static void
727 fill_tiles_yuv_planar(const struct format_info *info,
728                       unsigned char *y_mem, unsigned char *u_mem,
729                       unsigned char *v_mem, unsigned int width,
730                       unsigned int height, unsigned int stride)
731 {
732         const struct yuv_info *yuv = &info->yuv;
733         unsigned int cs = yuv->chroma_stride;
734         unsigned int xsub = yuv->xsub;
735         unsigned int ysub = yuv->ysub;
736         unsigned int x;
737         unsigned int y;
738
739         for (y = 0; y < height; ++y) {
740                 for (x = 0; x < width; ++x) {
741                         div_t d = div(x+y, width);
742                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
743                                        + 0x000a1120 * (d.rem >> 6);
744                         struct color_yuv color =
745                                 MAKE_YUV_601((rgb32 >> 16) & 0xff,
746                                              (rgb32 >> 8) & 0xff, rgb32 & 0xff);
747
748                         y_mem[x] = color.y;
749                         u_mem[x/xsub*cs] = color.u;
750                         v_mem[x/xsub*cs] = color.v;
751                 }
752
753                 y_mem += stride;
754                 if ((y + 1) % ysub == 0) {
755                         u_mem += stride * cs / xsub;
756                         v_mem += stride * cs / xsub;
757                 }
758         }
759 }
760
761 static void
762 fill_tiles_yuv_packed(const struct format_info *info, unsigned char *mem,
763                       unsigned int width, unsigned int height,
764                       unsigned int stride)
765 {
766         const struct yuv_info *yuv = &info->yuv;
767         unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1;
768         unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1;
769         unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0;
770         unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0;
771         unsigned int x;
772         unsigned int y;
773
774         for (y = 0; y < height; ++y) {
775                 for (x = 0; x < width; x += 2) {
776                         div_t d = div(x+y, width);
777                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
778                                        + 0x000a1120 * (d.rem >> 6);
779                         struct color_yuv color =
780                                 MAKE_YUV_601((rgb32 >> 16) & 0xff,
781                                              (rgb32 >> 8) & 0xff, rgb32 & 0xff);
782
783                         y_mem[2*x] = color.y;
784                         c_mem[2*x+u] = color.u;
785                         y_mem[2*x+2] = color.y;
786                         c_mem[2*x+v] = color.v;
787                 }
788
789                 y_mem += stride;
790                 c_mem += stride;
791         }
792 }
793
794 static void
795 fill_tiles_rgb16(const struct format_info *info, unsigned char *mem,
796                  unsigned int width, unsigned int height, unsigned int stride)
797 {
798         const struct rgb_info *rgb = &info->rgb;
799         unsigned char *mem_base = mem;
800         unsigned int x, y;
801
802         for (y = 0; y < height; ++y) {
803                 for (x = 0; x < width; ++x) {
804                         div_t d = div(x+y, width);
805                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
806                                        + 0x000a1120 * (d.rem >> 6);
807                         uint16_t color =
808                                 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
809                                           (rgb32 >> 8) & 0xff, rgb32 & 0xff,
810                                           255);
811
812                         ((uint16_t *)mem)[x] = color;
813                 }
814                 mem += stride;
815         }
816
817         make_pwetty(mem_base, width, height, stride, info->format);
818 }
819
820 static void
821 fill_tiles_rgb24(const struct format_info *info, unsigned char *mem,
822                  unsigned int width, unsigned int height, unsigned int stride)
823 {
824         const struct rgb_info *rgb = &info->rgb;
825         unsigned int x, y;
826
827         for (y = 0; y < height; ++y) {
828                 for (x = 0; x < width; ++x) {
829                         div_t d = div(x+y, width);
830                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
831                                        + 0x000a1120 * (d.rem >> 6);
832                         struct color_rgb24 color =
833                                 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff,
834                                            (rgb32 >> 8) & 0xff, rgb32 & 0xff);
835
836                         ((struct color_rgb24 *)mem)[x] = color;
837                 }
838                 mem += stride;
839         }
840 }
841
842 static void
843 fill_tiles_rgb32(const struct format_info *info, unsigned char *mem,
844                  unsigned int width, unsigned int height, unsigned int stride)
845 {
846         const struct rgb_info *rgb = &info->rgb;
847         unsigned char *mem_base = mem;
848         unsigned int x, y;
849
850         for (y = 0; y < height; ++y) {
851                 for (x = 0; x < width; ++x) {
852                         div_t d = div(x+y, width);
853                         uint32_t rgb32 = 0x00130502 * (d.quot >> 6)
854                                        + 0x000a1120 * (d.rem >> 6);
855                         uint32_t color =
856                                 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff,
857                                           (rgb32 >> 8) & 0xff, rgb32 & 0xff,
858                                           255);
859
860                         ((uint32_t *)mem)[x] = color;
861                 }
862                 mem += stride;
863         }
864
865         make_pwetty(mem_base, width, height, stride, info->format);
866 }
867
868 static void
869 fill_tiles(const struct format_info *info, void *planes[3], unsigned int width,
870            unsigned int height, unsigned int stride)
871 {
872         unsigned char *u, *v;
873
874         switch (info->format) {
875         case DRM_FORMAT_UYVY:
876         case DRM_FORMAT_VYUY:
877         case DRM_FORMAT_YUYV:
878         case DRM_FORMAT_YVYU:
879                 return fill_tiles_yuv_packed(info, planes[0],
880                                              width, height, stride);
881
882         case DRM_FORMAT_NV12:
883         case DRM_FORMAT_NV21:
884         case DRM_FORMAT_NV16:
885         case DRM_FORMAT_NV61:
886                 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
887                 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
888                 return fill_tiles_yuv_planar(info, planes[0], u, v,
889                                              width, height, stride);
890
891         case DRM_FORMAT_YUV420:
892                 return fill_tiles_yuv_planar(info, planes[0], planes[1],
893                                              planes[2], width, height, stride);
894
895         case DRM_FORMAT_YVU420:
896                 return fill_tiles_yuv_planar(info, planes[0], planes[2],
897                                              planes[1], width, height, stride);
898
899         case DRM_FORMAT_ARGB4444:
900         case DRM_FORMAT_XRGB4444:
901         case DRM_FORMAT_ABGR4444:
902         case DRM_FORMAT_XBGR4444:
903         case DRM_FORMAT_RGBA4444:
904         case DRM_FORMAT_RGBX4444:
905         case DRM_FORMAT_BGRA4444:
906         case DRM_FORMAT_BGRX4444:
907         case DRM_FORMAT_RGB565:
908         case DRM_FORMAT_BGR565:
909         case DRM_FORMAT_ARGB1555:
910         case DRM_FORMAT_XRGB1555:
911         case DRM_FORMAT_ABGR1555:
912         case DRM_FORMAT_XBGR1555:
913         case DRM_FORMAT_RGBA5551:
914         case DRM_FORMAT_RGBX5551:
915         case DRM_FORMAT_BGRA5551:
916         case DRM_FORMAT_BGRX5551:
917                 return fill_tiles_rgb16(info, planes[0],
918                                         width, height, stride);
919
920         case DRM_FORMAT_BGR888:
921         case DRM_FORMAT_RGB888:
922                 return fill_tiles_rgb24(info, planes[0],
923                                         width, height, stride);
924         case DRM_FORMAT_ARGB8888:
925         case DRM_FORMAT_XRGB8888:
926         case DRM_FORMAT_ABGR8888:
927         case DRM_FORMAT_XBGR8888:
928         case DRM_FORMAT_RGBA8888:
929         case DRM_FORMAT_RGBX8888:
930         case DRM_FORMAT_BGRA8888:
931         case DRM_FORMAT_BGRX8888:
932         case DRM_FORMAT_ARGB2101010:
933         case DRM_FORMAT_XRGB2101010:
934         case DRM_FORMAT_ABGR2101010:
935         case DRM_FORMAT_XBGR2101010:
936         case DRM_FORMAT_RGBA1010102:
937         case DRM_FORMAT_RGBX1010102:
938         case DRM_FORMAT_BGRA1010102:
939         case DRM_FORMAT_BGRX1010102:
940                 return fill_tiles_rgb32(info, planes[0],
941                                         width, height, stride);
942         }
943 }
944
945 static void
946 fill_plain(const struct format_info *info, void *planes[3], unsigned int width,
947            unsigned int height, unsigned int stride)
948 {
949         memset(planes[0], 0x77, stride * height);
950 }
951
952 /*
953  * fill_pattern - Fill a buffer with a test pattern
954  * @format: Pixel format
955  * @pattern: Test pattern
956  * @buffer: Buffer memory
957  * @width: Width in pixels
958  * @height: Height in pixels
959  * @stride: Line stride (pitch) in bytes
960  *
961  * Fill the buffer with the test pattern specified by the pattern parameter.
962  * Supported formats vary depending on the selected pattern.
963  */
964 static void
965 fill_pattern(unsigned int format, enum fill_pattern pattern, void *planes[3],
966              unsigned int width, unsigned int height, unsigned int stride)
967 {
968         const struct format_info *info = NULL;
969         unsigned int i;
970
971         for (i = 0; i < ARRAY_SIZE(format_info); ++i) {
972                 if (format_info[i].format == format) {
973                         info = &format_info[i];
974                         break;
975                 }
976         }
977
978         if (info == NULL)
979                 return;
980
981         switch (pattern) {
982         case PATTERN_TILES:
983                 return fill_tiles(info, planes, width, height, stride);
984
985         case PATTERN_SMPTE:
986                 return fill_smpte(info, planes, width, height, stride);
987
988         case PATTERN_PLAIN:
989                 return fill_plain(info, planes, width, height, stride);
990
991         default:
992                 printf("Error: unsupported test pattern %u.\n", pattern);
993                 break;
994         }
995 }
996
997 /* -----------------------------------------------------------------------------
998  * Buffers management
999  */
1000
1001 static struct kms_bo *
1002 allocate_buffer(struct kms_driver *kms, unsigned int width, unsigned int height,
1003                 unsigned int *stride)
1004 {
1005         struct kms_bo *bo;
1006         unsigned bo_attribs[] = {
1007                 KMS_WIDTH,   0,
1008                 KMS_HEIGHT,  0,
1009                 KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
1010                 KMS_TERMINATE_PROP_LIST
1011         };
1012         int ret;
1013
1014         bo_attribs[1] = width;
1015         bo_attribs[3] = height;
1016
1017         ret = kms_bo_create(kms, bo_attribs, &bo);
1018         if (ret) {
1019                 fprintf(stderr, "failed to alloc buffer: %s\n",
1020                         strerror(-ret));
1021                 return NULL;
1022         }
1023
1024         ret = kms_bo_get_prop(bo, KMS_PITCH, stride);
1025         if (ret) {
1026                 fprintf(stderr, "failed to retreive buffer stride: %s\n",
1027                         strerror(-ret));
1028                 kms_bo_destroy(&bo);
1029                 return NULL;
1030         }
1031
1032         return bo;
1033 }
1034
1035 struct kms_bo *
1036 create_test_buffer(struct kms_driver *kms, unsigned int format,
1037                    unsigned int width, unsigned int height,
1038                    unsigned int handles[4], unsigned int pitches[4],
1039                    unsigned int offsets[4], enum fill_pattern pattern)
1040 {
1041         struct kms_bo *bo;
1042         void *planes[3] = { 0, };
1043         void *virtual;
1044         int ret;
1045
1046         bo = allocate_buffer(kms, width, height, &pitches[0]);
1047         if (!bo)
1048                 return NULL;
1049
1050         ret = kms_bo_map(bo, &virtual);
1051         if (ret) {
1052                 fprintf(stderr, "failed to map buffer: %s\n",
1053                         strerror(-ret));
1054                 kms_bo_destroy(&bo);
1055                 return NULL;
1056         }
1057
1058         /* just testing a limited # of formats to test single
1059          * and multi-planar path.. would be nice to add more..
1060          */
1061         switch (format) {
1062         case DRM_FORMAT_UYVY:
1063         case DRM_FORMAT_VYUY:
1064         case DRM_FORMAT_YUYV:
1065         case DRM_FORMAT_YVYU:
1066                 offsets[0] = 0;
1067                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
1068                 kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]);
1069
1070                 planes[0] = virtual;
1071                 break;
1072
1073         case DRM_FORMAT_NV12:
1074         case DRM_FORMAT_NV21:
1075         case DRM_FORMAT_NV16:
1076         case DRM_FORMAT_NV61:
1077                 offsets[0] = 0;
1078                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
1079                 kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]);
1080                 pitches[1] = pitches[0];
1081                 offsets[1] = pitches[0] * height;
1082                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
1083
1084                 planes[0] = virtual;
1085                 planes[1] = virtual + offsets[1];
1086                 break;
1087
1088         case DRM_FORMAT_YUV420:
1089         case DRM_FORMAT_YVU420:
1090                 offsets[0] = 0;
1091                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
1092                 kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]);
1093                 pitches[1] = pitches[0] / 2;
1094                 offsets[1] = pitches[0] * height;
1095                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]);
1096                 pitches[2] = pitches[1];
1097                 offsets[2] = offsets[1] + pitches[1] * height / 2;
1098                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]);
1099
1100                 planes[0] = virtual;
1101                 planes[1] = virtual + offsets[1];
1102                 planes[2] = virtual + offsets[2];
1103                 break;
1104
1105         case DRM_FORMAT_ARGB4444:
1106         case DRM_FORMAT_XRGB4444:
1107         case DRM_FORMAT_ABGR4444:
1108         case DRM_FORMAT_XBGR4444:
1109         case DRM_FORMAT_RGBA4444:
1110         case DRM_FORMAT_RGBX4444:
1111         case DRM_FORMAT_BGRA4444:
1112         case DRM_FORMAT_BGRX4444:
1113         case DRM_FORMAT_ARGB1555:
1114         case DRM_FORMAT_XRGB1555:
1115         case DRM_FORMAT_ABGR1555:
1116         case DRM_FORMAT_XBGR1555:
1117         case DRM_FORMAT_RGBA5551:
1118         case DRM_FORMAT_RGBX5551:
1119         case DRM_FORMAT_BGRA5551:
1120         case DRM_FORMAT_BGRX5551:
1121         case DRM_FORMAT_RGB565:
1122         case DRM_FORMAT_BGR565:
1123         case DRM_FORMAT_BGR888:
1124         case DRM_FORMAT_RGB888:
1125         case DRM_FORMAT_ARGB8888:
1126         case DRM_FORMAT_XRGB8888:
1127         case DRM_FORMAT_ABGR8888:
1128         case DRM_FORMAT_XBGR8888:
1129         case DRM_FORMAT_RGBA8888:
1130         case DRM_FORMAT_RGBX8888:
1131         case DRM_FORMAT_BGRA8888:
1132         case DRM_FORMAT_BGRX8888:
1133         case DRM_FORMAT_ARGB2101010:
1134         case DRM_FORMAT_XRGB2101010:
1135         case DRM_FORMAT_ABGR2101010:
1136         case DRM_FORMAT_XBGR2101010:
1137         case DRM_FORMAT_RGBA1010102:
1138         case DRM_FORMAT_RGBX1010102:
1139         case DRM_FORMAT_BGRA1010102:
1140         case DRM_FORMAT_BGRX1010102:
1141                 offsets[0] = 0;
1142                 kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]);
1143                 kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]);
1144
1145                 planes[0] = virtual;
1146                 break;
1147         }
1148
1149         fill_pattern(format, pattern, planes, width, height, pitches[0]);
1150         kms_bo_unmap(bo);
1151
1152         return bo;
1153 }