• 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 
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