aboutsummaryrefslogtreecommitdiffstats
path: root/lib/gem.c
blob: 1f401929d7549467c31fbad53bd006b4ca127d5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "gem.h"

#include "gem_msm.h"

struct gem_driver_lookup
{
	const char name[16];
	struct gem_driver *driver;
};

static struct gem_driver_lookup drivers[] = {
	{
		.name = "msm_drm",
		.driver = &gem_msm_driver
	}
};

static inline size_t num_drivers()
{
	return ARRAY_SIZE(drivers);
}

struct gem_driver *gem_get_driver(int drm_fd)
{
	char name[16] = {0};
	drm_version_t version = {};

	version.name_len = sizeof(name);
	version.name = name;

	if (drmIoctl(drm_fd, DRM_IOCTL_VERSION, &version))
	{
		return NULL;
	}

	for (struct gem_driver_lookup *di = drivers;
	     di - drivers < num_drivers();
	     ++di)
	{
		if (!strncmp(name, di->name, sizeof(name)))
		{
			return di->driver;
		}
	}

	return NULL;
}

int gem_size(int drm_fd, size_t *size, uint32_t gem_handle)
{
	struct drm_gem_flink drm_gem_flink_arg = {
		.handle = gem_handle,
		.name = 0
	};

	if (drmIoctl(drm_fd,
		     DRM_IOCTL_GEM_FLINK,
		     &drm_gem_flink_arg))
	{
		return -1;
	}

	struct drm_gem_open drm_gem_open_arg = {
		.name = drm_gem_flink_arg.name,
		.handle = 0,
		.size = 0
	};

	if (drmIoctl(drm_fd,
		     DRM_IOCTL_GEM_OPEN,
		     &drm_gem_open_arg))
	{
		return -1;
	}

	*size = drm_gem_open_arg.size;

	if (drm_gem_open_arg.handle != gem_handle)
	{
		gem_release_handle(drm_fd, drm_gem_open_arg.handle);
	}

	return 0;
}

void gem_release_handle(int drm_fd, uint32_t gem_handle)
{
	struct drm_gem_close drm_gem_close_arg = {
		.handle = gem_handle,
		.pad = 0
	};

	drmIoctl(drm_fd, DRM_IOCTL_GEM_CLOSE, &drm_gem_close_arg);
}

int drm_fb_for_gem_handle(int drm_fd, uint32_t *fb_id, uint32_t gem_handle,
			     const struct fb_configuration *fb_config)
{
	struct drm_mode_fb_cmd2 drm_mode_addfb2_arg = {
		.fb_id = 0,
		.width = fb_config->width,
		.height = fb_config->height,
		.pixel_format = fb_config->pixel_format,
		.flags = DRM_MODE_FB_MODIFIERS,
		.handles = { gem_handle, 0, 0, 0 },
		.pitches = { fb_config->width * fb_config->pixel_size, 0, 0, 0 },
		.offsets = { 0, 0, 0, 0 },
		.modifier = { 0 }
	};

	if (drmIoctl(drm_fd, DRM_IOCTL_MODE_ADDFB2, &drm_mode_addfb2_arg))
	{
		return -1;
	}

	*fb_id = drm_mode_addfb2_arg.fb_id;

	return 0;
}