Mesa (master): vc4: Add dmabuf support.

Eric Anholt anholt at kemper.freedesktop.org
Thu Dec 18 00:09:32 UTC 2014


Module: Mesa
Branch: master
Commit: 39bc9360116e1c944c1d0d04f67a6ec5f010371f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=39bc9360116e1c944c1d0d04f67a6ec5f010371f

Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 14 11:21:04 2014 +0100

vc4: Add dmabuf support.

This gets DRI3 working on modesetting with glamor.  It's not enabled under
simulation, because it looks like handing our dumb-allocated buffers off
to the server doesn't actually work for the server's rendering.

---

 .../auxiliary/target-helpers/inline_drm_helper.h   |    5 ++
 src/gallium/drivers/vc4/vc4_bufmgr.c               |   75 ++++++++++++++++----
 src/gallium/drivers/vc4/vc4_bufmgr.h               |    3 +
 src/gallium/drivers/vc4/vc4_screen.c               |   19 +++--
 4 files changed, 78 insertions(+), 24 deletions(-)

diff --git a/src/gallium/auxiliary/target-helpers/inline_drm_helper.h b/src/gallium/auxiliary/target-helpers/inline_drm_helper.h
index 81649d4..df818fe 100644
--- a/src/gallium/auxiliary/target-helpers/inline_drm_helper.h
+++ b/src/gallium/auxiliary/target-helpers/inline_drm_helper.h
@@ -468,6 +468,11 @@ dd_configuration(enum drm_conf conf)
       return configuration_query(conf);
    else
 #endif
+#if defined(GALLIUM_VC4)
+   if (strcmp(driver_name, "vc4") == 0)
+      return configuration_query(conf);
+   else
+#endif
       return NULL;
 }
 #endif /* INLINE_DRM_HELPER_H */
diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.c b/src/gallium/drivers/vc4/vc4_bufmgr.c
index 3b73ac8..64fe2e4 100644
--- a/src/gallium/drivers/vc4/vc4_bufmgr.c
+++ b/src/gallium/drivers/vc4/vc4_bufmgr.c
@@ -24,6 +24,7 @@
 #include <errno.h>
 #include <err.h>
 #include <sys/mman.h>
+#include <fcntl.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
 
@@ -88,26 +89,19 @@ vc4_bo_free(struct vc4_bo *bo)
         free(bo);
 }
 
-struct vc4_bo *
-vc4_bo_open_name(struct vc4_screen *screen, uint32_t name,
-                 uint32_t winsys_stride)
+static struct vc4_bo *
+vc4_bo_open_handle(struct vc4_screen *screen,
+                   uint32_t winsys_stride,
+                   uint32_t handle, uint32_t size)
 {
         struct vc4_bo *bo = CALLOC_STRUCT(vc4_bo);
 
-        struct drm_gem_open o;
-        o.name = name;
-        int ret = drmIoctl(screen->fd, DRM_IOCTL_GEM_OPEN, &o);
-        if (ret) {
-                fprintf(stderr, "Failed to open bo %d: %s\n",
-                        name, strerror(errno));
-                free(bo);
-                return NULL;
-        }
+        assert(size);
 
         pipe_reference_init(&bo->reference, 1);
         bo->screen = screen;
-        bo->handle = o.handle;
-        bo->size = o.size;
+        bo->handle = handle;
+        bo->size = size;
         bo->name = "winsys";
 
 #ifdef USE_VC4_SIMULATOR
@@ -121,6 +115,59 @@ vc4_bo_open_name(struct vc4_screen *screen, uint32_t name,
 }
 
 struct vc4_bo *
+vc4_bo_open_name(struct vc4_screen *screen, uint32_t name,
+                 uint32_t winsys_stride)
+{
+        struct drm_gem_open o = {
+                .name = name
+        };
+        int ret = drmIoctl(screen->fd, DRM_IOCTL_GEM_OPEN, &o);
+        if (ret) {
+                fprintf(stderr, "Failed to open bo %d: %s\n",
+                        name, strerror(errno));
+                return NULL;
+        }
+
+        return vc4_bo_open_handle(screen, winsys_stride, o.handle, o.size);
+}
+
+struct vc4_bo *
+vc4_bo_open_dmabuf(struct vc4_screen *screen, int fd, uint32_t winsys_stride)
+{
+        uint32_t handle;
+        int ret = drmPrimeFDToHandle(screen->fd, fd, &handle);
+        int size;
+        if (ret) {
+                fprintf(stderr, "Failed to get vc4 handle for dmabuf %d\n", fd);
+                return NULL;
+        }
+
+        /* Determine the size of the bo we were handed. */
+        size = lseek(fd, 0, SEEK_END);
+        if (size == -1) {
+                fprintf(stderr, "Couldn't get size of dmabuf fd %d.\n", fd);
+                return NULL;
+        }
+
+        return vc4_bo_open_handle(screen, winsys_stride, handle, size);
+}
+
+int
+vc4_bo_get_dmabuf(struct vc4_bo *bo)
+{
+        int fd;
+        int ret = drmPrimeHandleToFD(bo->screen->fd, bo->handle,
+                                     O_CLOEXEC, &fd);
+        if (ret != 0) {
+                fprintf(stderr, "Failed to export gem bo %d to dmabuf\n",
+                        bo->handle);
+                return -1;
+        }
+
+        return fd;
+}
+
+struct vc4_bo *
 vc4_bo_alloc_mem(struct vc4_screen *screen, const void *data, uint32_t size,
                  const char *name)
 {
diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.h b/src/gallium/drivers/vc4/vc4_bufmgr.h
index 4a1d4a4..baaecfd 100644
--- a/src/gallium/drivers/vc4/vc4_bufmgr.h
+++ b/src/gallium/drivers/vc4/vc4_bufmgr.h
@@ -50,7 +50,10 @@ struct vc4_bo *vc4_bo_alloc_mem(struct vc4_screen *screen, const void *data,
 void vc4_bo_free(struct vc4_bo *bo);
 struct vc4_bo *vc4_bo_open_name(struct vc4_screen *screen, uint32_t name,
                                 uint32_t winsys_stride);
+struct vc4_bo *vc4_bo_open_dmabuf(struct vc4_screen *screen, int fd,
+                                  uint32_t winsys_stride);
 bool vc4_bo_flink(struct vc4_bo *bo, uint32_t *name);
+int vc4_bo_get_dmabuf(struct vc4_bo *bo);
 
 static inline void
 vc4_bo_set_reference(struct vc4_bo **old_bo, struct vc4_bo *new_bo)
diff --git a/src/gallium/drivers/vc4/vc4_screen.c b/src/gallium/drivers/vc4/vc4_screen.c
index 98c51c1..b532cc6 100644
--- a/src/gallium/drivers/vc4/vc4_screen.c
+++ b/src/gallium/drivers/vc4/vc4_screen.c
@@ -482,6 +482,9 @@ vc4_screen_bo_get_handle(struct pipe_screen *pscreen,
         case DRM_API_HANDLE_TYPE_KMS:
                 whandle->handle = bo->handle;
                 return TRUE;
+        case DRM_API_HANDLE_TYPE_FD:
+                whandle->handle = vc4_bo_get_dmabuf(bo);
+                return whandle->handle != -1;
         }
 
         return FALSE;
@@ -492,20 +495,16 @@ vc4_screen_bo_from_handle(struct pipe_screen *pscreen,
                           struct winsys_handle *whandle)
 {
         struct vc4_screen *screen = vc4_screen(pscreen);
-        struct vc4_bo *bo;
 
-        if (whandle->type != DRM_API_HANDLE_TYPE_SHARED) {
+        switch (whandle->type) {
+        case DRM_API_HANDLE_TYPE_SHARED:
+                return vc4_bo_open_name(screen, whandle->handle, whandle->stride);
+        case DRM_API_HANDLE_TYPE_FD:
+                return vc4_bo_open_dmabuf(screen, whandle->handle, whandle->stride);
+        default:
                 fprintf(stderr,
                         "Attempt to import unsupported handle type %d\n",
                         whandle->type);
                 return NULL;
         }
-
-        bo = vc4_bo_open_name(screen, whandle->handle, whandle->stride);
-        if (!bo) {
-                fprintf(stderr, "Open name %d failed\n", whandle->handle);
-                return NULL;
-        }
-
-        return bo;
 }




More information about the mesa-commit mailing list