Home | History | Annotate | Download | only in src
      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 };
    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}}},
    118 	{GBM_FORMAT_RGB332, 1, {{8, 1}}},
    119 	{GBM_FORMAT_BGR233, 1, {{8, 1}}},
    120 	{GBM_FORMAT_XRGB4444, 1, {{16, 1}}},
    121 	{GBM_FORMAT_XBGR4444, 1, {{16, 1}}},
    122 	{GBM_FORMAT_RGBX4444, 1, {{16, 1}}},
    123 	{GBM_FORMAT_BGRX4444, 1, {{16, 1}}},
    124 	{GBM_FORMAT_ARGB4444, 1, {{16, 1}}},
    125 	{GBM_FORMAT_ABGR4444, 1, {{16, 1}}},
    126 	{GBM_FORMAT_RGBA4444, 1, {{16, 1}}},
    127 	{GBM_FORMAT_BGRA4444, 1, {{16, 1}}},
    128 	{GBM_FORMAT_XRGB1555, 1, {{16, 1}}},
    129 	{GBM_FORMAT_XBGR1555, 1, {{16, 1}}},
    130 	{GBM_FORMAT_RGBX5551, 1, {{16, 1}}},
    131 	{GBM_FORMAT_BGRX5551, 1, {{16, 1}}},
    132 	{GBM_FORMAT_ARGB1555, 1, {{16, 1}}},
    133 	{GBM_FORMAT_ABGR1555, 1, {{16, 1}}},
    134 	{GBM_FORMAT_RGBA5551, 1, {{16, 1}}},
    135 	{GBM_FORMAT_BGRA5551, 1, {{16, 1}}},
    136 	{GBM_FORMAT_RGB565, 1, {{16, 1}}},
    137 	{GBM_FORMAT_BGR565, 1, {{16, 1}}},
    138 	{GBM_FORMAT_RGB888, 1, {{24, 1}}},
    139 	{GBM_FORMAT_BGR888, 1, {{24, 1}}},
    140 	{GBM_FORMAT_XRGB8888, 1, {{32, 1}}},
    141 	{GBM_FORMAT_XBGR8888, 1, {{32, 1}}},
    142 	{GBM_FORMAT_RGBX8888, 1, {{32, 1}}},
    143 	{GBM_FORMAT_BGRX8888, 1, {{32, 1}}},
    144 	{GBM_FORMAT_ARGB8888, 1, {{32, 1}}},
    145 	{GBM_FORMAT_ABGR8888, 1, {{32, 1}}},
    146 	{GBM_FORMAT_RGBA8888, 1, {{32, 1}}},
    147 	{GBM_FORMAT_BGRA8888, 1, {{32, 1}}},
    148 	{GBM_FORMAT_XRGB2101010, 1, {{32, 1}}},
    149 	{GBM_FORMAT_XBGR2101010, 1, {{32, 1}}},
    150 	{GBM_FORMAT_RGBX1010102, 1, {{32, 1}}},
    151 	{GBM_FORMAT_BGRX1010102, 1, {{32, 1}}},
    152 	{GBM_FORMAT_ARGB2101010, 1, {{32, 1}}},
    153 	{GBM_FORMAT_ABGR2101010, 1, {{32, 1}}},
    154 	{GBM_FORMAT_RGBA1010102, 1, {{32, 1}}},
    155 	{GBM_FORMAT_BGRA1010102, 1, {{32, 1}}},
    156 	{GBM_FORMAT_YUYV, 1, {{16, 1}}},
    157 	{GBM_FORMAT_YVYU, 1, {{16, 1}}},
    158 	{GBM_FORMAT_UYVY, 1, {{16, 1}}},
    159 	{GBM_FORMAT_VYUY, 1, {{16, 1}}},
    160 	{GBM_FORMAT_AYUV, 1, {{32, 1}}},
    161 	{GBM_FORMAT_NV12, 2, {{8, 1}, {16, 2}}},
    162 	{GBM_FORMAT_YVU420, 3, {{8, 1}, {8, 2}, {8,2}}},
    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 
    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_num_planes(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_plane_handle(bo, 0).u32 == gbm_bo_get_handle(bo).u32);
    220 
    221 	CHECK(gbm_bo_get_plane_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_plane_stride(bo, 0) == gbm_bo_get_stride(bo));
    225 
    226 	for (plane = 0; plane < num_planes; plane++) {
    227 		CHECK(gbm_bo_get_plane_handle(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_plane_offset(bo, plane);
    234 		CHECK(gbm_bo_get_plane_size(bo, plane));
    235 		CHECK(gbm_bo_get_plane_stride(bo, plane));
    236 	}
    237 
    238 	return 1;
    239 }
    240 
    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 
    260 static int drm_open()
    261 {
    262 	int fd;
    263 	unsigned i;
    264 	bool has_drm_device = false;
    265 
    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 			has_drm_device = true;
    288 			if (find_first_connected_connector(fd, res)) {
    289 				drmModeFreeResources(res);
    290 				return fd;
    291 			}
    292 		}
    293 
    294 		drmClose(fd);
    295 		drmModeFreeResources(res);
    296 	}
    297 
    298 	if (has_drm_device)
    299 		return ENODISPLAY;
    300 	else
    301 		return ENODRM;
    302 }
    303 
    304 static int drm_open_vgem()
    305 {
    306 	const char g_sys_card_path_format[] =
    307 		"/sys/bus/platform/devices/vgem/drm/card%d";
    308 	const char g_dev_card_path_format[] =
    309 		"/dev/dri/card%d";
    310 	char *name;
    311 	int i, fd;
    312 
    313 	for (i = 0; i < 16; i++) {
    314 		struct stat _stat;
    315 		int ret;
    316 		ret = asprintf(&name, g_sys_card_path_format, i);
    317 		assert(ret != -1);
    318 
    319 		if (stat(name, &_stat) == -1) {
    320 			free(name);
    321 			continue;
    322 		}
    323 
    324 		free(name);
    325 		ret = asprintf(&name, g_dev_card_path_format, i);
    326 		assert(ret != -1);
    327 
    328 		fd = open(name, O_RDWR);
    329 		free(name);
    330 		if (fd == -1) {
    331 			return -1;
    332 		}
    333 		return fd;
    334 	}
    335 	return -1;
    336 }
    337 
    338 static int create_vgem_bo(int fd, size_t size, uint32_t * handle)
    339 {
    340 	struct drm_mode_create_dumb create;
    341 	int ret;
    342 
    343 	memset(&create, 0, sizeof(create));
    344 	create.height = size;
    345 	create.width = 1;
    346 	create.bpp = 8;
    347 
    348 	ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
    349 	if (ret)
    350 		return ret;
    351 
    352 	assert(create.size >= size);
    353 
    354 	*handle = create.handle;
    355 
    356 	return 0;
    357 }
    358 
    359 /*
    360  * Tests initialization.
    361  */
    362 static int test_init()
    363 {
    364 	fd = drm_open();
    365 	if (fd == ENODISPLAY)
    366 		return ENODISPLAY;
    367 	CHECK(fd >= 0);
    368 
    369 	gbm = gbm_create_device(fd);
    370 
    371 	CHECK(gbm_device_get_fd(gbm) == fd);
    372 
    373 	const char* backend_name = gbm_device_get_backend_name(gbm);
    374 
    375 	CHECK(backend_name);
    376 
    377 	return 1;
    378 }
    379 
    380 /*
    381  * Tests reinitialization.
    382  */
    383 static int test_reinit()
    384 {
    385 	gbm_device_destroy(gbm);
    386 	close(fd);
    387 
    388 	fd = drm_open();
    389 	CHECK(fd >= 0);
    390 
    391 	gbm = gbm_create_device(fd);
    392 
    393 	CHECK(gbm_device_get_fd(gbm) == fd);
    394 
    395 	struct gbm_bo *bo;
    396 	bo = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
    397 	CHECK(check_bo(bo));
    398 	gbm_bo_destroy(bo);
    399 
    400 	return 1;
    401 }
    402 
    403 /*
    404  * Tests repeated alloc/free.
    405  */
    406 static int test_alloc_free()
    407 {
    408 	int i;
    409 	for(i = 0; i < 1000; i++) {
    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 that we can allocate different buffer dimensions.
    420  */
    421 static int test_alloc_free_sizes()
    422 {
    423 	int i;
    424 	for(i = 1; i < 1920; i++) {
    425 		struct gbm_bo *bo;
    426 		bo = gbm_bo_create(gbm, i, i, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
    427 		CHECK(check_bo(bo));
    428 		gbm_bo_destroy(bo);
    429 	}
    430 
    431 	for(i = 1; i < 1920; i++) {
    432 		struct gbm_bo *bo;
    433 		bo = gbm_bo_create(gbm, i, 1, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
    434 		CHECK(check_bo(bo));
    435 		gbm_bo_destroy(bo);
    436 	}
    437 
    438 	for(i = 1; i < 1920; i++) {
    439 		struct gbm_bo *bo;
    440 		bo = gbm_bo_create(gbm, 1, i, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
    441 		CHECK(check_bo(bo));
    442 		gbm_bo_destroy(bo);
    443 	}
    444 
    445 	return 1;
    446 }
    447 
    448 /*
    449  * Tests that we can allocate different buffer formats.
    450  */
    451 static int test_alloc_free_formats()
    452 {
    453 	int i;
    454 
    455 	for(i = 0; i < ARRAY_SIZE(format_list); i++) {
    456 		uint32_t format = format_list[i];
    457 		if (gbm_device_is_format_supported(gbm, format, GBM_BO_USE_RENDERING)) {
    458 			struct gbm_bo *bo;
    459 			bo = gbm_bo_create(gbm, 1024, 1024, format, GBM_BO_USE_RENDERING);
    460 			CHECK(check_bo(bo));
    461 			gbm_bo_destroy(bo);
    462 		}
    463 	}
    464 
    465 	return 1;
    466 }
    467 
    468 /*
    469  * Tests that we find at least one working format for each usage.
    470  */
    471 static int test_alloc_free_usage()
    472 {
    473 	int i, j;
    474 
    475 	for(i = 0; i < ARRAY_SIZE(usage_list); i++) {
    476 		uint32_t usage = usage_list[i];
    477 		int found = 0;
    478 		for(j = 0; j < ARRAY_SIZE(format_list); j++) {
    479 			uint32_t format = format_list[j];
    480 			if (gbm_device_is_format_supported(gbm, format, usage)) {
    481 				struct gbm_bo *bo;
    482 				if (usage == GBM_BO_USE_CURSOR_64X64)
    483 					bo = gbm_bo_create(gbm, 64, 64, format, usage);
    484 				else
    485 					bo = gbm_bo_create(gbm, 1024, 1024, format, usage);
    486 				CHECK(check_bo(bo));
    487 				found = 1;
    488 				gbm_bo_destroy(bo);
    489 			}
    490 		}
    491 		CHECK(found);
    492 	}
    493 
    494 	return 1;
    495 }
    496 
    497 /*
    498  * Tests user data.
    499  */
    500 static int been_there1;
    501 static int been_there2;
    502 
    503 void destroy_data1(struct gbm_bo *bo, void *data)
    504 {
    505 	been_there1 = 1;
    506 }
    507 
    508 void destroy_data2(struct gbm_bo *bo, void *data)
    509 {
    510 	been_there2 = 1;
    511 }
    512 
    513 static int test_user_data()
    514 {
    515 	struct gbm_bo *bo1, *bo2;
    516 	char *data1, *data2;
    517 
    518 	been_there1 = 0;
    519 	been_there2 = 0;
    520 
    521 	bo1 = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
    522 	bo2 = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
    523 	data1 = (char*)malloc(1);
    524 	data2 = (char*)malloc(1);
    525 	CHECK(data1);
    526 	CHECK(data2);
    527 
    528 	gbm_bo_set_user_data(bo1, data1, destroy_data1);
    529 	gbm_bo_set_user_data(bo2, data2, destroy_data2);
    530 
    531 	CHECK((char*)gbm_bo_get_user_data(bo1) == data1);
    532 	CHECK((char*)gbm_bo_get_user_data(bo2) == data2);
    533 
    534 	gbm_bo_destroy(bo1);
    535 	CHECK(been_there1 == 1);
    536 
    537 	gbm_bo_set_user_data(bo2, NULL, NULL);
    538 	gbm_bo_destroy(bo2);
    539 	CHECK(been_there2 == 0);
    540 
    541 	free(data1);
    542 	free(data2);
    543 
    544 	return 1;
    545 }
    546 
    547 /*
    548  * Tests destruction.
    549  */
    550 static int test_destroy()
    551 {
    552 	gbm_device_destroy(gbm);
    553 	close(fd);
    554 
    555 	return 1;
    556 }
    557 
    558 /*
    559  * Tests prime export.
    560  */
    561 static int test_export()
    562 {
    563 	struct gbm_bo *bo;
    564 	int prime_fd;
    565 
    566 	bo = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
    567 	CHECK(check_bo(bo));
    568 
    569 	prime_fd = gbm_bo_get_fd(bo);
    570 	CHECK(prime_fd > 0);
    571 	close(prime_fd);
    572 
    573 	gbm_bo_destroy(bo);
    574 
    575 	return 1;
    576 }
    577 
    578 /*
    579  * Tests prime import using VGEM sharing buffer.
    580  */
    581 static int test_import_vgem()
    582 {
    583 	struct gbm_import_fd_data fd_data;
    584 	int vgem_fd = drm_open_vgem();
    585 	struct drm_prime_handle prime_handle;
    586 	struct gbm_bo *bo;
    587 	const int width = 123;
    588 	const int height = 456;
    589 	const int bytes_per_pixel = 4;
    590 	const int size = width * height * bytes_per_pixel;
    591 
    592 	if (vgem_fd <= 0)
    593 		return 1;
    594 
    595 	CHECK(create_vgem_bo(vgem_fd, size, &prime_handle.handle) == 0);
    596 	prime_handle.flags = DRM_CLOEXEC;
    597 	CHECK(drmIoctl(vgem_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle) == 0);
    598 
    599 	fd_data.fd = prime_handle.fd;
    600 	fd_data.width = width;
    601 	fd_data.height = height;
    602 	fd_data.stride = width * bytes_per_pixel;
    603 	fd_data.format = GBM_FORMAT_XRGB8888;
    604 
    605 	bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &fd_data, GBM_BO_USE_RENDERING);
    606 	CHECK(check_bo(bo));
    607 	gbm_bo_destroy(bo);
    608 	close(prime_handle.fd);
    609 
    610 	close(vgem_fd);
    611 
    612 	return 1;
    613 }
    614 
    615 /*
    616  * Tests prime import using dma-buf API.
    617  */
    618 static int test_import_dmabuf()
    619 {
    620 	struct gbm_import_fd_data fd_data;
    621 	struct gbm_bo *bo1, *bo2;
    622 	const int width = 123;
    623 	const int height = 456;
    624 	int prime_fd;
    625 
    626 	bo1 = gbm_bo_create(gbm, width, height, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING);
    627 	CHECK(check_bo(bo1));
    628 
    629 	prime_fd = gbm_bo_get_fd(bo1);
    630 	CHECK(prime_fd >= 0);
    631 
    632 	fd_data.fd = prime_fd;
    633 	fd_data.width = width;
    634 	fd_data.height = height;
    635 	fd_data.stride = gbm_bo_get_stride(bo1);
    636 	fd_data.format = GBM_FORMAT_XRGB8888;
    637 
    638 	gbm_bo_destroy(bo1);
    639 
    640 	bo2 = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &fd_data, GBM_BO_USE_RENDERING);
    641 	CHECK(check_bo(bo2));
    642 	CHECK(fd_data.width == gbm_bo_get_width(bo2));
    643 	CHECK(fd_data.height == gbm_bo_get_height(bo2));
    644 	CHECK(fd_data.stride == gbm_bo_get_stride(bo2));
    645 
    646 	gbm_bo_destroy(bo2);
    647 	close(prime_fd);
    648 
    649 	return 1;
    650 }
    651 
    652 
    653 /*
    654  * Tests GBM_BO_IMPORT_FD_PLANAR entry point.
    655  */
    656 static int test_import_planar()
    657 {
    658 	struct gbm_import_fd_planar_data fd_data;
    659 	struct gbm_bo *bo1, *bo2;
    660 	const int width = 567;
    661 	const int height = 891;
    662 	size_t num_planes, p;
    663 	int i;
    664 
    665 	for (i = 0; i < ARRAY_SIZE(format_list); i++) {
    666 		uint32_t format = format_list[i];
    667 		if (gbm_device_is_format_supported(gbm, format, GBM_BO_USE_RENDERING)) {
    668 			bo1 = gbm_bo_create(gbm, width, height, format, GBM_BO_USE_RENDERING);
    669 			CHECK(check_bo(bo1));
    670 
    671 			num_planes = gbm_bo_get_num_planes(bo1);
    672 			for (p = 0; p < num_planes; p++) {
    673 				fd_data.fds[p] = gbm_bo_get_plane_fd(bo1, p);
    674 				CHECK(fd_data.fds[p] >= 0);
    675 
    676 				fd_data.strides[p] = gbm_bo_get_plane_stride(bo1, p);
    677 				fd_data.offsets[p] = gbm_bo_get_plane_offset(bo1, p);
    678 				fd_data.format_modifiers[p] =
    679 					gbm_bo_get_plane_format_modifier(bo1, p);
    680 			}
    681 
    682 			fd_data.width = width;
    683 			fd_data.height = height;
    684 			fd_data.format = format;
    685 
    686 			gbm_bo_destroy(bo1);
    687 
    688 			bo2 = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_PLANAR, &fd_data,
    689 					    GBM_BO_USE_RENDERING);
    690 
    691 			CHECK(check_bo(bo2));
    692 			CHECK(fd_data.width == gbm_bo_get_width(bo2));
    693 			CHECK(fd_data.height == gbm_bo_get_height(bo2));
    694 
    695 			for (p = 0; p < num_planes; p++) {
    696 				CHECK(fd_data.strides[p] == gbm_bo_get_plane_stride(bo2, p));
    697 				CHECK(fd_data.offsets[p] == gbm_bo_get_plane_offset(bo2, p));
    698 				CHECK(fd_data.format_modifiers[p] ==
    699 				      gbm_bo_get_plane_format_modifier(bo2, p));
    700 			}
    701 
    702 			gbm_bo_destroy(bo2);
    703 
    704 			for (p = 0; p < num_planes; p++)
    705 				close(fd_data.fds[p]);
    706 		}
    707 	}
    708 
    709 	return 1;
    710 }
    711 
    712 static int test_gem_map()
    713 {
    714 	uint32_t *pixel, pixel_size;
    715 	struct gbm_bo *bo;
    716 	void *map_data, *addr;
    717 
    718 	uint32_t stride = 0;
    719 	const int width = 666;
    720 	const int height = 777;
    721 
    722 	addr = map_data = NULL;
    723 
    724 	bo = gbm_bo_create(gbm, width, height, GBM_FORMAT_ARGB8888,
    725 			   GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY);
    726 	CHECK(check_bo(bo));
    727 
    728 	addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ_WRITE, &stride,
    729 			  &map_data, 0);
    730 
    731 	CHECK(addr != MAP_FAILED);
    732 	CHECK(map_data);
    733 	CHECK(stride > 0);
    734 
    735 	pixel = (uint32_t *)addr;
    736 	pixel_size = sizeof(*pixel);
    737 
    738 	pixel[(height / 2) * (stride / pixel_size) + width / 2] = 0xABBAABBA;
    739 	gbm_bo_unmap(bo, map_data);
    740 
    741 	/* Re-map and verify written previously data. */
    742 	stride = 0;
    743 	addr = map_data = NULL;
    744 
    745 	addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ_WRITE, &stride,
    746 			  &map_data, 0);
    747 
    748 	CHECK(addr != MAP_FAILED);
    749 	CHECK(map_data);
    750 	CHECK(stride > 0);
    751 
    752 	pixel = (uint32_t *)addr;
    753 	CHECK(pixel[(height / 2) * (stride / pixel_size) + width / 2] == 0xABBAABBA);
    754 
    755 	gbm_bo_unmap(bo, map_data);
    756 	gbm_bo_destroy(bo);
    757 
    758 	return 1;
    759 }
    760 
    761 static int test_dmabuf_map()
    762 {
    763 	uint32_t *pixel;
    764 	struct gbm_bo *bo;
    765 	void *addr, *map_data;
    766 	const int width = 666;
    767 	const int height = 777;
    768 	int x, y, ret, prime_fd;
    769 	struct dma_buf_sync sync_end = { 0 };
    770 	struct dma_buf_sync sync_start = { 0 };
    771 	uint32_t pixel_size, stride, stride_pixels, length;
    772 
    773 	bo = gbm_bo_create(gbm, width, height, GBM_FORMAT_ARGB8888, GBM_BO_USE_LINEAR);
    774 	CHECK(check_bo(bo));
    775 
    776 	prime_fd = gbm_bo_get_fd(bo);
    777 	CHECK(prime_fd > 0);
    778 
    779 	stride = gbm_bo_get_stride(bo);
    780 	length = gbm_bo_get_plane_size(bo, 0);
    781 	CHECK(stride > 0);
    782 	CHECK(length > 0);
    783 
    784 	addr = mmap(NULL, length, (PROT_READ | PROT_WRITE), MAP_SHARED, prime_fd, 0);
    785 	CHECK(addr != MAP_FAILED);
    786 
    787 	pixel = (uint32_t *)addr;
    788 	pixel_size = sizeof(*pixel);
    789 	stride_pixels = stride / pixel_size;
    790 
    791 	sync_start.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE;
    792 	ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_start));
    793 	CHECK(ret == 0);
    794 
    795 	for (y = 0; y < height; ++y)
    796 		for (x = 0; x < width; ++x)
    797 			pixel[y * stride_pixels + x] = ((y << 16) | x);
    798 
    799 	sync_end.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE;
    800 	ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_end));
    801 	CHECK(ret == 0);
    802 
    803 	ret = munmap(addr, length);
    804 	CHECK(ret == 0);
    805 
    806 	ret = close(prime_fd);
    807 	CHECK(ret == 0);
    808 
    809 	prime_fd = gbm_bo_get_fd(bo);
    810 	CHECK(prime_fd > 0);
    811 
    812 	addr = mmap(NULL, length, (PROT_READ | PROT_WRITE), MAP_SHARED, prime_fd, 0);
    813 	CHECK(addr != MAP_FAILED);
    814 
    815 	pixel = (uint32_t *)addr;
    816 
    817 	memset(&sync_start, 0, sizeof(sync_start));
    818 	memset(&sync_end, 0, sizeof(sync_end));
    819 
    820 	sync_start.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ;
    821 	ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_start));
    822 	CHECK(ret == 0);
    823 
    824 	for (y = 0; y < height; ++y)
    825 		for (x = 0; x < width; ++x)
    826 			CHECK(pixel[y * stride_pixels + x] == ((y << 16) | x));
    827 
    828 	sync_end.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_READ;
    829 	ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_end));
    830 	CHECK(ret == 0);
    831 
    832 	ret = munmap(addr, length);
    833 	CHECK(ret == 0);
    834 
    835 	ret = close(prime_fd);
    836 	CHECK(ret == 0);
    837 
    838 	addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ, &stride,
    839 			  &map_data, 0);
    840 
    841 	CHECK(addr != MAP_FAILED);
    842 	CHECK(map_data);
    843 	CHECK(stride > 0);
    844 
    845 	pixel = (uint32_t *)addr;
    846 
    847 	for (y = 0; y < height; ++y)
    848 		for (x = 0; x < width; ++x)
    849 			CHECK(pixel[y * stride_pixels + x] == ((y << 16) | x));
    850 
    851 	gbm_bo_unmap(bo, map_data);
    852 	gbm_bo_destroy(bo);
    853 
    854 	return 1;
    855 }
    856 
    857 static int test_gem_map_tiling(enum gbm_bo_flags buffer_create_flag)
    858 {
    859 	uint32_t *pixel, pixel_size;
    860 	struct gbm_bo *bo;
    861 	void *map_data, *addr;
    862 
    863 	uint32_t stride = 0;
    864 	uint32_t stride_pixels = 0;
    865 	const int width = 666;
    866 	const int height = 777;
    867 	int x, y;
    868 
    869 	addr = map_data = NULL;
    870 
    871 	bo = gbm_bo_create(gbm, width, height, GBM_FORMAT_ARGB8888, buffer_create_flag);
    872 	CHECK(check_bo(bo));
    873 
    874 	addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_WRITE, &stride,
    875 			  &map_data, 0);
    876 
    877 	CHECK(addr != MAP_FAILED);
    878 	CHECK(map_data);
    879 	CHECK(stride > 0);
    880 
    881 	pixel = (uint32_t *)addr;
    882 	pixel_size = sizeof(*pixel);
    883 	stride_pixels = stride / pixel_size;
    884 
    885 	for (y = 0; y < height; ++y)
    886 		for (x = 0; x < width; ++x)
    887 			pixel[y * stride_pixels + x] = ((y << 16) | x);
    888 
    889 	gbm_bo_unmap(bo, map_data);
    890 
    891 	/* Re-map and verify written previously data. */
    892 	stride = 0;
    893 	addr = map_data = NULL;
    894 
    895 	addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ, &stride,
    896 			  &map_data, 0);
    897 
    898 	CHECK(addr != MAP_FAILED);
    899 	CHECK(map_data);
    900 	CHECK(stride > 0);
    901 
    902 	pixel = (uint32_t *)addr;
    903 	pixel_size = sizeof(*pixel);
    904 	stride_pixels = stride / pixel_size;
    905 
    906 	for (y = 0; y < height; ++y)
    907 		for (x = 0; x < width; ++x)
    908 			CHECK(pixel[y * stride_pixels + x] == ((y << 16) | x));
    909 
    910 	gbm_bo_unmap(bo, map_data);
    911 	gbm_bo_destroy(bo);
    912 
    913 	return 1;
    914 }
    915 
    916 
    917 static int test_gem_map_format(int format_index,
    918 			       enum gbm_bo_flags buffer_create_flag)
    919 {
    920 	uint8_t *pixel;
    921 	struct gbm_bo *bo;
    922 	void *map_data, *addr;
    923 	uint32_t x, y, p, w, h, b, planes, bytes_per_pixel, idx;
    924 	uint32_t stride = 0;
    925 	const int width = 333;
    926 	const int height = 444;
    927 	const uint32_t pixel_format = format_info_list[format_index].pixel_format;
    928 
    929 	addr = map_data = NULL;
    930 	if (!gbm_device_is_format_supported(gbm, pixel_format, buffer_create_flag))
    931 		return 1;
    932 
    933 	bo = gbm_bo_create(gbm, width, height, pixel_format, buffer_create_flag);
    934 	CHECK(check_bo(bo));
    935 	planes = gbm_bo_get_num_planes(bo);
    936 	CHECK(planes == format_info_list[format_index].num_planes);
    937 
    938 	for (p = 0; p < planes; ++p) {
    939 		w = width / format_info_list[format_index].planes[p].subsample_rate;
    940 		h = height / format_info_list[format_index].planes[p].subsample_rate;
    941 		addr = gbm_bo_map(bo, 0, 0, w, h, GBM_BO_TRANSFER_WRITE, &stride,
    942 				  &map_data, p);
    943 
    944 		CHECK(addr != MAP_FAILED);
    945 		CHECK(map_data);
    946 		CHECK(stride > 0);
    947 
    948 		pixel = (uint8_t *)addr;
    949 		bytes_per_pixel = format_info_list[format_index].planes[p].bits_per_pixel / 8;
    950 		for (y = 0; y < h; ++y) {
    951 			for (x = 0; x < w; ++x) {
    952 				idx = y * stride + x * bytes_per_pixel;
    953 				for (b = 0; b < bytes_per_pixel; ++b)
    954 					pixel[idx + b] = y ^ x ^ b;
    955 			}
    956 		}
    957 		gbm_bo_unmap(bo, map_data);
    958 		stride = 0;
    959 		addr = map_data = NULL;
    960 	}
    961 
    962 	/* Re-map and verify written previously data. */
    963 	for (p = 0; p < planes; ++p) {
    964 		w = width / format_info_list[format_index].planes[p].subsample_rate;
    965 		h = height / format_info_list[format_index].planes[p].subsample_rate;
    966 		addr = gbm_bo_map(bo, 0, 0, w, h, GBM_BO_TRANSFER_READ, &stride,
    967 				  &map_data, p);
    968 
    969 		CHECK(addr != MAP_FAILED);
    970 		CHECK(map_data);
    971 		CHECK(stride > 0);
    972 
    973 		pixel = (uint8_t *)addr;
    974 		bytes_per_pixel = format_info_list[format_index].planes[p].bits_per_pixel / 8;
    975 		for (y = 0; y < h; ++y) {
    976 			for (x = 0; x < w; ++x) {
    977 				idx = y * stride + x * bytes_per_pixel;
    978 				for (b = 0; b < bytes_per_pixel; ++b)
    979 					CHECK(pixel[idx + b] == (uint8_t)(y ^ x ^ b));
    980 			}
    981 		}
    982 		gbm_bo_unmap(bo, map_data);
    983 		stride = 0;
    984 		addr = map_data = NULL;
    985 	}
    986 
    987 	gbm_bo_destroy(bo);
    988 	return 1;
    989 }
    990 
    991 
    992 int main(int argc, char *argv[])
    993 {
    994 	int result, i, j;
    995 
    996 	result = test_init();
    997 	if (result == ENODISPLAY) {
    998 		printf("[  PASSED  ] graphics_Gbm test no connected display found\n");
    999 		return EXIT_SUCCESS;
   1000 	} else if (!result) {
   1001 		printf("[  FAILED  ] graphics_Gbm test initialization failed\n");
   1002 		return EXIT_FAILURE;
   1003 	}
   1004 
   1005 	result &= test_reinit();
   1006 	result &= test_alloc_free();
   1007 	result &= test_alloc_free_sizes();
   1008 	result &= test_alloc_free_formats();
   1009 	result &= test_alloc_free_usage();
   1010 	result &= test_user_data();
   1011 	result &= test_export();
   1012 	result &= test_import_vgem();
   1013 	result &= test_import_dmabuf();
   1014 	result &= test_import_planar();
   1015 	result &= test_gem_map();
   1016 
   1017 	// TODO(crbug.com/752669)
   1018 	if (strcmp(gbm_device_get_backend_name(gbm), "tegra")) {
   1019 		for (i = 0; i < ARRAY_SIZE(buffer_list); ++i) {
   1020 			result &= test_gem_map_tiling(buffer_list[i]);
   1021 			for (j = 0; j < ARRAY_SIZE(format_info_list); ++j)
   1022 				result &= test_gem_map_format(j, buffer_list[i]);
   1023 		}
   1024 
   1025 		result &= test_dmabuf_map();
   1026 	}
   1027 	result &= test_destroy();
   1028 
   1029 	if (!result) {
   1030 		printf("[  FAILED  ] graphics_Gbm test failed\n");
   1031 		return EXIT_FAILURE;
   1032 	} else {
   1033 		printf("[  PASSED  ] graphics_Gbm test success\n");
   1034 		return EXIT_SUCCESS;
   1035 	}
   1036 }
   1037