aboutsummaryrefslogtreecommitdiffstats
path: root/lib/gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gem.c')
-rw-r--r--lib/gem.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/lib/gem.c b/lib/gem.c
new file mode 100644
index 00000000..1f401929
--- /dev/null
+++ b/lib/gem.c
@@ -0,0 +1,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;
+}