}
hash_table *glsl_type::array_types = NULL;
+hash_table *glsl_type::record_types = NULL;
+
+glsl_type::glsl_type(GLenum gl_type,
+ unsigned base_type, unsigned vector_elements,
+ unsigned matrix_columns, const char *name) :
+ gl_type(gl_type),
+ base_type(base_type),
+ sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+ sampler_type(0),
+ vector_elements(vector_elements), matrix_columns(matrix_columns),
+ name(name),
+ length(0)
+{
+ /* Neither dimension is zero or both dimensions are zero.
+ */
+ assert((vector_elements == 0) == (matrix_columns == 0));
+ memset(& fields, 0, sizeof(fields));
+}
+
+glsl_type::glsl_type(GLenum gl_type,
+ enum glsl_sampler_dim dim, bool shadow, bool array,
+ unsigned type, const char *name) :
+ gl_type(gl_type),
+ base_type(GLSL_TYPE_SAMPLER),
+ sampler_dimensionality(dim), sampler_shadow(shadow),
+ sampler_array(array), sampler_type(type),
+ vector_elements(0), matrix_columns(0),
+ name(name),
+ length(0)
+{
+ memset(& fields, 0, sizeof(fields));
+}
static void
add_types_to_symbol_table(glsl_symbol_table *symtab,
}
-static void
-generate_110_types(glsl_symbol_table *symtab)
+void
+glsl_type::generate_110_types(glsl_symbol_table *symtab)
{
add_types_to_symbol_table(symtab, builtin_core_types,
Elements(builtin_core_types),
}
-static void
-generate_120_types(glsl_symbol_table *symtab)
+void
+glsl_type::generate_120_types(glsl_symbol_table *symtab)
{
generate_110_types(symtab);
}
-static void
-generate_130_types(glsl_symbol_table *symtab)
+void
+glsl_type::generate_130_types(glsl_symbol_table *symtab)
{
generate_120_types(symtab);
}
-static void
-generate_ARB_texture_rectangle_types(glsl_symbol_table *symtab, bool warn)
+void
+glsl_type::generate_ARB_texture_rectangle_types(glsl_symbol_table *symtab,
+ bool warn)
{
add_types_to_symbol_table(symtab, builtin_ARB_texture_rectangle_types,
Elements(builtin_ARB_texture_rectangle_types),
}
-static void
-generate_EXT_texture_array_types(glsl_symbol_table *symtab, bool warn)
+void
+glsl_type::generate_EXT_texture_array_types(glsl_symbol_table *symtab,
+ bool warn)
{
add_types_to_symbol_table(symtab, builtin_EXT_texture_array_types,
Elements(builtin_EXT_texture_array_types),
{
switch (state->language_version) {
case 110:
- generate_110_types(state->symbols);
+ glsl_type::generate_110_types(state->symbols);
break;
case 120:
- generate_120_types(state->symbols);
+ glsl_type::generate_120_types(state->symbols);
break;
case 130:
- generate_130_types(state->symbols);
+ glsl_type::generate_130_types(state->symbols);
break;
default:
/* error */
}
if (state->ARB_texture_rectangle_enable) {
- generate_ARB_texture_rectangle_types(state->symbols,
+ glsl_type::generate_ARB_texture_rectangle_types(state->symbols,
state->ARB_texture_rectangle_warn);
}
if (state->EXT_texture_array_enable && state->language_version < 130) {
// These are already included in 130; don't create twice.
- generate_EXT_texture_array_types(state->symbols,
+ glsl_type::generate_EXT_texture_array_types(state->symbols,
state->EXT_texture_array_warn);
}
}
}
+int
+glsl_type::record_key_compare(const void *a, const void *b)
+{
+ const glsl_type *const key1 = (glsl_type *) a;
+ const glsl_type *const key2 = (glsl_type *) b;
+
+ /* Return zero is the types match (there is zero difference) or non-zero
+ * otherwise.
+ */
+ if (strcmp(key1->name, key2->name) != 0)
+ return 1;
+
+ if (key1->length != key2->length)
+ return 1;
+
+ for (unsigned i = 0; i < key1->length; i++)
+ /* FINISHME: Is the name of the structure field also significant? */
+ if (key1->fields.structure[i].type != key2->fields.structure[i].type)
+ return 1;
+
+ return 0;
+}
+
+
+unsigned
+glsl_type::record_key_hash(const void *a)
+{
+ const glsl_type *const key = (glsl_type *) a;
+ char hash_key[128];
+ unsigned size = 0;
+
+ size = snprintf(hash_key, sizeof(hash_key), "%08x", key->length);
+
+ for (unsigned i = 0; i < key->length; i++) {
+ if (size >= sizeof(hash_key))
+ break;
+
+ size += snprintf(& hash_key[size], sizeof(hash_key) - size,
+ "%p", key->fields.structure[i].type);
+ }
+
+ return hash_table_string_hash(& hash_key);
+}
+
+
+const glsl_type *
+glsl_type::get_record_instance(const glsl_struct_field *fields,
+ unsigned num_fields,
+ const char *name)
+{
+ const glsl_type key(fields, num_fields, name);
+
+ 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) {
+ t = new(NULL) glsl_type(fields, num_fields, name);
+
+ hash_table_insert(record_types, (void *) t, t);
+ }
+
+ assert(t->base_type == GLSL_TYPE_STRUCT);
+ assert(t->length == num_fields);
+ assert(strcmp(t->name, name) == 0);
+
+ return t;
+}
+
+
const glsl_type *
glsl_type::field_type(const char *name) const
{