omap: add API to import bo's from dmabuf fd's
[platform/upstream/libdrm.git] / omap / omap_drm.c
index e611806..1d37e45 100644 (file)
@@ -34,6 +34,8 @@
 #include <linux/stddef.h>
 #include <errno.h>
 #include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #include <xf86drm.h>
 
@@ -56,6 +58,7 @@ struct omap_bo {
        uint32_t        handle;
        uint32_t        name;           /* flink global handle (DRI2 name) */
        uint64_t        offset;         /* offset to mmap() */
+       int             fd;             /* dmabuf handle */
 };
 
 struct omap_device * omap_device_new(int fd)
@@ -102,7 +105,7 @@ int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value)
 static struct omap_bo * omap_bo_new_impl(struct omap_device *dev,
                union omap_gem_size size, uint32_t flags)
 {
-       struct omap_bo *bo;
+       struct omap_bo *bo = NULL;
        struct drm_omap_gem_new req = {
                        .size = size,
                        .flags = flags,
@@ -215,6 +218,38 @@ fail:
        return NULL;
 }
 
+/* import a buffer from dmabuf fd, does not take ownership of the
+ * fd so caller should close() the fd when it is otherwise done
+ * with it (even if it is still using the 'struct omap_bo *')
+ */
+struct omap_bo * omap_bo_from_dmabuf(struct omap_device *dev, int fd)
+{
+       struct omap_bo *bo;
+       struct drm_prime_handle req = {
+                       .fd = fd,
+       };
+       int ret;
+
+       bo = calloc(sizeof(*bo), 1);
+       if (!bo) {
+               goto fail;
+       }
+
+       ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req);
+       if (ret) {
+               goto fail;
+       }
+
+       bo->dev = dev;
+       bo->handle = req.handle;
+
+       return bo;
+
+fail:
+       free(bo);
+       return NULL;
+}
+
 /* destroy a buffer object */
 void omap_bo_del(struct omap_bo *bo)
 {
@@ -226,6 +261,10 @@ void omap_bo_del(struct omap_bo *bo)
                munmap(bo->map, bo->size);
        }
 
+       if (bo->fd) {
+               close(bo->fd);
+       }
+
        if (bo->handle) {
                struct drm_gem_close req = {
                                .handle = bo->handle,
@@ -264,6 +303,28 @@ uint32_t omap_bo_handle(struct omap_bo *bo)
        return bo->handle;
 }
 
+/* caller owns the dmabuf fd that is returned and is responsible
+ * to close() it when done
+ */
+int omap_bo_dmabuf(struct omap_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);
+}
+
 uint32_t omap_bo_size(struct omap_bo *bo)
 {
        if (!bo->size) {