OSDN Git Service

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