GLSL fixes:
[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 /* slang_variable_scope */
124
125 int slang_variable_scope_construct (slang_variable_scope *scope)
126 {
127 scope->variables = NULL;
128 scope->num_variables = 0;
129 scope->outer_scope = NULL;
130 return 1;
131 }
132
133 void slang_variable_scope_destruct (slang_variable_scope *scope)
134 {
135 unsigned int i;
136
137 for (i = 0; i < scope->num_variables; i++)
138 slang_variable_destruct (scope->variables + i);
139 slang_alloc_free (scope->variables);
140 /* do not free scope->outer_scope */
141 }
142
143 int slang_variable_scope_copy (slang_variable_scope *x, const slang_variable_scope *y)
144 {
145 slang_variable_scope z;
146 unsigned int i;
147
148 if (!slang_variable_scope_construct (&z))
149 return 0;
150 z.variables = (slang_variable *) slang_alloc_malloc (y->num_variables * sizeof (slang_variable));
151 if (z.variables == NULL)
152 {
153 slang_variable_scope_destruct (&z);
154 return 0;
155 }
156 for (z.num_variables = 0; z.num_variables < y->num_variables; z.num_variables++)
157 if (!slang_variable_construct (&z.variables[z.num_variables]))
158 {
159 slang_variable_scope_destruct (&z);
160 return 0;
161 }
162 for (i = 0; i < z.num_variables; i++)
163 if (!slang_variable_copy (&z.variables[i], &y->variables[i]))
164 {
165 slang_variable_scope_destruct (&z);
166 return 0;
167 }
168 z.outer_scope = y->outer_scope;
169 slang_variable_scope_destruct (x);
170 *x = z;
171 return 1;
172 }
173
174 /* slang_variable */
175
176 int slang_variable_construct (slang_variable *var)
177 {
178 if (!slang_fully_specified_type_construct (&var->type))
179 return 0;
180 var->a_name = SLANG_ATOM_NULL;
181 var->array_len = 0;
182 var->initializer = NULL;
183 var->address = ~0;
184 var->size = 0;
185 var->global = 0;
186 return 1;
187 }
188
189 void slang_variable_destruct (slang_variable *var)
190 {
191 slang_fully_specified_type_destruct (&var->type);
192 if (var->initializer != NULL)
193 {
194 slang_operation_destruct (var->initializer);
195 slang_alloc_free (var->initializer);
196 }
197 }
198
199 int slang_variable_copy (slang_variable *x, const slang_variable *y)
200 {
201 slang_variable z;
202
203 if (!slang_variable_construct (&z))
204 return 0;
205 if (!slang_fully_specified_type_copy (&z.type, &y->type))
206 {
207 slang_variable_destruct (&z);
208 return 0;
209 }
210 z.a_name = y->a_name;
211 z.array_len = y->array_len;
212 if (y->initializer != NULL)
213 {
214 z.initializer = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));
215 if (z.initializer == NULL)
216 {
217 slang_variable_destruct (&z);
218 return 0;
219 }
220 if (!slang_operation_construct (z.initializer))
221 {
222 slang_alloc_free (z.initializer);
223 slang_variable_destruct (&z);
224 return 0;
225 }
226 if (!slang_operation_copy (z.initializer, y->initializer))
227 {
228 slang_variable_destruct (&z);
229 return 0;
230 }
231 }
232 z.address = y->address;
233 z.size = y->size;
234 z.global = y->global;
235 slang_variable_destruct (x);
236 *x = z;
237 return 1;
238 }
239
240 slang_variable *_slang_locate_variable (slang_variable_scope *scope, slang_atom a_name, GLboolean all)
241 {
242 GLuint i;
243
244 for (i = 0; i < scope->num_variables; i++)
245 if (a_name == scope->variables[i].a_name)
246 return &scope->variables[i];
247 if (all && scope->outer_scope != NULL)
248 return _slang_locate_variable (scope->outer_scope, a_name, 1);
249 return NULL;
250 }
251
252 /*
253 * _slang_build_export_data_table()
254 */
255
256 static GLenum gl_type_from_specifier (const slang_type_specifier *type)
257 {
258 switch (type->type)
259 {
260 case slang_spec_bool:
261 return GL_BOOL_ARB;
262 case slang_spec_bvec2:
263 return GL_BOOL_VEC2_ARB;
264 case slang_spec_bvec3:
265 return GL_BOOL_VEC3_ARB;
266 case slang_spec_bvec4:
267 return GL_BOOL_VEC4_ARB;
268 case slang_spec_int:
269 return GL_INT;
270 case slang_spec_ivec2:
271 return GL_INT_VEC2_ARB;
272 case slang_spec_ivec3:
273 return GL_INT_VEC3_ARB;
274 case slang_spec_ivec4:
275 return GL_INT_VEC4_ARB;
276 case slang_spec_float:
277 return GL_FLOAT;
278 case slang_spec_vec2:
279 return GL_FLOAT_VEC2_ARB;
280 case slang_spec_vec3:
281 return GL_FLOAT_VEC3_ARB;
282 case slang_spec_vec4:
283 return GL_FLOAT_VEC4_ARB;
284 case slang_spec_mat2:
285 return GL_FLOAT_MAT2_ARB;
286 case slang_spec_mat3:
287 return GL_FLOAT_MAT3_ARB;
288 case slang_spec_mat4:
289 return GL_FLOAT_MAT4_ARB;
290 case slang_spec_sampler1D:
291 return GL_SAMPLER_1D_ARB;
292 case slang_spec_sampler2D:
293 return GL_SAMPLER_2D_ARB;
294 case slang_spec_sampler3D:
295 return GL_SAMPLER_3D_ARB;
296 case slang_spec_samplerCube:
297 return GL_SAMPLER_CUBE_ARB;
298 case slang_spec_sampler1DShadow:
299 return GL_SAMPLER_1D_SHADOW_ARB;
300 case slang_spec_sampler2DShadow:
301 return GL_SAMPLER_2D_SHADOW_ARB;
302 case slang_spec_array:
303 return gl_type_from_specifier (type->_array);
304 default:
305 return GL_FLOAT;
306 }
307 }
308
309 static GLboolean build_quant (slang_export_data_quant *q, slang_variable *var)
310 {
311 slang_type_specifier *spec = &var->type.specifier;
312
313 q->name = var->a_name;
314 q->size = var->size;
315 if (spec->type == slang_spec_array)
316 {
317 q->array_len = var->array_len;
318 q->size /= var->array_len;
319 spec = spec->_array;
320 }
321 if (spec->type == slang_spec_struct)
322 {
323 GLuint i;
324
325 q->u.field_count = spec->_struct->fields->num_variables;
326 q->structure = (slang_export_data_quant *) slang_alloc_malloc (
327 q->u.field_count * sizeof (slang_export_data_quant));
328 if (q->structure == NULL)
329 return GL_FALSE;
330
331 for (i = 0; i < q->u.field_count; i++)
332 slang_export_data_quant_ctr (&q->structure[i]);
333 for (i = 0; i < q->u.field_count; i++)
334 if (!build_quant (&q->structure[i], &spec->_struct->fields->variables[i]))
335 return GL_FALSE;
336 }
337 else
338 q->u.basic_type = gl_type_from_specifier (spec);
339 return GL_TRUE;
340 }
341
342 GLboolean _slang_build_export_data_table (slang_export_data_table *tbl, slang_variable_scope *vars)
343 {
344 GLuint i;
345
346 for (i = 0; i < vars->num_variables; i++)
347 {
348 slang_variable *var = &vars->variables[i];
349 slang_export_data_entry *e;
350
351 e = slang_export_data_table_add (tbl);
352 if (e == NULL)
353 return GL_FALSE;
354 if (!build_quant (&e->quant, var))
355 return GL_FALSE;
356 if (var->type.qualifier == slang_qual_uniform)
357 e->access = slang_exp_uniform;
358 else if (var->type.qualifier == slang_qual_attribute)
359 e->access = slang_exp_attribute;
360 else
361 e->access = slang_exp_varying;
362 e->address = var->address;
363 }
364
365 if (vars->outer_scope != NULL)
366 return _slang_build_export_data_table (tbl, vars->outer_scope);
367 return GL_TRUE;
368 }
369