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 GLboolean slang_export_data_quant_array (slang_export_data_quant *self)
73 {
74 return self->array_len != 0;
75 }
76
77 GLboolean slang_export_data_quant_struct (slang_export_data_quant *self)
78 {
79 return self->structure != NULL;
80 }
81
82 GLenum slang_export_data_quant_type (slang_export_data_quant *self)
83 {
84 assert (self->structure == NULL);
85 return self->u.basic_type;
86 }
87
88 GLuint slang_export_data_quant_fields (slang_export_data_quant *self)
89 {
90 assert (self->structure != NULL);
91 return self->u.field_count;
92 }
93
94 GLuint slang_export_data_quant_elements (slang_export_data_quant *self)
95 {
96 if (self->array_len == 0)
97 return 1;
98 return self->array_len;
99 }
100
101 GLuint slang_export_data_quant_components (slang_export_data_quant *self)
102 {
103 return self->size / 4;
104 }
105
106 GLuint slang_export_data_quant_size (slang_export_data_quant *self)
107 {
108 return self->size;
109 }
110
111 /*
112 * slang_export_data_entry
113 */
114
115 GLvoid slang_export_data_entry_ctr (slang_export_data_entry *self)
116 {
117 slang_export_data_quant_ctr (&self->quant);
118 self->access = slang_exp_uniform;
119 self->address = ~0;
120 }
121
122 GLvoid slang_export_data_entry_dtr (slang_export_data_entry *self)
123 {
124 slang_export_data_quant_dtr (&self->quant);
125 }
126
127 /*
128 * slang_export_data_table
129 */
130
131 GLvoid slang_export_data_table_ctr (slang_export_data_table *self)
132 {
133 self->entries = NULL;
134 self->count = 0;
135 self->atoms = NULL;
136 }
137
138 GLvoid slang_export_data_table_dtr (slang_export_data_table *self)
139 {
140 if (self->entries != NULL)
141 {
142 GLuint i;
143
144 for (i = 0; i < self->count; i++)
145 slang_export_data_entry_dtr (&self->entries[i]);
146 slang_alloc_free (self->entries);
147 }
148 }
149
150 slang_export_data_entry *slang_export_data_table_add (slang_export_data_table *self)
151 {
152 const GLuint n = self->count;
153
154 self->entries = (slang_export_data_entry *) slang_alloc_realloc (self->entries,
155 n * sizeof (slang_export_data_entry), (n + 1) * sizeof (slang_export_data_entry));
156 if (self->entries == NULL)
157 return NULL;
158 slang_export_data_entry_ctr (&self->entries[n]);
159 self->count++;
160 return &self->entries[n];
161 }
162
163 /*
164 * slang_export_code_entry
165 */
166
167 static GLvoid slang_export_code_entry_ctr (slang_export_code_entry *self)
168 {
169 self->name = SLANG_ATOM_NULL;
170 self->address = ~0;
171 }
172
173 static GLvoid slang_export_code_entry_dtr (slang_export_code_entry *self)
174 {
175 }
176
177 /*
178 * slang_export_code_table
179 */
180
181 GLvoid slang_export_code_table_ctr (slang_export_code_table *self)
182 {
183 self->entries = NULL;
184 self->count = 0;
185 self->atoms = NULL;
186 }
187
188 GLvoid slang_export_code_table_dtr (slang_export_code_table *self)
189 {
190 if (self->entries != NULL)
191 {
192 GLuint i;
193
194 for (i = 0; i < self->count; i++)
195 slang_export_code_entry_dtr (&self->entries[i]);
196 slang_alloc_free (self->entries);
197 }
198 }
199
200 slang_export_code_entry *slang_export_code_table_add (slang_export_code_table *self)
201 {
202 const GLuint n = self->count;
203
204 self->entries = (slang_export_code_entry *) slang_alloc_realloc (self->entries,
205 n * sizeof (slang_export_code_entry), (n + 1) * sizeof (slang_export_code_entry));
206 if (self->entries == NULL)
207 return NULL;
208 slang_export_code_entry_ctr (&self->entries[n]);
209 self->count++;
210 return &self->entries[n];
211 }
212
213 /*
214 * _slang_find_exported_data()
215 */
216
217 #define EXTRACT_ERROR 0
218 #define EXTRACT_BASIC 1
219 #define EXTRACT_ARRAY 2
220 #define EXTRACT_STRUCT 3
221 #define EXTRACT_STRUCT_ARRAY 4
222
223 #define EXTRACT_MAXLEN 255
224
225 static GLuint extract_name (const char *name, char *parsed, GLuint *element, const char **end)
226 {
227 GLuint i;
228
229 if ((name[0] >= 'a' && name[0] <= 'z') || (name[0] >= 'A' && name[0] <= 'Z') || name[0] == '_')
230 {
231 parsed[0] = name[0];
232
233 for (i = 1; i < EXTRACT_MAXLEN; i++)
234 {
235 if ((name[i] >= 'a' && name[i] <= 'z') || (name[i] >= 'A' && name[i] <= 'Z') ||
236 (name[i] >= '0' && name[i] <= '9') || name[0] == '_')
237 {
238 parsed[i] = name[i];
239 }
240 else
241 {
242 if (name[i] == '\0')
243 {
244 parsed[i] = '\0';
245 return EXTRACT_BASIC;
246 }
247 if (name[i] == '.')
248 {
249 parsed[i] = '\0';
250 *end = &name[i + 1];
251 return EXTRACT_STRUCT;
252 }
253 if (name[i] == '[')
254 {
255 parsed[i] = '\0';
256 i++;
257 if (name[i] >= '0' && name[i] <= '9')
258 {
259 *element = name[i] - '0';
260 for (i++; ; i++)
261 {
262 if (name[i] >= '0' && name[i] <= '9')
263 *element = *element * 10 + (name[i] - '0');
264 else
265 {
266 if (name[i] == ']')
267 {
268 i++;
269 if (name[i] == '.')
270 {
271 *end = &name[i + 1];
272 return EXTRACT_STRUCT_ARRAY;
273 }
274 *end = &name[i];
275 return EXTRACT_ARRAY;
276 }
277 break;
278 }
279 }
280 }
281 }
282 break;
283 }
284 }
285 }
286 return EXTRACT_ERROR;
287 }
288
289 static GLboolean validate_extracted (slang_export_data_quant *q, GLuint element, GLuint extr)
290 {
291 switch (extr)
292 {
293 case EXTRACT_BASIC:
294 return GL_TRUE;
295 case EXTRACT_ARRAY:
296 return element < slang_export_data_quant_elements (q);
297 case EXTRACT_STRUCT:
298 return slang_export_data_quant_struct (q);
299 case EXTRACT_STRUCT_ARRAY:
300 return slang_export_data_quant_struct (q) && element < slang_export_data_quant_elements (q);
301 }
302 return GL_FALSE;
303 }
304
305 static GLuint calculate_offset (slang_export_data_quant *q, GLuint element)
306 {
307 if (slang_export_data_quant_array (q))
308 return element * slang_export_data_quant_size (q);
309 return 0;
310 }
311
312 static GLboolean find_exported_data (slang_export_data_quant *q, const char *name,
313 slang_export_data_quant **quant, GLuint *offset, slang_atom_pool *atoms)
314 {
315 char parsed[EXTRACT_MAXLEN];
316 GLuint result, element, i;
317 const char *end;
318 slang_atom atom;
319 const GLuint fields = slang_export_data_quant_fields (q);
320
321 result = extract_name (name, parsed, &element, &end);
322 if (result == EXTRACT_ERROR)
323 return GL_FALSE;
324
325 atom = slang_atom_pool_atom (atoms, parsed);
326 if (atom == SLANG_ATOM_NULL)
327 return GL_FALSE;
328
329 for (i = 0; i < fields; i++)
330 if (q->structure[i].name == atom)
331 {
332 if (!validate_extracted (&q->structure[i], element, result))
333 return GL_FALSE;
334 *offset += calculate_offset (&q->structure[i], element);
335 if (result == EXTRACT_BASIC || result == EXTRACT_ARRAY)
336 {
337 if (*end != '\0')
338 return GL_FALSE;
339 *quant = &q->structure[i];
340 return GL_TRUE;
341 }
342 return find_exported_data (&q->structure[i], end, quant, offset, atoms);
343 }
344 return GL_FALSE;
345 }
346
347 GLboolean _slang_find_exported_data (slang_export_data_table *table, const char *name,
348 slang_export_data_entry **entry, slang_export_data_quant **quant, GLuint *offset)
349 {
350 char parsed[EXTRACT_MAXLEN];
351 GLuint result, element, i;
352 const char *end;
353 slang_atom atom;
354
355 result = extract_name (name, parsed, &element, &end);
356 if (result == EXTRACT_ERROR)
357 return GL_FALSE;
358
359 atom = slang_atom_pool_atom (table->atoms, parsed);
360 if (atom == SLANG_ATOM_NULL)
361 return GL_FALSE;
362
363 for (i = 0; i < table->count; i++)
364 if (table->entries[i].quant.name == atom)
365 {
366 if (!validate_extracted (&table->entries[i].quant, element, result))
367 return GL_FALSE;
368 *entry = &table->entries[i];
369 *offset = calculate_offset (&table->entries[i].quant, element);
370 if (result == EXTRACT_BASIC || result == EXTRACT_ARRAY)
371 {
372 if (*end != '\0')
373 return GL_FALSE;
374 *quant = &table->entries[i].quant;
375 return GL_TRUE;
376 }
377 return find_exported_data (&table->entries[i].quant, end, quant, offset, table->atoms);
378 }
379 return GL_FALSE;
380 }
381