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