From e19644967f20a6baf82c5ffd6973e2b25fac92b3 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Thu, 15 Oct 2020 08:55:41 +0300 Subject: [PATCH] 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 v3: - slight rework necessary after splitting the computation of usable extensions (Ian) Reviewed-by: Ian Romanick Signed-off-by: Martin Peres Part-of: --- src/glx/glxclient.h | 3 ++ src/glx/glxextensions.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++- src/glx/glxextensions.h | 2 ++ 3 files changed, 90 insertions(+), 1 deletion(-) 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 @@ struct glx_screen /*@{ */ 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 #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 @@ __glXEnableDirectExtension(struct glx_screen * psc, const char *name) 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 @@ __glXExtensionsCtrScreen(struct glx_screen * psc) 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 @@ __glXCalculateUsableExtensions(struct glx_screen * psc, 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 @@ __glXCalculateUsableExtensions(struct glx_screen * psc, /* 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 @@ extern void __glXCalculateUsableExtensions(struct glx_screen *psc, 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, -- 2.7.4