More GLSL code:
[mesa.git] / src / mesa / shader / slang / slang_export.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 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_export.c
27 * interface between assembly code and the application
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_export.h"
33
34 /*
35 * slang_export_data_quant
36 */
37
38 GLvoid slang_export_data_quant_ctr (slang_export_data_quant *self)
39 {
40 self->name = SLANG_ATOM_NULL;
41 self->size = 0;
42 self->array_len = 0;
43 self->structure = NULL;
44 self->u.basic_type = GL_FLOAT;
45 }
46
47 GLvoid slang_export_data_quant_dtr (slang_export_data_quant *self)
48 {
49 if (self->structure != NULL)
50 {
51 GLuint i;
52
53 for (i = 0; i < self->u.field_count; i++)
54 slang_export_data_quant_dtr (&self->structure[i]);
55 slang_alloc_free (self->structure);
56 }
57 }
58
59 slang_export_data_quant *slang_export_data_quant_add_field (slang_export_data_quant *self)
60 {
61 const GLuint n = self->u.field_count;
62
63 self->structure = (slang_export_data_quant *) slang_alloc_realloc (self->structure,
64 n * sizeof (slang_export_data_quant), (n + 1) * sizeof (slang_export_data_quant));
65 if (self->structure == NULL)
66 return NULL;
67 slang_export_data_quant_ctr (&self->structure[n]);
68 self->u.field_count++;
69 return &self->structure[n];
70 }
71
72 /*
73 * slang_export_data_entry
74 */
75
76 GLvoid slang_export_data_entry_ctr (slang_export_data_entry *self)
77 {
78 slang_export_data_quant_ctr (&self->quant);
79 self->access = slang_exp_uniform;
80 self->address = ~0;
81 }
82
83 GLvoid slang_export_data_entry_dtr (slang_export_data_entry *self)
84 {
85 slang_export_data_quant_dtr (&self->quant);
86 }
87
88 /*
89 * slang_export_data_table
90 */
91
92 GLvoid slang_export_data_table_ctr (slang_export_data_table *self)
93 {
94 self->entries = NULL;
95 self->count = 0;
96 self->atoms = NULL;
97 }
98
99 GLvoid slang_export_data_table_dtr (slang_export_data_table *self)
100 {
101 if (self->entries != NULL)
102 {
103 GLuint i;
104
105 for (i = 0; i < self->count; i++)
106 slang_export_data_entry_dtr (&self->entries[i]);
107 slang_alloc_free (self->entries);
108 }
109 }
110
111 slang_export_data_entry *slang_export_data_table_add (slang_export_data_table *self)
112 {
113 const GLuint n = self->count;
114
115 self->entries = (slang_export_data_entry *) slang_alloc_realloc (self->entries,
116 n * sizeof (slang_export_data_entry), (n + 1) * sizeof (slang_export_data_entry));
117 if (self->entries == NULL)
118 return NULL;
119 slang_export_data_entry_ctr (&self->entries[n]);
120 self->count++;
121 return &self->entries[n];
122 }
123
124 /*
125 * slang_export_code_entry
126 */
127
128 GLvoid slang_export_code_entry_ctr (slang_export_code_entry *self)
129 {
130 self->name = SLANG_ATOM_NULL;
131 self->address = ~0;
132 }
133
134 GLvoid slang_export_code_entry_dtr (slang_export_code_entry *self)
135 {
136 }
137
138 /*
139 * slang_export_code_table
140 */
141
142 GLvoid slang_export_code_table_ctr (slang_export_code_table *self)
143 {
144 self->entries = NULL;
145 self->count = 0;
146 self->atoms = NULL;
147 }
148
149 GLvoid slang_export_code_table_dtr (slang_export_code_table *self)
150 {
151 if (self->entries != NULL)
152 {
153 GLuint i;
154
155 for (i = 0; i < self->count; i++)
156 slang_export_code_entry_dtr (&self->entries[i]);
157 slang_alloc_free (self->entries);
158 }
159 }
160
161 slang_export_code_entry *slang_export_code_table_add (slang_export_code_table *self)
162 {
163 const GLuint n = self->count;
164
165 self->entries = (slang_export_code_entry *) slang_alloc_realloc (self->entries,
166 n * sizeof (slang_export_code_entry), (n + 1) * sizeof (slang_export_code_entry));
167 if (self->entries == NULL)
168 return NULL;
169 slang_export_code_entry_ctr (&self->entries[n]);
170 self->count++;
171 return &self->entries[n];
172 }
173
174 /*
175 * _slang_find_exported_data()
176 */
177
178 #define EXTRACT_ERROR 0
179 #define EXTRACT_BASIC 1
180 #define EXTRACT_ARRAY 2
181 #define EXTRACT_STRUCT 3
182 #define EXTRACT_STRUCT_ARRAY 4
183
184 #define EXTRACT_MAXLEN 255
185
186 static GLuint extract_name (const char *name, char *parsed, GLuint *element, const char **end)
187 {
188 GLuint i;
189
190 if ((name[0] >= 'a' && name[0] <= 'z') || (name[0] >= 'A' && name[0] <= 'Z') || name[0] == '_')
191 {
192 parsed[0] = name[0];
193
194 for (i = 1; i < EXTRACT_MAXLEN; i++)
195 {
196 if ((name[i] >= 'a' && name[i] <= 'z') || (name[i] >= 'A' && name[i] <= 'Z') ||
197 (name[i] >= '0' && name[i] <= '9') || name[0] == '_')
198 {
199 parsed[i] = name[i];
200 }
201 else
202 {
203 if (name[i] == '\0')
204 {
205 parsed[i] = '\0';
206 return EXTRACT_BASIC;
207 }
208 if (name[i] == '.')
209 {
210 parsed[i] = '\0';
211 *end = &name[i + 1];
212 return EXTRACT_STRUCT;
213 }
214 if (name[i] == '[')
215 {
216 parsed[i] = '\0';
217 i++;
218 if (name[i] >= '0' && name[i] <= '9')
219 {
220 *element = name[i] - '0';
221 for (i++; ; i++)
222 {
223 if (name[i] >= '0' && name[i] <= '9')
224 *element = *element * 10 + (name[i] - '0');
225 else
226 {
227 if (name[i] == ']')
228 {
229 i++;
230 if (name[i] == '.')
231 {
232 *end = &name[i + 1];
233 return EXTRACT_STRUCT_ARRAY;
234 }
235 *end = &name[i];
236 return EXTRACT_ARRAY;
237 }
238 break;
239 }
240 }
241 }
242 }
243 break;
244 }
245 }
246 }
247 return EXTRACT_ERROR;
248 }
249
250 static GLboolean validate_extracted (slang_export_data_quant *q, GLuint element, GLuint extr)
251 {
252 switch (extr)
253 {
254 case EXTRACT_BASIC:
255 return GL_TRUE;
256 case EXTRACT_ARRAY:
257 return element < q->array_len;
258 case EXTRACT_STRUCT:
259 return q->structure != NULL;
260 case EXTRACT_STRUCT_ARRAY:
261 return q->structure != NULL && element < q->array_len;
262 }
263 return GL_FALSE;
264 }
265
266 static GLuint calculate_offset (slang_export_data_quant *q, GLuint element)
267 {
268 if (q->array_len != 0)
269 return element * q->size;
270 return 0;
271 }
272
273 static GLboolean find_exported_data (slang_export_data_quant *q, const char *name,
274 slang_export_data_quant **quant, GLuint *offset, slang_atom_pool *atoms)
275 {
276 char parsed[EXTRACT_MAXLEN];
277 GLuint result, element, i;
278 const char *end;
279 slang_atom atom;
280
281 result = extract_name (name, parsed, &element, &end);
282 if (result == EXTRACT_ERROR)
283 return GL_FALSE;
284
285 atom = slang_atom_pool_atom (atoms, parsed);
286 if (atom == SLANG_ATOM_NULL)
287 return GL_FALSE;
288
289 for (i = 0; i < q->u.field_count; i++)
290 if (q->structure[i].name == atom)
291 {
292 if (!validate_extracted (&q->structure[i], element, result))
293 return GL_FALSE;
294 *offset += calculate_offset (&q->structure[i], element);
295 if (result == EXTRACT_BASIC || result == EXTRACT_ARRAY)
296 {
297 if (*end != '\0')
298 return GL_FALSE;
299 *quant = &q->structure[i];
300 return GL_TRUE;
301 }
302 return find_exported_data (&q->structure[i], end, quant, offset, atoms);
303 }
304 return GL_FALSE;
305 }
306
307 GLboolean _slang_find_exported_data (slang_export_data_table *table, const char *name,
308 slang_export_data_entry **entry, slang_export_data_quant **quant, GLuint *offset)
309 {
310 char parsed[EXTRACT_MAXLEN];
311 GLuint result, element, i;
312 const char *end;
313 slang_atom atom;
314
315 result = extract_name (name, parsed, &element, &end);
316 if (result == EXTRACT_ERROR)
317 return GL_FALSE;
318
319 atom = slang_atom_pool_atom (table->atoms, parsed);
320 if (atom == SLANG_ATOM_NULL)
321 return GL_FALSE;
322
323 for (i = 0; i < table->count; i++)
324 if (table->entries[i].quant.name == atom)
325 {
326 if (!validate_extracted (&table->entries[i].quant, element, result))
327 return GL_FALSE;
328 *entry = &table->entries[i];
329 *offset = calculate_offset (&table->entries[i].quant, element);
330 if (result == EXTRACT_BASIC || result == EXTRACT_ARRAY)
331 {
332 if (*end != '\0')
333 return GL_FALSE;
334 *quant = &table->entries[i].quant;
335 return GL_TRUE;
336 }
337 return find_exported_data (&table->entries[i].quant, end, quant, offset, table->atoms);
338 }
339 return GL_FALSE;
340 }
341