summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <robclark@freedesktop.org>2014-09-16 16:26:50 -0400
committerRob Clark <robclark@freedesktop.org>2014-09-21 22:16:37 -0400
commit666788a6062de62aa0b3560760fbb0903167a319 (patch)
treec393c7f8e6fb3c6065455aac4e65e6d3995f7e80
parent77dce9a012c2bb9d152fe32458f17d3d5fc715a7 (diff)
freedreno: add dmabuf import/export helpers
Signed-off-by: Rob Clark <robclark@freedesktop.org>
-rw-r--r--freedreno/freedreno_bo.c43
-rw-r--r--freedreno/freedreno_drmif.h2
-rw-r--r--freedreno/freedreno_priv.h1
3 files changed, 46 insertions, 0 deletions
diff --git a/freedreno/freedreno_bo.c b/freedreno/freedreno_bo.c
index 3a2e4649..b90fc567 100644
--- a/freedreno/freedreno_bo.c
+++ b/freedreno/freedreno_bo.c
@@ -209,6 +209,25 @@ fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size)
return bo;
}
+drm_public struct fd_bo *
+fd_bo_from_dmabuf(struct fd_device *dev, int fd)
+{
+ struct drm_prime_handle req = {
+ .fd = fd,
+ };
+ int ret, size;
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req);
+ if (ret) {
+ return NULL;
+ }
+
+ /* hmm, would be nice if we had a way to figure out the size.. */
+ size = 0;
+
+ return fd_bo_from_handle(dev, req.handle, size);
+}
+
drm_public struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name)
{
struct drm_gem_open req = {
@@ -255,6 +274,11 @@ drm_public void fd_bo_del(struct fd_bo *bo)
if (!atomic_dec_and_test(&bo->refcnt))
return;
+ if (bo->fd) {
+ close(bo->fd);
+ bo->fd = 0;
+ }
+
pthread_mutex_lock(&table_lock);
if (bo->bo_reuse) {
@@ -335,6 +359,25 @@ drm_public uint32_t fd_bo_handle(struct fd_bo *bo)
return bo->handle;
}
+drm_public int fd_bo_dmabuf(struct fd_bo *bo)
+{
+ if (!bo->fd) {
+ struct drm_prime_handle req = {
+ .handle = bo->handle,
+ .flags = DRM_CLOEXEC,
+ };
+ int ret;
+
+ ret = drmIoctl(bo->dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req);
+ if (ret) {
+ return ret;
+ }
+
+ bo->fd = req.fd;
+ }
+ return dup(bo->fd);
+}
+
drm_public uint32_t fd_bo_size(struct fd_bo *bo)
{
return bo->size;
diff --git a/freedreno/freedreno_drmif.h b/freedreno/freedreno_drmif.h
index 7c54e04b..88fc03de 100644
--- a/freedreno/freedreno_drmif.h
+++ b/freedreno/freedreno_drmif.h
@@ -98,10 +98,12 @@ struct fd_bo * fd_bo_from_fbdev(struct fd_pipe *pipe,
struct fd_bo *fd_bo_from_handle(struct fd_device *dev,
uint32_t handle, uint32_t size);
struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name);
+struct fd_bo * fd_bo_from_dmabuf(struct fd_device *dev, int fd);
struct fd_bo * fd_bo_ref(struct fd_bo *bo);
void fd_bo_del(struct fd_bo *bo);
int fd_bo_get_name(struct fd_bo *bo, uint32_t *name);
uint32_t fd_bo_handle(struct fd_bo *bo);
+int fd_bo_dmabuf(struct fd_bo *bo);
uint32_t fd_bo_size(struct fd_bo *bo);
void * fd_bo_map(struct fd_bo *bo);
int fd_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op);
diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h
index 416a3b3c..b204e534 100644
--- a/freedreno/freedreno_priv.h
+++ b/freedreno/freedreno_priv.h
@@ -139,6 +139,7 @@ struct fd_bo {
uint32_t size;
uint32_t handle;
uint32_t name;
+ int fd; /* dmabuf handle */
void *map;
atomic_t refcnt;
struct fd_bo_funcs *funcs;