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