diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c index 6640f16da77..b71244f0e76 100644 --- a/src/gbm/backends/dri/gbm_dri.c +++ b/src/gbm/backends/dri/gbm_dri.c @@ -32,6 +32,7 @@ #include #include #include +#include /* for O_RDWR, which DRM_RDWR is defined as */ #include #include #include @@ -446,8 +447,19 @@ gbm_dri_bo_get_fd(struct gbm_bo *_bo) struct gbm_dri_bo *bo = gbm_dri_bo(_bo); int fd; - if (bo->image == NULL) + if (bo->image == NULL) { +#ifdef HAVE_LIBDRM + struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); + if (dri->has_dmabuf_export) { + int ret; + int prime_fd = -1; + ret = drmPrimeHandleToFD(dri->base.v0.fd, bo->handle, DRM_RDWR, &prime_fd); + if (!ret) + return prime_fd; + } +#endif return -1; + } if (!dri2_query_image(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd)) return -1; @@ -664,6 +676,43 @@ gbm_dri_bo_destroy(struct gbm_bo *_bo) free(bo); } +static struct gbm_bo * +dumb_bo_from_fd(struct gbm_device *gbm, + struct gbm_import_fd_data *fd_data) +{ +#ifdef HAVE_LIBDRM + struct gbm_dri_bo *bo; + int ret; + uint32_t handle; + + bo = calloc(1, sizeof *bo); + if (bo == NULL) { + errno = ENOMEM; + return NULL; + } + + ret = drmPrimeFDToHandle(gbm->v0.fd, fd_data->fd, &handle); + if (ret) { + free(bo); + return NULL; + } + + bo->base.gbm = gbm; + bo->base.v0.width = fd_data->width; + bo->base.v0.height = fd_data->height; + bo->base.v0.stride = fd_data->stride; + bo->base.v0.format = fd_data->format; + bo->base.v0.handle.u32 = handle; + bo->handle = handle; + bo->size = fd_data->stride * fd_data->height; + + return &bo->base; +#else + errno = ENOSYS; + return NULL; +#endif +} + static struct gbm_bo * gbm_dri_bo_import(struct gbm_device *gbm, uint32_t type, void *buffer, uint32_t usage) @@ -738,6 +787,9 @@ gbm_dri_bo_import(struct gbm_device *gbm, * the sARGB format. */ fourcc = core->v0.format_canonicalize(fd_data->format); + if (!dri->screen) + return dumb_bo_from_fd(gbm, fd_data); + image = dri2_from_dma_bufs(dri->screen, fd_data->width, fd_data->height, @@ -766,6 +818,11 @@ gbm_dri_bo_import(struct gbm_device *gbm, * the sARGB format. */ fourcc = core->v0.format_canonicalize(fd_data->format); + if (!dri->screen) { + errno = EINVAL; + return NULL; + } + image = dri2_from_dma_bufs(dri->screen, fd_data->width, fd_data->height, fourcc, fd_data->modifier,