• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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