6f56872b593f70d9149de5f39b3662dd4f0a00da
[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_utility.h"
33 #include "slang_compile_variable.h"
34 #include "slang_compile_struct.h"
35 #include "slang_compile_operation.h"
36
37 /* slang_type_specifier_type */
38
39 typedef struct
40 {
41 const char *name;
42 slang_type_specifier_type type;
43 } type_specifier_type_name;
44
45 static type_specifier_type_name type_specifier_type_names[] = {
46 { "void", slang_spec_void },
47 { "bool", slang_spec_bool },
48 { "bvec2", slang_spec_bvec2 },
49 { "bvec3", slang_spec_bvec3 },
50 { "bvec4", slang_spec_bvec4 },
51 { "int", slang_spec_int },
52 { "ivec2", slang_spec_ivec2 },
53 { "ivec3", slang_spec_ivec3 },
54 { "ivec4", slang_spec_ivec4 },
55 { "float", slang_spec_float },
56 { "vec2", slang_spec_vec2 },
57 { "vec3", slang_spec_vec3 },
58 { "vec4", slang_spec_vec4 },
59 { "mat2", slang_spec_mat2 },
60 { "mat3", slang_spec_mat3 },
61 { "mat4", slang_spec_mat4 },
62 { "sampler1D", slang_spec_sampler1D },
63 { "sampler2D", slang_spec_sampler2D },
64 { "sampler3D", slang_spec_sampler3D },
65 { "samplerCube", slang_spec_samplerCube },
66 { "sampler1DShadow", slang_spec_sampler1DShadow },
67 { "sampler2DShadow", slang_spec_sampler2DShadow },
68 { NULL, slang_spec_void }
69 };
70
71 slang_type_specifier_type slang_type_specifier_type_from_string (const char *name)
72 {
73 type_specifier_type_name *p = type_specifier_type_names;
74 while (p->name != NULL)
75 {
76 if (slang_string_compare (p->name, name) == 0)
77 break;
78 p++;
79 }
80 return p->type;
81 }
82
83 const char *slang_type_specifier_type_to_string (slang_type_specifier_type type)
84 {
85 type_specifier_type_name *p = type_specifier_type_names;
86 while (p->name != NULL)
87 {
88 if (p->type == type)
89 break;
90 p++;
91 }
92 return p->name;
93 }
94
95 /* slang_type_specifier */
96
97 int slang_type_specifier_construct (slang_type_specifier *spec)
98 {
99 spec->type = slang_spec_void;
100 spec->_struct = NULL;
101 spec->_array = NULL;
102 return 1;
103 }
104
105 void slang_type_specifier_destruct (slang_type_specifier *spec)
106 {
107 if (spec->_struct != NULL)
108 {
109 slang_struct_destruct (spec->_struct);
110 slang_alloc_free (spec->_struct);
111 }
112 if (spec->_array != NULL)
113 {
114 slang_type_specifier_destruct (spec->_array);
115 slang_alloc_free (spec->_array);
116 }
117 }
118
119 int slang_type_specifier_copy (slang_type_specifier *x, const slang_type_specifier *y)
120 {
121 slang_type_specifier z;
122
123 if (!slang_type_specifier_construct (&z))
124 return 0;
125 z.type = y->type;
126 if (z.type == slang_spec_struct)
127 {
128 z._struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));
129 if (z._struct == NULL)
130 {
131 slang_type_specifier_destruct (&z);
132 return 0;
133 }
134 if (!slang_struct_construct (z._struct))
135 {
136 slang_alloc_free (z._struct);
137 slang_type_specifier_destruct (&z);
138 return 0;
139 }
140 if (!slang_struct_copy (z._struct, y->_struct))
141 {
142 slang_type_specifier_destruct (&z);
143 return 0;
144 }
145 }
146 else if (z.type == slang_spec_array)
147 {
148 z._array = (slang_type_specifier *) slang_alloc_malloc (sizeof (slang_type_specifier));
149 if (z._array == NULL)
150 {
151 slang_type_specifier_destruct (&z);
152 return 0;
153 }
154 if (!slang_type_specifier_construct (z._array))
155 {
156 slang_alloc_free (z._array);
157 slang_type_specifier_destruct (&z);
158 return 0;
159 }
160 if (!slang_type_specifier_copy (z._array, y->_array))
161 {
162 slang_type_specifier_destruct (&z);
163 return 0;
164 }
165 }
166 slang_type_specifier_destruct (x);
167 *x = z;
168 return 1;
169 }
170
171 int slang_type_specifier_equal (const slang_type_specifier *x, const slang_type_specifier *y)
172 {
173 if (x->type != y->type)
174 return 0;
175 if (x->type == slang_spec_struct)
176 return slang_struct_equal (x->_struct, y->_struct);
177 if (x->type == slang_spec_array)
178 return slang_type_specifier_equal (x->_array, y->_array);
179 return 1;
180 }
181
182 /* slang_fully_specified_type */
183
184 int slang_fully_specified_type_construct (slang_fully_specified_type *type)
185 {
186 type->qualifier = slang_qual_none;
187 if (!slang_type_specifier_construct (&type->specifier))
188 return 0;
189 return 1;
190 }
191
192 void slang_fully_specified_type_destruct (slang_fully_specified_type *type)
193 {
194 slang_type_specifier_destruct (&type->specifier);
195 }
196
197 int slang_fully_specified_type_copy (slang_fully_specified_type *x, const slang_fully_specified_type *y)
198 {
199 slang_fully_specified_type z;
200
201 if (!slang_fully_specified_type_construct (&z))
202 return 0;
203 z.qualifier = y->qualifier;
204 if (!slang_type_specifier_copy (&z.specifier, &y->specifier))
205 {
206 slang_fully_specified_type_destruct (&z);
207 return 0;
208 }
209 slang_fully_specified_type_destruct (x);
210 *x = z;
211 return 1;
212 }
213
214 /* slang_variable_scope */
215
216 int slang_variable_scope_construct (slang_variable_scope *scope)
217 {
218 scope->variables = NULL;
219 scope->num_variables = 0;
220 scope->outer_scope = NULL;
221 return 1;
222 }
223
224 void slang_variable_scope_destruct (slang_variable_scope *scope)
225 {
226 unsigned int i;
227
228 for (i = 0; i < scope->num_variables; i++)
229 slang_variable_destruct (scope->variables + i);
230 slang_alloc_free (scope->variables);
231 /* do not free scope->outer_scope */
232 }
233
234 int slang_variable_scope_copy (slang_variable_scope *x, const slang_variable_scope *y)
235 {
236 slang_variable_scope z;
237 unsigned int i;
238
239 if (!slang_variable_scope_construct (&z))
240 return 0;
241 z.variables = (slang_variable *) slang_alloc_malloc (y->num_variables * sizeof (slang_variable));
242 if (z.variables == NULL)
243 {
244 slang_variable_scope_destruct (&z);
245 return 0;
246 }
247 for (z.num_variables = 0; z.num_variables < y->num_variables; z.num_variables++)
248 if (!slang_variable_construct (&z.variables[z.num_variables]))
249 {
250 slang_variable_scope_destruct (&z);
251 return 0;
252 }
253 for (i = 0; i < z.num_variables; i++)
254 if (!slang_variable_copy (&z.variables[i], &y->variables[i]))
255 {
256 slang_variable_scope_destruct (&z);
257 return 0;
258 }
259 z.outer_scope = y->outer_scope;
260 slang_variable_scope_destruct (x);
261 *x = z;
262 return 1;
263 }
264
265 /* slang_variable */
266
267 int slang_variable_construct (slang_variable *var)
268 {
269 if (!slang_fully_specified_type_construct (&var->type))
270 return 0;
271 var->a_name = SLANG_ATOM_NULL;
272 var->array_len = 0;
273 var->initializer = NULL;
274 var->address = ~0;
275 var->size = 0;
276 var->global = 0;
277 return 1;
278 }
279
280 void slang_variable_destruct (slang_variable *var)
281 {
282 slang_fully_specified_type_destruct (&var->type);
283 if (var->initializer != NULL)
284 {
285 slang_operation_destruct (var->initializer);
286 slang_alloc_free (var->initializer);
287 }
288 }
289
290 int slang_variable_copy (slang_variable *x, const slang_variable *y)
291 {
292 slang_variable z;
293
294 if (!slang_variable_construct (&z))
295 return 0;
296 if (!slang_fully_specified_type_copy (&z.type, &y->type))
297 {
298 slang_variable_destruct (&z);
299 return 0;
300 }
301 z.a_name = y->a_name;
302 z.array_len = y->array_len;
303 if (y->initializer != NULL)
304 {
305 z.initializer = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));
306 if (z.initializer == NULL)
307 {
308 slang_variable_destruct (&z);
309 return 0;
310 }
311 if (!slang_operation_construct (z.initializer))
312 {
313 slang_alloc_free (z.initializer);
314 slang_variable_destruct (&z);
315 return 0;
316 }
317 if (!slang_operation_copy (z.initializer, y->initializer))
318 {
319 slang_variable_destruct (&z);
320 return 0;
321 }
322 }
323 z.address = y->address;
324 z.size = y->size;
325 z.global = y->global;
326 slang_variable_destruct (x);
327 *x = z;
328 return 1;
329 }
330
331 slang_variable *_slang_locate_variable (slang_variable_scope *scope, slang_atom a_name, GLboolean all)
332 {
333 GLuint i;
334
335 for (i = 0; i < scope->num_variables; i++)
336 if (a_name == scope->variables[i].a_name)
337 return &scope->variables[i];
338 if (all && scope->outer_scope != NULL)
339 return _slang_locate_variable (scope->outer_scope, a_name, 1);
340 return NULL;
341 }
342
343 /*
344 * slang_active_uniforms
345 */
346
347 GLvoid slang_active_uniforms_ctr (slang_active_uniforms *self)
348 {
349 self->table = NULL;
350 self->count = 0;
351 }
352
353 GLvoid slang_active_uniforms_dtr (slang_active_uniforms *self)
354 {
355 GLuint i;
356
357 for (i = 0; i < self->count; i++)
358 slang_alloc_free (self->table[i].name);
359 slang_alloc_free (self->table);
360 }
361
362 GLboolean slang_active_uniforms_add (slang_active_uniforms *self, slang_export_data_quant *q,
363 const char *name)
364 {
365 const GLuint n = self->count;
366
367 self->table = (slang_active_uniform *) slang_alloc_realloc (self->table,
368 n * sizeof (slang_active_uniform), (n + 1) * sizeof (slang_active_uniform));
369 if (self->table == NULL)
370 return GL_FALSE;
371 self->table[n].quant = q;
372 self->table[n].name = slang_string_duplicate (name);
373 if (self->table[n].name == NULL)
374 return GL_FALSE;
375 self->count++;
376 return GL_TRUE;
377 }
378
379 static GLenum gl_type_from_specifier (const slang_type_specifier *type)
380 {
381 switch (type->type)
382 {
383 case slang_spec_bool:
384 return GL_BOOL_ARB;
385 case slang_spec_bvec2:
386 return GL_BOOL_VEC2_ARB;
387 case slang_spec_bvec3:
388 return GL_BOOL_VEC3_ARB;
389 case slang_spec_bvec4:
390 return GL_BOOL_VEC4_ARB;
391 case slang_spec_int:
392 return GL_INT;
393 case slang_spec_ivec2:
394 return GL_INT_VEC2_ARB;
395 case slang_spec_ivec3:
396 return GL_INT_VEC3_ARB;
397 case slang_spec_ivec4:
398 return GL_INT_VEC4_ARB;
399 case slang_spec_float:
400 return GL_FLOAT;
401 case slang_spec_vec2:
402 return GL_FLOAT_VEC2_ARB;
403 case slang_spec_vec3:
404 return GL_FLOAT_VEC3_ARB;
405 case slang_spec_vec4:
406 return GL_FLOAT_VEC4_ARB;
407 case slang_spec_mat2:
408 return GL_FLOAT_MAT2_ARB;
409 case slang_spec_mat3:
410 return GL_FLOAT_MAT3_ARB;
411 case slang_spec_mat4:
412 return GL_FLOAT_MAT4_ARB;
413 case slang_spec_sampler1D:
414 return GL_SAMPLER_1D_ARB;
415 case slang_spec_sampler2D:
416 return GL_SAMPLER_2D_ARB;
417 case slang_spec_sampler3D:
418 return GL_SAMPLER_3D_ARB;
419 case slang_spec_samplerCube:
420 return GL_SAMPLER_CUBE_ARB;
421 case slang_spec_sampler1DShadow:
422 return GL_SAMPLER_1D_SHADOW_ARB;
423 case slang_spec_sampler2DShadow:
424 return GL_SAMPLER_2D_SHADOW_ARB;
425 case slang_spec_array:
426 return gl_type_from_specifier (type->_array);
427 default:
428 return GL_FLOAT;
429 }
430 }
431
432 static GLboolean build_quant (slang_export_data_quant *q, slang_variable *var)
433 {
434 slang_type_specifier *spec = &var->type.specifier;
435
436 q->name = var->a_name;
437 q->size = var->size;
438 if (spec->type == slang_spec_array)
439 {
440 q->array_len = var->array_len;
441 q->size /= var->array_len;
442 spec = spec->_array;
443 }
444 if (spec->type == slang_spec_struct)
445 {
446 GLuint i;
447
448 q->u.field_count = spec->_struct->fields->num_variables;
449 q->structure = (slang_export_data_quant *) slang_alloc_malloc (
450 q->u.field_count * sizeof (slang_export_data_quant));
451 if (q->structure == NULL)
452 return GL_FALSE;
453
454 for (i = 0; i < q->u.field_count; i++)
455 slang_export_data_quant_ctr (&q->structure[i]);
456 for (i = 0; i < q->u.field_count; i++)
457 if (!build_quant (&q->structure[i], &spec->_struct->fields->variables[i]))
458 return GL_FALSE;
459 }
460 else
461 q->u.basic_type = gl_type_from_specifier (spec);
462 return GL_TRUE;
463 }
464
465 GLboolean _slang_build_export_data_table (slang_export_data_table *tbl, slang_variable_scope *vars)
466 {
467 GLuint i;
468
469 for (i = 0; i < vars->num_variables; i++)
470 {
471 slang_variable *var = &vars->variables[i];
472
473 if (var->type.qualifier == slang_qual_uniform)
474 {
475 slang_export_data_entry *e = slang_export_data_table_add (tbl);
476 if (e == NULL)
477 return GL_FALSE;
478 if (!build_quant (&e->quant, var))
479 return GL_FALSE;
480 e->access = slang_exp_uniform;
481 e->address = var->address;
482 }
483 }
484
485 if (vars->outer_scope != NULL)
486 return _slang_build_export_data_table (tbl, vars->outer_scope);
487 return GL_TRUE;
488 }
489
490 static GLboolean insert_uniform (slang_active_uniforms *u, slang_export_data_quant *q, char *name,
491 slang_atom_pool *atoms)
492 {
493 slang_string_concat (name, slang_atom_pool_id (atoms, q->name));
494 if (q->array_len != 0)
495 slang_string_concat (name, "[0]");
496
497 if (q->structure != NULL)
498 {
499 GLuint save, i;
500
501 slang_string_concat (name, ".");
502 save = slang_string_length (name);
503
504 for (i = 0; i < q->u.field_count; i++)
505 {
506 if (!insert_uniform (u, &q->structure[i], name, atoms))
507 return GL_FALSE;
508 name[save] = '\0';
509 }
510
511 return GL_TRUE;
512 }
513
514 return slang_active_uniforms_add (u, q, name);
515 }
516
517 GLboolean _slang_gather_active_uniforms (slang_active_uniforms *u, slang_export_data_table *tbl)
518 {
519 GLuint i;
520
521 for (i = 0; i < tbl->count; i++)
522 {
523 char name[1024] = "";
524
525 if (!insert_uniform (u, &tbl->entries[i].quant, name, tbl->atoms))
526 return GL_FALSE;
527 }
528
529 return GL_TRUE;
530 }
531