libdrm全解析十 —— 源码全解析(7)

接前一篇文章: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。

其余宏定义将在后续文章中继续解析。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/132470768