2 * Mesa 3-D graphics library
5 * Copyright (C) 2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
32 #include "slang_link.h"
33 #include "slang_analyse.h"
36 * slang_uniform_bindings
39 static GLvoid
slang_uniform_bindings_ctr (slang_uniform_bindings
*self
)
45 static GLvoid
slang_uniform_bindings_dtr (slang_uniform_bindings
*self
)
49 for (i
= 0; i
< self
->count
; i
++)
50 slang_alloc_free (self
->table
[i
].name
);
51 slang_alloc_free (self
->table
);
54 static GLboolean
slang_uniform_bindings_add (slang_uniform_bindings
*self
, slang_export_data_quant
*q
,
55 const char *name
, GLuint index
, GLuint address
)
57 const GLuint n
= self
->count
;
60 for (i
= 0; i
< n
; i
++)
61 if (slang_string_compare (self
->table
[i
].name
, name
) == 0)
63 self
->table
[i
].address
[index
] = address
;
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
)
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
)
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
)
87 slang_string_concat (name
, slang_atom_pool_id (atoms
, q
->name
));
89 if (q
->array_len
== 0)
94 for (i
= 0; i
< count
; i
++)
98 save
= slang_string_length (name
);
99 if (q
->array_len
!= 0)
100 _mesa_sprintf (name
+ slang_string_length (name
), "[%d]", i
);
102 if (q
->structure
!= NULL
)
106 slang_string_concat (name
, ".");
107 save
= slang_string_length (name
);
109 for (i
= 0; i
< q
->u
.field_count
; i
++)
111 if (!insert_binding (bind
, &q
->structure
[i
], name
, atoms
, index
, addr
))
114 addr
+= q
->structure
[i
].size
;
119 if (!slang_uniform_bindings_add (bind
, q
, name
, index
, addr
))
129 static GLboolean
gather_uniform_bindings (slang_uniform_bindings
*bind
, slang_export_data_table
*tbl
,
134 for (i
= 0; i
< tbl
->count
; i
++)
135 if (tbl
->entries
[i
].access
== slang_exp_uniform
)
137 char name
[1024] = "";
139 if (!insert_binding (bind
, &tbl
->entries
[i
].quant
, name
, tbl
->atoms
, index
,
140 tbl
->entries
[i
].address
))
148 * slang_active_uniforms
151 static GLvoid
slang_active_uniforms_ctr (slang_active_uniforms
*self
)
157 static GLvoid
slang_active_uniforms_dtr (slang_active_uniforms
*self
)
161 for (i
= 0; i
< self
->count
; i
++)
162 slang_alloc_free (self
->table
[i
].name
);
163 slang_alloc_free (self
->table
);
166 static GLboolean
slang_active_uniforms_add (slang_active_uniforms
*self
, slang_export_data_quant
*q
,
169 const GLuint n
= self
->count
;
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
)
175 self
->table
[n
].quant
= q
;
176 self
->table
[n
].name
= slang_string_duplicate (name
);
177 if (self
->table
[n
].name
== NULL
)
183 static GLboolean
insert_uniform (slang_active_uniforms
*u
, slang_export_data_quant
*q
, char *name
,
184 slang_atom_pool
*atoms
)
186 slang_string_concat (name
, slang_atom_pool_id (atoms
, q
->name
));
187 if (q
->array_len
!= 0)
188 slang_string_concat (name
, "[0]");
190 if (q
->structure
!= NULL
)
194 slang_string_concat (name
, ".");
195 save
= slang_string_length (name
);
197 for (i
= 0; i
< q
->u
.field_count
; i
++)
199 if (!insert_uniform (u
, &q
->structure
[i
], name
, atoms
))
207 return slang_active_uniforms_add (u
, q
, name
);
210 static GLboolean
gather_active_uniforms (slang_active_uniforms
*u
, slang_export_data_table
*tbl
)
214 for (i
= 0; i
< tbl
->count
; i
++)
215 if (tbl
->entries
[i
].access
== slang_exp_uniform
)
217 char name
[1024] = "";
219 if (!insert_uniform (u
, &tbl
->entries
[i
].quant
, name
, tbl
->atoms
))
227 * slang_texture_bindings
230 GLvoid
slang_texture_usages_ctr (slang_texture_usages
*self
)
236 GLvoid
slang_texture_usages_dtr (slang_texture_usages
*self
)
238 slang_alloc_free (self
->table
);
245 GLvoid
slang_program_ctr (slang_program
*self
)
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
++)
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
;
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;
269 GLvoid
slang_program_dtr (slang_program
*self
)
271 slang_uniform_bindings_dtr (&self
->uniforms
);
272 slang_active_uniforms_dtr (&self
->active_uniforms
);
273 slang_texture_usages_dtr (&self
->texture_usage
);
280 static GLuint
gd (slang_export_data_table
*tbl
, const char *name
)
285 atom
= slang_atom_pool_atom (tbl
->atoms
, name
);
286 if (atom
== SLANG_ATOM_NULL
)
289 for (i
= 0; i
< tbl
->count
; i
++)
290 if (atom
== tbl
->entries
[i
].quant
.name
)
291 return tbl
->entries
[i
].address
;
295 static GLvoid
resolve_common_fixed (GLuint e
[], slang_export_data_table
*tbl
)
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");
344 static GLvoid
resolve_vertex_fixed (GLuint e
[], slang_export_data_table
*tbl
)
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");
370 static GLvoid
resolve_fragment_fixed (GLuint e
[], slang_export_data_table
*tbl
)
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");
383 static GLuint
gc (slang_export_code_table
*tbl
, const char *name
)
388 atom
= slang_atom_pool_atom (tbl
->atoms
, name
);
389 if (atom
== SLANG_ATOM_NULL
)
392 for (i
= 0; i
< tbl
->count
; i
++)
393 if (atom
== tbl
->entries
[i
].name
)
394 return tbl
->entries
[i
].address
;
398 static GLvoid
resolve_common_code (GLuint code
[], slang_export_code_table
*tbl
)
400 code
[SLANG_COMMON_CODE_MAIN
] = gc (tbl
, "@main");
403 GLboolean
_slang_link (slang_program
*prog
, slang_translation_unit
**units
, GLuint count
)
407 for (i
= 0; i
< count
; i
++)
411 if (units
[i
]->type
== slang_unit_fragment_shader
)
413 index
= SLANG_SHADER_FRAGMENT
;
414 resolve_fragment_fixed (prog
->fragment_fixed_entries
, &units
[i
]->exp_data
);
418 index
= SLANG_SHADER_VERTEX
;
419 resolve_vertex_fixed (prog
->vertex_fixed_entries
, &units
[i
]->exp_data
);
422 if (!gather_uniform_bindings (&prog
->uniforms
, &units
[i
]->exp_data
, index
))
424 if (!gather_active_uniforms (&prog
->active_uniforms
, &units
[i
]->exp_data
))
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
;
432 if (!_slang_analyse_texture_usage (prog
))