From bebd31516110ec781fc5f6ab5fdfc307b6866660 Mon Sep 17 00:00:00 2001 From: Brendan King Date: Wed, 28 Apr 2021 16:33:42 +0100 Subject: [PATCH 43/58] dri3: a linear buffer is not needed with DRM format modifiers If the X Server supports DRM format modifiers, there is no need for an additional linear buffer, as the client can allocate buffers with attributes known to the Server. --- src/egl/drivers/dri2/platform_x11_dri3.c | 7 +- src/glx/dri3_glx.c | 137 +++++++++++++++-------- src/loader/loader_dri3_helper.c | 15 +++ src/loader/loader_dri3_helper.h | 4 + 4 files changed, 113 insertions(+), 50 deletions(-) diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c index 860d975ba5c..4d2e3049071 100644 --- a/src/egl/drivers/dri2/platform_x11_dri3.c +++ b/src/egl/drivers/dri2/platform_x11_dri3.c @@ -158,6 +158,7 @@ dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf, struct dri3_egl_surface *dri3_surf; const __DRIconfig *dri_config; xcb_drawable_t drawable; + bool is_incompat_gpu; dri3_surf = calloc(1, sizeof *dri3_surf); if (!dri3_surf) { @@ -165,6 +166,10 @@ dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf, return NULL; } + is_incompat_gpu = dri2_dpy->is_different_gpu && + !loader_dri3_has_modifiers(dri2_dpy->multibuffers_available, + dri2_dpy->image); + if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf, attrib_list, false, native_surface)) goto cleanup_surf; @@ -190,7 +195,7 @@ dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf, if (loader_dri3_drawable_init(dri2_dpy->conn, drawable, egl_to_loader_dri3_drawable_type(type), dri2_dpy->dri_screen, - dri2_dpy->is_different_gpu, + is_incompat_gpu, dri2_dpy->multibuffers_available, true, dri_config, diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index cf7fc613c86..81e088efc29 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -364,6 +364,21 @@ glx_to_loader_dri3_drawable_type(int type) } } +static bool +dri3_has_multibuffer(const __DRIimageExtension *image, + const struct dri3_display *pdp) +{ +#ifdef HAVE_DRI3_MODIFIERS + return (image && image->base.version >= 15) && + (pdp->dri3Major > 1 || + (pdp->dri3Major == 1 && pdp->dri3Minor >= 2)) && + (pdp->presentMajor > 1 || + (pdp->presentMajor == 1 && pdp->presentMinor >= 2)); +#else + return false; +#endif +} + static __GLXDRIdrawable * dri3_create_drawable(struct glx_screen *base, XID xDrawable, GLXDrawable drawable, int type, @@ -372,11 +387,9 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable, struct dri3_drawable *pdraw; struct dri3_screen *psc = (struct dri3_screen *) base; __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; - bool has_multibuffer = false; -#ifdef HAVE_DRI3_MODIFIERS const struct dri3_display *const pdp = (struct dri3_display *) base->display->dri3Display; -#endif + bool has_multibuffer = dri3_has_multibuffer(psc->image, pdp); pdraw = calloc(1, sizeof(*pdraw)); if (!pdraw) @@ -387,14 +400,6 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable, pdraw->base.drawable = drawable; pdraw->base.psc = &psc->base; -#ifdef HAVE_DRI3_MODIFIERS - if ((psc->image && psc->image->base.version >= 15) && - (pdp->dri3Major > 1 || (pdp->dri3Major == 1 && pdp->dri3Minor >= 2)) && - (pdp->presentMajor > 1 || - (pdp->presentMajor == 1 && pdp->presentMinor >= 2))) - has_multibuffer = true; -#endif - (void) __glXInitialize(psc->base.dpy); if (loader_dri3_drawable_init(XGetXCBConnection(base->dpy), @@ -751,13 +756,14 @@ static const struct glx_context_vtable dri3_context_vtable = { .interop_export_object = dri3_interop_export_object }; -/** dri3_bind_extensions +/** dri3_bind_extensions_part1 * - * Enable all of the extensions supported on DRI3 + * Enable the extensions supported on DRI3 that don't depend on + * whether we are using a different GPU. */ static void -dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv, - const char *driverName) +dri3_bind_extensions_part1(struct dri3_screen *psc, struct glx_display * priv, + const char *driverName) { const __DRIextension **extensions; unsigned mask; @@ -788,16 +794,6 @@ dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv, } for (i = 0; extensions[i]; i++) { - /* when on a different gpu than the server, the server pixmaps - * can have a tiling mode we can't read. Thus we can't create - * a texture from them. - */ - if (!psc->is_different_gpu && - (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { - psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; - __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap"); - } - if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) { psc->f = (__DRI2flushExtension *) extensions[i]; /* internal driver extension, no GL extension exposed */ @@ -833,6 +829,33 @@ dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv, } } +/** dri3_bind_extensions_part2 + * + * Enable the extensions supported on DRI3 that depend on whether we + * are using a different GPU. + */ +static void +dri3_bind_extensions_part2(struct dri3_screen *psc, struct glx_display * priv, + const char *driverName) +{ + const __DRIextension **extensions; + int i; + + extensions = psc->core->getExtensions(psc->driScreen); + + for (i = 0; extensions[i]; i++) { + /* when on a different gpu than the server, the server pixmaps + * can have a tiling mode we can't read. Thus we can't create + * a texture from them. + */ + if (!psc->is_different_gpu && + (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { + psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; + __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap"); + } + } +} + static char * dri3_get_driver_name(struct glx_screen *glx_screen) { @@ -875,6 +898,8 @@ dri3_create_screen(int screen, struct glx_display * priv) char *driverName = NULL, *driverNameDisplayGPU, *tmp; int i; int fd_old; + bool is_different_gpu; + bool have_modifiers; psc = calloc(1, sizeof *psc); if (psc == NULL) @@ -906,8 +931,8 @@ dri3_create_screen(int screen, struct glx_display * priv) fd_old = psc->fd; psc->fd_dpy = os_dupfd_cloexec(psc->fd); psc->fd_display_gpu = fcntl(psc->fd, F_DUPFD_CLOEXEC, 3); - psc->fd = loader_get_user_preferred_fd(psc->fd, &psc->is_different_gpu); - if (!psc->is_different_gpu) { + psc->fd = loader_get_user_preferred_fd(psc->fd, &is_different_gpu); + if (!is_different_gpu) { close(psc->fd_display_gpu); psc->fd_display_gpu = -1; } @@ -949,27 +974,6 @@ dri3_create_screen(int screen, struct glx_display * priv) goto handle_error; } - if (psc->is_different_gpu) { - driverNameDisplayGPU = loader_get_driver_for_fd(psc->fd_display_gpu); - if (driverNameDisplayGPU) { - - /* check if driver name is matching so that non mesa drivers - * will not crash. Also need this check since image extension - * pointer from render gpu is shared with display gpu. Image - * extension pointer is shared because it keeps things simple. - */ - if (strcmp(driverName, driverNameDisplayGPU) == 0) { - psc->driScreenDisplayGPU = - psc->image_driver->createNewScreen2(screen, psc->fd_display_gpu, - pdp->loader_extensions, - extensions, - &driver_configs, psc); - } - - free(driverNameDisplayGPU); - } - } - psc->driScreen = psc->image_driver->createNewScreen2(screen, psc->fd, pdp->loader_extensions, @@ -981,7 +985,42 @@ dri3_create_screen(int screen, struct glx_display * priv) goto handle_error; } - dri3_bind_extensions(psc, priv, driverName); + dri3_bind_extensions_part1(psc, priv, driverName); + + have_modifiers = loader_dri3_has_modifiers(dri3_has_multibuffer(psc->image, + pdp), + psc->image); + + if (is_different_gpu) { + if (have_modifiers) { + close(psc->fd_display_gpu); + psc->fd_display_gpu = -1; + } else { + driverNameDisplayGPU = loader_get_driver_for_fd(psc->fd_display_gpu); + if (driverNameDisplayGPU) { + + /* check if driver name is matching so that non mesa drivers + * will not crash. Also need this check since image extension + * pointer from render gpu is shared with display gpu. Image + * extension pointer is shared because it keeps things simple. + */ + if (strcmp(driverName, driverNameDisplayGPU) == 0) { + psc->driScreenDisplayGPU = + psc->image_driver->createNewScreen2(screen, + psc->fd_display_gpu, + pdp->loader_extensions, + extensions, + &driver_configs, psc); + } + + free(driverNameDisplayGPU); + } + } + } + + psc->is_different_gpu = is_different_gpu && !have_modifiers; + + dri3_bind_extensions_part2(psc, priv, driverName); if (!psc->image || psc->image->base.version < 7 || !psc->image->createImageFromFds) { ErrorMessageF("Version 7 or imageFromFds image extension not found\n"); diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c index 364695d0667..d431d23cf2f 100644 --- a/src/loader/loader_dri3_helper.c +++ b/src/loader/loader_dri3_helper.c @@ -2407,3 +2407,18 @@ dri3_find_back_alloc(struct loader_dri3_drawable *draw) return back; } + +bool +loader_dri3_has_modifiers(bool multiplanes_available, + const __DRIimageExtension *image) +{ +#ifdef HAVE_DRI3_MODIFIERS + return multiplanes_available && image && + image->base.version >= 15 && + image->queryDmaBufModifiers && + image->createImageWithModifiers && + image->createImageFromDmaBufs2; +#else + return false; +#endif +} diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h index 792f7270098..3226a7250d2 100644 --- a/src/loader/loader_dri3_helper.h +++ b/src/loader/loader_dri3_helper.h @@ -293,4 +293,8 @@ loader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw); void loader_dri3_close_screen(__DRIscreen *dri_screen); + +bool +loader_dri3_has_modifiers(bool multiplanes_available, + const __DRIimageExtension *image); #endif -- 2.25.1