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 <imirkin@alum.mit.edu>
This commit is contained in:
Simon Ser 2021-01-21 10:14:23 +01:00
parent 7bc8dbb991
commit 4f06ce2550

View file

@ -33,18 +33,30 @@ static bool export_gbm_bo(struct gbm_bo *bo,
attribs.modifier = gbm_bo_get_modifier(bo); attribs.modifier = gbm_bo_get_modifier(bo);
int i; int i;
int32_t handle = -1;
for (i = 0; i < attribs.n_planes; ++i) { for (i = 0; i < attribs.n_planes; ++i) {
union gbm_bo_handle handle = gbm_bo_get_handle_for_plane(bo, i); // GBM is lacking a function to get a FD for a given plane. Instead,
if (handle.s32 < 0) { // 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"); wlr_log(WLR_ERROR, "gbm_bo_get_handle_for_plane failed");
goto error_fd; 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)); attribs.fd[i] = gbm_bo_get_fd(bo);
int ret = drmPrimeHandleToFD(drm_fd, handle.s32, if (attribs.fd[i] < 0) {
DRM_CLOEXEC, &attribs.fd[i]); wlr_log(WLR_ERROR, "gbm_bo_get_fd failed");
if (ret < 0 || attribs.fd[i] < 0) {
wlr_log_errno(WLR_ERROR, "drmPrimeHandleToFD failed");
goto error_fd; goto error_fd;
} }