Cleanup code. Change constructor prototype.
[mesa.git] / src / mesa / shader / slang / slang_compile_variable.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file slang_compile_variable.c
27 * slang front-end compiler
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_compile.h"
33
34 /* slang_type_specifier_type */
35
36 typedef struct
37 {
38 const char *name;
39 slang_type_specifier_type type;
40 } type_specifier_type_name;
41
42 static type_specifier_type_name type_specifier_type_names[] = {
43 { "void", slang_spec_void },
44 { "bool", slang_spec_bool },
45 { "bvec2", slang_spec_bvec2 },
46 { "bvec3", slang_spec_bvec3 },
47 { "bvec4", slang_spec_bvec4 },
48 { "int", slang_spec_int },
49 { "ivec2", slang_spec_ivec2 },
50 { "ivec3", slang_spec_ivec3 },
51 { "ivec4", slang_spec_ivec4 },
52 { "float", slang_spec_float },
53 { "vec2", slang_spec_vec2 },
54 { "vec3", slang_spec_vec3 },
55 { "vec4", slang_spec_vec4 },
56 { "mat2", slang_spec_mat2 },
57 { "mat3", slang_spec_mat3 },
58 { "mat4", slang_spec_mat4 },
59 { "sampler1D", slang_spec_sampler1D },
60 { "sampler2D", slang_spec_sampler2D },
61 { "sampler3D", slang_spec_sampler3D },
62 { "samplerCube", slang_spec_samplerCube },
63 { "sampler1DShadow", slang_spec_sampler1DShadow },
64 { "sampler2DShadow", slang_spec_sampler2DShadow },
65 { NULL, slang_spec_void }
66 };
67
68 slang_type_specifier_type slang_type_specifier_type_from_string (const char *name)
69 {
70 type_specifier_type_name *p = type_specifier_type_names;
71 while (p->name != NULL)
72 {
73 if (slang_string_compare (p->name, name) == 0)
74 break;
75 p++;
76 }
77 return p->type;
78 }
79
80 const char *slang_type_specifier_type_to_string (slang_type_specifier_type type)
81 {
82 type_specifier_type_name *p = type_specifier_type_names;
83 while (p->name != NULL)
84 {
85 if (p->type == type)
86 break;
87 p++;
88 }
89 return p->name;
90 }
91
92 /* slang_fully_specified_type */
93
94 int slang_fully_specified_type_construct (slang_fully_specified_type *type)
95 {
96 type->qualifier = slang_qual_none;
97 slang_type_specifier_ctr (&type->specifier);
98 return 1;
99 }
100
101 void slang_fully_specified_type_destruct (slang_fully_specified_type *type)
102 {
103 slang_type_specifier_dtr (&type->specifier);
104 }
105
106 int slang_fully_specified_type_copy (slang_fully_specified_type *x, const slang_fully_specified_type *y)
107 {
108 slang_fully_specified_type z;
109
110 if (!slang_fully_specified_type_construct (&z))
111 return 0;
112 z.qualifier = y->qualifier;
113 if (!slang_type_specifier_copy (&z.specifier, &y->specifier))
114 {
115 slang_fully_specified_type_destruct (&z);
116 return 0;
117 }
118 slang_fully_specified_type_destruct (x);
119 *x = z;
120 return 1;
121 }
122
123 /*
124 * slang_variable_scope
125 */
126
127 GLvoid
128 _slang_variable_scope_ctr (slang_variable_scope *self)
129 {
130 self->variables = NULL;
131 self->num_variables = 0;
132 self->outer_scope = NULL;
133 }
134
135 void slang_variable_scope_destruct (slang_variable_scope *scope)
136 {
137 unsigned int i;
138
139 for (i = 0; i < scope->num_variables; i++)
140 slang_variable_destruct (scope->variables + i);
141 slang_alloc_free (scope->variables);
142 /* do not free scope->outer_scope */
143 }
144
145 int slang_variable_scope_copy (slang_variable_scope *x, const slang_variable_scope *y)
146 {
147 slang_variable_scope z;
148 unsigned int i;
149
150 _slang_variable_scope_ctr (&z);
151 z.variables = (slang_variable *) slang_alloc_malloc (y->num_variables * sizeof (slang_variable));
152 if (z.variables == NULL)
153 {
154 slang_variable_scope_destruct (&z);
155 return 0;
156 }
157 for (z.num_variables = 0; z.num_variables < y->num_variables; z.num_variables++)
158 if (!slang_variable_construct (&z.variables[z.num_variables]))
159 {
160 slang_variable_scope_destruct (&z);
161 return 0;
162 }
163 for (i = 0; i < z.num_variables; i++)
164 if (!slang_variable_copy (&z.variables[i], &y->variables[i]))
165 {
166 slang_variable_scope_destruct (&z);
167 return 0;
168 }
169 z.outer_scope = y->outer_scope;
170 slang_variable_scope_destruct (x);
171 *x = z;
172 return 1;
173 }
174
175 /* slang_variable */
176
177 int slang_variable_construct (slang_variable *var)
178 {
179 if (!slang_fully_specified_type_construct (&var->type))
180 return 0;
181 var->a_name = SLANG_ATOM_NULL;
182 var->array_len = 0;
183 var->initializer = NULL;
184 var->address = ~0;
185 var->size = 0;
186 var->global = 0;
187 return 1;
188 }
189
190 void slang_variable_destruct (slang_variable *var)
191 {
192 slang_fully_specified_type_destruct (&var->type);
193 if (var->initializer != NULL)
194 {
195 slang_operation_destruct (var->initializer);
196 slang_alloc_free (var->initializer);
197 }
198 }
199
200 int slang_variable_copy (slang_variable *x, const slang_variable *y)
201 {
202 slang_variable z;
203
204 if (!slang_variable_construct (&z))
205 return 0;
206 if (!slang_fully_specified_type_copy (&z.type, &y->type))
207 {
208 slang_variable_destruct (&z);
209 return 0;
210 }
211 z.a_name = y->a_name;
212 z.array_len = y->array_len;
213 if (y->initializer != NULL)
214 {
215 z.initializer = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));
216 if (z.initializer == NULL)
217 {
218 slang_variable_destruct (&z);
219 return 0;
220 }
221 if (!slang_operation_construct (z.initializer))
222 {
223 slang_alloc_free (z.initializer);
224 slang_variable_destruct (&z);
225 return 0;
226 }
227 if (!slang_operation_copy (z.initializer, y->initializer))
228 {
229 slang_variable_destruct (&z);
230 return 0;
231 }
232 }
233 z.address = y->address;
234 z.size = y->size;
235 z.global = y->global;
236 slang_variable_destruct (x);
237 *x = z;
238 return 1;
239 }
240
241 slang_variable *_slang_locate_variable (slang_variable_scope *scope, slang_atom a_name, GLboolean all)
242 {
243 GLuint i;
244
245 for (i = 0; i < scope->num_variables; i++)
246 if (a_name == scope->variables[i].a_name)
247 return &scope->variables[i];
248 if (all && scope->outer_scope != NULL)
249 return _slang_locate_variable (scope->outer_scope, a_name, 1);
250 return NULL;
251 }
252
253 /*
254 * _slang_build_export_data_table()
255 */
256
257 static GLenum gl_type_from_specifier (const slang_type_specifier *type)
258 {
259 switch (type->type)
260 {
261 case slang_spec_bool:
262 return GL_BOOL_ARB;
263 case slang_spec_bvec2:
264 return GL_BOOL_VEC2_ARB;
265 case slang_spec_bvec3:
266 return GL_BOOL_VEC3_ARB;
267 case slang_spec_bvec4:
268 return GL_BOOL_VEC4_ARB;
269 case slang_spec_int:
270 return GL_INT;
271 case slang_spec_ivec2:
272 return GL_INT_VEC2_ARB;
273 case slang_spec_ivec3:
274 return GL_INT_VEC3_ARB;
275 case slang_spec_ivec4:
276 return GL_INT_VEC4_ARB;
277 case slang_spec_float:
278 return GL_FLOAT;
279 case slang_spec_vec2:
280 return GL_FLOAT_VEC2_ARB;
281 case slang_spec_vec3:
282 return GL_FLOAT_VEC3_ARB;
283 case slang_spec_vec4:
284 return GL_FLOAT_VEC4_ARB;
285 case slang_spec_mat2:
286 return GL_FLOAT_MAT2_ARB;
287 case slang_spec_mat3:
288 return GL_FLOAT_MAT3_ARB;
289 case slang_spec_mat4:
290 return GL_FLOAT_MAT4_ARB;
291 case slang_spec_sampler1D:
292 return GL_SAMPLER_1D_ARB;
293 case slang_spec_sampler2D:
294 return GL_SAMPLER_2D_ARB;
295 case slang_spec_sampler3D:
296 return GL_SAMPLER_3D_ARB;
297 case slang_spec_samplerCube:
298 return GL_SAMPLER_CUBE_ARB;
299 case slang_spec_sampler1DShadow:
300 return GL_SAMPLER_1D_SHADOW_ARB;
301 case slang_spec_sampler2DShadow:
302 return GL_SAMPLER_2D_SHADOW_ARB;
303 case slang_spec_array:
304 return gl_type_from_specifier (type->_array);
305 default:
306 return GL_FLOAT;
307 }
308 }
309
310 static GLboolean build_quant (slang_export_data_quant *q, slang_variable *var)
311 {
312 slang_type_specifier *spec = &var->type.specifier;
313
314 q->name = var->a_name;
315 q->size = var->size;
316 if (spec->type == slang_spec_array)
317 {
318 q->array_len = var->array_len;
319 q->size /= var->array_len;
320 spec = spec->_array;
321 }
322 if (spec->type == slang_spec_struct)
323 {
324 GLuint i;
325
326 q->u.field_count = spec->_struct->fields->num_variables;
327 q->structure = (slang_export_data_quant *) slang_alloc_malloc (
328 q->u.field_count * sizeof (slang_export_data_quant));
329 if (q->structure == NULL)
330 return GL_FALSE;
331
332 for (i = 0; i < q->u.field_count; i++)
333 slang_export_data_quant_ctr (&q->structure[i]);
334 for (i = 0; i < q->u.field_count; i++)
335 if (!build_quant (&q->structure[i], &spec->_struct->fields->variables[i]))
336 return GL_FALSE;
337 }
338 else
339 q->u.basic_type = gl_type_from_specifier (spec);
340 return GL_TRUE;
341 }
342
343 GLboolean _slang_build_export_data_table (slang_export_data_table *tbl, slang_variable_scope *vars)
344 {
345 GLuint i;
346
347 for (i = 0; i < vars->num_variables; i++)
348 {
349 slang_variable *var = &vars->variables[i];
350 slang_export_data_entry *e;
351
352 e = slang_export_data_table_add (tbl);
353 if (e == NULL)
354 return GL_FALSE;
355 if (!build_quant (&e->quant, var))
356 return GL_FALSE;
357 if (var->type.qualifier == slang_qual_uniform)
358 e->access = slang_exp_uniform;
359 else if (var->type.qualifier == slang_qual_attribute)
360 e->access = slang_exp_attribute;
361 else
362 e->access = slang_exp_varying;
363 e->address = var->address;
364 }
365
366 if (vars->outer_scope != NULL)
367 return _slang_build_export_data_table (tbl, vars->outer_scope);
368 return GL_TRUE;
369 }
370