GLSL fixes:
[mesa.git] / src / mesa / shader / slang / slang_link.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_link.c
27 * slang linker
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_link.h"
33 #include "slang_analyse.h"
34
35 /*
36 * slang_uniform_bindings
37 */
38
39 static GLvoid slang_uniform_bindings_ctr (slang_uniform_bindings *self)
40 {
41 self->table = NULL;
42 self->count = 0;
43 }
44
45 static GLvoid slang_uniform_bindings_dtr (slang_uniform_bindings *self)
46 {
47 GLuint i;
48
49 for (i = 0; i < self->count; i++)
50 slang_alloc_free (self->table[i].name);
51 slang_alloc_free (self->table);
52 }
53
54 static GLboolean slang_uniform_bindings_add (slang_uniform_bindings *self, slang_export_data_quant *q,
55 const char *name, GLuint index, GLuint address)
56 {
57 const GLuint n = self->count;
58 GLuint i;
59
60 for (i = 0; i < n; i++)
61 if (slang_string_compare (self->table[i].name, name) == 0)
62 {
63 self->table[i].address[index] = address;
64 return GL_TRUE;
65 }
66
67 self->table = (slang_uniform_binding *) slang_alloc_realloc (self->table,
68 n * sizeof (slang_uniform_binding), (n + 1) * sizeof (slang_uniform_binding));
69 if (self->table == NULL)
70 return GL_FALSE;
71 self->table[n].quant = q;
72 self->table[n].name = slang_string_duplicate (name);
73 for (i = 0; i < SLANG_SHADER_MAX; i++)
74 self->table[n].address[i] = ~0;
75 self->table[n].address[index] = address;
76 if (self->table[n].name == NULL)
77 return GL_FALSE;
78 self->count++;
79 return GL_TRUE;
80 }
81
82 static GLboolean insert_binding (slang_uniform_bindings *bind, slang_export_data_quant *q,
83 char *name, slang_atom_pool *atoms, GLuint index, GLuint addr)
84 {
85 GLuint count, i;
86
87 slang_string_concat (name, slang_atom_pool_id (atoms, q->name));
88
89 if (q->array_len == 0)
90 count = 1;
91 else
92 count = q->array_len;
93
94 for (i = 0; i < count; i++)
95 {
96 GLuint save;
97
98 save = slang_string_length (name);
99 if (q->array_len != 0)
100 _mesa_sprintf (name + slang_string_length (name), "[%d]", i);
101
102 if (q->structure != NULL)
103 {
104 GLuint save, i;
105
106 slang_string_concat (name, ".");
107 save = slang_string_length (name);
108
109 for (i = 0; i < q->u.field_count; i++)
110 {
111 if (!insert_binding (bind, &q->structure[i], name, atoms, index, addr))
112 return GL_FALSE;
113 name[save] = '\0';
114 addr += q->structure[i].size;
115 }
116 }
117 else
118 {
119 if (!slang_uniform_bindings_add (bind, q, name, index, addr))
120 return GL_FALSE;
121 addr += q->size;
122 }
123 name[save] = '\0';
124 }
125
126 return GL_TRUE;
127 }
128
129 static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind, slang_export_data_table *tbl,
130 GLuint index)
131 {
132 GLuint i;
133
134 for (i = 0; i < tbl->count; i++)
135 if (tbl->entries[i].access == slang_exp_uniform)
136 {
137 char name[1024] = "";
138
139 if (!insert_binding (bind, &tbl->entries[i].quant, name, tbl->atoms, index,
140 tbl->entries[i].address))
141 return GL_FALSE;
142 }
143
144 return GL_TRUE;
145 }
146
147 /*
148 * slang_active_uniforms
149 */
150
151 static GLvoid slang_active_uniforms_ctr (slang_active_uniforms *self)
152 {
153 self->table = NULL;
154 self->count = 0;
155 }
156
157 static GLvoid slang_active_uniforms_dtr (slang_active_uniforms *self)
158 {
159 GLuint i;
160
161 for (i = 0; i < self->count; i++)
162 slang_alloc_free (self->table[i].name);
163 slang_alloc_free (self->table);
164 }
165
166 static GLboolean slang_active_uniforms_add (slang_active_uniforms *self, slang_export_data_quant *q,
167 const char *name)
168 {
169 const GLuint n = self->count;
170
171 self->table = (slang_active_uniform *) slang_alloc_realloc (self->table,
172 n * sizeof (slang_active_uniform), (n + 1) * sizeof (slang_active_uniform));
173 if (self->table == NULL)
174 return GL_FALSE;
175 self->table[n].quant = q;
176 self->table[n].name = slang_string_duplicate (name);
177 if (self->table[n].name == NULL)
178 return GL_FALSE;
179 self->count++;
180 return GL_TRUE;
181 }
182
183 static GLboolean insert_uniform (slang_active_uniforms *u, slang_export_data_quant *q, char *name,
184 slang_atom_pool *atoms)
185 {
186 slang_string_concat (name, slang_atom_pool_id (atoms, q->name));
187 if (q->array_len != 0)
188 slang_string_concat (name, "[0]");
189
190 if (q->structure != NULL)
191 {
192 GLuint save, i;
193
194 slang_string_concat (name, ".");
195 save = slang_string_length (name);
196
197 for (i = 0; i < q->u.field_count; i++)
198 {
199 if (!insert_uniform (u, &q->structure[i], name, atoms))
200 return GL_FALSE;
201 name[save] = '\0';
202 }
203
204 return GL_TRUE;
205 }
206
207 return slang_active_uniforms_add (u, q, name);
208 }
209
210 static GLboolean gather_active_uniforms (slang_active_uniforms *u, slang_export_data_table *tbl)
211 {
212 GLuint i;
213
214 for (i = 0; i < tbl->count; i++)
215 if (tbl->entries[i].access == slang_exp_uniform)
216 {
217 char name[1024] = "";
218
219 if (!insert_uniform (u, &tbl->entries[i].quant, name, tbl->atoms))
220 return GL_FALSE;
221 }
222
223 return GL_TRUE;
224 }
225
226 /*
227 * slang_texture_bindings
228 */
229
230 GLvoid slang_texture_usages_ctr (slang_texture_usages *self)
231 {
232 self->table = NULL;
233 self->count = 0;
234 }
235
236 GLvoid slang_texture_usages_dtr (slang_texture_usages *self)
237 {
238 slang_alloc_free (self->table);
239 }
240
241 /*
242 * slang_program
243 */
244
245 GLvoid slang_program_ctr (slang_program *self)
246 {
247 GLuint i;
248
249 slang_uniform_bindings_ctr (&self->uniforms);
250 slang_active_uniforms_ctr (&self->active_uniforms);
251 slang_texture_usages_ctr (&self->texture_usage);
252 for (i = 0; i < SLANG_SHADER_MAX; i++)
253 {
254 GLuint j;
255
256 for (j = 0; j < SLANG_COMMON_FIXED_MAX; j++)
257 self->common_fixed_entries[i][j] = ~0;
258 for (j = 0; j < SLANG_COMMON_CODE_MAX; j++)
259 self->code[i][j] = ~0;
260 self->machines[i] = NULL;
261 self->assemblies[i] = NULL;
262 }
263 for (i = 0; i < SLANG_VERTEX_FIXED_MAX; i++)
264 self->vertex_fixed_entries[i] = ~0;
265 for (i = 0; i < SLANG_FRAGMENT_FIXED_MAX; i++)
266 self->fragment_fixed_entries[i] = ~0;
267 }
268
269 GLvoid slang_program_dtr (slang_program *self)
270 {
271 slang_uniform_bindings_dtr (&self->uniforms);
272 slang_active_uniforms_dtr (&self->active_uniforms);
273 slang_texture_usages_dtr (&self->texture_usage);
274 }
275
276 /*
277 * _slang_link()
278 */
279
280 static GLuint gd (slang_export_data_table *tbl, const char *name)
281 {
282 slang_atom atom;
283 GLuint i;
284
285 atom = slang_atom_pool_atom (tbl->atoms, name);
286 if (atom == SLANG_ATOM_NULL)
287 return ~0;
288
289 for (i = 0; i < tbl->count; i++)
290 if (atom == tbl->entries[i].quant.name)
291 return tbl->entries[i].address;
292 return ~0;
293 }
294
295 static GLvoid resolve_common_fixed (GLuint e[], slang_export_data_table *tbl)
296 {
297 e[SLANG_COMMON_FIXED_MODELVIEWMATRIX] = gd (tbl, "gl_ModelViewMatrix");
298 e[SLANG_COMMON_FIXED_PROJECTIONMATRIX] = gd (tbl, "gl_ProjectionMatrix");
299 e[SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIX] = gd (tbl, "gl_ModelViewProjectionMatrix");
300 e[SLANG_COMMON_FIXED_TEXTUREMATRIX] = gd (tbl, "gl_TextureMatrix");
301 e[SLANG_COMMON_FIXED_NORMALMATRIX] = gd (tbl, "gl_NormalMatrix");
302 e[SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSE] = gd (tbl, "gl_ModelViewMatrixInverse");
303 e[SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSE] = gd (tbl, "gl_ProjectionMatrixInverse");
304 e[SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSE] =
305 gd (tbl, "gl_ModelViewProjectionMatrixInverse");
306 e[SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSE] = gd (tbl, "gl_TextureMatrixInverse");
307 e[SLANG_COMMON_FIXED_MODELVIEWMATRIXTRANSPOSE] = gd (tbl, "gl_ModelViewMatrixTranspose");
308 e[SLANG_COMMON_FIXED_PROJECTIONMATRIXTRANSPOSE] = gd (tbl, "gl_ProjectionMatrixTranspose");
309 e[SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXTRANSPOSE] =
310 gd (tbl, "gl_ModelViewProjectionMatrixTranspose");
311 e[SLANG_COMMON_FIXED_TEXTUREMATRIXTRANSPOSE] = gd (tbl, "gl_TextureMatrixTranspose");
312 e[SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSETRANSPOSE] =
313 gd (tbl, "gl_ModelViewMatrixInverseTranspose");
314 e[SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSETRANSPOSE] =
315 gd (tbl, "gl_ProjectionMatrixInverseTranspose");
316 e[SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSETRANSPOSE] =
317 gd (tbl, "gl_ModelViewProjectionMatrixInverseTranspose");
318 e[SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSETRANSPOSE] =
319 gd (tbl, "gl_TextureMatrixInverseTranspose");
320 e[SLANG_COMMON_FIXED_NORMALSCALE] = gd (tbl, "gl_NormalScale");
321 e[SLANG_COMMON_FIXED_DEPTHRANGE] = gd (tbl, "gl_DepthRange");
322 e[SLANG_COMMON_FIXED_CLIPPLANE] = gd (tbl, "gl_ClipPlane");
323 e[SLANG_COMMON_FIXED_POINT] = gd (tbl, "gl_Point");
324 e[SLANG_COMMON_FIXED_FRONTMATERIAL] = gd (tbl, "gl_FrontMaterial");
325 e[SLANG_COMMON_FIXED_BACKMATERIAL] = gd (tbl, "gl_BackMaterial");
326 e[SLANG_COMMON_FIXED_LIGHTSOURCE] = gd (tbl, "gl_LightSource");
327 e[SLANG_COMMON_FIXED_LIGHTMODEL] = gd (tbl, "gl_LightModel");
328 e[SLANG_COMMON_FIXED_FRONTLIGHTMODELPRODUCT] = gd (tbl, "gl_FrontLightModelProduct");
329 e[SLANG_COMMON_FIXED_BACKLIGHTMODELPRODUCT] = gd (tbl, "gl_BackLightModelProduct");
330 e[SLANG_COMMON_FIXED_FRONTLIGHTPRODUCT] = gd (tbl, "gl_FrontLightProduct");
331 e[SLANG_COMMON_FIXED_BACKLIGHTPRODUCT] = gd (tbl, "gl_BackLightProduct");
332 e[SLANG_COMMON_FIXED_TEXTUREENVCOLOR] = gd (tbl, "gl_TextureEnvColor");
333 e[SLANG_COMMON_FIXED_EYEPLANES] = gd (tbl, "gl_EyePlaneS");
334 e[SLANG_COMMON_FIXED_EYEPLANET] = gd (tbl, "gl_EyePlaneT");
335 e[SLANG_COMMON_FIXED_EYEPLANER] = gd (tbl, "gl_EyePlaneR");
336 e[SLANG_COMMON_FIXED_EYEPLANEQ] = gd (tbl, "gl_EyePlaneQ");
337 e[SLANG_COMMON_FIXED_OBJECTPLANES] = gd (tbl, "gl_ObjectPlaneS");
338 e[SLANG_COMMON_FIXED_OBJECTPLANET] = gd (tbl, "gl_ObjectPlaneT");
339 e[SLANG_COMMON_FIXED_OBJECTPLANER] = gd (tbl, "gl_ObjectPlaneR");
340 e[SLANG_COMMON_FIXED_OBJECTPLANEQ] = gd (tbl, "gl_ObjectPlaneQ");
341 e[SLANG_COMMON_FIXED_FOG] = gd (tbl, "gl_Fog");
342 }
343
344 static GLvoid resolve_vertex_fixed (GLuint e[], slang_export_data_table *tbl)
345 {
346 e[SLANG_VERTEX_FIXED_POSITION] = gd (tbl, "gl_Position");
347 e[SLANG_VERTEX_FIXED_POINTSIZE] = gd (tbl, "gl_PointSize");
348 e[SLANG_VERTEX_FIXED_CLIPVERTEX] = gd (tbl, "gl_ClipVertex");
349 e[SLANG_VERTEX_FIXED_COLOR] = gd (tbl, "gl_Color");
350 e[SLANG_VERTEX_FIXED_SECONDARYCOLOR] = gd (tbl, "gl_SecondaryColor");
351 e[SLANG_VERTEX_FIXED_NORMAL] = gd (tbl, "gl_Normal");
352 e[SLANG_VERTEX_FIXED_VERTEX] = gd (tbl, "gl_Vertex");
353 e[SLANG_VERTEX_FIXED_MULTITEXCOORD0] = gd (tbl, "gl_MultiTexCoord0");
354 e[SLANG_VERTEX_FIXED_MULTITEXCOORD1] = gd (tbl, "gl_MultiTexCoord1");
355 e[SLANG_VERTEX_FIXED_MULTITEXCOORD2] = gd (tbl, "gl_MultiTexCoord2");
356 e[SLANG_VERTEX_FIXED_MULTITEXCOORD3] = gd (tbl, "gl_MultiTexCoord3");
357 e[SLANG_VERTEX_FIXED_MULTITEXCOORD4] = gd (tbl, "gl_MultiTexCoord4");
358 e[SLANG_VERTEX_FIXED_MULTITEXCOORD5] = gd (tbl, "gl_MultiTexCoord5");
359 e[SLANG_VERTEX_FIXED_MULTITEXCOORD6] = gd (tbl, "gl_MultiTexCoord6");
360 e[SLANG_VERTEX_FIXED_MULTITEXCOORD7] = gd (tbl, "gl_MultiTexCoord7");
361 e[SLANG_VERTEX_FIXED_FOGCOORD] = gd (tbl, "gl_FogCoord");
362 e[SLANG_VERTEX_FIXED_FRONTCOLOR] = gd (tbl, "gl_FrontColor");
363 e[SLANG_VERTEX_FIXED_BACKCOLOR] = gd (tbl, "gl_BackColor");
364 e[SLANG_VERTEX_FIXED_FRONTSECONDARYCOLOR] = gd (tbl, "gl_FrontSecondaryColor");
365 e[SLANG_VERTEX_FIXED_BACKSECONDARYCOLOR] = gd (tbl, "gl_BackSecondaryColor");
366 e[SLANG_VERTEX_FIXED_TEXCOORD] = gd (tbl, "gl_TexCoord");
367 e[SLANG_VERTEX_FIXED_FOGFRAGCOORD] = gd (tbl, "gl_FogFragCoord");
368 }
369
370 static GLvoid resolve_fragment_fixed (GLuint e[], slang_export_data_table *tbl)
371 {
372 e[SLANG_FRAGMENT_FIXED_FRAGCOORD] = gd (tbl, "gl_FragCoord");
373 e[SLANG_FRAGMENT_FIXED_FRONTFACING] = gd (tbl, "gl_FrontFacing");
374 e[SLANG_FRAGMENT_FIXED_FRAGCOLOR] = gd (tbl, "gl_FragColor");
375 e[SLANG_FRAGMENT_FIXED_FRAGDATA] = gd (tbl, "gl_FragData");
376 e[SLANG_FRAGMENT_FIXED_FRAGDEPTH] = gd (tbl, "gl_FragDepth");
377 e[SLANG_FRAGMENT_FIXED_COLOR] = gd (tbl, "gl_Color");
378 e[SLANG_FRAGMENT_FIXED_SECONDARYCOLOR] = gd (tbl, "gl_SecondaryColor");
379 e[SLANG_FRAGMENT_FIXED_TEXCOORD] = gd (tbl, "gl_TexCoord");
380 e[SLANG_FRAGMENT_FIXED_FOGFRAGCOORD] = gd (tbl, "gl_FogFragCoord");
381 }
382
383 static GLuint gc (slang_export_code_table *tbl, const char *name)
384 {
385 slang_atom atom;
386 GLuint i;
387
388 atom = slang_atom_pool_atom (tbl->atoms, name);
389 if (atom == SLANG_ATOM_NULL)
390 return ~0;
391
392 for (i = 0; i < tbl->count; i++)
393 if (atom == tbl->entries[i].name)
394 return tbl->entries[i].address;
395 return ~0;
396 }
397
398 static GLvoid resolve_common_code (GLuint code[], slang_export_code_table *tbl)
399 {
400 code[SLANG_COMMON_CODE_MAIN] = gc (tbl, "@main");
401 }
402
403 GLboolean _slang_link (slang_program *prog, slang_translation_unit **units, GLuint count)
404 {
405 GLuint i;
406
407 for (i = 0; i < count; i++)
408 {
409 GLuint index;
410
411 if (units[i]->type == slang_unit_fragment_shader)
412 {
413 index = SLANG_SHADER_FRAGMENT;
414 resolve_fragment_fixed (prog->fragment_fixed_entries, &units[i]->exp_data);
415 }
416 else
417 {
418 index = SLANG_SHADER_VERTEX;
419 resolve_vertex_fixed (prog->vertex_fixed_entries, &units[i]->exp_data);
420 }
421
422 if (!gather_uniform_bindings (&prog->uniforms, &units[i]->exp_data, index))
423 return GL_FALSE;
424 if (!gather_active_uniforms (&prog->active_uniforms, &units[i]->exp_data))
425 return GL_FALSE;
426 resolve_common_fixed (prog->common_fixed_entries[index], &units[i]->exp_data);
427 resolve_common_code (prog->code[index], &units[i]->exp_code);
428 prog->machines[index] = units[i]->machine;
429 prog->assemblies[index] = units[i]->assembly;
430 }
431
432 if (!_slang_analyse_texture_usage (prog))
433 return GL_FALSE;
434
435 return GL_TRUE;
436 }
437