diff options
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r-- | mesalib/src/glsl/Makefile.sources | 4 | ||||
-rw-r--r-- | mesalib/src/glsl/ast.h | 29 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_lexer.ll | 23 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_parser_extras.cpp | 10 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_types.cpp | 59 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_types.h | 33 | ||||
-rwxr-xr-x | mesalib/src/glsl/ir.cpp | 48 | ||||
-rw-r--r-- | mesalib/src/glsl/ir.h | 30 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_optimization.h | 1 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_reader.cpp | 2 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_uniform.h | 6 | ||||
-rw-r--r-- | mesalib/src/glsl/link_uniforms.cpp | 50 | ||||
-rw-r--r-- | mesalib/src/glsl/linker.cpp | 44 | ||||
-rw-r--r-- | mesalib/src/glsl/list.h | 21 | ||||
-rw-r--r-- | mesalib/src/glsl/loop_unroll.cpp | 13 | ||||
-rw-r--r-- | mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp | 111 | ||||
-rw-r--r-- | mesalib/src/glsl/main.cpp | 10 | ||||
-rw-r--r-- | mesalib/src/glsl/opt_algebraic.cpp | 49 | ||||
-rw-r--r-- | mesalib/src/glsl/opt_cse.cpp | 9 | ||||
-rw-r--r-- | mesalib/src/glsl/s_expression.cpp | 2 | ||||
-rw-r--r-- | mesalib/src/glsl/s_expression.h | 2 | ||||
-rw-r--r-- | mesalib/src/glsl/strtod.c | 79 | ||||
-rw-r--r-- | mesalib/src/glsl/strtod.h | 46 |
23 files changed, 369 insertions, 312 deletions
diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index 0c55327d6..676fa0d7a 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -59,6 +59,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/loop_controls.cpp \ $(GLSL_SRCDIR)/loop_unroll.cpp \ $(GLSL_SRCDIR)/lower_clip_distance.cpp \ + $(GLSL_SRCDIR)/lower_const_arrays_to_uniforms.cpp \ $(GLSL_SRCDIR)/lower_discard.cpp \ $(GLSL_SRCDIR)/lower_discard_flow.cpp \ $(GLSL_SRCDIR)/lower_if_to_cond_assign.cpp \ @@ -104,8 +105,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_swizzle_swizzle.cpp \ $(GLSL_SRCDIR)/opt_tree_grafting.cpp \ $(GLSL_SRCDIR)/opt_vectorize.cpp \ - $(GLSL_SRCDIR)/s_expression.cpp \ - $(GLSL_SRCDIR)/strtod.c + $(GLSL_SRCDIR)/s_expression.cpp # glsl_compiler diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 83dfafd75..deb8c7a7f 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -644,19 +644,6 @@ class ast_declarator_list; class ast_struct_specifier : public ast_node { public: - /** - * \brief Make a shallow copy of an ast_struct_specifier. - * - * Use only if the objects are allocated from the same context and will not - * be modified. Zeros the inherited ast_node's fields. - */ - ast_struct_specifier(const ast_struct_specifier& that): - ast_node(), name(that.name), declarations(that.declarations), - is_declaration(that.is_declaration) - { - /* empty */ - } - ast_struct_specifier(const char *identifier, ast_declarator_list *declarator_list); virtual void print(void) const; @@ -674,22 +661,6 @@ public: class ast_type_specifier : public ast_node { public: - /** - * \brief Make a shallow copy of an ast_type_specifier, specifying array - * fields. - * - * Use only if the objects are allocated from the same context and will not - * be modified. Zeros the inherited ast_node's fields. - */ - ast_type_specifier(const ast_type_specifier *that, - ast_array_specifier *array_specifier) - : ast_node(), type_name(that->type_name), structure(that->structure), - array_specifier(array_specifier), - default_precision(that->default_precision) - { - /* empty */ - } - /** Construct a type specifier from a type name */ ast_type_specifier(const char *name) : type_name(name), structure(NULL), array_specifier(NULL), diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index e66a93591..57c46be84 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -23,7 +23,7 @@ */ #include <ctype.h> #include <limits.h> -#include "strtod.h" +#include "util/strtod.h" #include "ast.h" #include "glsl_parser_extras.h" #include "glsl_parser.h" @@ -450,24 +450,11 @@ layout { return LITERAL_INTEGER(8); } -[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]? { - yylval->real = glsl_strtof(yytext, NULL); - return FLOATCONSTANT; - } -\.[0-9]+([eE][+-]?[0-9]+)?[fF]? { - yylval->real = glsl_strtof(yytext, NULL); - return FLOATCONSTANT; - } -[0-9]+\.([eE][+-]?[0-9]+)?[fF]? { - yylval->real = glsl_strtof(yytext, NULL); - return FLOATCONSTANT; - } +[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]? | +\.[0-9]+([eE][+-]?[0-9]+)?[fF]? | +[0-9]+\.([eE][+-]?[0-9]+)?[fF]? | [0-9]+[eE][+-]?[0-9]+[fF]? { - yylval->real = glsl_strtof(yytext, NULL); - return FLOATCONSTANT; - } -[0-9]+[fF] { - yylval->real = glsl_strtof(yytext, NULL); + yylval->real = _mesa_strtof(yytext, NULL); return FLOATCONSTANT; } diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index 79f849465..27e3301e2 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -1350,9 +1350,15 @@ ast_struct_specifier::ast_struct_specifier(const char *identifier, ast_declarator_list *declarator_list) { if (identifier == NULL) { + static mtx_t mutex = _MTX_INITIALIZER_NP; static unsigned anon_count = 1; - identifier = ralloc_asprintf(this, "#anon_struct_%04x", anon_count); - anon_count++; + unsigned count; + + mtx_lock(&mutex); + count = anon_count++; + mtx_unlock(&mutex); + + identifier = ralloc_asprintf(this, "#anon_struct_%04x", count); } name = identifier; this->declarations.push_degenerate_list_at_head(&declarator_list->link); diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index c11d86482..5f9919348 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -29,6 +29,7 @@ extern "C" { #include "program/hash_table.h" } +mtx_t glsl_type::mutex = _MTX_INITIALIZER_NP; hash_table *glsl_type::array_types = NULL; hash_table *glsl_type::record_types = NULL; hash_table *glsl_type::interface_types = NULL; @@ -53,9 +54,14 @@ glsl_type::glsl_type(GLenum gl_type, vector_elements(vector_elements), matrix_columns(matrix_columns), length(0) { + mtx_lock(&glsl_type::mutex); + init_ralloc_type_ctx(); assert(name != NULL); this->name = ralloc_strdup(this->mem_ctx, name); + + mtx_unlock(&glsl_type::mutex); + /* Neither dimension is zero or both dimensions are zero. */ assert((vector_elements == 0) == (matrix_columns == 0)); @@ -71,9 +77,14 @@ glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type, sampler_array(array), sampler_type(type), interface_packing(0), length(0) { + mtx_lock(&glsl_type::mutex); + init_ralloc_type_ctx(); assert(name != NULL); this->name = ralloc_strdup(this->mem_ctx, name); + + mtx_unlock(&glsl_type::mutex); + memset(& fields, 0, sizeof(fields)); if (base_type == GLSL_TYPE_SAMPLER) { @@ -95,11 +106,14 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, { unsigned int i; + mtx_lock(&glsl_type::mutex); + init_ralloc_type_ctx(); assert(name != NULL); this->name = ralloc_strdup(this->mem_ctx, name); this->fields.structure = ralloc_array(this->mem_ctx, glsl_struct_field, length); + for (i = 0; i < length; i++) { this->fields.structure[i].type = fields[i].type; this->fields.structure[i].name = ralloc_strdup(this->fields.structure, @@ -110,6 +124,8 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, this->fields.structure[i].sample = fields[i].sample; this->fields.structure[i].matrix_layout = fields[i].matrix_layout; } + + mtx_unlock(&glsl_type::mutex); } glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, @@ -123,6 +139,8 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, { unsigned int i; + mtx_lock(&glsl_type::mutex); + init_ralloc_type_ctx(); assert(name != NULL); this->name = ralloc_strdup(this->mem_ctx, name); @@ -138,6 +156,8 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, this->fields.structure[i].sample = fields[i].sample; this->fields.structure[i].matrix_layout = fields[i].matrix_layout; } + + mtx_unlock(&glsl_type::mutex); } @@ -285,6 +305,8 @@ const glsl_type *glsl_type::get_scalar_type() const void _mesa_glsl_release_types(void) { + mtx_lock(&glsl_type::mutex); + if (glsl_type::array_types != NULL) { hash_table_dtor(glsl_type::array_types); glsl_type::array_types = NULL; @@ -294,6 +316,8 @@ _mesa_glsl_release_types(void) hash_table_dtor(glsl_type::record_types); glsl_type::record_types = NULL; } + + mtx_unlock(&glsl_type::mutex); } @@ -302,7 +326,7 @@ glsl_type::glsl_type(const glsl_type *array, unsigned length) : sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), sampler_type(0), interface_packing(0), vector_elements(0), matrix_columns(0), - name(NULL), length(length) + length(length), name(NULL) { this->fields.array = array; /* Inherit the gl type of the base. The GL type is used for @@ -316,7 +340,10 @@ glsl_type::glsl_type(const glsl_type *array, unsigned length) : * NUL. */ const unsigned name_length = strlen(array->name) + 10 + 3; + + mtx_lock(&glsl_type::mutex); char *const n = (char *) ralloc_size(this->mem_ctx, name_length); + mtx_unlock(&glsl_type::mutex); if (length == 0) snprintf(n, name_length, "%s[]", array->name); @@ -452,12 +479,6 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns) const glsl_type * glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) { - - if (array_types == NULL) { - array_types = hash_table_ctor(64, hash_table_string_hash, - hash_table_string_compare); - } - /* Generate a name using the base type pointer in the key. This is * done because the name of the base type may not be unique across * shaders. For example, two shaders may have different record types @@ -466,9 +487,19 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) char key[128]; snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size); + mtx_lock(&glsl_type::mutex); + + if (array_types == NULL) { + array_types = hash_table_ctor(64, hash_table_string_hash, + hash_table_string_compare); + } + const glsl_type *t = (glsl_type *) hash_table_find(array_types, key); + if (t == NULL) { + mtx_unlock(&glsl_type::mutex); t = new glsl_type(base, array_size); + mtx_lock(&glsl_type::mutex); hash_table_insert(array_types, (void *) t, ralloc_strdup(mem_ctx, key)); } @@ -477,6 +508,8 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) assert(t->length == array_size); assert(t->fields.array == base); + mtx_unlock(&glsl_type::mutex); + return t; } @@ -575,13 +608,17 @@ glsl_type::get_record_instance(const glsl_struct_field *fields, { const glsl_type key(fields, num_fields, name); + mtx_lock(&glsl_type::mutex); + if (record_types == NULL) { record_types = hash_table_ctor(64, record_key_hash, record_key_compare); } const glsl_type *t = (glsl_type *) hash_table_find(record_types, & key); if (t == NULL) { + mtx_unlock(&glsl_type::mutex); t = new glsl_type(fields, num_fields, name); + mtx_lock(&glsl_type::mutex); hash_table_insert(record_types, (void *) t, t); } @@ -590,6 +627,8 @@ glsl_type::get_record_instance(const glsl_struct_field *fields, assert(t->length == num_fields); assert(strcmp(t->name, name) == 0); + mtx_unlock(&glsl_type::mutex); + return t; } @@ -602,13 +641,17 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields, { const glsl_type key(fields, num_fields, packing, block_name); + mtx_lock(&glsl_type::mutex); + if (interface_types == NULL) { interface_types = hash_table_ctor(64, record_key_hash, record_key_compare); } const glsl_type *t = (glsl_type *) hash_table_find(interface_types, & key); if (t == NULL) { + mtx_unlock(&glsl_type::mutex); t = new glsl_type(fields, num_fields, packing, block_name); + mtx_lock(&glsl_type::mutex); hash_table_insert(interface_types, (void *) t, t); } @@ -617,6 +660,8 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields, assert(t->length == num_fields); assert(strcmp(t->name, block_name) == 0); + mtx_unlock(&glsl_type::mutex); + return t; } diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index eeb14c274..474b12914 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -122,16 +122,18 @@ struct glsl_type { * easier to just ralloc_free 'mem_ctx' (or any of its ancestors). */ static void* operator new(size_t size) { - if (glsl_type::mem_ctx == NULL) { - glsl_type::mem_ctx = ralloc_context(NULL); - assert(glsl_type::mem_ctx != NULL); - } + mtx_lock(&glsl_type::mutex); + + /* mem_ctx should have been created by the static members */ + assert(glsl_type::mem_ctx != NULL); void *type; type = ralloc_size(glsl_type::mem_ctx, size); assert(type != NULL); + mtx_unlock(&glsl_type::mutex); + return type; } @@ -139,7 +141,9 @@ struct glsl_type { * ralloc_free in that case. */ static void operator delete(void *type) { + mtx_lock(&glsl_type::mutex); ralloc_free(type); + mtx_unlock(&glsl_type::mutex); } /** @@ -149,18 +153,11 @@ struct glsl_type { * these will be 0. */ /*@{*/ - unsigned vector_elements:3; /**< 1, 2, 3, or 4 vector elements. */ - unsigned matrix_columns:3; /**< 1, 2, 3, or 4 matrix columns. */ + uint8_t vector_elements; /**< 1, 2, 3, or 4 vector elements. */ + uint8_t matrix_columns; /**< 1, 2, 3, or 4 matrix columns. */ /*@}*/ /** - * Name of the data type - * - * Will never be \c NULL. - */ - const char *name; - - /** * For \c GLSL_TYPE_ARRAY, this is the length of the array. For * \c GLSL_TYPE_STRUCT or \c GLSL_TYPE_INTERFACE, it is the number of * elements in the structure and the number of values pointed to by @@ -169,6 +166,13 @@ struct glsl_type { unsigned length; /** + * Name of the data type + * + * Will never be \c NULL. + */ + const char *name; + + /** * Subtype of composite data types. */ union { @@ -618,6 +622,9 @@ struct glsl_type { bool record_compare(const glsl_type *b) const; private: + + static mtx_t mutex; + /** * ralloc context for all glsl_type allocations * diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index 5907854f6..f6aeb6158 100755 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -46,11 +46,6 @@ bool ir_rvalue::is_negative_one() const return false; } -bool ir_rvalue::is_basis() const -{ - return false; -} - /** * Modify the swizzle make to move one component to another * @@ -1191,49 +1186,6 @@ ir_constant::is_negative_one() const } bool -ir_constant::is_basis() const -{ - if (!this->type->is_scalar() && !this->type->is_vector()) - return false; - - if (this->type->is_boolean()) - return false; - - unsigned ones = 0; - for (unsigned c = 0; c < this->type->vector_elements; c++) { - switch (this->type->base_type) { - case GLSL_TYPE_FLOAT: - if (this->value.f[c] == 1.0) - ones++; - else if (this->value.f[c] != 0.0) - return false; - break; - case GLSL_TYPE_INT: - if (this->value.i[c] == 1) - ones++; - else if (this->value.i[c] != 0) - return false; - break; - case GLSL_TYPE_UINT: - if (int(this->value.u[c]) == 1) - ones++; - else if (int(this->value.u[c]) != 0) - return false; - break; - default: - /* The only other base types are structures, arrays, samplers, and - * booleans. Samplers cannot be constants, and the others should - * have been filtered out above. - */ - assert(!"Should not get here."); - return false; - } - } - - return ones == 1; -} - -bool ir_constant::is_uint16_constant() const { if (!type->is_integer()) diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 90c443c3d..a0f48b2af 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -251,8 +251,7 @@ public: * for vector and scalar types that have all elements set to the value * zero (or \c false for booleans). * - * \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one, - * ir_constant::is_basis + * \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one */ virtual bool is_zero() const; @@ -264,8 +263,7 @@ public: * for vector and scalar types that have all elements set to the value * one (or \c true for booleans). * - * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one, - * ir_constant::is_basis + * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one */ virtual bool is_one() const; @@ -278,25 +276,10 @@ public: * negative one. For boolean types, the result is always \c false. * * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one - * ir_constant::is_basis */ virtual bool is_negative_one() const; /** - * Determine if an r-value is a basis vector - * - * The base implementation of this function always returns \c false. The - * \c ir_constant class over-rides this function to return \c true \b only - * for vector and scalar types that have one element set to the value one, - * and the other elements set to the value zero. For boolean types, the - * result is always \c false. - * - * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one, - * is_constant::is_negative_one - */ - virtual bool is_basis() const; - - /** * Determine if an r-value is an unsigned integer constant which can be * stored in 16 bits. * @@ -359,6 +342,12 @@ enum ir_var_declaration_type { * re-declared by the shader. */ ir_var_declared_implicitly, + + /** + * Variable is implicitly generated by the compiler and should not be + * visible via the API. + */ + ir_var_hidden, }; /** @@ -2257,7 +2246,7 @@ public: * Determine whether a constant has the same value as another constant * * \sa ir_constant::is_zero, ir_constant::is_one, - * ir_constant::is_negative_one, ir_constant::is_basis + * ir_constant::is_negative_one */ bool has_value(const ir_constant *) const; @@ -2270,7 +2259,6 @@ public: virtual bool is_zero() const; virtual bool is_one() const; virtual bool is_negative_one() const; - virtual bool is_basis() const; /** * Return true for constants that could be stored as 16-bit unsigned values. diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index e25857ac5..34e0b4b94 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -114,6 +114,7 @@ bool lower_noise(exec_list *instructions); bool lower_variable_index_to_cond_assign(exec_list *instructions, bool lower_input, bool lower_output, bool lower_temp, bool lower_uniform); bool lower_quadop_vector(exec_list *instructions, bool dont_lower_swz); +bool lower_const_arrays_to_uniforms(exec_list *instructions); bool lower_clip_distance(gl_shader *shader); void lower_output_reads(exec_list *instructions); bool lower_packing_builtins(exec_list *instructions, int op_mask); diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index ae00e7934..fd318c046 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -972,7 +972,7 @@ ir_reader::read_texture(s_expression *expr) op = ir_query_levels; } else if (MATCH(expr, other_pattern)) { op = ir_texture::get_opcode(tag->value()); - if (op == -1) + if (op == (ir_texture_opcode) -1) return NULL; } else { ir_read_error(NULL, "unexpected texture pattern %s", tag->value()); diff --git a/mesalib/src/glsl/ir_uniform.h b/mesalib/src/glsl/ir_uniform.h index b9ecf7cdd..21b5d05c1 100644 --- a/mesalib/src/glsl/ir_uniform.h +++ b/mesalib/src/glsl/ir_uniform.h @@ -175,6 +175,12 @@ struct gl_uniform_storage { * arrays this is the first element in the array. */ unsigned remap_location; + + /** + * This is a compiler-generated uniform that should not be advertised + * via the API. + */ + bool hidden; }; #ifdef __cplusplus diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index f613abc99..a77b5868a 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -585,6 +585,8 @@ private: this->uniforms[id].driver_storage = NULL; this->uniforms[id].storage = this->values; this->uniforms[id].atomic_buffer_index = -1; + this->uniforms[id].hidden = + current_var->data.how_declared == ir_var_hidden; if (this->ubo_block_index != -1) { this->uniforms[id].block_index = this->ubo_block_index; @@ -806,6 +808,50 @@ link_set_image_access_qualifiers(struct gl_shader_program *prog) } } +/** + * Sort the array of uniform storage so that the non-hidden uniforms are first + * + * This function sorts the list "in place." This is important because some of + * the storage accessible from \c uniforms has \c uniforms as its \c ralloc + * context. If \c uniforms is freed, some other storage will also be freed. + */ +static unsigned +move_hidden_uniforms_to_end(struct gl_shader_program *prog, + struct gl_uniform_storage *uniforms, + unsigned num_elements) +{ + struct gl_uniform_storage *sorted_uniforms = + ralloc_array(prog, struct gl_uniform_storage, num_elements); + unsigned hidden_uniforms = 0; + unsigned j = 0; + + /* Add the non-hidden uniforms. */ + for (unsigned i = 0; i < num_elements; i++) { + if (!uniforms[i].hidden) + sorted_uniforms[j++] = uniforms[i]; + } + + /* Add and count the hidden uniforms. */ + for (unsigned i = 0; i < num_elements; i++) { + if (uniforms[i].hidden) { + sorted_uniforms[j++] = uniforms[i]; + hidden_uniforms++; + } + } + + assert(prog->UniformHash != NULL); + prog->UniformHash->clear(); + for (unsigned i = 0; i < num_elements; i++) { + if (sorted_uniforms[i].name != NULL) + prog->UniformHash->put(i, sorted_uniforms[i].name); + } + + memcpy(uniforms, sorted_uniforms, sizeof(uniforms[0]) * num_elements); + ralloc_free(sorted_uniforms); + + return hidden_uniforms; +} + void link_assign_uniform_locations(struct gl_shader_program *prog, unsigned int boolean_true) @@ -926,6 +972,9 @@ link_assign_uniform_locations(struct gl_shader_program *prog, sizeof(prog->_LinkedShaders[i]->SamplerTargets)); } + const unsigned hidden_uniforms = + move_hidden_uniforms_to_end(prog, uniforms, num_user_uniforms); + /* Reserve all the explicit locations of the active uniforms. */ for (unsigned i = 0; i < num_user_uniforms; i++) { if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC) { @@ -977,6 +1026,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog, #endif prog->NumUserUniformStorage = num_user_uniforms; + prog->NumHiddenUniforms = hidden_uniforms; prog->UniformStorage = uniforms; link_set_image_access_qualifiers(prog); diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 2d31801d3..de6b1fb9f 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -642,7 +642,7 @@ validate_geometry_shader_emissions(struct gl_context *ctx, emit_vertex.run(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir); if (emit_vertex.error()) { linker_error(prog, "Invalid call %s(%d). Accepted values for the " - "stream parameter are in the range [0, %d].", + "stream parameter are in the range [0, %d].\n", emit_vertex.error_func(), emit_vertex.error_stream(), ctx->Const.MaxVertexStreams - 1); @@ -676,7 +676,7 @@ validate_geometry_shader_emissions(struct gl_context *ctx, */ if (prog->Geom.UsesStreams && prog->Geom.OutputType != GL_POINTS) { linker_error(prog, "EmitStreamVertex(n) and EndStreamPrimitive(n) " - "with n>0 requires point output"); + "with n>0 requires point output\n"); } } } @@ -808,7 +808,7 @@ cross_validate_globals(struct gl_shader_program *prog, linker_error(prog, "All redeclarations of gl_FragDepth in all " "fragment shaders in a single program must have " - "the same set of qualifiers."); + "the same set of qualifiers.\n"); } if (var->data.used && layout_differs) { @@ -817,7 +817,7 @@ cross_validate_globals(struct gl_shader_program *prog, "qualifier in any fragment shader, it must be " "redeclared with the same layout qualifier in " "all fragment shaders that have assignments to " - "gl_FragDepth"); + "gl_FragDepth\n"); } } @@ -948,7 +948,7 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog) &sh->UniformBlocks[j]); if (index == -1) { - linker_error(prog, "uniform block `%s' has mismatching definitions", + linker_error(prog, "uniform block `%s' has mismatching definitions\n", sh->UniformBlocks[j].Name); return false; } @@ -1635,7 +1635,7 @@ link_intrastage_shaders(void *mem_ctx, if ((other_sig != NULL) && other_sig->is_defined && !other_sig->is_builtin()) { - linker_error(prog, "function `%s' is multiply defined", + linker_error(prog, "function `%s' is multiply defined\n", f->name); return NULL; } @@ -2086,7 +2086,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, if (attr + slots > max_index) { linker_error(prog, "insufficient contiguous locations " - "available for %s `%s' %d %d %d", string, + "available for %s `%s' %d %d %d\n", string, var->name, used_locations, use_mask, attr); return false; } @@ -2155,7 +2155,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, linker_error(prog, "insufficient contiguous locations " - "available for %s `%s'", + "available for %s `%s'\n", string, to_assign[i].var->name); return false; } @@ -2257,7 +2257,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) continue; if (sh->num_samplers > ctx->Const.Program[i].MaxTextureImageUnits) { - linker_error(prog, "Too many %s shader texture samplers", + linker_error(prog, "Too many %s shader texture samplers\n", _mesa_shader_stage_to_string(i)); } @@ -2271,7 +2271,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) _mesa_shader_stage_to_string(i)); } else { linker_error(prog, "Too many %s shader default uniform block " - "components", + "components\n", _mesa_shader_stage_to_string(i)); } } @@ -2284,7 +2284,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) "this is non-portable out-of-spec behavior\n", _mesa_shader_stage_to_string(i)); } else { - linker_error(prog, "Too many %s shader uniform components", + linker_error(prog, "Too many %s shader uniform components\n", _mesa_shader_stage_to_string(i)); } } @@ -2302,7 +2302,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) } if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) { - linker_error(prog, "Too many combined uniform blocks (%d/%d)", + linker_error(prog, "Too many combined uniform blocks (%d/%d)\n", prog->NumUniformBlocks, ctx->Const.MaxCombinedUniformBlocks); } else { @@ -2310,7 +2310,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) const unsigned max_uniform_blocks = ctx->Const.Program[i].MaxUniformBlocks; if (blocks[i] > max_uniform_blocks) { - linker_error(prog, "Too many %s uniform blocks (%d/%d)", + linker_error(prog, "Too many %s uniform blocks (%d/%d)\n", _mesa_shader_stage_to_string(i), blocks[i], max_uniform_blocks); @@ -2338,7 +2338,7 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog) if (sh) { if (sh->NumImages > ctx->Const.Program[i].MaxImageUniforms) - linker_error(prog, "Too many %s shader image uniforms", + linker_error(prog, "Too many %s shader image uniforms\n", _mesa_shader_stage_to_string(i)); total_image_units += sh->NumImages; @@ -2354,11 +2354,11 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog) } if (total_image_units > ctx->Const.MaxCombinedImageUniforms) - linker_error(prog, "Too many combined image uniforms"); + linker_error(prog, "Too many combined image uniforms\n"); if (total_image_units + fragment_outputs > ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs) - linker_error(prog, "Too many combined image uniforms and fragment outputs"); + linker_error(prog, "Too many combined image uniforms and fragment outputs\n"); } @@ -2382,7 +2382,7 @@ reserve_explicit_locations(struct gl_shader_program *prog, max_loc + 1); if (!prog->UniformRemapTable) { - linker_error(prog, "Out of memory during linking."); + linker_error(prog, "Out of memory during linking.\n"); return false; } @@ -2411,8 +2411,8 @@ reserve_explicit_locations(struct gl_shader_program *prog, * or linker error will be generated." */ linker_error(prog, - "location qualifier for uniform %s overlaps" - "previously used location", + "location qualifier for uniform %s overlaps " + "previously used location\n", var->name); return false; } @@ -2447,7 +2447,7 @@ check_explicit_uniform_locations(struct gl_context *ctx, string_to_uint_map *uniform_map = new string_to_uint_map; if (!uniform_map) { - linker_error(prog, "Out of memory during linking."); + linker_error(prog, "Out of memory during linking.\n"); return; } @@ -2678,6 +2678,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) &ctx->Const.ShaderCompilerOptions[i], ctx->Const.NativeIntegers)) ; + + lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir); } /* Check and validate stream emissions in geometry shaders */ @@ -2719,7 +2721,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) */ if (first == MESA_SHADER_FRAGMENT) { linker_error(prog, "Transform feedback varyings specified, but " - "no vertex or geometry shader is present."); + "no vertex or geometry shader is present.\n"); goto done; } diff --git a/mesalib/src/glsl/list.h b/mesalib/src/glsl/list.h index b40764cae..bebe17fcf 100644 --- a/mesalib/src/glsl/list.h +++ b/mesalib/src/glsl/list.h @@ -529,6 +529,27 @@ exec_node_insert_list_before(struct exec_node *n, struct exec_list *before) exec_list_make_empty(before); } +static inline void +exec_list_validate(const struct exec_list *list) +{ + const struct exec_node *node; + + assert(list->head->prev == (const struct exec_node *) &list->head); + assert(list->tail == NULL); + assert(list->tail_pred->next == (const struct exec_node *) &list->tail); + + /* We could try to use one of the interators below for this but they all + * either require C++ or assume the exec_node is embedded in a structure + * which is not the case for this function. + */ + for (node = exec_list_get_head_const(list); + !exec_node_is_tail_sentinel(node); + node = exec_node_get_next_const(node)) { + assert(node->next->prev == node); + assert(node->prev->next == node); + } +} + #ifdef __cplusplus inline void exec_list::make_empty() { diff --git a/mesalib/src/glsl/loop_unroll.cpp b/mesalib/src/glsl/loop_unroll.cpp index ce795f6cd..635e1dd99 100644 --- a/mesalib/src/glsl/loop_unroll.cpp +++ b/mesalib/src/glsl/loop_unroll.cpp @@ -64,6 +64,7 @@ class loop_unroll_count : public ir_hierarchical_visitor { public: int nodes; bool unsupported_variable_indexing; + bool array_indexed_by_induction_var_with_exact_iterations; /* If there are nested loops, the node count will be inaccurate. */ bool nested_loop; @@ -74,6 +75,7 @@ public: nodes = 0; nested_loop = false; unsupported_variable_indexing = false; + array_indexed_by_induction_var_with_exact_iterations = false; run(list); } @@ -112,6 +114,14 @@ public: ir_variable *array = ir->array->variable_referenced(); loop_variable *lv = ls->get(ir->array_index->variable_referenced()); if (array && lv && lv->is_induction_var()) { + /* If an array is indexed by a loop induction variable, and the + * array size is exactly the number of loop iterations, this is + * probably a simple for-loop trying to access each element in + * turn; the application may expect it to be unrolled. + */ + if (int(array->type->length) == ls->limiting_terminator->iterations) + array_indexed_by_induction_var_with_exact_iterations = true; + switch (array->data.mode) { case ir_var_auto: case ir_var_temporary: @@ -314,7 +324,8 @@ loop_unroll_visitor::visit_leave(ir_loop *ir) bool loop_too_large = count.nested_loop || count.nodes * iterations > max_iterations * 5; - if (loop_too_large && !count.unsupported_variable_indexing) + if (loop_too_large && !count.unsupported_variable_indexing && + !count.array_indexed_by_induction_var_with_exact_iterations) return visit_continue; /* Note: the limiting terminator contributes 1 to ls->num_loop_jumps. diff --git a/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp b/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp new file mode 100644 index 000000000..2243f479a --- /dev/null +++ b/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp @@ -0,0 +1,111 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file lower_const_arrays_to_uniforms.cpp + * + * Lower constant arrays to uniform arrays. + * + * Some driver backends (such as i965 and nouveau) don't handle constant arrays + * gracefully, instead treating them as ordinary writable temporary arrays. + * Since arrays can be large, this often means spilling them to scratch memory, + * which usually involves a large number of instructions. + * + * This must be called prior to link_set_uniform_initializers(); we need the + * linker to process our new uniform's constant initializer. + * + * This should be called after optimizations, since those can result in + * splitting and removing arrays that are indexed by constant expressions. + */ +#include "ir.h" +#include "ir_visitor.h" +#include "ir_rvalue_visitor.h" +#include "glsl_types.h" + +namespace { +class lower_const_array_visitor : public ir_rvalue_visitor { +public: + lower_const_array_visitor(exec_list *insts) + { + instructions = insts; + progress = false; + index = 0; + } + + bool run() + { + visit_list_elements(this, instructions); + return progress; + } + + void handle_rvalue(ir_rvalue **rvalue); + +private: + exec_list *instructions; + bool progress; + unsigned index; +}; + +void +lower_const_array_visitor::handle_rvalue(ir_rvalue **rvalue) +{ + if (!*rvalue) + return; + + ir_dereference_array *dra = (*rvalue)->as_dereference_array(); + if (!dra) + return; + + ir_constant *con = dra->array->as_constant(); + if (!con || !con->type->is_array()) + return; + + void *mem_ctx = ralloc_parent(con); + + char *uniform_name = ralloc_asprintf(mem_ctx, "constarray__%d", index++); + + ir_variable *uni = + new(mem_ctx) ir_variable(con->type, uniform_name, ir_var_uniform); + uni->constant_initializer = con; + uni->constant_value = con; + uni->data.has_initializer = true; + uni->data.how_declared = ir_var_hidden; + uni->data.read_only = true; + /* Assume the whole thing is accessed. */ + uni->data.max_array_access = uni->type->length - 1; + instructions->push_head(uni); + + ir_dereference_variable *varref = new(mem_ctx) ir_dereference_variable(uni); + *rvalue = new(mem_ctx) ir_dereference_array(varref, dra->array_index); + + progress = true; +} + +} /* anonymous namespace */ + +bool +lower_const_arrays_to_uniforms(exec_list *instructions) +{ + lower_const_array_visitor v(instructions); + return v.run(); +} diff --git a/mesalib/src/glsl/main.cpp b/mesalib/src/glsl/main.cpp index 79e943831..432643707 100644 --- a/mesalib/src/glsl/main.cpp +++ b/mesalib/src/glsl/main.cpp @@ -46,6 +46,7 @@ #include "glsl_parser_extras.h" #include "ir_optimization.h" #include "program.h" +#include "program/hash_table.h" #include "loop_analysis.h" #include "standalone_scaffolding.h" @@ -368,6 +369,11 @@ main(int argc, char **argv) assert(whole_program != NULL); whole_program->InfoLog = ralloc_strdup(whole_program, ""); + /* Created just to avoid segmentation faults */ + whole_program->AttributeBindings = new string_to_uint_map; + whole_program->FragDataBindings = new string_to_uint_map; + whole_program->FragDataIndexBindings = new string_to_uint_map; + for (/* empty */; argc > optind; optind++) { whole_program->Shaders = reralloc(whole_program, whole_program->Shaders, @@ -426,6 +432,10 @@ main(int argc, char **argv) for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) ralloc_free(whole_program->_LinkedShaders[i]); + delete whole_program->AttributeBindings; + delete whole_program->FragDataBindings; + delete whole_program->FragDataIndexBindings; + ralloc_free(whole_program); _mesa_glsl_release_types(); _mesa_glsl_release_builtin_functions(); diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index 0cdb8ecfc..430f5cb97 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -105,12 +105,6 @@ is_vec_negative_one(ir_constant *ir) } static inline bool -is_vec_basis(ir_constant *ir) -{ - return (ir == NULL) ? false : ir->is_basis(); -} - -static inline bool is_valid_vec_const(ir_constant *ir) { if (ir == NULL) @@ -537,21 +531,34 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) return ir_constant::zero(mem_ctx, ir->type); - if (is_vec_basis(op_const[0])) { - unsigned component = 0; - for (unsigned c = 0; c < op_const[0]->type->vector_elements; c++) { - if (op_const[0]->value.f[c] == 1.0) - component = c; - } - return new(mem_ctx) ir_swizzle(ir->operands[1], component, 0, 0, 0, 1); - } - if (is_vec_basis(op_const[1])) { - unsigned component = 0; - for (unsigned c = 0; c < op_const[1]->type->vector_elements; c++) { - if (op_const[1]->value.f[c] == 1.0) - component = c; - } - return new(mem_ctx) ir_swizzle(ir->operands[0], component, 0, 0, 0, 1); + for (int i = 0; i < 2; i++) { + if (!op_const[i]) + continue; + + unsigned components[4] = { 0 }, count = 0; + + for (unsigned c = 0; c < op_const[i]->type->vector_elements; c++) { + if (op_const[i]->value.f[c] == 0.0) + continue; + + components[count] = c; + count++; + } + + /* No channels had zero values; bail. */ + if (count >= op_const[i]->type->vector_elements) + break; + + ir_expression_operation op = count == 1 ? + ir_binop_mul : ir_binop_dot; + + /* Swizzle both operands to remove the channels that were zero. */ + return new(mem_ctx) + ir_expression(op, glsl_type::float_type, + new(mem_ctx) ir_swizzle(ir->operands[0], + components, count), + new(mem_ctx) ir_swizzle(ir->operands[1], + components, count)); } break; diff --git a/mesalib/src/glsl/opt_cse.cpp b/mesalib/src/glsl/opt_cse.cpp index 9c96835dd..b0b67f496 100644 --- a/mesalib/src/glsl/opt_cse.cpp +++ b/mesalib/src/glsl/opt_cse.cpp @@ -194,6 +194,8 @@ is_cse_candidate_visitor::visit(ir_dereference_variable *ir) if (ir->var->data.read_only) { return visit_continue; } else { + if (debug) + printf("CSE: non-candidate: var %s is not read only\n", ir->var->name); ok = false; return visit_stop; } @@ -220,8 +222,11 @@ is_cse_candidate(ir_rvalue *ir) /* Our temporary variable assignment generation isn't ready to handle * anything bigger than a vector. */ - if (!ir->type->is_vector() && !ir->type->is_scalar()) + if (!ir->type->is_vector() && !ir->type->is_scalar()) { + if (debug) + printf("CSE: non-candidate: not a vector/scalar\n"); return false; + } /* Only handle expressions and textures currently. We may want to extend * to variable-index array dereferences at some point. @@ -231,6 +236,8 @@ is_cse_candidate(ir_rvalue *ir) case ir_type_texture: break; default: + if (debug) + printf("CSE: non-candidate: not an expression/texture\n"); return false; } diff --git a/mesalib/src/glsl/s_expression.cpp b/mesalib/src/glsl/s_expression.cpp index 1a28e1d52..2928a4db8 100644 --- a/mesalib/src/glsl/s_expression.cpp +++ b/mesalib/src/glsl/s_expression.cpp @@ -73,7 +73,7 @@ read_atom(void *ctx, const char *&src, char *&symbol_buffer) } else { // Check if the atom is a number. char *float_end = NULL; - float f = glsl_strtof(src, &float_end); + float f = _mesa_strtof(src, &float_end); if (float_end != src) { char *int_end = NULL; int i = strtol(src, &int_end, 10); diff --git a/mesalib/src/glsl/s_expression.h b/mesalib/src/glsl/s_expression.h index 642af19b4..1d4753530 100644 --- a/mesalib/src/glsl/s_expression.h +++ b/mesalib/src/glsl/s_expression.h @@ -27,7 +27,7 @@ #define S_EXPRESSION_H #include "main/core.h" /* for Elements */ -#include "strtod.h" +#include "util/strtod.h" #include "list.h" /* Type-safe downcasting macros (also safe to pass NULL) */ diff --git a/mesalib/src/glsl/strtod.c b/mesalib/src/glsl/strtod.c deleted file mode 100644 index 5d4346b5a..000000000 --- a/mesalib/src/glsl/strtod.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2010 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -#include <stdlib.h> - -#ifdef _GNU_SOURCE -#include <locale.h> -#ifdef __APPLE__ -#include <xlocale.h> -#endif -#endif - -#include "strtod.h" - - - -/** - * Wrapper around strtod which uses the "C" locale so the decimal - * point is always '.' - */ -double -glsl_strtod(const char *s, char **end) -{ -#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && \ - !defined(__HAIKU__) && !defined(__UCLIBC__) - static locale_t loc = NULL; - if (!loc) { - loc = newlocale(LC_CTYPE_MASK, "C", NULL); - } - return strtod_l(s, end, loc); -#else - return strtod(s, end); -#endif -} - - -/** - * Wrapper around strtof which uses the "C" locale so the decimal - * point is always '.' - */ -float -glsl_strtof(const char *s, char **end) -{ -#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && \ - !defined(__HAIKU__) && !defined(__UCLIBC__) - static locale_t loc = NULL; - if (!loc) { - loc = newlocale(LC_CTYPE_MASK, "C", NULL); - } - return strtof_l(s, end, loc); -#elif _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE - return strtof(s, end); -#else - return (float) strtod(s, end); -#endif -} diff --git a/mesalib/src/glsl/strtod.h b/mesalib/src/glsl/strtod.h deleted file mode 100644 index ad847dbb0..000000000 --- a/mesalib/src/glsl/strtod.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2010 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -#ifndef STRTOD_H -#define STRTOD_H - -#ifdef __cplusplus -extern "C" { -#endif - -extern double -glsl_strtod(const char *s, char **end); - -extern float -glsl_strtof(const char *s, char **end); - - -#ifdef __cplusplus -} -#endif - - -#endif |