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@amd.com> Signed-off-by: Qiang Yu <yuq825@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14926>
This commit is contained in:
@@ -49,6 +49,7 @@ DRI_CONF_SECTION_DEBUG
|
|||||||
DRI_CONF_IGNORE_MAP_UNSYNCHRONIZED(false)
|
DRI_CONF_IGNORE_MAP_UNSYNCHRONIZED(false)
|
||||||
DRI_CONF_FORCE_DIRECT_GLX_CONTEXT(false)
|
DRI_CONF_FORCE_DIRECT_GLX_CONTEXT(false)
|
||||||
DRI_CONF_ALLOW_INVALID_GLX_DESTROY_WINDOW(false)
|
DRI_CONF_ALLOW_INVALID_GLX_DESTROY_WINDOW(false)
|
||||||
|
DRI_CONF_KEEP_NATIVE_WINDOW_GLX_DRAWABLE(false)
|
||||||
DRI_CONF_SECTION_END
|
DRI_CONF_SECTION_END
|
||||||
|
|
||||||
DRI_CONF_SECTION_MISCELLANEOUS
|
DRI_CONF_SECTION_MISCELLANEOUS
|
||||||
|
@@ -1055,6 +1055,13 @@ dri3_create_screen(int screen, struct glx_display * priv)
|
|||||||
&invalid_glx_destroy_window) == 0) {
|
&invalid_glx_destroy_window) == 0) {
|
||||||
psc->base.allow_invalid_glx_destroy_window = invalid_glx_destroy_window;
|
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);
|
free(driverName);
|
||||||
|
@@ -357,6 +357,9 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) {
|
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 ++;
|
pdraw->refcount ++;
|
||||||
return pdraw;
|
return pdraw;
|
||||||
}
|
}
|
||||||
@@ -419,6 +422,46 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
|
|||||||
return pdraw;
|
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
|
static void
|
||||||
releaseDrawable(const struct glx_display *priv, GLXDrawable drawable)
|
releaseDrawable(const struct glx_display *priv, GLXDrawable drawable)
|
||||||
{
|
{
|
||||||
@@ -433,12 +476,17 @@ releaseDrawable(const struct glx_display *priv, GLXDrawable drawable)
|
|||||||
* hold the last refcount until destroy the GLXPbuffer object.
|
* hold the last refcount until destroy the GLXPbuffer object.
|
||||||
*/
|
*/
|
||||||
if (pdraw->refcount == 0) {
|
if (pdraw->refcount == 0) {
|
||||||
|
if (pdraw->psc->keep_native_window_glx_drawable) {
|
||||||
|
checkServerGLXDrawableAlive(priv);
|
||||||
|
_mesa_set_add(priv->zombieGLXDrawable, pdraw);
|
||||||
|
} else {
|
||||||
pdraw->destroyDrawable(pdraw);
|
pdraw->destroyDrawable(pdraw);
|
||||||
__glxHashDelete(priv->drawHash, drawable);
|
__glxHashDelete(priv->drawHash, drawable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_X_HIDDEN void
|
_X_HIDDEN void
|
||||||
driReleaseDrawables(struct glx_context *gc)
|
driReleaseDrawables(struct glx_context *gc)
|
||||||
|
@@ -54,6 +54,7 @@
|
|||||||
#include "glxhash.h"
|
#include "glxhash.h"
|
||||||
#include "util/macros.h"
|
#include "util/macros.h"
|
||||||
#include "util/u_thread.h"
|
#include "util/u_thread.h"
|
||||||
|
#include "util/set.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "glxextensions.h"
|
#include "glxextensions.h"
|
||||||
|
|
||||||
@@ -524,6 +525,7 @@ struct glx_screen
|
|||||||
int scr;
|
int scr;
|
||||||
bool force_direct_context;
|
bool force_direct_context;
|
||||||
bool allow_invalid_glx_destroy_window;
|
bool allow_invalid_glx_destroy_window;
|
||||||
|
bool keep_native_window_glx_drawable;
|
||||||
|
|
||||||
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
#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)
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
||||||
__glxHashTable *drawHash;
|
__glxHashTable *drawHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GLXDrawable created from native window and about to be released.
|
||||||
|
*/
|
||||||
|
struct set *zombieGLXDrawable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Per display direct rendering interface functions and data.
|
* Per display direct rendering interface functions and data.
|
||||||
*/
|
*/
|
||||||
|
@@ -268,6 +268,16 @@ FreeScreenConfigs(struct glx_display * priv)
|
|||||||
priv->screens = NULL;
|
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
|
static void
|
||||||
glx_display_free(struct glx_display *priv)
|
glx_display_free(struct glx_display *priv)
|
||||||
{
|
{
|
||||||
@@ -279,6 +289,11 @@ glx_display_free(struct glx_display *priv)
|
|||||||
__glXSetCurrentContextNull();
|
__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);
|
FreeScreenConfigs(priv);
|
||||||
|
|
||||||
__glxHashDestroy(priv->glXDrawHash);
|
__glxHashDestroy(priv->glXDrawHash);
|
||||||
@@ -914,6 +929,8 @@ __glXInitialize(Display * dpy)
|
|||||||
|
|
||||||
dpyPriv->drawHash = __glxHashCreate();
|
dpyPriv->drawHash = __glxHashCreate();
|
||||||
|
|
||||||
|
dpyPriv->zombieGLXDrawable = _mesa_pointer_set_create(NULL);
|
||||||
|
|
||||||
#ifndef GLX_USE_APPLEGL
|
#ifndef GLX_USE_APPLEGL
|
||||||
/* Set the logger before the *CreateDisplay functions. */
|
/* Set the logger before the *CreateDisplay functions. */
|
||||||
loader_set_logger(glx_message);
|
loader_set_logger(glx_message);
|
||||||
|
@@ -250,6 +250,10 @@
|
|||||||
DRI_CONF_OPT_B(allow_invalid_glx_destroy_window, def, \
|
DRI_CONF_OPT_B(allow_invalid_glx_destroy_window, def, \
|
||||||
"Allow passing an invalid window into glXDestroyWindow")
|
"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() \
|
#define DRI_CONF_OVERRIDE_VRAM_SIZE() \
|
||||||
DRI_CONF_OPT_I(override_vram_size, -1, -1, 2147483647, \
|
DRI_CONF_OPT_I(override_vram_size, -1, -1, 2147483647, \
|
||||||
"Override the VRAM size advertised to the application in MiB (-1 = default)")
|
"Override the VRAM size advertised to the application in MiB (-1 = default)")
|
||||||
|
Reference in New Issue
Block a user