#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; }