From 1726ce9399c7d893ae02ca8327269bf524ba2613 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Fri, 22 Aug 2025 22:00:59 +0300 Subject: [PATCH 1/2] glamor: Use EGL_LINUX_DMA_BUF_EXT to create GBM bo EGLImages Port https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/751 to xorg Fixes glamor with modesetting on nvidia This is needed for glamor to work with modesetting on nvidia, according to the nvidia docs: https://download.nvidia.com/XFree86/Linux-x86_64/510.39.01/README/gbm.html From the mr above: The X server was passing GBM bos directly to eglCreateImageKHR using the EGL_NATIVE_PIXMAP_KHR target. Given the EGL GBM platform spec claims it is invalid to create a EGLSurface from a native pixmap on the GBM platform, implying there is no mapping between GBM objects and EGL's concept of native pixmaps, this seems a bit questionable. This change modifies the bo import function to extract all the required data from the bo and then imports it as a dma-buf instead when the dma-buf + modifiers path is available. Signed-off-by: stefan11111 --- glamor/glamor_egl.c | 100 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 88b1e8e93..178235c6f 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -231,12 +231,106 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, Bool ret = FALSE; glamor_egl = glamor_egl_get_screen_private(scrn); +#ifdef GBM_BO_FD_FOR_PLANE + uint64_t modifier = gbm_bo_get_modifier(bo); + const int num_planes = gbm_bo_get_plane_count(bo); + int fds[GBM_MAX_PLANES]; + int plane; + int attr_num = 0; + EGLint img_attrs[64] = {0}; + enum PlaneAttrs { + PLANE_FD, + PLANE_OFFSET, + PLANE_PITCH, + PLANE_MODIFIER_LO, + PLANE_MODIFIER_HI, + NUM_PLANE_ATTRS + }; + static const EGLint planeAttrs[][NUM_PLANE_ATTRS] = { + { + EGL_DMA_BUF_PLANE0_FD_EXT, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, + EGL_DMA_BUF_PLANE0_PITCH_EXT, + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, + }, + { + EGL_DMA_BUF_PLANE1_FD_EXT, + EGL_DMA_BUF_PLANE1_OFFSET_EXT, + EGL_DMA_BUF_PLANE1_PITCH_EXT, + EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT, + }, + { + EGL_DMA_BUF_PLANE2_FD_EXT, + EGL_DMA_BUF_PLANE2_OFFSET_EXT, + EGL_DMA_BUF_PLANE2_PITCH_EXT, + EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT, + }, + { + EGL_DMA_BUF_PLANE3_FD_EXT, + EGL_DMA_BUF_PLANE3_OFFSET_EXT, + EGL_DMA_BUF_PLANE3_PITCH_EXT, + EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT, + }, + }; + + for (plane = 0; plane < num_planes; plane++) fds[plane] = -1; +#endif glamor_make_current(glamor_priv); - image = eglCreateImageKHR(glamor_egl->display, - EGL_NO_CONTEXT, - EGL_NATIVE_PIXMAP_KHR, bo, NULL); +#ifdef GBM_BO_FD_FOR_PLANE + if (glamor_egl->dmabuf_capable) { +#define ADD_ATTR(attrs, num, attr) \ + do { \ + assert(((num) + 1) < (sizeof(attrs) / sizeof((attrs)[0]))); \ + (attrs)[(num)++] = (attr); \ + } while (0) + ADD_ATTR(img_attrs, attr_num, EGL_WIDTH); + ADD_ATTR(img_attrs, attr_num, gbm_bo_get_width(bo)); + ADD_ATTR(img_attrs, attr_num, EGL_HEIGHT); + ADD_ATTR(img_attrs, attr_num, gbm_bo_get_height(bo)); + ADD_ATTR(img_attrs, attr_num, EGL_LINUX_DRM_FOURCC_EXT); + ADD_ATTR(img_attrs, attr_num, gbm_bo_get_format(bo)); + + for (plane = 0; plane < num_planes; plane++) { + fds[plane] = gbm_bo_get_fd_for_plane(bo, plane); + ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_FD]); + ADD_ATTR(img_attrs, attr_num, fds[plane]); + ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_OFFSET]); + ADD_ATTR(img_attrs, attr_num, gbm_bo_get_offset(bo, plane)); + ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_PITCH]); + ADD_ATTR(img_attrs, attr_num, gbm_bo_get_stride_for_plane(bo, plane)); + ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_MODIFIER_LO]); + ADD_ATTR(img_attrs, attr_num, (uint32_t)(modifier & 0xFFFFFFFFULL)); + ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_MODIFIER_HI]); + ADD_ATTR(img_attrs, attr_num, (uint32_t)(modifier >> 32ULL)); + } + ADD_ATTR(img_attrs, attr_num, EGL_NONE); +#undef ADD_ATTR + + image = eglCreateImageKHR(glamor_egl->display, + EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + NULL, + img_attrs); + + for (plane = 0; plane < num_planes; plane++) { + close(fds[plane]); + fds[plane] = -1; + } + } + else +#endif + { + image = eglCreateImageKHR(glamor_egl->display, + EGL_NO_CONTEXT, + EGL_NATIVE_PIXMAP_KHR, bo, NULL); + } + if (image == EGL_NO_IMAGE_KHR) { glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); goto done; From db9eefa82ee34baaa06e27c21bcea027c8e29f18 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Fri, 22 Aug 2025 22:03:37 +0300 Subject: [PATCH 2/2] glamor: Enable dma-buf on nvidia Nvidia needs dma-buf for glamor acceleration to work when using the modesetting ddx driver. Signed-off-by: stefan11111 --- glamor/glamor_egl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 178235c6f..c4d8ce7c0 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -1317,6 +1317,8 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) glamor_egl->dmabuf_capable = TRUE; else if (strstr((const char *)renderer, "zink")) glamor_egl->dmabuf_capable = TRUE; + else if (strstr((const char *)renderer, "NVIDIA")) + glamor_egl->dmabuf_capable = TRUE; else glamor_egl->dmabuf_capable = FALSE; }