304 lines
12 KiB
Diff
304 lines
12 KiB
Diff
From d4d79415ca824cee38f8c8cdcdfe108179d092c0 Mon Sep 17 00:00:00 2001
|
|
From: Imagination Technologies <powervr@imgtec.com>
|
|
Date: Wed, 28 Apr 2021 16:33:42 +0100
|
|
Subject: [PATCH 042/168] 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 | 3 +
|
|
4 files changed, 112 insertions(+), 50 deletions(-)
|
|
|
|
diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c
|
|
index 8fd794bce99..63d3dc589d7 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 f6eb405d130..6921ed9fcb5 100644
|
|
--- a/src/glx/dri3_glx.c
|
|
+++ b/src/glx/dri3_glx.c
|
|
@@ -358,6 +358,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,
|
|
@@ -366,11 +381,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)
|
|
@@ -381,14 +394,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),
|
|
@@ -728,13 +733,14 @@ static const struct glx_context_vtable dri3_context_vtable = {
|
|
.interop_flush_objects = dri3_interop_flush_objects
|
|
};
|
|
|
|
-/** 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;
|
|
@@ -765,16 +771,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 */
|
|
@@ -810,6 +806,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)
|
|
{
|
|
@@ -852,6 +875,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)
|
|
@@ -883,8 +908,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;
|
|
}
|
|
@@ -926,27 +951,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,
|
|
@@ -958,7 +962,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 ad6f0b624b3..2192b20116d 100644
|
|
--- a/src/loader/loader_dri3_helper.c
|
|
+++ b/src/loader/loader_dri3_helper.c
|
|
@@ -2597,3 +2597,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 6d20162c47c..8b39af04e9e 100644
|
|
--- a/src/loader/loader_dri3_helper.h
|
|
+++ b/src/loader/loader_dri3_helper.h
|
|
@@ -330,5 +330,8 @@ loader_dri3_update_screen_resources(struct loader_dri3_screen_resources *res);
|
|
void
|
|
loader_dri3_destroy_screen_resources(struct loader_dri3_screen_resources *res);
|
|
|
|
+bool
|
|
+loader_dri3_has_modifiers(bool multiplanes_available,
|
|
+ const __DRIimageExtension *image);
|
|
|
|
#endif
|
|
--
|
|
2.17.1
|
|
|