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