glx: initial plumbing to let users force-enable/disable extensions
This can be useful for debugging or working around bugs such as
Mesa#106 where Wine is expecting to find a visual that isn't
available.
v2:
- split the indirect GL extension override to its own commit
- memset the bitfields to 0 in __glXExtensionsCtrScreen
Reviewed-by: Adam Jackson <ajax@redhat.com>
v3:
- slight rework necessary after splitting the computation of usable
extensions (Ian)
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Signed-off-by: Martin Peres <martin.peres@mupuf.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7212>
diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h
index f4ffff4..42285b9 100644
--- a/src/glx/glxclient.h
+++ b/src/glx/glxclient.h
@@ -546,6 +546,9 @@
/*@{ */
unsigned char direct_support[__GLX_EXT_BYTES];
GLboolean ext_list_first_time;
+
+ unsigned char glx_force_enabled[__GLX_EXT_BYTES];
+ unsigned char glx_force_disabled[__GLX_EXT_BYTES];
/*@} */
};
diff --git a/src/glx/glxextensions.c b/src/glx/glxextensions.c
index ba14487..2b5280f 100644
--- a/src/glx/glxextensions.c
+++ b/src/glx/glxextensions.c
@@ -34,6 +34,7 @@
#include <string.h>
#include "glxextensions.h"
+#include "util/driconf.h"
#define SET_BIT(m,b) (m[ (b) / 8 ] |= (1U << ((b) % 8)))
#define CLR_BIT(m,b) (m[ (b) / 8 ] &= ~(1U << ((b) % 8)))
@@ -455,6 +456,74 @@
name, strlen(name), GL_TRUE, psc->direct_support);
}
+static void
+__ParseExtensionOverride(struct glx_screen *psc,
+ const struct extension_info *ext_list,
+ unsigned char *force_enable,
+ unsigned char *force_disable,
+ const char *override)
+{
+ const struct extension_info *ext;
+ char *env, *field;
+
+ if (override == NULL)
+ return;
+
+ /* Copy env_const because strtok() is destructive. */
+ env = strdup(override);
+ if (env == NULL)
+ return;
+
+ for (field = strtok(env, " "); field!= NULL; field = strtok(NULL, " ")) {
+ GLboolean enable;
+
+ switch (field[0]) {
+ case '+':
+ enable = GL_TRUE;
+ ++field;
+ break;
+ case '-':
+ enable = GL_FALSE;
+ ++field;
+ break;
+ default:
+ enable = GL_TRUE;
+ break;
+ }
+
+ ext = find_extension(ext_list, field, strlen(field));
+ if (ext) {
+ if (enable)
+ SET_BIT(force_enable, ext->bit);
+ else
+ SET_BIT(force_disable, ext->bit);
+ } else {
+ fprintf(stderr, "WARNING: Trying to %s the unknown extension '%s'\n",
+ enable ? "enable" : "disable", field);
+ }
+ }
+}
+
+/**
+ * \brief Parse the list of GLX extensions that the user wants to
+ * force-enable/disable by using \c override, and write the results to the
+ * screen's context.
+ *
+ * \param psc Pointer to GLX per-screen record.
+ * \param override A space-separated list of extensions to enable or disable.
+ * The list is processed thus:
+ * - Enable recognized extension names that are prefixed with '+'.
+ * - Disable recognized extension names that are prefixed with '-'.
+ * - Enable recognized extension names that are not prefixed.
+ */
+void
+__glXParseExtensionOverride(struct glx_screen *psc, const char *override)
+{
+ __ParseExtensionOverride(psc, known_glx_extensions, psc->glx_force_enabled,
+ psc->glx_force_disabled, override);
+}
+
+
/**
* Initialize global extension support tables.
*/
@@ -530,6 +599,10 @@
psc->ext_list_first_time = GL_FALSE;
(void) memcpy(psc->direct_support, direct_glx_support,
sizeof(direct_glx_support));
+ (void) memset(psc->glx_force_enabled, 0,
+ sizeof(psc->glx_force_enabled));
+ (void) memset(psc->glx_force_disabled, 0,
+ sizeof(psc->glx_force_disabled));
}
}
@@ -707,8 +780,13 @@
u |= client_glx_support[i] & psc->direct_support[i] &
(server_support[i] | direct_glx_only[i]);
- usable[i] = u;
+ /* Finally, apply driconf options to force some extension bits either
+ * enabled or disabled.
+ */
+ u |= psc->glx_force_enabled[i];
+ u &= ~psc->glx_force_disabled[i];
+ usable[i] = u;
}
}
else {
@@ -721,6 +799,12 @@
/* Enable extensions that the client and server both support */
u |= client_glx_support[i] & server_support[i];
+ /* Finally, apply driconf options to force some extension bits either
+ * enabled or disabled.
+ */
+ u |= psc->glx_force_enabled[i];
+ u &= ~psc->glx_force_disabled[i];
+
usable[i] = u;
}
}
diff --git a/src/glx/glxextensions.h b/src/glx/glxextensions.h
index 96bc753..abcac95 100644
--- a/src/glx/glxextensions.h
+++ b/src/glx/glxextensions.h
@@ -265,6 +265,8 @@
display_is_direct_capable,
int server_minor_version);
+extern void __glXParseExtensionOverride(struct glx_screen *psc,
+ const char *override);
extern void __glXCalculateUsableGLExtensions(struct glx_context *gc,
const char *server_string,
int major_version,