X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fextensions.c;h=6ded1bb426983fc1262405809f6f2c07d31d8ff1;hp=e94d2b74749b970304c7be89351c4d95656c421e;hb=9037005d6034d6bcbeb508e0f783622e2351b957;hpb=79f68306d23bfb48ef645c4bded8ee7b74d2d661 diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index e94d2b74749..6ded1bb4269 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -31,7 +31,7 @@ #include "glheader.h" -#include "imports.h" + #include "context.h" #include "extensions.h" #include "macros.h" @@ -39,9 +39,12 @@ struct gl_extensions _mesa_extension_override_enables; struct gl_extensions _mesa_extension_override_disables; -static char *extra_extensions = NULL; -static char *cant_disable_extensions = NULL; +#define MAX_UNRECOGNIZED_EXTENSIONS 16 +static struct { + char *env; + const char *names[MAX_UNRECOGNIZED_EXTENSIONS]; +} unrecognized_extensions; /** * Given a member \c x of struct gl_extensions, return offset of @@ -49,56 +52,46 @@ static char *cant_disable_extensions = NULL; */ #define o(x) offsetof(struct gl_extensions, x) - -/** - * \brief Table of supported OpenGL extensions for all API's. - */ -const struct mesa_extension _mesa_extension_table[] = { -#define EXT(name_str, driver_cap, gll_ver, glc_ver, gles_ver, gles2_ver, yyyy) \ - { .name = "GL_" #name_str, .offset = o(driver_cap), \ - .version = { \ - [API_OPENGL_COMPAT] = gll_ver, \ - [API_OPENGL_CORE] = glc_ver, \ - [API_OPENGLES] = gles_ver, \ - [API_OPENGLES2] = gles2_ver, \ - }, \ - .year = yyyy \ - }, -#include "extensions_table.h" -#undef EXT -}; - +static int +extension_name_compare(const void *name, const void *elem) +{ + const struct mesa_extension *entry = elem; + return strcmp(name, entry->name); +} /** * Given an extension name, lookup up the corresponding member of struct - * gl_extensions and return that member's offset (in bytes). If the name is - * not found in the \c _mesa_extension_table, return 0. + * gl_extensions and return that member's index. If the name is + * not found in the \c _mesa_extension_table, return -1. * * \param name Name of extension. - * \return Offset of member in struct gl_extensions. + * \return Index of member in struct gl_extensions. */ -static size_t -name_to_offset(const char* name) +static int +name_to_index(const char* name) { - unsigned i; + const struct mesa_extension *entry; - if (name == 0) - return 0; + if (!name) + return -1; - for (i = 0; i < ARRAY_SIZE(_mesa_extension_table); ++i) { - if (strcmp(name, _mesa_extension_table[i].name) == 0) - return _mesa_extension_table[i].offset; - } + entry = bsearch(name, + _mesa_extension_table, MESA_EXTENSION_COUNT, + sizeof(_mesa_extension_table[0]), + extension_name_compare); + + if (entry) + return entry - _mesa_extension_table; - return 0; + return -1; } /** * Overrides extensions in \c ctx based on the values in * _mesa_extension_override_enables and _mesa_extension_override_disables. */ -static void -override_extensions_in_context(struct gl_context *ctx) +void +_mesa_override_extensions(struct gl_context *ctx) { unsigned i; const GLboolean *enables = @@ -107,7 +100,7 @@ override_extensions_in_context(struct gl_context *ctx) (GLboolean*) &_mesa_extension_override_disables; GLboolean *ctx_ext = (GLboolean*)&ctx->Extensions; - for (i = 0; i < ARRAY_SIZE(_mesa_extension_table); ++i) { + for (i = 0; i < MESA_EXTENSION_COUNT; ++i) { size_t offset = _mesa_extension_table[i].offset; assert(!enables[offset] || !disables[offset]); @@ -149,9 +142,8 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.ARB_texture_env_combine = GL_TRUE; ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE; ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE; -#ifdef TEXTURE_FLOAT_ENABLED + ctx->Extensions.ARB_texture_filter_anisotropic = GL_TRUE; ctx->Extensions.ARB_texture_float = GL_TRUE; -#endif ctx->Extensions.ARB_texture_mirror_clamp_to_edge = GL_TRUE; ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE; ctx->Extensions.ARB_texture_rg = GL_TRUE; @@ -164,7 +156,6 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.ATI_texture_compression_3dc = GL_TRUE; ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE; ctx->Extensions.ATI_texture_mirror_once = GL_TRUE; - ctx->Extensions.ATI_separate_stencil = GL_TRUE; ctx->Extensions.EXT_blend_color = GL_TRUE; ctx->Extensions.EXT_blend_equation_separate = GL_TRUE; ctx->Extensions.EXT_blend_func_separate = GL_TRUE; @@ -195,10 +186,8 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE; ctx->Extensions.OES_standard_derivatives = GL_TRUE; ctx->Extensions.TDFX_texture_compression_FXT1 = GL_TRUE; - if (ctx->Mesa_DXTn) { - ctx->Extensions.ANGLE_texture_compression_dxt = GL_TRUE; - ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE; - } + ctx->Extensions.ANGLE_texture_compression_dxt = GL_TRUE; + ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE; } /** @@ -206,11 +195,11 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) * \return offset of extensions withint `ext' or 0 if extension is not known */ static size_t -set_extension(struct gl_extensions *ext, const char *name, GLboolean state) +set_extension(struct gl_extensions *ext, int i, GLboolean state) { size_t offset; - offset = name_to_offset(name); + offset = i < 0 ? 0 : _mesa_extension_table[i].offset; if (offset != 0 && (offset != o(dummy_true) || state != GL_FALSE)) { ((GLboolean *) ext)[offset] = state; } @@ -218,62 +207,33 @@ set_extension(struct gl_extensions *ext, const char *name, GLboolean state) return offset; } -/** - * \brief Apply the \c MESA_EXTENSION_OVERRIDE environment variable. - * - * \c MESA_EXTENSION_OVERRIDE is 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. - * - Collect unrecognized extension names in a new string. - * - * \c MESA_EXTENSION_OVERRIDE was previously parsed during - * _mesa_one_time_init_extension_overrides. We just use the results of that - * parsing in this function. - * - * \return Space-separated list of unrecognized extension names (which must - * be freed). Does not return \c NULL. - */ -static char * -get_extension_override( struct gl_context *ctx ) -{ - override_extensions_in_context(ctx); - - if (cant_disable_extensions != NULL) { - _mesa_problem(ctx, - "Trying to disable permanently enabled extensions: %s", - cant_disable_extensions); - } - - if (extra_extensions == NULL) { - return calloc(1, sizeof(char)); - } else { - _mesa_problem(ctx, "Trying to enable unknown extensions: %s", - extra_extensions); - return strdup(extra_extensions); - } -} - /** - * \brief Free extra_extensions and cant_disable_extensions strings + * \brief Free string pointed by unrecognized_extensions * - * These strings are allocated early during the first context creation by + * This string is allocated early during the first context creation by * _mesa_one_time_init_extension_overrides. */ static void free_unknown_extensions_strings(void) { - free(extra_extensions); - free(cant_disable_extensions); + free(unrecognized_extensions.env); + for (int i = 0; i < MAX_UNRECOGNIZED_EXTENSIONS; ++i) + unrecognized_extensions.names[i] = NULL; } /** - * \brief Initialize extension override tables. + * \brief Initialize extension override tables based on \c MESA_EXTENSION_OVERRIDE * * This should be called one time early during first context initialization. + + * \c MESA_EXTENSION_OVERRIDE is 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. + * - Collect unrecognized extension names in a new string. */ void _mesa_one_time_init_extension_overrides(void) @@ -281,10 +241,8 @@ _mesa_one_time_init_extension_overrides(void) const char *env_const = getenv("MESA_EXTENSION_OVERRIDE"); char *env; char *ext; - int len; size_t offset; - - atexit(free_unknown_extensions_strings); + unsigned unknown_ext = 0; memset(&_mesa_extension_override_enables, 0, sizeof(struct gl_extensions)); memset(&_mesa_extension_override_disables, 0, sizeof(struct gl_extensions)); @@ -293,23 +251,15 @@ _mesa_one_time_init_extension_overrides(void) return; } - /* extra_exts: List of unrecognized extensions. */ - extra_extensions = calloc(ALIGN(strlen(env_const) + 2, 4), sizeof(char)); - cant_disable_extensions = calloc(ALIGN(strlen(env_const) + 2, 4), sizeof(char)); - /* Copy env_const because strtok() is destructive. */ env = strdup(env_const); - if (env == NULL || extra_extensions == NULL || - cant_disable_extensions == NULL) { - free(env); - free(extra_extensions); - free(cant_disable_extensions); - return; - } + if (env == NULL) + return; for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) { int enable; + int i; bool recognized; switch (ext[0]) { case '+': @@ -325,41 +275,37 @@ _mesa_one_time_init_extension_overrides(void) break; } - offset = set_extension(&_mesa_extension_override_enables, ext, enable); - if (offset != 0 && (offset != o(dummy_true) || enable != GL_FALSE)) { - ((GLboolean *) &_mesa_extension_override_disables)[offset] = !enable; + i = name_to_index(ext); + offset = set_extension(&_mesa_extension_override_enables, i, enable); + offset = set_extension(&_mesa_extension_override_disables, i, !enable); + if (offset != 0) recognized = true; - } else { + else recognized = false; - } - if (!recognized) { - if (enable) { - strcat(extra_extensions, ext); - strcat(extra_extensions, " "); - } else if (offset == o(dummy_true)) { - strcat(cant_disable_extensions, ext); - strcat(cant_disable_extensions, " "); + if (!recognized && enable) { + if (unknown_ext >= MAX_UNRECOGNIZED_EXTENSIONS) { + static bool warned; + + if (!warned) { + warned = true; + _mesa_problem(NULL, "Trying to enable too many unknown extension. " + "Only the first %d will be honoured", + MAX_UNRECOGNIZED_EXTENSIONS); + } + } else { + unrecognized_extensions.names[unknown_ext] = ext; + unknown_ext++; + _mesa_problem(NULL, "Trying to enable unknown extension: %s", ext); } } } - free(env); - - /* Remove trailing space, and free if unused. */ - len = strlen(extra_extensions); - if (len == 0) { - free(extra_extensions); - extra_extensions = NULL; - } else if (extra_extensions[len - 1] == ' ') { - extra_extensions[len - 1] = '\0'; - } - len = strlen(cant_disable_extensions); - if (len == 0) { - free(cant_disable_extensions); - cant_disable_extensions = NULL; - } else if (cant_disable_extensions[len - 1] == ' ') { - cant_disable_extensions[len - 1] = '\0'; + if (!unknown_ext) { + free(env); + } else { + unrecognized_extensions.env = env; + atexit(free_unknown_extensions_strings); } } @@ -443,9 +389,7 @@ _mesa_make_extension_string(struct gl_context *ctx) /* Number of extensions */ unsigned count; /* Indices of the extensions sorted by year */ - extension_index *extension_indices; - /* String of extra extensions. */ - char *extra_extensions = get_extension_override(ctx); + extension_index extension_indices[MESA_EXTENSION_COUNT]; unsigned k; unsigned j; unsigned maxYear = ~0; @@ -462,7 +406,7 @@ _mesa_make_extension_string(struct gl_context *ctx) /* Compute length of the extension string. */ count = 0; - for (k = 0; k < ARRAY_SIZE(_mesa_extension_table); ++k) { + for (k = 0; k < MESA_EXTENSION_COUNT; ++k) { const struct mesa_extension *i = _mesa_extension_table + k; if (i->year <= maxYear && @@ -471,29 +415,24 @@ _mesa_make_extension_string(struct gl_context *ctx) ++count; } } - if (extra_extensions != NULL) - length += 1 + strlen(extra_extensions); /* +1 for space */ + for (k = 0; k < MAX_UNRECOGNIZED_EXTENSIONS; k++) + if (unrecognized_extensions.names[k]) + length += 1 + strlen(unrecognized_extensions.names[k]); /* +1 for space */ exts = calloc(ALIGN(length + 1, 4), sizeof(char)); if (exts == NULL) { - free(extra_extensions); return NULL; } - extension_indices = malloc(count * sizeof(extension_index)); - if (extension_indices == NULL) { - free(exts); - free(extra_extensions); - return NULL; - } - - /* Sort extensions in chronological order because certain old applications - * (e.g., Quake3 demo) store the extension list in a static size buffer so - * chronologically order ensure that the extensions that such applications - * expect will fit into that buffer. + /* Sort extensions in chronological order because idTech 2/3 games + * (e.g., Quake3 demo) store the extension list in a fixed size buffer. + * Some cases truncate, while others overflow the buffer. Resulting in + * misrendering and crashes, respectively. + * Address the former here, while the latter will be addressed by setting + * the MESA_EXTENSION_MAX_YEAR environment variable. */ j = 0; - for (k = 0; k < ARRAY_SIZE(_mesa_extension_table); ++k) { + for (k = 0; k < MESA_EXTENSION_COUNT; ++k) { if (_mesa_extension_table[k].year <= maxYear && _mesa_extension_supported(ctx, k)) { extension_indices[j++] = k; @@ -510,10 +449,11 @@ _mesa_make_extension_string(struct gl_context *ctx) strcat(exts, i->name); strcat(exts, " "); } - free(extension_indices); - if (extra_extensions != 0) { - strcat(exts, extra_extensions); - free(extra_extensions); + for (j = 0; j < MAX_UNRECOGNIZED_EXTENSIONS; j++) { + if (unrecognized_extensions.names[j]) { + strcat(exts, unrecognized_extensions.names[j]); + strcat(exts, " "); + } } return (GLubyte *) exts; @@ -531,10 +471,15 @@ _mesa_get_extension_count(struct gl_context *ctx) if (ctx->Extensions.Count != 0) return ctx->Extensions.Count; - for (k = 0; k < ARRAY_SIZE(_mesa_extension_table); ++k) { + for (k = 0; k < MESA_EXTENSION_COUNT; ++k) { if (_mesa_extension_supported(ctx, k)) ctx->Extensions.Count++; } + + for (k = 0; k < MAX_UNRECOGNIZED_EXTENSIONS; ++k) { + if (unrecognized_extensions.names[k]) + ctx->Extensions.Count++; + } return ctx->Extensions.Count; } @@ -547,7 +492,7 @@ _mesa_get_enabled_extension(struct gl_context *ctx, GLuint index) size_t n = 0; unsigned i; - for (i = 0; i < ARRAY_SIZE(_mesa_extension_table); ++i) { + for (i = 0; i < MESA_EXTENSION_COUNT; ++i) { if (_mesa_extension_supported(ctx, i)) { if (n == index) return (const GLubyte*) _mesa_extension_table[i].name; @@ -556,5 +501,13 @@ _mesa_get_enabled_extension(struct gl_context *ctx, GLuint index) } } + for (i = 0; i < MAX_UNRECOGNIZED_EXTENSIONS; ++i) { + if (unrecognized_extensions.names[i]) { + if (n == index) + return (const GLubyte*) unrecognized_extensions.names[i]; + else + ++n; + } + } return NULL; }