From 4f06ce255029a8d216d49e437632e2ecc79ef433 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 21 Jan 2021 10:14:23 +0100 Subject: [PATCH] render/gbm_allocator: avoid drmPrimeHandleToFD Some drivers (e.g. nouveau) need to do some book-keeping when exporting a BO handle to a DMA-BUF [1]. Using drmPrimeHandleToFD directly hides the export from the user-space drivers and causes some ref'counting issues. So we can't properly handle BOs with a different handle for each plane until [2] lands. [1]: https://gitlab.freedesktop.org/drm/nouveau/-/issues/43#note_772661 [2]: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5442 Suggested-by: Ilia Mirkin --- render/gbm_allocator.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/render/gbm_allocator.c b/render/gbm_allocator.c index 955e65af..e01be091 100644 --- a/render/gbm_allocator.c +++ b/render/gbm_allocator.c @@ -33,18 +33,30 @@ static bool export_gbm_bo(struct gbm_bo *bo, attribs.modifier = gbm_bo_get_modifier(bo); int i; + int32_t handle = -1; for (i = 0; i < attribs.n_planes; ++i) { - union gbm_bo_handle handle = gbm_bo_get_handle_for_plane(bo, i); - if (handle.s32 < 0) { + // GBM is lacking a function to get a FD for a given plane. Instead, + // check all planes have the same handle. We can't use + // drmPrimeHandleToFD because that messes up handle ref'counting in + // the user-space driver. + // TODO: use gbm_bo_get_plane_fd when it lands, see + // https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5442 + union gbm_bo_handle plane_handle = gbm_bo_get_handle_for_plane(bo, i); + if (plane_handle.s32 < 0) { wlr_log(WLR_ERROR, "gbm_bo_get_handle_for_plane failed"); goto error_fd; } + if (i == 0) { + handle = plane_handle.s32; + } else if (plane_handle.s32 != handle) { + wlr_log(WLR_ERROR, "Failed to export GBM BO: " + "all planes don't have the same GEM handle"); + goto error_fd; + } - int drm_fd = gbm_device_get_fd(gbm_bo_get_device(bo)); - int ret = drmPrimeHandleToFD(drm_fd, handle.s32, - DRM_CLOEXEC, &attribs.fd[i]); - if (ret < 0 || attribs.fd[i] < 0) { - wlr_log_errno(WLR_ERROR, "drmPrimeHandleToFD failed"); + attribs.fd[i] = gbm_bo_get_fd(bo); + if (attribs.fd[i] < 0) { + wlr_log(WLR_ERROR, "gbm_bo_get_fd failed"); goto error_fd; }