Mesa (main): glx: keep native window glx drawable by driconf option
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Feb 22 07:35:14 UTC 2022
Module: Mesa
Branch: main
Commit: 1dac5454eacc4b0410e6a974cf8af437b95d3776
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=1dac5454eacc4b0410e6a974cf8af437b95d3776
Author: Qiang Yu <yuq825 at gmail.com>
Date: Mon Feb 7 17:54:57 2022 +0800
glx: keep native window glx drawable by driconf option
DRI3 window back buffer is a client resource, so it's destroyed
when context switch drawable for native window.
But some application like Abaqus may leave a dirty back buffer
and reuse it when switch back. So add a driconf option for these
kind of app to keep the entire GLX drawable for native window.
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Signed-off-by: Qiang Yu <yuq825 at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14926>
---
.../auxiliary/pipe-loader/driinfo_gallium.h | 1 +
src/glx/dri3_glx.c | 7 +++
src/glx/dri_common.c | 52 +++++++++++++++++++++-
src/glx/glxclient.h | 7 +++
src/glx/glxext.c | 17 +++++++
src/util/driconf.h | 4 ++
6 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h b/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h
index e79da788178..067348a3733 100644
--- a/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h
+++ b/src/gallium/auxiliary/pipe-loader/driinfo_gallium.h
@@ -49,6 +49,7 @@ DRI_CONF_SECTION_DEBUG
DRI_CONF_IGNORE_MAP_UNSYNCHRONIZED(false)
DRI_CONF_FORCE_DIRECT_GLX_CONTEXT(false)
DRI_CONF_ALLOW_INVALID_GLX_DESTROY_WINDOW(false)
+ DRI_CONF_KEEP_NATIVE_WINDOW_GLX_DRAWABLE(false)
DRI_CONF_SECTION_END
DRI_CONF_SECTION_MISCELLANEOUS
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
index dc7aba9c985..1623a10ce44 100644
--- a/src/glx/dri3_glx.c
+++ b/src/glx/dri3_glx.c
@@ -1055,6 +1055,13 @@ dri3_create_screen(int screen, struct glx_display * priv)
&invalid_glx_destroy_window) == 0) {
psc->base.allow_invalid_glx_destroy_window = invalid_glx_destroy_window;
}
+
+ uint8_t keep_native_window_glx_drawable = false;
+ if (psc->config->configQueryb(psc->driScreen,
+ "keep_native_window_glx_drawable",
+ &keep_native_window_glx_drawable) == 0) {
+ psc->base.keep_native_window_glx_drawable = keep_native_window_glx_drawable;
+ }
}
free(driverName);
diff --git a/src/glx/dri_common.c b/src/glx/dri_common.c
index fd52b0e347d..7e2809d0c79 100644
--- a/src/glx/dri_common.c
+++ b/src/glx/dri_common.c
@@ -357,6 +357,9 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
return NULL;
if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) {
+ /* Resurrected, so remove from the alive-query-set if exist. */
+ _mesa_set_remove_key(priv->zombieGLXDrawable, pdraw);
+
pdraw->refcount ++;
return pdraw;
}
@@ -419,6 +422,46 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
return pdraw;
}
+static int
+discardGLXBadDrawableHandler(Display *display, xError *err, XExtCodes *codes,
+ int *ret_code)
+{
+ int code = codes->first_error + GLXBadDrawable;
+
+ /* Only discard error which is expected. */
+ if (err->majorCode == codes->major_opcode &&
+ err->minorCode == X_GLXGetDrawableAttributes &&
+ /* newer xserver use GLXBadDrawable, old one use BadDrawable */
+ (err->errorCode == code || err->errorCode == BadDrawable)) {
+ *ret_code = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+checkServerGLXDrawableAlive(const struct glx_display *priv)
+{
+ ErrorType old = XESetError(priv->dpy, priv->codes.extension,
+ discardGLXBadDrawableHandler);
+
+ set_foreach(priv->zombieGLXDrawable, entry) {
+ __GLXDRIdrawable *pdraw = (__GLXDRIdrawable *)entry->key;
+ GLXDrawable drawable = pdraw->drawable;
+ unsigned int dummy;
+
+ /* Fail to query, so the window has been closed. Release the GLXDrawable. */
+ if (!__glXGetDrawableAttribute(priv->dpy, drawable, GLX_WIDTH, &dummy)) {
+ pdraw->destroyDrawable(pdraw);
+ __glxHashDelete(priv->drawHash, drawable);
+ _mesa_set_remove(priv->zombieGLXDrawable, entry);
+ }
+ }
+
+ XESetError(priv->dpy, priv->codes.extension, old);
+}
+
static void
releaseDrawable(const struct glx_display *priv, GLXDrawable drawable)
{
@@ -433,8 +476,13 @@ releaseDrawable(const struct glx_display *priv, GLXDrawable drawable)
* hold the last refcount until destroy the GLXPbuffer object.
*/
if (pdraw->refcount == 0) {
- pdraw->destroyDrawable(pdraw);
- __glxHashDelete(priv->drawHash, drawable);
+ if (pdraw->psc->keep_native_window_glx_drawable) {
+ checkServerGLXDrawableAlive(priv);
+ _mesa_set_add(priv->zombieGLXDrawable, pdraw);
+ } else {
+ pdraw->destroyDrawable(pdraw);
+ __glxHashDelete(priv->drawHash, drawable);
+ }
}
}
}
diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h
index 4ea091f986b..54c12a4227b 100644
--- a/src/glx/glxclient.h
+++ b/src/glx/glxclient.h
@@ -54,6 +54,7 @@
#include "glxhash.h"
#include "util/macros.h"
#include "util/u_thread.h"
+#include "util/set.h"
#include "loader.h"
#include "glxextensions.h"
@@ -524,6 +525,7 @@ struct glx_screen
int scr;
bool force_direct_context;
bool allow_invalid_glx_destroy_window;
+ bool keep_native_window_glx_drawable;
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
/**
@@ -595,6 +597,11 @@ struct glx_display
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
__glxHashTable *drawHash;
+ /**
+ * GLXDrawable created from native window and about to be released.
+ */
+ struct set *zombieGLXDrawable;
+
/**
* Per display direct rendering interface functions and data.
*/
diff --git a/src/glx/glxext.c b/src/glx/glxext.c
index 48a60ad35cc..d828da227d4 100644
--- a/src/glx/glxext.c
+++ b/src/glx/glxext.c
@@ -268,6 +268,16 @@ FreeScreenConfigs(struct glx_display * priv)
priv->screens = NULL;
}
+#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
+static void
+free_zombie_glx_drawable(struct set_entry *entry)
+{
+ __GLXDRIdrawable *pdraw = (__GLXDRIdrawable *)entry->key;
+
+ pdraw->destroyDrawable(pdraw);
+}
+#endif
+
static void
glx_display_free(struct glx_display *priv)
{
@@ -279,6 +289,11 @@ glx_display_free(struct glx_display *priv)
__glXSetCurrentContextNull();
}
+ /* Needs to be done before free screen. */
+#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
+ _mesa_set_destroy(priv->zombieGLXDrawable, free_zombie_glx_drawable);
+#endif
+
FreeScreenConfigs(priv);
__glxHashDestroy(priv->glXDrawHash);
@@ -914,6 +929,8 @@ __glXInitialize(Display * dpy)
dpyPriv->drawHash = __glxHashCreate();
+ dpyPriv->zombieGLXDrawable = _mesa_pointer_set_create(NULL);
+
#ifndef GLX_USE_APPLEGL
/* Set the logger before the *CreateDisplay functions. */
loader_set_logger(glx_message);
diff --git a/src/util/driconf.h b/src/util/driconf.h
index 5e1c9591853..115430226e8 100644
--- a/src/util/driconf.h
+++ b/src/util/driconf.h
@@ -250,6 +250,10 @@
DRI_CONF_OPT_B(allow_invalid_glx_destroy_window, def, \
"Allow passing an invalid window into glXDestroyWindow")
+#define DRI_CONF_KEEP_NATIVE_WINDOW_GLX_DRAWABLE(def) \
+ DRI_CONF_OPT_B(keep_native_window_glx_drawable, def, \
+ "Keep GLX drawable created from native window when switch context")
+
#define DRI_CONF_OVERRIDE_VRAM_SIZE() \
DRI_CONF_OPT_I(override_vram_size, -1, -1, 2147483647, \
"Override the VRAM size advertised to the application in MiB (-1 = default)")
More information about the mesa-commit
mailing list