2 * Mesa 3-D graphics library
5 * Copyright (C) 2005-2007 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.
26 * \file slang_builtin.c
27 * Resolve built-in uniform vars.
33 #include "slang_builtin.h"
34 #include "slang_typeinfo.h"
35 #include "slang_codegen.h"
36 #include "slang_compile.h"
40 #include "prog_instruction.h"
41 #include "prog_parameter.h"
42 #include "prog_statevars.h"
43 #include "slang_print.h"
48 * XXX we might consider moving much of this into the prog_statevars.c file
53 * Determine if 'name' is a state variable (pre-defined uniform).
54 * If so, create a new program parameter for it, and return the
57 * \param swizzleOut returns the swizzle needed to access 'float' values
58 * \return the state value's position in the parameter list, or -1 if error
61 _slang_lookup_statevar(const char *name
, GLint index
,
62 struct gl_program_parameter_list
*paramList
,
67 const GLuint NumRows
; /** for matrices */
69 const GLint Indexes
[STATE_LENGTH
];
71 static const struct state_info state
[] = {
72 { "gl_ModelViewMatrix", 4, SWIZZLE_NOOP
,
73 { STATE_MATRIX
, STATE_MODELVIEW
, 0, 0, 0, 0 } },
74 { "gl_NormalMatrix", 3, SWIZZLE_NOOP
,
75 { STATE_MATRIX
, STATE_MODELVIEW
, 0, 0, 0, 0 } },
76 { "gl_ProjectionMatrix", 4, SWIZZLE_NOOP
,
77 { STATE_MATRIX
, STATE_PROJECTION
, 0, 0, 0, 0 } },
78 { "gl_ModelViewProjectionMatrix", 4, SWIZZLE_NOOP
,
79 { STATE_MATRIX
, STATE_MVP
, 0, 0, 0, 0 } },
80 { "gl_TextureMatrix", 4, SWIZZLE_NOOP
,
81 { STATE_MATRIX
, STATE_TEXTURE
, 0, 0, 0, 0 } },
82 { "gl_NormalScale", 1, SWIZZLE_NOOP
,
83 { STATE_INTERNAL
, STATE_NORMAL_SCALE
, 0, 0, 0, 0} },
85 /* For aggregate/structs we need entries for both the base name
88 { "gl_DepthRange", 1, SWIZZLE_NOOP
,
89 { STATE_DEPTH_RANGE
, 0, 0, 0, 0, 0 } },
90 { "gl_DepthRange.near", 1, SWIZZLE_XXXX
,
91 { STATE_DEPTH_RANGE
, 0, 0, 0, 0, 0 } },
92 { "gl_DepthRange.far", 1, SWIZZLE_YYYY
,
93 { STATE_DEPTH_RANGE
, 0, 0, 0, 0, 0 } },
94 { "gl_DepthRange.diff", 1, SWIZZLE_ZZZZ
,
95 { STATE_DEPTH_RANGE
, 0, 0, 0, 0, 0 } },
97 { "gl_Point", 1, SWIZZLE_NOOP
,
98 { STATE_POINT_SIZE
, 0, 0, 0, 0, 0 } },
99 { "gl_Point.size", 1, SWIZZLE_XXXX
,
100 { STATE_POINT_SIZE
, 0, 0, 0, 0, 0 } },
101 { "gl_Point.sizeMin", 1, SWIZZLE_YYYY
,
102 { STATE_POINT_SIZE
, 0, 0, 0, 0, 0 } },
103 { "gl_Point.sizeMax", 1, SWIZZLE_ZZZZ
,
104 { STATE_POINT_SIZE
, 0, 0, 0, 0, 0 } },
105 { "gl_Point.fadeThresholdSize", 1, SWIZZLE_WWWW
,
106 { STATE_POINT_SIZE
, 0, 0, 0, 0, 0 } },
107 { "gl_Point.distanceConstantAttenuation", 1, SWIZZLE_XXXX
,
108 { STATE_POINT_ATTENUATION
, 0, 0, 0, 0, 0 } },
109 { "gl_Point.distanceLinearAttenuation", 1, SWIZZLE_YYYY
,
110 { STATE_POINT_ATTENUATION
, 0, 0, 0, 0, 0 } },
111 { "gl_Point.distanceQuadraticAttenuation", 1, SWIZZLE_ZZZZ
,
112 { STATE_POINT_ATTENUATION
, 0, 0, 0, 0, 0 } },
114 { "gl_FrontMaterial", 1, SWIZZLE_NOOP
,
115 { STATE_MATERIAL
, 0, STATE_EMISSION
, 0, 0, 0 } },
116 { "gl_FrontMaterial.emission", 1, SWIZZLE_NOOP
,
117 { STATE_MATERIAL
, 0, STATE_EMISSION
, 0, 0, 0 } },
118 { "gl_FrontMaterial.ambient", 1, SWIZZLE_NOOP
,
119 { STATE_MATERIAL
, 0, STATE_AMBIENT
, 0, 0, 0 } },
120 { "gl_FrontMaterial.diffuse", 1, SWIZZLE_NOOP
,
121 { STATE_MATERIAL
, 0, STATE_DIFFUSE
, 0, 0, 0 } },
122 { "gl_FrontMaterial.specular", 1, SWIZZLE_NOOP
,
123 { STATE_MATERIAL
, 0, STATE_SPECULAR
, 0, 0, 0 } },
124 { "gl_FrontMaterial.shininess", 1, SWIZZLE_XXXX
,
125 { STATE_MATERIAL
, 0, STATE_SHININESS
, 0, 0, 0 } },
127 { "gl_BackMaterial", 1, SWIZZLE_NOOP
,
128 { STATE_MATERIAL
, 1, STATE_EMISSION
, 0, 0, 0 } },
129 { "gl_BackMaterial.emission", 1, SWIZZLE_NOOP
,
130 { STATE_MATERIAL
, 1, STATE_EMISSION
, 0, 0, 0 } },
131 { "gl_BackMaterial.ambient", 1, SWIZZLE_NOOP
,
132 { STATE_MATERIAL
, 1, STATE_AMBIENT
, 0, 0, 0 } },
133 { "gl_BackMaterial.diffuse", 1, SWIZZLE_NOOP
,
134 { STATE_MATERIAL
, 1, STATE_DIFFUSE
, 0, 0, 0 } },
135 { "gl_BackMaterial.specular", 1, SWIZZLE_NOOP
,
136 { STATE_MATERIAL
, 1, STATE_SPECULAR
, 0, 0, 0 } },
137 { "gl_BackMaterial.shininess", 1, SWIZZLE_XXXX
,
138 { STATE_MATERIAL
, 1, STATE_SHININESS
, 0, 0, 0 } },
140 { "gl_LightModel", 1, SWIZZLE_NOOP
,
141 { STATE_LIGHTMODEL_AMBIENT
, 0, 0, 0, 0, 0 } },
142 { "gl_LightModel.ambient", 1, SWIZZLE_NOOP
,
143 { STATE_LIGHTMODEL_AMBIENT
, 0, 0, 0, 0, 0 } },
145 { "gl_FrontLightModelProduct", 1, SWIZZLE_NOOP
,
146 { STATE_LIGHTMODEL_SCENECOLOR
, 0, 0, 0, 0, 0 } },
147 { "gl_FrontLightModelProduct.sceneColor", 1, SWIZZLE_NOOP
,
148 { STATE_LIGHTMODEL_SCENECOLOR
, 0, 0, 0, 0, 0 } },
150 { "gl_BackLightModelProduct", 1, SWIZZLE_NOOP
,
151 { STATE_LIGHTMODEL_SCENECOLOR
, 1, 0, 0, 0, 0 } },
152 { "gl_BackLightModelProduct.sceneColor", 1, SWIZZLE_NOOP
,
153 { STATE_LIGHTMODEL_SCENECOLOR
, 1, 0, 0, 0, 0 } },
155 { "gl_FrontLightProduct", 1, SWIZZLE_NOOP
,
156 { STATE_LIGHTPROD
, 0, STATE_AMBIENT
, 0, 0, 0 } },
159 { "gl_Fog", 1, SWIZZLE_NOOP
,
160 { STATE_FOG_COLOR
, 0, 0, 0, 0, 0 } },
161 { "gl_Fog.color", 1, SWIZZLE_NOOP
,
162 { STATE_FOG_COLOR
, 0, 0, 0, 0, 0 } },
163 { "gl_Fog.density", 1, SWIZZLE_XXXX
,
164 { STATE_FOG_PARAMS
, 0, 0, 0, 0, 0 } },
165 { "gl_Fog.start", 1, SWIZZLE_YYYY
,
166 { STATE_FOG_PARAMS
, 0, 0, 0, 0, 0 } },
167 { "gl_Fog.end", 1, SWIZZLE_ZZZZ
,
168 { STATE_FOG_PARAMS
, 0, 0, 0, 0, 0 } },
169 { "gl_Fog.scale", 1, SWIZZLE_WWWW
,
170 { STATE_FOG_PARAMS
, 0, 0, 0, 0, 0 } },
172 { "gl_ClipPlane", 1, SWIZZLE_NOOP
,
173 { STATE_CLIPPLANE
, 0, 0, 0, 0, 0 } },
175 { NULL
, 0, 0, {0, 0, 0, 0, 0, 0} }
179 for (i
= 0; state
[i
].Name
; i
++) {
180 if (strcmp(state
[i
].Name
, name
) == 0) {
182 *swizzleOut
= state
[i
].Swizzle
;
184 if (state
[i
].NumRows
> 1) {
187 GLint pos
[4], indexesCopy
[STATE_LENGTH
];
188 /* make copy of state tokens */
189 for (j
= 0; j
< STATE_LENGTH
; j
++)
190 indexesCopy
[j
] = state
[i
].Indexes
[j
];
192 for (j
= 0; j
< state
[i
].NumRows
; j
++) {
193 indexesCopy
[3] = indexesCopy
[4] = j
; /* jth row of matrix */
194 pos
[j
] = _mesa_add_state_reference(paramList
, indexesCopy
);
200 /* non-matrix state */
202 = _mesa_add_state_reference(paramList
, state
[i
].Indexes
);
214 _slang_lookup_statevar_field(const char *base
, const char *field
,
215 struct gl_program_parameter_list
*paramList
,
219 const GLint len
= _mesa_strlen(base
)
220 + _mesa_strlen(field
) + 2;
221 char *name
= (char *) _mesa_malloc(len
);
226 _mesa_strcpy(name
, base
);
227 /*_mesa_*/strcat(name
, ".");
228 /*_mesa_*/strcat(name
, field
);
229 printf("FULL NAME: %s\n", name
);
231 pos
= _slang_lookup_statevar(name
, 0, paramList
, swizzleOut
);
241 gl_state_index Token
;
246 #define MT_FIELD { NULL, 0, -1, 0 }
248 #define INDEX_POS 1000
250 struct state_uniform_info
{
252 gl_state_index StateTokens
[2];
253 struct field_info Fields
[MAX_FIELDS
];
258 static const struct state_uniform_info Uniforms
[] = {
259 { "gl_ModelViewMatrix", { STATE_MATRIX
, STATE_MODELVIEW
},
260 { MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
}
262 { "gl_ProjectionMatrix", { STATE_MATRIX
, STATE_PROJECTION
},
263 { MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
}
265 { "gl_ModelViewProjectionMatrix", { STATE_MATRIX
, STATE_MVP
},
266 { MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
}
268 { "gl_NormalMatrix", { STATE_MATRIX
, STATE_MODELVIEW
},
269 { MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
}
271 { "gl_TextureMatrix", { STATE_MATRIX
, STATE_TEXTURE
},
272 { MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
}
275 { "gl_ClipPlane", { STATE_CLIPPLANE
, INDEX_POS
},
276 { MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
}
279 { "gl_DepthRange", { STATE_DEPTH_RANGE
, 0 },
281 { "near", 0, -1, SWIZZLE_XXXX
},
282 { "far", 0, -1, SWIZZLE_YYYY
},
283 { "diff", 0, -1, SWIZZLE_ZZZZ
},
289 { "gl_Fog", { 0, 0 },
291 { "color", STATE_FOG_COLOR
, 0, SWIZZLE_NOOP
},
292 { "density", STATE_FOG_PARAMS
, 0, SWIZZLE_XXXX
},
293 { "start", STATE_FOG_PARAMS
, 0, SWIZZLE_YYYY
},
294 { "end", STATE_FOG_PARAMS
, 0, SWIZZLE_ZZZZ
},
295 { "scale", STATE_FOG_PARAMS
, 0, SWIZZLE_WWWW
}
300 { MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
, MT_FIELD
}
306 lookup_statevar(const char *var
, GLint index
, const char *field
,
308 struct gl_program_parameter_list
*paramList
)
310 gl_state_index tokens
[STATE_LENGTH
];
314 for (i
= 0; i
< STATE_LENGTH
; i
++) {
318 for (i
= 0; Uniforms
[i
].Name
; i
++) {
319 if (strcmp(var
, Uniforms
[i
].Name
) == 0) {
320 /* found the uniform */
322 for (j
= 0; j
< 2; j
++) {
323 tokens
[j
] = Uniforms
[i
].StateTokens
[j
];
324 if (tokens
[j
] == INDEX_POS
) {
325 /* replace INDEX_POS with actual array index */
332 /* extra work for var.field */
333 for (j
= 0; j
< MAX_FIELDS
; j
++) {
334 if (!Uniforms
[i
].Fields
[j
].Name
) {
335 /* field not found! */
336 _mesa_problem(NULL
, "field not found");
339 else if (strcmp(field
, Uniforms
[i
].Fields
[j
].Name
) == 0) {
340 /* found the field */
341 GLint tokenPos
= Uniforms
[i
].Fields
[j
].TokenPos
;
343 tokens
[tokenPos
] = Uniforms
[i
].Fields
[j
].Token
;
345 *swizzleOut
= Uniforms
[i
].Fields
[j
].Swizzle
;
352 if (tokens
[0] == STATE_MATRIX
) {
356 gl_state_index indexesCopy
[STATE_LENGTH
];
357 /* make copy of state tokens */
358 for (j
= 0; j
< STATE_LENGTH
; j
++)
359 indexesCopy
[j
] = tokens
[j
];
361 for (j
= 0; j
< 4/*state[i].NumRows*/; j
++) {
362 indexesCopy
[3] = indexesCopy
[4] = j
; /* jth row of matrix */
363 pos
[j
] = _mesa_add_state_reference(paramList
, (GLint
*) indexesCopy
);
366 return pos
[0] + index
;
369 pos
= _mesa_add_state_reference(paramList
, (GLint
*) tokens
);
380 * Allocate storage for a pre-defined uniform (a GL state variable).
381 * As a memory-saving optimization, we try to only allocate storage for
382 * state vars that are actually used.
383 * For example, the "gl_LightSource" uniform is huge. If we only use
384 * a handful of gl_LightSource fields, we don't want to allocate storage
385 * for all of gl_LightSource.
387 * Currently, all pre-defined uniforms are in one of these forms:
394 _slang_alloc_statevar(slang_ir_node
*n
,
395 struct gl_program_parameter_list
*paramList
)
397 const char *field
= NULL
, *var
;
398 GLint index
= -1, pos
;
401 if (n
->Opcode
== IR_FIELD
) {
406 if (n
->Opcode
== IR_ELEMENT
) {
407 /* XXX can only handle constant indexes for now */
408 assert(n
->Children
[1]->Opcode
== IR_FLOAT
);
409 index
= (GLint
) n
->Children
[1]->Value
[0];
413 assert(n
->Opcode
== IR_VAR
);
414 var
= (char *) n
->Var
->a_name
;
416 pos
= lookup_statevar(var
, index
, field
, &swizzle
, paramList
);
419 n
->Store
->Index
= pos
;
420 n
->Store
->Swizzle
= swizzle
;