接前一篇文章:libdrm全解析九 —— 源码全解析(6)
本文参考以下博文:
DRM 驱动程序开发(VKMS)
特此致谢!
本文继续对include/drm/drm.h中实际功能宏定义进行讲解。
11. DRM_IOCTL_GEM_FLINK
第11个宏是DRM_IOCTL_GEM_FLINK,相应代码如下:
#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink)
结合之前文章中的_IOWR(type,nr,size)的最终定义,得到如下代码:
#define DRM_IOCTL_GEM_FLINK ( ((3) << 30) | (('d') << 8) | ((0x0a) << 0) | ((sizeof(struct drm_gem_flink)) << 16) )
struct drm_gem_flink在同文件(include/drm/drm.h)中定义,代码如下:
/* DRM_IOCTL_GEM_FLINK ioctl argument type */
struct drm_gem_flink {/** Handle for the object being named */__u32 handle;/** Returned global name */__u32 name;
};
drm_gem_flink结构中各成员的意义代码注释描述得很清楚了,在此无需赘述。
DRM_IOCTL_GEM_FLINK虽然并无直接对应的Userspace API(即没有对应的封装),但是libdrm源码中有多处直接对其进行了调用。
- amdgpu/amdgpu_bo.c中:
static int amdgpu_bo_export_flink(amdgpu_bo_handle bo)
{struct drm_gem_flink flink;int fd, dma_fd;uint32_t handle;int r;fd = bo->dev->fd;handle = bo->handle;if (bo->flink_name)return 0;……memset(&flink, 0, sizeof(flink));flink.handle = handle;r = drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &flink);if (r)return r;……return r;
}
- etnaviv/etnaviv_bo.c中:
/* get the global flink/DRI2 buffer name */
drm_public int etna_bo_get_name(struct etna_bo *bo, uint32_t *name)
{if (!bo->name) {struct drm_gem_flink req = {.handle = bo->handle,};int ret;ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);if (ret) {return ret;}pthread_mutex_lock(&table_lock);set_name(bo, req.name);pthread_mutex_unlock(&table_lock);bo->reuse = 0;}*name = bo->name;return 0;
}
- exynos/exynos_drm.c中:
/** Get a gem global object name from a gem object handle.** @bo: a exynos buffer object including gem handle.* @name: a gem global object name to be got by kernel driver.** this interface is used to get a gem global object name from a gem object* handle to a buffer that wants to share it with another process.** if true, return 0 else negative.*/
drm_public int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name)
{if (!bo->name) {struct drm_gem_flink req = {.handle = bo->handle,};int ret;ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);if (ret) {fprintf(stderr, "failed to get gem global name[%s].\n",strerror(errno));return ret;}bo->name = req.name;}*name = bo->name;return 0;
}
- freedreno/freedreno_bo.c中:
drm_public int fd_bo_get_name(struct fd_bo *bo, uint32_t *name)
{if (!bo->name) {struct drm_gem_flink req = {.handle = bo->handle,};int ret;ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);if (ret) {return ret;}pthread_mutex_lock(&table_lock);set_name(bo, req.name);pthread_mutex_unlock(&table_lock);bo->bo_reuse = NO_CACHE;}*name = bo->name;return 0;
}
- intel/intel_bufmgr_gem.c中:
static int
drm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name)
{drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;if (!bo_gem->global_name) {struct drm_gem_flink flink;memclear(flink);flink.handle = bo_gem->gem_handle;if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink))return -errno;pthread_mutex_lock(&bufmgr_gem->lock);if (!bo_gem->global_name) {bo_gem->global_name = flink.name;bo_gem->reusable = false;HASH_ADD(name_hh, bufmgr_gem->name_table,global_name, sizeof(bo_gem->global_name),bo_gem);}pthread_mutex_unlock(&bufmgr_gem->lock);}*name = bo_gem->global_name;return 0;
}
- nouveau/nouveau.c中:
drm_public int
nouveau_bo_name_get(struct nouveau_bo *bo, uint32_t *name)
{struct drm_gem_flink req = { .handle = bo->handle };struct nouveau_drm *drm = nouveau_drm(&bo->device->object);struct nouveau_bo_priv *nvbo = nouveau_bo(bo);*name = nvbo->name;if (!*name) {int ret = drmIoctl(drm->fd, DRM_IOCTL_GEM_FLINK, &req);if (ret) {*name = 0;return ret;}nvbo->name = *name = req.name;nouveau_bo_make_global(nvbo);}return 0;
}
- omap/omap_drm.c中:
/* get the global flink/DRI2 buffer name */
drm_public int omap_bo_get_name(struct omap_bo *bo, uint32_t *name)
{if (!bo->name) {struct drm_gem_flink req = {.handle = bo->handle,};int ret;ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);if (ret) {return ret;}bo->name = req.name;}*name = bo->name;return 0;
}
- radeon/radeon_bo_gem.c中:
drm_public int
radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name)
{struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;struct radeon_bo_int *boi = (struct radeon_bo_int *)bo;struct drm_gem_flink flink;int r;if (bo_gem->name) {*name = bo_gem->name;return 0;}flink.handle = bo->handle;r = drmIoctl(boi->bom->fd, DRM_IOCTL_GEM_FLINK, &flink);if (r) {return r;}bo_gem->name = flink.name;*name = flink.name;return 0;
}
- tegra/tegra.c中:
drm_public int drm_tegra_bo_get_name(struct drm_tegra_bo *bo, uint32_t *name)
{struct drm_tegra *drm = bo->drm;struct drm_gem_flink args;int err;memset(&args, 0, sizeof(args));args.handle = bo->handle;err = drmIoctl(drm->fd, DRM_IOCTL_GEM_FLINK, &args);if (err < 0)return err;if (name)*name = args.name;return 0;
}
这里顺带把各种显卡都列出来了。每种显卡都会调用DRM_IOCTL_GEM_FLINK对应的drmIoctl。
其余宏定义将在后续文章中继续解析。