From 39bc9360116e1c944c1d0d04f67a6ec5f010371f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 14 Oct 2014 11:21:04 +0100 Subject: [PATCH] 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. --- .../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 81649d42582..df818fed713 100644 --- a/src/gallium/auxiliary/target-helpers/inline_drm_helper.h +++ b/src/gallium/auxiliary/target-helpers/inline_drm_helper.h @@ -467,6 +467,11 @@ dd_configuration(enum drm_conf conf) if ((strcmp(driver_name, "kgsl") == 0) || (strcmp(driver_name, "msm") == 0)) return configuration_query(conf); else +#endif +#if defined(GALLIUM_VC4) + if (strcmp(driver_name, "vc4") == 0) + return configuration_query(conf); + else #endif return NULL; } diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.c b/src/gallium/drivers/vc4/vc4_bufmgr.c index 3b73ac80bf6..64fe2e40e42 100644 --- a/src/gallium/drivers/vc4/vc4_bufmgr.c +++ b/src/gallium/drivers/vc4/vc4_bufmgr.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -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 @@ -120,6 +114,59 @@ vc4_bo_open_name(struct vc4_screen *screen, uint32_t name, return bo; } +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 4a1d4a4ef0d..baaecfdfd3f 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 98c51c1ce7a..b532cc6782f 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; } -- 2.30.2