1 /*
2 * Copyright 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 #define _GNU_SOURCE
8 #include <assert.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <linux/dma-buf.h>
12 #include <stdbool.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <sys/ioctl.h>
19 #include <sys/mman.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include <xf86drm.h>
24 #include <xf86drmMode.h>
25
26 #include <gbm.h>
27
28 #define CHECK(cond) do {\
29 if (!(cond)) {\
30 printf("CHECK failed in %s() %s:%d\n", __func__, __FILE__, __LINE__);\
31 return 0;\
32 }\
33 } while(0)
34
35 #define HANDLE_EINTR(x) \
36 ({ \
37 int eintr_wrapper_counter = 0; \
38 int eintr_wrapper_result; \
39 do { \
40 eintr_wrapper_result = (x); \
41 } while (eintr_wrapper_result == -1 && errno == EINTR && \
42 eintr_wrapper_counter++ < 100); \
43 eintr_wrapper_result; \
44 })
45
46 #define ARRAY_SIZE(A) (sizeof(A)/sizeof(*(A)))
47
48 #define ENODRM -1
49 #define ENODISPLAY -2
50
51 static int fd;
52 static struct gbm_device *gbm;
53
54 static const uint32_t format_list[] = {
55 GBM_FORMAT_C8,
56 GBM_FORMAT_RGB332,
57 GBM_FORMAT_BGR233,
58 GBM_FORMAT_XRGB4444,
59 GBM_FORMAT_XBGR4444,
60 GBM_FORMAT_RGBX4444,
61 GBM_FORMAT_BGRX4444,
62 GBM_FORMAT_ARGB4444,
63 GBM_FORMAT_ABGR4444,
64 GBM_FORMAT_RGBA4444,
65 GBM_FORMAT_BGRA4444,
66 GBM_FORMAT_XRGB1555,
67 GBM_FORMAT_XBGR1555,
68 GBM_FORMAT_RGBX5551,
69 GBM_FORMAT_BGRX5551,
70 GBM_FORMAT_ARGB1555,
71 GBM_FORMAT_ABGR1555,
72 GBM_FORMAT_RGBA5551,
73 GBM_FORMAT_BGRA5551,
74 GBM_FORMAT_RGB565,
75 GBM_FORMAT_BGR565,
76 GBM_FORMAT_RGB888,
77 GBM_FORMAT_BGR888,
78 GBM_FORMAT_XRGB8888,
79 GBM_FORMAT_XBGR8888,
80 GBM_FORMAT_RGBX8888,
81 GBM_FORMAT_BGRX8888,
82 GBM_FORMAT_ARGB8888,
83 GBM_FORMAT_ABGR8888,
84 GBM_FORMAT_RGBA8888,
85 GBM_FORMAT_BGRA8888,
86 GBM_FORMAT_XRGB2101010,
87 GBM_FORMAT_XBGR2101010,
88 GBM_FORMAT_RGBX1010102,
89 GBM_FORMAT_BGRX1010102,
90 GBM_FORMAT_ARGB2101010,
91 GBM_FORMAT_ABGR2101010,
92 GBM_FORMAT_RGBA1010102,
93 GBM_FORMAT_BGRA1010102,
94 GBM_FORMAT_YUYV,
95 GBM_FORMAT_YVYU,
96 GBM_FORMAT_UYVY,
97 GBM_FORMAT_VYUY,
98 GBM_FORMAT_AYUV,
99 GBM_FORMAT_NV12,
100 GBM_FORMAT_YVU420,
101 };
102
103 struct plane_info {
104 uint32_t bits_per_pixel;
105 uint32_t subsample_rate;
106 uint32_t data_mask;
107 };
108
109 #define MAX_PLANES 3
110 struct format_info {
111 uint32_t pixel_format;
112 int num_planes;
113 struct plane_info planes[MAX_PLANES];
114 };
115
116 /* Bits per pixel for each. */
117 static const struct format_info format_info_list[] = {
118 {GBM_FORMAT_C8, 1, {{8, 1, 0xFF}}},
119 {GBM_FORMAT_RGB332, 1, {{8, 1, 0xFF}}},
120 {GBM_FORMAT_BGR233, 1, {{8, 1, 0xFF}}},
121 {GBM_FORMAT_XRGB4444, 1, {{16, 1, 0x0FFF}}},
122 {GBM_FORMAT_XBGR4444, 1, {{16, 1, 0x0FFF}}},
123 {GBM_FORMAT_RGBX4444, 1, {{16, 1, 0xFFF0}}},
124 {GBM_FORMAT_BGRX4444, 1, {{16, 1, 0xFFF0}}},
125 {GBM_FORMAT_ARGB4444, 1, {{16, 1, 0xFFFF}}},
126 {GBM_FORMAT_ABGR4444, 1, {{16, 1, 0xFFFF}}},
127 {GBM_FORMAT_RGBA4444, 1, {{16, 1, 0xFFFF}}},
128 {GBM_FORMAT_BGRA4444, 1, {{16, 1, 0xFFFF}}},
129 {GBM_FORMAT_XRGB1555, 1, {{16, 1, 0x7FFF}}},
130 {GBM_FORMAT_XBGR1555, 1, {{16, 1, 0x7FFF}}},
131 {GBM_FORMAT_RGBX5551, 1, {{16, 1, 0xFFFE}}},
132 {GBM_FORMAT_BGRX5551, 1, {{16, 1, 0xFFFE}}},
133 {GBM_FORMAT_ARGB1555, 1, {{16, 1, 0xFFFF}}},
134 {GBM_FORMAT_ABGR1555, 1, {{16, 1, 0xFFFF}}},
135 {GBM_FORMAT_RGBA5551, 1, {{16, 1, 0xFFFF}}},
136 {GBM_FORMAT_BGRA5551, 1, {{16, 1, 0xFFFF}}},
137 {GBM_FORMAT_RGB565, 1, {{16, 1, 0xFFFF}}},
138 {GBM_FORMAT_BGR565, 1, {{16, 1, 0xFFFF}}},
139 {GBM_FORMAT_RGB888, 1, {{24, 1, 0xFFFFFF}}},
140 {GBM_FORMAT_BGR888, 1, {{24, 1, 0xFFFFFF}}},
141 {GBM_FORMAT_XRGB8888, 1, {{32, 1, 0x00FFFFFF}}},
142 {GBM_FORMAT_XBGR8888, 1, {{32, 1, 0x00FFFFFF}}},
143 {GBM_FORMAT_RGBX8888, 1, {{32, 1, 0xFFFFFF00}}},
144 {GBM_FORMAT_BGRX8888, 1, {{32, 1, 0xFFFFFF00}}},
145 {GBM_FORMAT_ARGB8888, 1, {{32, 1, 0xFFFFFFFF}}},
146 {GBM_FORMAT_ABGR8888, 1, {{32, 1, 0xFFFFFFFF}}},
147 {GBM_FORMAT_RGBA8888, 1, {{32, 1, 0xFFFFFFFF}}},
148 {GBM_FORMAT_BGRA8888, 1, {{32, 1, 0xFFFFFFFF}}},
149 {GBM_FORMAT_XRGB2101010, 1, {{32, 1, 0x3FFFFFFF}}},
150 {GBM_FORMAT_XBGR2101010, 1, {{32, 1, 0x3FFFFFFF}}},
151 {GBM_FORMAT_RGBX1010102, 1, {{32, 1, 0xFFFFFFFC}}},
152 {GBM_FORMAT_BGRX1010102, 1, {{32, 1, 0xFFFFFFFC}}},
153 {GBM_FORMAT_ARGB2101010, 1, {{32, 1, 0xFFFFFFFF}}},
154 {GBM_FORMAT_ABGR2101010, 1, {{32, 1, 0xFFFFFFFF}}},
155 {GBM_FORMAT_RGBA1010102, 1, {{32, 1, 0xFFFFFFFF}}},
156 {GBM_FORMAT_BGRA1010102, 1, {{32, 1, 0xFFFFFFFF}}},
157 {GBM_FORMAT_YUYV, 1, {{16, 1, 0xFFFF}}},
158 {GBM_FORMAT_YVYU, 1, {{16, 1, 0xFFFF}}},
159 {GBM_FORMAT_UYVY, 1, {{16, 1, 0xFFFF}}},
160 {GBM_FORMAT_VYUY, 1, {{16, 1, 0xFFFF}}},
161 {GBM_FORMAT_AYUV, 1, {{32, 1, 0xFFFFFFFF}}},
162 {GBM_FORMAT_NV12, 2, {{8, 1, 0xFF}, {16, 2, 0xFFFF}}},
163 {GBM_FORMAT_YVU420, 3, {{8, 1, 0xFF}, {8, 2, 0xFF}, {8,2, 0xFF}}},
164 };
165
166 static const uint32_t usage_list[] = {
167 GBM_BO_USE_SCANOUT,
168 GBM_BO_USE_CURSOR_64X64,
169 GBM_BO_USE_RENDERING,
170 GBM_BO_USE_LINEAR,
171 GBM_BO_USE_SW_READ_OFTEN,
172 GBM_BO_USE_SW_READ_RARELY,
173 GBM_BO_USE_SW_WRITE_OFTEN,
174 GBM_BO_USE_SW_WRITE_RARELY,
175 };
176
177 static const uint32_t buffer_list[] = {
178 GBM_BO_USE_SCANOUT | GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY,
179 GBM_BO_USE_RENDERING | GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY,
180 GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY,
181 GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY | GBM_BO_USE_TEXTURING,
182 GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY | GBM_BO_USE_TEXTURING,
183
184 GBM_BO_USE_RENDERING | GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY |
185 GBM_BO_USE_TEXTURING,
186
187 GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT | GBM_BO_USE_SW_READ_RARELY |
188 GBM_BO_USE_SW_WRITE_RARELY,
189
190 GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT | GBM_BO_USE_SW_READ_RARELY |
191 GBM_BO_USE_SW_WRITE_RARELY | GBM_BO_USE_TEXTURING,
192 };
193
check_bo(struct gbm_bo * bo)194 static int check_bo(struct gbm_bo *bo)
195 {
196 uint32_t format;
197 size_t num_planes, plane;
198 int fd;
199 int i;
200
201 CHECK(bo);
202 CHECK(gbm_bo_get_width(bo) >= 0);
203 CHECK(gbm_bo_get_height(bo) >= 0);
204 CHECK(gbm_bo_get_stride(bo) >= gbm_bo_get_width(bo));
205
206 format = gbm_bo_get_format(bo);
207 for (i = 0; i < ARRAY_SIZE(format_list); i++)
208 if (format_list[i] == format)
209 break;
210 CHECK(i < ARRAY_SIZE(format_list));
211
212 num_planes = gbm_bo_get_plane_count(bo);
213 if (format == GBM_FORMAT_NV12)
214 CHECK(num_planes == 2);
215 else if (format == GBM_FORMAT_YVU420)
216 CHECK(num_planes == 3);
217 else
218 CHECK(num_planes == 1);
219
220 CHECK(gbm_bo_get_handle_for_plane(bo, 0).u32 == gbm_bo_get_handle(bo).u32);
221
222 CHECK(gbm_bo_get_offset(bo, 0) == 0);
223 CHECK(gbm_bo_get_plane_size(bo, 0) >=
224 gbm_bo_get_width(bo) * gbm_bo_get_height(bo));
225 CHECK(gbm_bo_get_stride_for_plane(bo, 0) == gbm_bo_get_stride(bo));
226
227 for (plane = 0; plane < num_planes; plane++) {
228 CHECK(gbm_bo_get_handle_for_plane(bo, plane).u32);
229
230 fd = gbm_bo_get_plane_fd(bo, plane);
231 CHECK(fd > 0);
232 close(fd);
233
234 gbm_bo_get_offset(bo, plane);
235 CHECK(gbm_bo_get_plane_size(bo, plane));
236 CHECK(gbm_bo_get_stride_for_plane(bo, plane));
237 }
238
239 return 1;
240 }
241
find_first_connected_connector(int fd,drmModeRes * resources)242 static drmModeConnector *find_first_connected_connector(int fd,
243 drmModeRes *resources)
244 {
245 int i;
246 for (i = 0; i < resources->count_connectors; i++) {
247 drmModeConnector *connector;
248
249 connector = drmModeGetConnector(fd, resources->connectors[i]);
250 if (connector) {
251 if ((connector->count_modes > 0) &&
252 (connector->connection == DRM_MODE_CONNECTED))
253 return connector;
254
255 drmModeFreeConnector(connector);
256 }
257 }
258 return NULL;
259 }
260
drm_open()261 static int drm_open()
262 {
263 int fd;
264 unsigned i;
265 bool has_drm_device = false;
266
267 for (i = 0; i < DRM_MAX_MINOR; i++) {
268 char* dev_name;
269 drmModeRes *res = NULL;
270 int ret;
271
272 ret = asprintf(&dev_name, DRM_DEV_NAME, DRM_DIR_NAME, i);
273 if (ret < 0)
274 continue;
275
276 fd = open(dev_name, O_RDWR, 0);
277 free(dev_name);
278 if (fd < 0)
279 continue;
280
281 res = drmModeGetResources(fd);
282 if (!res) {
283 drmClose(fd);
284 continue;
285 }
286
287 if (res->count_crtcs > 0 && res->count_connectors > 0) {
288 has_drm_device = true;
289 if (find_first_connected_connector(fd, res)) {
290 drmModeFreeResources(res);
291 return fd;
292 }
293 }
294
295 drmClose(fd);
296 drmModeFreeResources(res);
297 }
298
299 if (has_drm_device)
300 return ENODISPLAY;
301 else
302 return ENODRM;
303 }
304
drm_open_vgem()305 static int drm_open_vgem()
306 {
307 const char g_sys_card_path_format[] =
308 "/sys/bus/platform/devices/vgem/drm/card%d";
309 const char g_dev_card_path_format[] =
310 "/dev/dri/card%d";
311 char *name;
312 int i, fd;
313
314 for (i = 0; i < 16; i++) {
315 struct stat _stat;
316 int ret;
317 ret = asprintf(&name, g_sys_card_path_format, i);
318 assert(ret != -1);
319
320 if (stat(name, &_stat) == -1) {
321 free(name);
322 continue;
323 }
324
325 free(name);
326 ret = asprintf(&name, g_dev_card_path_format, i);
327 assert(ret != -1);
328
329 fd = open(name, O_RDWR);
330 free(name);
331 if (fd == -1) {
332 return -1;
333 }
334 return fd;
335 }
336 return -1;
337 }
338
create_vgem_bo(int fd,size_t size,uint32_t * handle)339 static int create_vgem_bo(int fd, size_t size, uint32_t * handle)
340 {
341 struct drm_mode_create_dumb create;
342 int ret;
343
344 memset(&create, 0, sizeof(create));
345 create.height = size;
346 create.width = 1;
347 create.bpp = 8;
348
349 ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
350 if (ret)
351 return ret;
352
353 assert(create.size >= size);
354
355 *handle = create.handle;
356
357 return 0;
358 }
359
360 /*
361 * Tests initialization.
362 */
test_init()363 static int test_init()
364 {
365 fd = drm_open();
366 if (fd == ENODISPLAY)
367 return ENODISPLAY;
368 CHECK(fd >= 0);
369
370 gbm = gbm_create_device(fd);
371
372 CHECK(gbm_device_get_fd(gbm) == fd);
373
374 const char* backend_name = gbm_device_get_backend_name(gbm);
375
376 CHECK(backend_name);
377
378 return 1;
379 }
380
381 /*
382 * Tests reinitialization.
383 */
test_reinit()384 static int test_reinit()
385 {
386 gbm_device_destroy(gbm);
387 close(fd);
388
389 fd = drm_open();
390 CHECK(fd >= 0);
391
392 gbm = gbm_create_device(fd);
393
394 CHECK(gbm_device_get_fd(gbm) == fd);
395
396 struct gbm_bo *bo;
397 bo = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
398 CHECK(check_bo(bo));
399 gbm_bo_destroy(bo);
400
401 return 1;
402 }
403
404 /*
405 * Tests repeated alloc/free.
406 */
test_alloc_free()407 static int test_alloc_free()
408 {
409 int i;
410 for(i = 0; i < 1000; i++) {
411 struct gbm_bo *bo;
412 bo = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
413 CHECK(check_bo(bo));
414 gbm_bo_destroy(bo);
415 }
416 return 1;
417 }
418
419 /*
420 * Tests that we can allocate different buffer dimensions.
421 */
test_alloc_free_sizes()422 static int test_alloc_free_sizes()
423 {
424 int i;
425 for(i = 1; i < 1920; i++) {
426 struct gbm_bo *bo;
427 bo = gbm_bo_create(gbm, i, i, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
428 CHECK(check_bo(bo));
429 gbm_bo_destroy(bo);
430 }
431
432 for(i = 1; i < 1920; i++) {
433 struct gbm_bo *bo;
434 bo = gbm_bo_create(gbm, i, 1, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
435 CHECK(check_bo(bo));
436 gbm_bo_destroy(bo);
437 }
438
439 for(i = 1; i < 1920; i++) {
440 struct gbm_bo *bo;
441 bo = gbm_bo_create(gbm, 1, i, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
442 CHECK(check_bo(bo));
443 gbm_bo_destroy(bo);
444 }
445
446 return 1;
447 }
448
449 /*
450 * Tests that we can allocate different buffer formats.
451 */
test_alloc_free_formats()452 static int test_alloc_free_formats()
453 {
454 int i;
455
456 for(i = 0; i < ARRAY_SIZE(format_list); i++) {
457 uint32_t format = format_list[i];
458 if (gbm_device_is_format_supported(gbm, format, GBM_BO_USE_RENDERING)) {
459 struct gbm_bo *bo;
460 bo = gbm_bo_create(gbm, 1024, 1024, format, GBM_BO_USE_RENDERING);
461 CHECK(check_bo(bo));
462 gbm_bo_destroy(bo);
463 }
464 }
465
466 return 1;
467 }
468
469 /*
470 * Tests that we find at least one working format for each usage.
471 */
test_alloc_free_usage()472 static int test_alloc_free_usage()
473 {
474 int i, j;
475
476 for(i = 0; i < ARRAY_SIZE(usage_list); i++) {
477 uint32_t usage = usage_list[i];
478 int found = 0;
479 for(j = 0; j < ARRAY_SIZE(format_list); j++) {
480 uint32_t format = format_list[j];
481 if (gbm_device_is_format_supported(gbm, format, usage)) {
482 struct gbm_bo *bo;
483 if (usage == GBM_BO_USE_CURSOR_64X64)
484 bo = gbm_bo_create(gbm, 64, 64, format, usage);
485 else
486 bo = gbm_bo_create(gbm, 1024, 1024, format, usage);
487 CHECK(check_bo(bo));
488 found = 1;
489 gbm_bo_destroy(bo);
490 }
491 }
492 CHECK(found);
493 }
494
495 return 1;
496 }
497
498 /*
499 * Tests user data.
500 */
501 static int been_there1;
502 static int been_there2;
503
destroy_data1(struct gbm_bo * bo,void * data)504 void destroy_data1(struct gbm_bo *bo, void *data)
505 {
506 been_there1 = 1;
507 }
508
destroy_data2(struct gbm_bo * bo,void * data)509 void destroy_data2(struct gbm_bo *bo, void *data)
510 {
511 been_there2 = 1;
512 }
513
test_user_data()514 static int test_user_data()
515 {
516 struct gbm_bo *bo1, *bo2;
517 char *data1, *data2;
518
519 been_there1 = 0;
520 been_there2 = 0;
521
522 bo1 = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
523 bo2 = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
524 data1 = (char*)malloc(1);
525 data2 = (char*)malloc(1);
526 CHECK(data1);
527 CHECK(data2);
528
529 gbm_bo_set_user_data(bo1, data1, destroy_data1);
530 gbm_bo_set_user_data(bo2, data2, destroy_data2);
531
532 CHECK((char*)gbm_bo_get_user_data(bo1) == data1);
533 CHECK((char*)gbm_bo_get_user_data(bo2) == data2);
534
535 gbm_bo_destroy(bo1);
536 CHECK(been_there1 == 1);
537
538 gbm_bo_set_user_data(bo2, NULL, NULL);
539 gbm_bo_destroy(bo2);
540 CHECK(been_there2 == 0);
541
542 free(data1);
543 free(data2);
544
545 return 1;
546 }
547
548 /*
549 * Tests destruction.
550 */
test_destroy()551 static int test_destroy()
552 {
553 gbm_device_destroy(gbm);
554 close(fd);
555
556 return 1;
557 }
558
559 /*
560 * Tests prime export.
561 */
test_export()562 static int test_export()
563 {
564 struct gbm_bo *bo;
565 int prime_fd;
566
567 bo = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
568 CHECK(check_bo(bo));
569
570 prime_fd = gbm_bo_get_fd(bo);
571 CHECK(prime_fd > 0);
572 close(prime_fd);
573
574 gbm_bo_destroy(bo);
575
576 return 1;
577 }
578
579 /*
580 * Tests prime import using VGEM sharing buffer.
581 */
test_import_vgem()582 static int test_import_vgem()
583 {
584 struct gbm_import_fd_data fd_data;
585 int vgem_fd = drm_open_vgem();
586 struct drm_prime_handle prime_handle;
587 struct gbm_bo *bo;
588 const int width = 123;
589 const int height = 456;
590 const int bytes_per_pixel = 4;
591 const int size = width * height * bytes_per_pixel;
592
593 if (vgem_fd <= 0)
594 return 1;
595
596 CHECK(create_vgem_bo(vgem_fd, size, &prime_handle.handle) == 0);
597 prime_handle.flags = DRM_CLOEXEC;
598 CHECK(drmIoctl(vgem_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle) == 0);
599
600 fd_data.fd = prime_handle.fd;
601 fd_data.width = width;
602 fd_data.height = height;
603 fd_data.stride = width * bytes_per_pixel;
604 fd_data.format = GBM_FORMAT_XRGB8888;
605
606 bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &fd_data, GBM_BO_USE_RENDERING);
607 CHECK(check_bo(bo));
608 gbm_bo_destroy(bo);
609 close(prime_handle.fd);
610
611 close(vgem_fd);
612
613 return 1;
614 }
615
616 /*
617 * Tests prime import using dma-buf API.
618 */
test_import_dmabuf()619 static int test_import_dmabuf()
620 {
621 struct gbm_import_fd_data fd_data;
622 struct gbm_bo *bo1, *bo2;
623 const int width = 123;
624 const int height = 456;
625 int prime_fd;
626
627 bo1 = gbm_bo_create(gbm, width, height, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
628 CHECK(check_bo(bo1));
629
630 prime_fd = gbm_bo_get_fd(bo1);
631 CHECK(prime_fd >= 0);
632
633 fd_data.fd = prime_fd;
634 fd_data.width = width;
635 fd_data.height = height;
636 fd_data.stride = gbm_bo_get_stride(bo1);
637 fd_data.format = GBM_FORMAT_XRGB8888;
638
639 gbm_bo_destroy(bo1);
640
641 bo2 = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &fd_data, GBM_BO_USE_RENDERING);
642 CHECK(check_bo(bo2));
643 CHECK(fd_data.width == gbm_bo_get_width(bo2));
644 CHECK(fd_data.height == gbm_bo_get_height(bo2));
645 CHECK(fd_data.stride == gbm_bo_get_stride(bo2));
646
647 gbm_bo_destroy(bo2);
648 close(prime_fd);
649
650 return 1;
651 }
652
653
654 /*
655 * Tests GBM_BO_IMPORT_FD_MODIFIER entry point.
656 */
test_import_modifier()657 static int test_import_modifier()
658 {
659 struct gbm_import_fd_modifier_data fd_data;
660 struct gbm_bo *bo1, *bo2;
661 const int width = 567;
662 const int height = 891;
663 size_t num_planes, p;
664 int i;
665
666 for (i = 0; i < ARRAY_SIZE(format_list); i++) {
667 uint32_t format = format_list[i];
668 if (gbm_device_is_format_supported(gbm, format, GBM_BO_USE_RENDERING)) {
669 bo1 = gbm_bo_create(gbm, width, height, format, GBM_BO_USE_RENDERING);
670 CHECK(check_bo(bo1));
671
672 num_planes = gbm_bo_get_plane_count(bo1);
673 fd_data.num_fds = num_planes;
674
675 for (p = 0; p < num_planes; p++) {
676 fd_data.fds[p] = gbm_bo_get_plane_fd(bo1, p);
677 CHECK(fd_data.fds[p] >= 0);
678
679 fd_data.strides[p] = gbm_bo_get_stride_for_plane(bo1, p);
680 fd_data.offsets[p] = gbm_bo_get_offset(bo1, p);
681 }
682
683 fd_data.modifier = gbm_bo_get_modifier(bo1);
684 fd_data.width = width;
685 fd_data.height = height;
686 fd_data.format = format;
687
688 gbm_bo_destroy(bo1);
689
690 bo2 = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_MODIFIER, &fd_data,
691 GBM_BO_USE_RENDERING);
692
693 CHECK(check_bo(bo2));
694 CHECK(fd_data.width == gbm_bo_get_width(bo2));
695 CHECK(fd_data.height == gbm_bo_get_height(bo2));
696 CHECK(fd_data.modifier == gbm_bo_get_modifier(bo2));
697
698 for (p = 0; p < num_planes; p++) {
699 CHECK(fd_data.strides[p] == gbm_bo_get_stride_for_plane(bo2, p));
700 CHECK(fd_data.offsets[p] == gbm_bo_get_offset(bo2, p));
701 }
702
703 gbm_bo_destroy(bo2);
704
705 for (p = 0; p < num_planes; p++)
706 close(fd_data.fds[p]);
707 }
708 }
709
710 return 1;
711 }
712
test_gem_map()713 static int test_gem_map()
714 {
715 uint32_t *pixel, pixel_size;
716 struct gbm_bo *bo;
717 void *map_data, *addr;
718
719 uint32_t stride = 0;
720 const int width = 666;
721 const int height = 777;
722
723 addr = map_data = NULL;
724
725 bo = gbm_bo_create(gbm, width, height, GBM_FORMAT_ARGB8888,
726 GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY);
727 CHECK(check_bo(bo));
728
729 addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ_WRITE, &stride,
730 &map_data, 0);
731
732 CHECK(addr != MAP_FAILED);
733 CHECK(map_data);
734 CHECK(stride > 0);
735
736 pixel = (uint32_t *)addr;
737 pixel_size = sizeof(*pixel);
738
739 pixel[(height / 2) * (stride / pixel_size) + width / 2] = 0xABBAABBA;
740 gbm_bo_unmap(bo, map_data);
741
742 /* Re-map and verify written previously data. */
743 stride = 0;
744 addr = map_data = NULL;
745
746 addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ_WRITE, &stride,
747 &map_data, 0);
748
749 CHECK(addr != MAP_FAILED);
750 CHECK(map_data);
751 CHECK(stride > 0);
752
753 pixel = (uint32_t *)addr;
754 CHECK(pixel[(height / 2) * (stride / pixel_size) + width / 2] == 0xABBAABBA);
755
756 gbm_bo_unmap(bo, map_data);
757 gbm_bo_destroy(bo);
758
759 return 1;
760 }
761
test_dmabuf_map()762 static int test_dmabuf_map()
763 {
764 uint32_t *pixel;
765 struct gbm_bo *bo;
766 void *addr, *map_data;
767 const int width = 666;
768 const int height = 777;
769 int x, y, ret, prime_fd;
770 struct dma_buf_sync sync_end = { 0 };
771 struct dma_buf_sync sync_start = { 0 };
772 uint32_t pixel_size, stride, stride_pixels, length;
773
774 bo = gbm_bo_create(gbm, width, height, GBM_FORMAT_ARGB8888, GBM_BO_USE_LINEAR);
775 CHECK(check_bo(bo));
776
777 prime_fd = gbm_bo_get_fd(bo);
778 CHECK(prime_fd > 0);
779
780 stride = gbm_bo_get_stride(bo);
781 length = gbm_bo_get_plane_size(bo, 0);
782 CHECK(stride > 0);
783 CHECK(length > 0);
784
785 addr = mmap(NULL, length, (PROT_READ | PROT_WRITE), MAP_SHARED, prime_fd, 0);
786 CHECK(addr != MAP_FAILED);
787
788 pixel = (uint32_t *)addr;
789 pixel_size = sizeof(*pixel);
790 stride_pixels = stride / pixel_size;
791
792 sync_start.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE;
793 ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_start));
794 CHECK(ret == 0);
795
796 for (y = 0; y < height; ++y)
797 for (x = 0; x < width; ++x)
798 pixel[y * stride_pixels + x] = ((y << 16) | x);
799
800 sync_end.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE;
801 ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_end));
802 CHECK(ret == 0);
803
804 ret = munmap(addr, length);
805 CHECK(ret == 0);
806
807 ret = close(prime_fd);
808 CHECK(ret == 0);
809
810 prime_fd = gbm_bo_get_fd(bo);
811 CHECK(prime_fd > 0);
812
813 addr = mmap(NULL, length, (PROT_READ | PROT_WRITE), MAP_SHARED, prime_fd, 0);
814 CHECK(addr != MAP_FAILED);
815
816 pixel = (uint32_t *)addr;
817
818 memset(&sync_start, 0, sizeof(sync_start));
819 memset(&sync_end, 0, sizeof(sync_end));
820
821 sync_start.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ;
822 ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_start));
823 CHECK(ret == 0);
824
825 for (y = 0; y < height; ++y)
826 for (x = 0; x < width; ++x)
827 CHECK(pixel[y * stride_pixels + x] == ((y << 16) | x));
828
829 sync_end.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_READ;
830 ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_end));
831 CHECK(ret == 0);
832
833 ret = munmap(addr, length);
834 CHECK(ret == 0);
835
836 ret = close(prime_fd);
837 CHECK(ret == 0);
838
839 addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ, &stride,
840 &map_data, 0);
841
842 CHECK(addr != MAP_FAILED);
843 CHECK(map_data);
844 CHECK(stride > 0);
845
846 pixel = (uint32_t *)addr;
847
848 for (y = 0; y < height; ++y)
849 for (x = 0; x < width; ++x)
850 CHECK(pixel[y * stride_pixels + x] == ((y << 16) | x));
851
852 gbm_bo_unmap(bo, map_data);
853 gbm_bo_destroy(bo);
854
855 return 1;
856 }
857
test_gem_map_tiling(enum gbm_bo_flags buffer_create_flag)858 static int test_gem_map_tiling(enum gbm_bo_flags buffer_create_flag)
859 {
860 uint32_t *pixel, pixel_size;
861 struct gbm_bo *bo;
862 void *map_data, *addr;
863
864 uint32_t stride = 0;
865 uint32_t stride_pixels = 0;
866 const int width = 666;
867 const int height = 777;
868 int x, y;
869
870 addr = map_data = NULL;
871
872 bo = gbm_bo_create(gbm, width, height, GBM_FORMAT_ARGB8888, buffer_create_flag);
873 CHECK(check_bo(bo));
874
875 addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_WRITE, &stride,
876 &map_data, 0);
877
878 CHECK(addr != MAP_FAILED);
879 CHECK(map_data);
880 CHECK(stride > 0);
881
882 pixel = (uint32_t *)addr;
883 pixel_size = sizeof(*pixel);
884 stride_pixels = stride / pixel_size;
885
886 for (y = 0; y < height; ++y)
887 for (x = 0; x < width; ++x)
888 pixel[y * stride_pixels + x] = ((y << 16) | x);
889
890 gbm_bo_unmap(bo, map_data);
891
892 /* Re-map and verify written previously data. */
893 stride = 0;
894 addr = map_data = NULL;
895
896 addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ, &stride,
897 &map_data, 0);
898
899 CHECK(addr != MAP_FAILED);
900 CHECK(map_data);
901 CHECK(stride > 0);
902
903 pixel = (uint32_t *)addr;
904 pixel_size = sizeof(*pixel);
905 stride_pixels = stride / pixel_size;
906
907 for (y = 0; y < height; ++y)
908 for (x = 0; x < width; ++x)
909 CHECK(pixel[y * stride_pixels + x] == ((y << 16) | x));
910
911 gbm_bo_unmap(bo, map_data);
912 gbm_bo_destroy(bo);
913
914 return 1;
915 }
916
917
test_gem_map_format(int format_index,enum gbm_bo_flags buffer_create_flag)918 static int test_gem_map_format(int format_index,
919 enum gbm_bo_flags buffer_create_flag)
920 {
921 uint8_t *pixel;
922 struct gbm_bo *bo;
923 void *map_data, *addr;
924 uint32_t x, y, p, w, h, b, planes, bytes_per_pixel, pixel_data_mask, idx;
925 uint8_t byte_mask;
926 uint32_t stride = 0;
927 const int width = 333;
928 const int height = 444;
929 const uint32_t pixel_format = format_info_list[format_index].pixel_format;
930
931 addr = map_data = NULL;
932 if (!gbm_device_is_format_supported(gbm, pixel_format, buffer_create_flag))
933 return 1;
934
935 bo = gbm_bo_create(gbm, width, height, pixel_format, buffer_create_flag);
936 CHECK(check_bo(bo));
937 planes = gbm_bo_get_plane_count(bo);
938 CHECK(planes == format_info_list[format_index].num_planes);
939
940 for (p = 0; p < planes; ++p) {
941 w = width / format_info_list[format_index].planes[p].subsample_rate;
942 h = height / format_info_list[format_index].planes[p].subsample_rate;
943 addr = gbm_bo_map(bo, 0, 0, w, h, GBM_BO_TRANSFER_WRITE, &stride,
944 &map_data, p);
945
946 CHECK(addr != MAP_FAILED);
947 CHECK(map_data);
948 CHECK(stride > 0);
949
950 pixel = (uint8_t *)addr;
951 bytes_per_pixel = format_info_list[format_index].planes[p].bits_per_pixel / 8;
952 for (y = 0; y < h; ++y) {
953 for (x = 0; x < w; ++x) {
954 idx = y * stride + x * bytes_per_pixel;
955 for (b = 0; b < bytes_per_pixel; ++b)
956 pixel[idx + b] = y ^ x ^ b;
957 }
958 }
959 gbm_bo_unmap(bo, map_data);
960 stride = 0;
961 addr = map_data = NULL;
962 }
963
964 /* Re-map and verify written previously data. */
965 for (p = 0; p < planes; ++p) {
966 w = width / format_info_list[format_index].planes[p].subsample_rate;
967 h = height / format_info_list[format_index].planes[p].subsample_rate;
968 addr = gbm_bo_map(bo, 0, 0, w, h, GBM_BO_TRANSFER_READ, &stride,
969 &map_data, p);
970
971 CHECK(addr != MAP_FAILED);
972 CHECK(map_data);
973 CHECK(stride > 0);
974
975 pixel = (uint8_t *)addr;
976 bytes_per_pixel = format_info_list[format_index].planes[p].bits_per_pixel / 8;
977 pixel_data_mask = format_info_list[format_index].planes[p].data_mask;
978 for (y = 0; y < h; ++y) {
979 for (x = 0; x < w; ++x) {
980 idx = y * stride + x * bytes_per_pixel;
981 for (b = 0; b < bytes_per_pixel; ++b) {
982 byte_mask = pixel_data_mask >> (8 * b);
983 CHECK((pixel[idx + b] & byte_mask) == ((uint8_t)(y ^ x ^ b) & byte_mask));
984 }
985 }
986 }
987 gbm_bo_unmap(bo, map_data);
988 stride = 0;
989 addr = map_data = NULL;
990 }
991
992 gbm_bo_destroy(bo);
993 return 1;
994 }
995
996
main(int argc,char * argv[])997 int main(int argc, char *argv[])
998 {
999 int result, i, j;
1000
1001 result = test_init();
1002 if (result == ENODISPLAY) {
1003 printf("[ PASSED ] graphics_Gbm test no connected display found\n");
1004 return EXIT_SUCCESS;
1005 } else if (!result) {
1006 printf("[ FAILED ] graphics_Gbm test initialization failed\n");
1007 return EXIT_FAILURE;
1008 }
1009
1010 result &= test_reinit();
1011 result &= test_alloc_free();
1012 result &= test_alloc_free_sizes();
1013 result &= test_alloc_free_formats();
1014 result &= test_alloc_free_usage();
1015 result &= test_user_data();
1016 result &= test_export();
1017 result &= test_import_vgem();
1018 result &= test_import_dmabuf();
1019 result &= test_import_modifier();
1020 result &= test_gem_map();
1021
1022 // TODO(crbug.com/752669)
1023 if (strcmp(gbm_device_get_backend_name(gbm), "tegra")) {
1024 for (i = 0; i < ARRAY_SIZE(buffer_list); ++i) {
1025 result &= test_gem_map_tiling(buffer_list[i]);
1026 for (j = 0; j < ARRAY_SIZE(format_info_list); ++j)
1027 result &= test_gem_map_format(j, buffer_list[i]);
1028 }
1029
1030 result &= test_dmabuf_map();
1031 }
1032 result &= test_destroy();
1033
1034 if (!result) {
1035 printf("[ FAILED ] graphics_Gbm test failed\n");
1036 return EXIT_FAILURE;
1037 } else {
1038 printf("[ PASSED ] graphics_Gbm test success\n");
1039 return EXIT_SUCCESS;
1040 }
1041 }
1042