diff options
Diffstat (limited to 'lib/gem.c')
-rw-r--r-- | lib/gem.c | 119 |
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; +} |