Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * Version: 7.1 |
||
4 | * |
||
5 | * Copyright (C) 1999-2007 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 prog_statevars.c |
||
27 | * Program state variable management. |
||
28 | * \author Brian Paul |
||
29 | */ |
||
30 | |||
31 | |||
32 | #include "main/glheader.h" |
||
33 | #include "main/context.h" |
||
34 | #include "main/imports.h" |
||
35 | #include "main/macros.h" |
||
36 | #include "main/mtypes.h" |
||
37 | #include "prog_statevars.h" |
||
38 | #include "prog_parameter.h" |
||
39 | |||
40 | |||
41 | /** |
||
42 | * Use the list of tokens in the state[] array to find global GL state |
||
43 | * and return it in |
||
44 | * but matrix queries may return as many as 16 values. |
||
45 | * This function is used for ARB vertex/fragment programs. |
||
46 | * The program parser will produce the state[] values. |
||
47 | */ |
||
48 | static void |
||
49 | _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[], |
||
50 | GLfloat *value) |
||
51 | { |
||
52 | switch (state[0]) { |
||
53 | case STATE_MATERIAL: |
||
54 | { |
||
55 | /* state[1] is either 0=front or 1=back side */ |
||
56 | const GLuint face = (GLuint) state[1]; |
||
57 | const struct gl_material *mat = &ctx->Light.Material; |
||
58 | ASSERT(face == 0 || face == 1); |
||
59 | /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */ |
||
60 | ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT); |
||
61 | /* XXX we could get rid of this switch entirely with a little |
||
62 | * work in arbprogparse.c's parse_state_single_item(). |
||
63 | */ |
||
64 | /* state[2] is the material attribute */ |
||
65 | switch (state[2]) { |
||
66 | case STATE_AMBIENT: |
||
67 | COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]); |
||
68 | return; |
||
69 | case STATE_DIFFUSE: |
||
70 | COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]); |
||
71 | return; |
||
72 | case STATE_SPECULAR: |
||
73 | COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]); |
||
74 | return; |
||
75 | case STATE_EMISSION: |
||
76 | COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]); |
||
77 | return; |
||
78 | case STATE_SHININESS: |
||
79 | value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0]; |
||
80 | value[1] = 0.0F; |
||
81 | value[2] = 0.0F; |
||
82 | value[3] = 1.0F; |
||
83 | return; |
||
84 | default: |
||
85 | _mesa_problem(ctx, "Invalid material state in fetch_state"); |
||
86 | return; |
||
87 | } |
||
88 | } |
||
89 | case STATE_LIGHT: |
||
90 | { |
||
91 | /* state[1] is the light number */ |
||
92 | const GLuint ln = (GLuint) state[1]; |
||
93 | /* state[2] is the light attribute */ |
||
94 | switch (state[2]) { |
||
95 | case STATE_AMBIENT: |
||
96 | COPY_4V(value, ctx->Light.Light[ln].Ambient); |
||
97 | return; |
||
98 | case STATE_DIFFUSE: |
||
99 | COPY_4V(value, ctx->Light.Light[ln].Diffuse); |
||
100 | return; |
||
101 | case STATE_SPECULAR: |
||
102 | COPY_4V(value, ctx->Light.Light[ln].Specular); |
||
103 | return; |
||
104 | case STATE_POSITION: |
||
105 | COPY_4V(value, ctx->Light.Light[ln].EyePosition); |
||
106 | return; |
||
107 | case STATE_ATTENUATION: |
||
108 | value[0] = ctx->Light.Light[ln].ConstantAttenuation; |
||
109 | value[1] = ctx->Light.Light[ln].LinearAttenuation; |
||
110 | value[2] = ctx->Light.Light[ln].QuadraticAttenuation; |
||
111 | value[3] = ctx->Light.Light[ln].SpotExponent; |
||
112 | return; |
||
113 | case STATE_SPOT_DIRECTION: |
||
114 | COPY_3V(value, ctx->Light.Light[ln].SpotDirection); |
||
115 | value[3] = ctx->Light.Light[ln]._CosCutoff; |
||
116 | return; |
||
117 | case STATE_SPOT_CUTOFF: |
||
118 | value[0] = ctx->Light.Light[ln].SpotCutoff; |
||
119 | return; |
||
120 | case STATE_HALF_VECTOR: |
||
121 | { |
||
122 | static const GLfloat eye_z[] = {0, 0, 1}; |
||
123 | GLfloat p[3]; |
||
124 | /* Compute infinite half angle vector: |
||
125 | * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) |
||
126 | * light.EyePosition.w should be 0 for infinite lights. |
||
127 | */ |
||
128 | COPY_3V(p, ctx->Light.Light[ln].EyePosition); |
||
129 | NORMALIZE_3FV(p); |
||
130 | ADD_3V(value, p, eye_z); |
||
131 | NORMALIZE_3FV(value); |
||
132 | value[3] = 1.0; |
||
133 | } |
||
134 | return; |
||
135 | default: |
||
136 | _mesa_problem(ctx, "Invalid light state in fetch_state"); |
||
137 | return; |
||
138 | } |
||
139 | } |
||
140 | case STATE_LIGHTMODEL_AMBIENT: |
||
141 | COPY_4V(value, ctx->Light.Model.Ambient); |
||
142 | return; |
||
143 | case STATE_LIGHTMODEL_SCENECOLOR: |
||
144 | if (state[1] == 0) { |
||
145 | /* front */ |
||
146 | GLint i; |
||
147 | for (i = 0; i < 3; i++) { |
||
148 | value[i] = ctx->Light.Model.Ambient[i] |
||
149 | * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] |
||
150 | + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; |
||
151 | } |
||
152 | value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; |
||
153 | } |
||
154 | else { |
||
155 | /* back */ |
||
156 | GLint i; |
||
157 | for (i = 0; i < 3; i++) { |
||
158 | value[i] = ctx->Light.Model.Ambient[i] |
||
159 | * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] |
||
160 | + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; |
||
161 | } |
||
162 | value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; |
||
163 | } |
||
164 | return; |
||
165 | case STATE_LIGHTPROD: |
||
166 | { |
||
167 | const GLuint ln = (GLuint) state[1]; |
||
168 | const GLuint face = (GLuint) state[2]; |
||
169 | GLint i; |
||
170 | ASSERT(face == 0 || face == 1); |
||
171 | switch (state[3]) { |
||
172 | case STATE_AMBIENT: |
||
173 | for (i = 0; i < 3; i++) { |
||
174 | value[i] = ctx->Light.Light[ln].Ambient[i] * |
||
175 | ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i]; |
||
176 | } |
||
177 | /* [3] = material alpha */ |
||
178 | value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3]; |
||
179 | return; |
||
180 | case STATE_DIFFUSE: |
||
181 | for (i = 0; i < 3; i++) { |
||
182 | value[i] = ctx->Light.Light[ln].Diffuse[i] * |
||
183 | ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i]; |
||
184 | } |
||
185 | /* [3] = material alpha */ |
||
186 | value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; |
||
187 | return; |
||
188 | case STATE_SPECULAR: |
||
189 | for (i = 0; i < 3; i++) { |
||
190 | value[i] = ctx->Light.Light[ln].Specular[i] * |
||
191 | ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i]; |
||
192 | } |
||
193 | /* [3] = material alpha */ |
||
194 | value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3]; |
||
195 | return; |
||
196 | default: |
||
197 | _mesa_problem(ctx, "Invalid lightprod state in fetch_state"); |
||
198 | return; |
||
199 | } |
||
200 | } |
||
201 | case STATE_TEXGEN: |
||
202 | { |
||
203 | /* state[1] is the texture unit */ |
||
204 | const GLuint unit = (GLuint) state[1]; |
||
205 | /* state[2] is the texgen attribute */ |
||
206 | switch (state[2]) { |
||
207 | case STATE_TEXGEN_EYE_S: |
||
208 | COPY_4V(value, ctx->Texture.Unit[unit].GenS.EyePlane); |
||
209 | return; |
||
210 | case STATE_TEXGEN_EYE_T: |
||
211 | COPY_4V(value, ctx->Texture.Unit[unit].GenT.EyePlane); |
||
212 | return; |
||
213 | case STATE_TEXGEN_EYE_R: |
||
214 | COPY_4V(value, ctx->Texture.Unit[unit].GenR.EyePlane); |
||
215 | return; |
||
216 | case STATE_TEXGEN_EYE_Q: |
||
217 | COPY_4V(value, ctx->Texture.Unit[unit].GenQ.EyePlane); |
||
218 | return; |
||
219 | case STATE_TEXGEN_OBJECT_S: |
||
220 | COPY_4V(value, ctx->Texture.Unit[unit].GenS.ObjectPlane); |
||
221 | return; |
||
222 | case STATE_TEXGEN_OBJECT_T: |
||
223 | COPY_4V(value, ctx->Texture.Unit[unit].GenT.ObjectPlane); |
||
224 | return; |
||
225 | case STATE_TEXGEN_OBJECT_R: |
||
226 | COPY_4V(value, ctx->Texture.Unit[unit].GenR.ObjectPlane); |
||
227 | return; |
||
228 | case STATE_TEXGEN_OBJECT_Q: |
||
229 | COPY_4V(value, ctx->Texture.Unit[unit].GenQ.ObjectPlane); |
||
230 | return; |
||
231 | default: |
||
232 | _mesa_problem(ctx, "Invalid texgen state in fetch_state"); |
||
233 | return; |
||
234 | } |
||
235 | } |
||
236 | case STATE_TEXENV_COLOR: |
||
237 | { |
||
238 | /* state[1] is the texture unit */ |
||
239 | const GLuint unit = (GLuint) state[1]; |
||
240 | COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); |
||
241 | } |
||
242 | return; |
||
243 | case STATE_FOG_COLOR: |
||
244 | COPY_4V(value, ctx->Fog.Color); |
||
245 | return; |
||
246 | case STATE_FOG_PARAMS: |
||
247 | value[0] = ctx->Fog.Density; |
||
248 | value[1] = ctx->Fog.Start; |
||
249 | value[2] = ctx->Fog.End; |
||
250 | value[3] = (ctx->Fog.End == ctx->Fog.Start) |
||
251 | ? 1.0f : (GLfloat)(1.0 / (ctx->Fog.End - ctx->Fog.Start)); |
||
252 | return; |
||
253 | case STATE_CLIPPLANE: |
||
254 | { |
||
255 | const GLuint plane = (GLuint) state[1]; |
||
256 | COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); |
||
257 | } |
||
258 | return; |
||
259 | case STATE_POINT_SIZE: |
||
260 | value[0] = ctx->Point.Size; |
||
261 | value[1] = ctx->Point.MinSize; |
||
262 | value[2] = ctx->Point.MaxSize; |
||
263 | value[3] = ctx->Point.Threshold; |
||
264 | return; |
||
265 | case STATE_POINT_ATTENUATION: |
||
266 | value[0] = ctx->Point.Params[0]; |
||
267 | value[1] = ctx->Point.Params[1]; |
||
268 | value[2] = ctx->Point.Params[2]; |
||
269 | value[3] = 1.0F; |
||
270 | return; |
||
271 | case STATE_MODELVIEW_MATRIX: |
||
272 | case STATE_PROJECTION_MATRIX: |
||
273 | case STATE_MVP_MATRIX: |
||
274 | case STATE_TEXTURE_MATRIX: |
||
275 | case STATE_PROGRAM_MATRIX: |
||
276 | { |
||
277 | /* state[0] = modelview, projection, texture, etc. */ |
||
278 | /* state[1] = which texture matrix or program matrix */ |
||
279 | /* state[2] = first row to fetch */ |
||
280 | /* state[3] = last row to fetch */ |
||
281 | /* state[4] = transpose, inverse or invtrans */ |
||
282 | const GLmatrix *matrix; |
||
283 | const gl_state_index mat = state[0]; |
||
284 | const GLuint index = (GLuint) state[1]; |
||
285 | const GLuint firstRow = (GLuint) state[2]; |
||
286 | const GLuint lastRow = (GLuint) state[3]; |
||
287 | const gl_state_index modifier = state[4]; |
||
288 | const GLfloat *m; |
||
289 | GLuint row, i; |
||
290 | ASSERT(firstRow >= 0); |
||
291 | ASSERT(firstRow < 4); |
||
292 | ASSERT(lastRow >= 0); |
||
293 | ASSERT(lastRow < 4); |
||
294 | if (mat == STATE_MODELVIEW_MATRIX) { |
||
295 | matrix = ctx->ModelviewMatrixStack.Top; |
||
296 | } |
||
297 | else if (mat == STATE_PROJECTION_MATRIX) { |
||
298 | matrix = ctx->ProjectionMatrixStack.Top; |
||
299 | } |
||
300 | else if (mat == STATE_MVP_MATRIX) { |
||
301 | matrix = &ctx->_ModelProjectMatrix; |
||
302 | } |
||
303 | else if (mat == STATE_TEXTURE_MATRIX) { |
||
304 | ASSERT(index < Elements(ctx->TextureMatrixStack)); |
||
305 | matrix = ctx->TextureMatrixStack[index].Top; |
||
306 | } |
||
307 | else if (mat == STATE_PROGRAM_MATRIX) { |
||
308 | ASSERT(index < Elements(ctx->ProgramMatrixStack)); |
||
309 | matrix = ctx->ProgramMatrixStack[index].Top; |
||
310 | } |
||
311 | else { |
||
312 | _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()"); |
||
313 | return; |
||
314 | } |
||
315 | if (modifier == STATE_MATRIX_INVERSE || |
||
316 | modifier == STATE_MATRIX_INVTRANS) { |
||
317 | /* Be sure inverse is up to date: |
||
318 | */ |
||
319 | _math_matrix_alloc_inv( (GLmatrix *) matrix ); |
||
320 | _math_matrix_analyse( (GLmatrix*) matrix ); |
||
321 | m = matrix->inv; |
||
322 | } |
||
323 | else { |
||
324 | m = matrix->m; |
||
325 | } |
||
326 | if (modifier == STATE_MATRIX_TRANSPOSE || |
||
327 | modifier == STATE_MATRIX_INVTRANS) { |
||
328 | for (i = 0, row = firstRow; row <= lastRow; row++) { |
||
329 | value[i++] = m[row * 4 + 0]; |
||
330 | value[i++] = m[row * 4 + 1]; |
||
331 | value[i++] = m[row * 4 + 2]; |
||
332 | value[i++] = m[row * 4 + 3]; |
||
333 | } |
||
334 | } |
||
335 | else { |
||
336 | for (i = 0, row = firstRow; row <= lastRow; row++) { |
||
337 | value[i++] = m[row + 0]; |
||
338 | value[i++] = m[row + 4]; |
||
339 | value[i++] = m[row + 8]; |
||
340 | value[i++] = m[row + 12]; |
||
341 | } |
||
342 | } |
||
343 | } |
||
344 | return; |
||
345 | case STATE_DEPTH_RANGE: |
||
346 | value[0] = ctx->Viewport.Near; /* near */ |
||
347 | value[1] = ctx->Viewport.Far; /* far */ |
||
348 | value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */ |
||
349 | value[3] = 1.0; |
||
350 | return; |
||
351 | case STATE_FRAGMENT_PROGRAM: |
||
352 | { |
||
353 | /* state[1] = {STATE_ENV, STATE_LOCAL} */ |
||
354 | /* state[2] = parameter index */ |
||
355 | const int idx = (int) state[2]; |
||
356 | switch (state[1]) { |
||
357 | case STATE_ENV: |
||
358 | COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); |
||
359 | return; |
||
360 | case STATE_LOCAL: |
||
361 | COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]); |
||
362 | return; |
||
363 | default: |
||
364 | _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); |
||
365 | return; |
||
366 | } |
||
367 | } |
||
368 | return; |
||
369 | |||
370 | case STATE_VERTEX_PROGRAM: |
||
371 | { |
||
372 | /* state[1] = {STATE_ENV, STATE_LOCAL} */ |
||
373 | /* state[2] = parameter index */ |
||
374 | const int idx = (int) state[2]; |
||
375 | switch (state[1]) { |
||
376 | case STATE_ENV: |
||
377 | COPY_4V(value, ctx->VertexProgram.Parameters[idx]); |
||
378 | return; |
||
379 | case STATE_LOCAL: |
||
380 | COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]); |
||
381 | return; |
||
382 | default: |
||
383 | _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); |
||
384 | return; |
||
385 | } |
||
386 | } |
||
387 | return; |
||
388 | |||
389 | case STATE_NORMAL_SCALE: |
||
390 | ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1); |
||
391 | return; |
||
392 | |||
393 | case STATE_INTERNAL: |
||
394 | switch (state[1]) { |
||
395 | case STATE_CURRENT_ATTRIB: |
||
396 | { |
||
397 | const GLuint idx = (GLuint) state[2]; |
||
398 | COPY_4V(value, ctx->Current.Attrib[idx]); |
||
399 | } |
||
400 | return; |
||
401 | |||
402 | case STATE_NORMAL_SCALE: |
||
403 | ASSIGN_4V(value, |
||
404 | ctx->_ModelViewInvScale, |
||
405 | ctx->_ModelViewInvScale, |
||
406 | ctx->_ModelViewInvScale, |
||
407 | 1); |
||
408 | return; |
||
409 | |||
410 | case STATE_TEXRECT_SCALE: |
||
411 | /* Value = { 1/texWidth, 1/texHeight, 0, 1 }. |
||
412 | * Used to convert unnormalized texcoords to normalized texcoords. |
||
413 | */ |
||
414 | { |
||
415 | const int unit = (int) state[2]; |
||
416 | const struct gl_texture_object *texObj |
||
417 | = ctx->Texture.Unit[unit]._Current; |
||
418 | if (texObj) { |
||
419 | struct gl_texture_image *texImage = texObj->Image[0][0]; |
||
420 | ASSIGN_4V(value, |
||
421 | (GLfloat) (1.0 / texImage->Width), |
||
422 | (GLfloat) (1.0 / texImage->Height), |
||
423 | 0.0f, 1.0f); |
||
424 | } |
||
425 | } |
||
426 | return; |
||
427 | |||
428 | case STATE_FOG_PARAMS_OPTIMIZED: |
||
429 | /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog) |
||
430 | * might be more expensive than EX2 on some hw, plus it needs |
||
431 | * another constant (e) anyway. Linear fog can now be done with a |
||
432 | * single MAD. |
||
433 | * linear: fogcoord * -1/(end-start) + end/(end-start) |
||
434 | * exp: 2^-(density/ln(2) * fogcoord) |
||
435 | * exp2: 2^-((density/(ln(2)^2) * fogcoord)^2) |
||
436 | */ |
||
437 | value[0] = (ctx->Fog.End == ctx->Fog.Start) |
||
438 | ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start)); |
||
439 | value[1] = ctx->Fog.End * -value[0]; |
||
440 | value[2] = (GLfloat)(ctx->Fog.Density * ONE_DIV_LN2); |
||
441 | value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2); |
||
442 | return; |
||
443 | |||
444 | case STATE_POINT_SIZE_CLAMPED: |
||
445 | { |
||
446 | /* this includes implementation dependent limits, to avoid |
||
447 | * another potentially necessary clamp. |
||
448 | * Note: for sprites, point smooth (point AA) is ignored |
||
449 | * and we'll clamp to MinPointSizeAA and MaxPointSize, because we |
||
450 | * expect drivers will want to say their minimum for AA size is 0.0 |
||
451 | * but for non-AA it's 1.0 (because normal points with size below 1.0 |
||
452 | * need to get rounded up to 1.0, hence never disappear). GL does |
||
453 | * not specify max clamp size for sprites, other than it needs to be |
||
454 | * at least as large as max AA size, hence use non-AA size there. |
||
455 | */ |
||
456 | GLfloat minImplSize; |
||
457 | GLfloat maxImplSize; |
||
458 | if (ctx->Point.PointSprite) { |
||
459 | minImplSize = ctx->Const.MinPointSizeAA; |
||
460 | maxImplSize = ctx->Const.MaxPointSize; |
||
461 | } |
||
462 | else if (ctx->Point.SmoothFlag || ctx->Multisample._Enabled) { |
||
463 | minImplSize = ctx->Const.MinPointSizeAA; |
||
464 | maxImplSize = ctx->Const.MaxPointSizeAA; |
||
465 | } |
||
466 | else { |
||
467 | minImplSize = ctx->Const.MinPointSize; |
||
468 | maxImplSize = ctx->Const.MaxPointSize; |
||
469 | } |
||
470 | value[0] = ctx->Point.Size; |
||
471 | value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize; |
||
472 | value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize; |
||
473 | value[3] = ctx->Point.Threshold; |
||
474 | } |
||
475 | return; |
||
476 | case STATE_POINT_SIZE_IMPL_CLAMP: |
||
477 | { |
||
478 | /* for implementation clamp only in vs */ |
||
479 | GLfloat minImplSize; |
||
480 | GLfloat maxImplSize; |
||
481 | if (ctx->Point.PointSprite) { |
||
482 | minImplSize = ctx->Const.MinPointSizeAA; |
||
483 | maxImplSize = ctx->Const.MaxPointSize; |
||
484 | } |
||
485 | else if (ctx->Point.SmoothFlag || ctx->Multisample._Enabled) { |
||
486 | minImplSize = ctx->Const.MinPointSizeAA; |
||
487 | maxImplSize = ctx->Const.MaxPointSizeAA; |
||
488 | } |
||
489 | else { |
||
490 | minImplSize = ctx->Const.MinPointSize; |
||
491 | maxImplSize = ctx->Const.MaxPointSize; |
||
492 | } |
||
493 | value[0] = ctx->Point.Size; |
||
494 | value[1] = minImplSize; |
||
495 | value[2] = maxImplSize; |
||
496 | value[3] = ctx->Point.Threshold; |
||
497 | } |
||
498 | return; |
||
499 | case STATE_LIGHT_SPOT_DIR_NORMALIZED: |
||
500 | { |
||
501 | /* here, state[2] is the light number */ |
||
502 | /* pre-normalize spot dir */ |
||
503 | const GLuint ln = (GLuint) state[2]; |
||
504 | COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection); |
||
505 | value[3] = ctx->Light.Light[ln]._CosCutoff; |
||
506 | } |
||
507 | return; |
||
508 | |||
509 | case STATE_LIGHT_POSITION: |
||
510 | { |
||
511 | const GLuint ln = (GLuint) state[2]; |
||
512 | COPY_4V(value, ctx->Light.Light[ln]._Position); |
||
513 | } |
||
514 | return; |
||
515 | |||
516 | case STATE_LIGHT_POSITION_NORMALIZED: |
||
517 | { |
||
518 | const GLuint ln = (GLuint) state[2]; |
||
519 | COPY_4V(value, ctx->Light.Light[ln]._Position); |
||
520 | NORMALIZE_3FV( value ); |
||
521 | } |
||
522 | return; |
||
523 | |||
524 | case STATE_LIGHT_HALF_VECTOR: |
||
525 | { |
||
526 | const GLuint ln = (GLuint) state[2]; |
||
527 | GLfloat p[3]; |
||
528 | /* Compute infinite half angle vector: |
||
529 | * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) |
||
530 | * light.EyePosition.w should be 0 for infinite lights. |
||
531 | */ |
||
532 | COPY_3V(p, ctx->Light.Light[ln]._Position); |
||
533 | NORMALIZE_3FV(p); |
||
534 | ADD_3V(value, p, ctx->_EyeZDir); |
||
535 | NORMALIZE_3FV(value); |
||
536 | value[3] = 1.0; |
||
537 | } |
||
538 | return; |
||
539 | |||
540 | case STATE_PT_SCALE: |
||
541 | value[0] = ctx->Pixel.RedScale; |
||
542 | value[1] = ctx->Pixel.GreenScale; |
||
543 | value[2] = ctx->Pixel.BlueScale; |
||
544 | value[3] = ctx->Pixel.AlphaScale; |
||
545 | return; |
||
546 | |||
547 | case STATE_PT_BIAS: |
||
548 | value[0] = ctx->Pixel.RedBias; |
||
549 | value[1] = ctx->Pixel.GreenBias; |
||
550 | value[2] = ctx->Pixel.BlueBias; |
||
551 | value[3] = ctx->Pixel.AlphaBias; |
||
552 | return; |
||
553 | |||
554 | case STATE_SHADOW_AMBIENT: |
||
555 | { |
||
556 | const int unit = (int) state[2]; |
||
557 | const struct gl_texture_object *texObj |
||
558 | = ctx->Texture.Unit[unit]._Current; |
||
559 | if (texObj) { |
||
560 | value[0] = |
||
561 | value[1] = |
||
562 | value[2] = |
||
563 | value[3] = texObj->CompareFailValue; |
||
564 | } |
||
565 | } |
||
566 | return; |
||
567 | |||
568 | case STATE_FB_SIZE: |
||
569 | value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1); |
||
570 | value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); |
||
571 | value[2] = 0.0F; |
||
572 | value[3] = 0.0F; |
||
573 | return; |
||
574 | |||
575 | case STATE_FB_WPOS_Y_TRANSFORM: |
||
576 | /* A driver may negate this conditional by using ZW swizzle |
||
577 | * instead of XY (based on e.g. some other state). */ |
||
578 | if (ctx->DrawBuffer->Name != 0) { |
||
579 | /* Identity (XY) followed by flipping Y upside down (ZW). */ |
||
580 | value[0] = 1.0F; |
||
581 | value[1] = 0.0F; |
||
582 | value[2] = -1.0F; |
||
583 | value[3] = (GLfloat) (ctx->DrawBuffer->Height - 1); |
||
584 | } else { |
||
585 | /* Flipping Y upside down (XY) followed by identity (ZW). */ |
||
586 | value[0] = -1.0F; |
||
587 | value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); |
||
588 | value[2] = 1.0F; |
||
589 | value[3] = 0.0F; |
||
590 | } |
||
591 | return; |
||
592 | |||
593 | case STATE_ROT_MATRIX_0: |
||
594 | { |
||
595 | const int unit = (int) state[2]; |
||
596 | GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix; |
||
597 | value[0] = rotMat22[0]; |
||
598 | value[1] = rotMat22[2]; |
||
599 | value[2] = 0.0; |
||
600 | value[3] = 0.0; |
||
601 | } |
||
602 | return; |
||
603 | |||
604 | case STATE_ROT_MATRIX_1: |
||
605 | { |
||
606 | const int unit = (int) state[2]; |
||
607 | GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix; |
||
608 | value[0] = rotMat22[1]; |
||
609 | value[1] = rotMat22[3]; |
||
610 | value[2] = 0.0; |
||
611 | value[3] = 0.0; |
||
612 | } |
||
613 | return; |
||
614 | |||
615 | /* XXX: make sure new tokens added here are also handled in the |
||
616 | * _mesa_program_state_flags() switch, below. |
||
617 | */ |
||
618 | default: |
||
619 | /* Unknown state indexes are silently ignored here. |
||
620 | * Drivers may do something special. |
||
621 | */ |
||
622 | return; |
||
623 | } |
||
624 | return; |
||
625 | |||
626 | default: |
||
627 | _mesa_problem(ctx, "Invalid state in _mesa_fetch_state"); |
||
628 | return; |
||
629 | } |
||
630 | } |
||
631 | |||
632 | |||
633 | /** |
||
634 | * Return a bitmask of the Mesa state flags (_NEW_* values) which would |
||
635 | * indicate that the given context state may have changed. |
||
636 | * The bitmask is used during validation to determine if we need to update |
||
637 | * vertex/fragment program parameters (like "state.material.color") when |
||
638 | * some GL state has changed. |
||
639 | */ |
||
640 | GLbitfield |
||
641 | _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]) |
||
642 | { |
||
643 | switch (state[0]) { |
||
644 | case STATE_MATERIAL: |
||
645 | case STATE_LIGHT: |
||
646 | case STATE_LIGHTMODEL_AMBIENT: |
||
647 | case STATE_LIGHTMODEL_SCENECOLOR: |
||
648 | case STATE_LIGHTPROD: |
||
649 | return _NEW_LIGHT; |
||
650 | |||
651 | case STATE_TEXGEN: |
||
652 | case STATE_TEXENV_COLOR: |
||
653 | return _NEW_TEXTURE; |
||
654 | |||
655 | case STATE_FOG_COLOR: |
||
656 | case STATE_FOG_PARAMS: |
||
657 | return _NEW_FOG; |
||
658 | |||
659 | case STATE_CLIPPLANE: |
||
660 | return _NEW_TRANSFORM; |
||
661 | |||
662 | case STATE_POINT_SIZE: |
||
663 | case STATE_POINT_ATTENUATION: |
||
664 | return _NEW_POINT; |
||
665 | |||
666 | case STATE_MODELVIEW_MATRIX: |
||
667 | return _NEW_MODELVIEW; |
||
668 | case STATE_PROJECTION_MATRIX: |
||
669 | return _NEW_PROJECTION; |
||
670 | case STATE_MVP_MATRIX: |
||
671 | return _NEW_MODELVIEW | _NEW_PROJECTION; |
||
672 | case STATE_TEXTURE_MATRIX: |
||
673 | return _NEW_TEXTURE_MATRIX; |
||
674 | case STATE_PROGRAM_MATRIX: |
||
675 | return _NEW_TRACK_MATRIX; |
||
676 | |||
677 | case STATE_DEPTH_RANGE: |
||
678 | return _NEW_VIEWPORT; |
||
679 | |||
680 | case STATE_FRAGMENT_PROGRAM: |
||
681 | case STATE_VERTEX_PROGRAM: |
||
682 | return _NEW_PROGRAM; |
||
683 | |||
684 | case STATE_NORMAL_SCALE: |
||
685 | return _NEW_MODELVIEW; |
||
686 | |||
687 | case STATE_INTERNAL: |
||
688 | switch (state[1]) { |
||
689 | case STATE_CURRENT_ATTRIB: |
||
690 | return _NEW_CURRENT_ATTRIB; |
||
691 | |||
692 | case STATE_NORMAL_SCALE: |
||
693 | return _NEW_MODELVIEW; |
||
694 | |||
695 | case STATE_TEXRECT_SCALE: |
||
696 | case STATE_SHADOW_AMBIENT: |
||
697 | case STATE_ROT_MATRIX_0: |
||
698 | case STATE_ROT_MATRIX_1: |
||
699 | return _NEW_TEXTURE; |
||
700 | case STATE_FOG_PARAMS_OPTIMIZED: |
||
701 | return _NEW_FOG; |
||
702 | case STATE_POINT_SIZE_CLAMPED: |
||
703 | case STATE_POINT_SIZE_IMPL_CLAMP: |
||
704 | return _NEW_POINT | _NEW_MULTISAMPLE; |
||
705 | case STATE_LIGHT_SPOT_DIR_NORMALIZED: |
||
706 | case STATE_LIGHT_POSITION: |
||
707 | case STATE_LIGHT_POSITION_NORMALIZED: |
||
708 | case STATE_LIGHT_HALF_VECTOR: |
||
709 | return _NEW_LIGHT; |
||
710 | |||
711 | case STATE_PT_SCALE: |
||
712 | case STATE_PT_BIAS: |
||
713 | return _NEW_PIXEL; |
||
714 | |||
715 | case STATE_FB_SIZE: |
||
716 | case STATE_FB_WPOS_Y_TRANSFORM: |
||
717 | return _NEW_BUFFERS; |
||
718 | |||
719 | default: |
||
720 | /* unknown state indexes are silently ignored and |
||
721 | * no flag set, since it is handled by the driver. |
||
722 | */ |
||
723 | return 0; |
||
724 | } |
||
725 | |||
726 | default: |
||
727 | _mesa_problem(NULL, "unexpected state[0] in make_state_flags()"); |
||
728 | return 0; |
||
729 | } |
||
730 | } |
||
731 | |||
732 | |||
733 | static void |
||
734 | append(char *dst, const char *src) |
||
735 | { |
||
736 | while (*dst) |
||
737 | dst++; |
||
738 | while (*src) |
||
739 | *dst++ = *src++; |
||
740 | *dst = 0; |
||
741 | } |
||
742 | |||
743 | |||
744 | /** |
||
745 | * Convert token 'k' to a string, append it onto 'dst' string. |
||
746 | */ |
||
747 | static void |
||
748 | append_token(char *dst, gl_state_index k) |
||
749 | { |
||
750 | switch (k) { |
||
751 | case STATE_MATERIAL: |
||
752 | append(dst, "material"); |
||
753 | break; |
||
754 | case STATE_LIGHT: |
||
755 | append(dst, "light"); |
||
756 | break; |
||
757 | case STATE_LIGHTMODEL_AMBIENT: |
||
758 | append(dst, "lightmodel.ambient"); |
||
759 | break; |
||
760 | case STATE_LIGHTMODEL_SCENECOLOR: |
||
761 | break; |
||
762 | case STATE_LIGHTPROD: |
||
763 | append(dst, "lightprod"); |
||
764 | break; |
||
765 | case STATE_TEXGEN: |
||
766 | append(dst, "texgen"); |
||
767 | break; |
||
768 | case STATE_FOG_COLOR: |
||
769 | append(dst, "fog.color"); |
||
770 | break; |
||
771 | case STATE_FOG_PARAMS: |
||
772 | append(dst, "fog.params"); |
||
773 | break; |
||
774 | case STATE_CLIPPLANE: |
||
775 | append(dst, "clip"); |
||
776 | break; |
||
777 | case STATE_POINT_SIZE: |
||
778 | append(dst, "point.size"); |
||
779 | break; |
||
780 | case STATE_POINT_ATTENUATION: |
||
781 | append(dst, "point.attenuation"); |
||
782 | break; |
||
783 | case STATE_MODELVIEW_MATRIX: |
||
784 | append(dst, "matrix.modelview"); |
||
785 | break; |
||
786 | case STATE_PROJECTION_MATRIX: |
||
787 | append(dst, "matrix.projection"); |
||
788 | break; |
||
789 | case STATE_MVP_MATRIX: |
||
790 | append(dst, "matrix.mvp"); |
||
791 | break; |
||
792 | case STATE_TEXTURE_MATRIX: |
||
793 | append(dst, "matrix.texture"); |
||
794 | break; |
||
795 | case STATE_PROGRAM_MATRIX: |
||
796 | append(dst, "matrix.program"); |
||
797 | break; |
||
798 | case STATE_MATRIX_INVERSE: |
||
799 | append(dst, ".inverse"); |
||
800 | break; |
||
801 | case STATE_MATRIX_TRANSPOSE: |
||
802 | append(dst, ".transpose"); |
||
803 | break; |
||
804 | case STATE_MATRIX_INVTRANS: |
||
805 | append(dst, ".invtrans"); |
||
806 | break; |
||
807 | case STATE_AMBIENT: |
||
808 | append(dst, ".ambient"); |
||
809 | break; |
||
810 | case STATE_DIFFUSE: |
||
811 | append(dst, ".diffuse"); |
||
812 | break; |
||
813 | case STATE_SPECULAR: |
||
814 | append(dst, ".specular"); |
||
815 | break; |
||
816 | case STATE_EMISSION: |
||
817 | append(dst, ".emission"); |
||
818 | break; |
||
819 | case STATE_SHININESS: |
||
820 | append(dst, "lshininess"); |
||
821 | break; |
||
822 | case STATE_HALF_VECTOR: |
||
823 | append(dst, ".half"); |
||
824 | break; |
||
825 | case STATE_POSITION: |
||
826 | append(dst, ".position"); |
||
827 | break; |
||
828 | case STATE_ATTENUATION: |
||
829 | append(dst, ".attenuation"); |
||
830 | break; |
||
831 | case STATE_SPOT_DIRECTION: |
||
832 | append(dst, ".spot.direction"); |
||
833 | break; |
||
834 | case STATE_SPOT_CUTOFF: |
||
835 | append(dst, ".spot.cutoff"); |
||
836 | break; |
||
837 | case STATE_TEXGEN_EYE_S: |
||
838 | append(dst, ".eye.s"); |
||
839 | break; |
||
840 | case STATE_TEXGEN_EYE_T: |
||
841 | append(dst, ".eye.t"); |
||
842 | break; |
||
843 | case STATE_TEXGEN_EYE_R: |
||
844 | append(dst, ".eye.r"); |
||
845 | break; |
||
846 | case STATE_TEXGEN_EYE_Q: |
||
847 | append(dst, ".eye.q"); |
||
848 | break; |
||
849 | case STATE_TEXGEN_OBJECT_S: |
||
850 | append(dst, ".object.s"); |
||
851 | break; |
||
852 | case STATE_TEXGEN_OBJECT_T: |
||
853 | append(dst, ".object.t"); |
||
854 | break; |
||
855 | case STATE_TEXGEN_OBJECT_R: |
||
856 | append(dst, ".object.r"); |
||
857 | break; |
||
858 | case STATE_TEXGEN_OBJECT_Q: |
||
859 | append(dst, ".object.q"); |
||
860 | break; |
||
861 | case STATE_TEXENV_COLOR: |
||
862 | append(dst, "texenv"); |
||
863 | break; |
||
864 | case STATE_DEPTH_RANGE: |
||
865 | append(dst, "depth.range"); |
||
866 | break; |
||
867 | case STATE_VERTEX_PROGRAM: |
||
868 | case STATE_FRAGMENT_PROGRAM: |
||
869 | break; |
||
870 | case STATE_ENV: |
||
871 | append(dst, "env"); |
||
872 | break; |
||
873 | case STATE_LOCAL: |
||
874 | append(dst, "local"); |
||
875 | break; |
||
876 | /* BEGIN internal state vars */ |
||
877 | case STATE_INTERNAL: |
||
878 | append(dst, ".internal."); |
||
879 | break; |
||
880 | case STATE_CURRENT_ATTRIB: |
||
881 | append(dst, "current"); |
||
882 | break; |
||
883 | case STATE_NORMAL_SCALE: |
||
884 | append(dst, "normalScale"); |
||
885 | break; |
||
886 | case STATE_TEXRECT_SCALE: |
||
887 | append(dst, "texrectScale"); |
||
888 | break; |
||
889 | case STATE_FOG_PARAMS_OPTIMIZED: |
||
890 | append(dst, "fogParamsOptimized"); |
||
891 | break; |
||
892 | case STATE_POINT_SIZE_CLAMPED: |
||
893 | append(dst, "pointSizeClamped"); |
||
894 | break; |
||
895 | case STATE_POINT_SIZE_IMPL_CLAMP: |
||
896 | append(dst, "pointSizeImplClamp"); |
||
897 | break; |
||
898 | case STATE_LIGHT_SPOT_DIR_NORMALIZED: |
||
899 | append(dst, "lightSpotDirNormalized"); |
||
900 | break; |
||
901 | case STATE_LIGHT_POSITION: |
||
902 | append(dst, "lightPosition"); |
||
903 | break; |
||
904 | case STATE_LIGHT_POSITION_NORMALIZED: |
||
905 | append(dst, "light.position.normalized"); |
||
906 | break; |
||
907 | case STATE_LIGHT_HALF_VECTOR: |
||
908 | append(dst, "lightHalfVector"); |
||
909 | break; |
||
910 | case STATE_PT_SCALE: |
||
911 | append(dst, "PTscale"); |
||
912 | break; |
||
913 | case STATE_PT_BIAS: |
||
914 | append(dst, "PTbias"); |
||
915 | break; |
||
916 | case STATE_SHADOW_AMBIENT: |
||
917 | append(dst, "CompareFailValue"); |
||
918 | break; |
||
919 | case STATE_FB_SIZE: |
||
920 | append(dst, "FbSize"); |
||
921 | break; |
||
922 | case STATE_FB_WPOS_Y_TRANSFORM: |
||
923 | append(dst, "FbWposYTransform"); |
||
924 | break; |
||
925 | case STATE_ROT_MATRIX_0: |
||
926 | append(dst, "rotMatrixRow0"); |
||
927 | break; |
||
928 | case STATE_ROT_MATRIX_1: |
||
929 | append(dst, "rotMatrixRow1"); |
||
930 | break; |
||
931 | default: |
||
932 | /* probably STATE_INTERNAL_DRIVER+i (driver private state) */ |
||
933 | append(dst, "driverState"); |
||
934 | } |
||
935 | } |
||
936 | |||
937 | static void |
||
938 | append_face(char *dst, GLint face) |
||
939 | { |
||
940 | if (face == 0) |
||
941 | append(dst, "front."); |
||
942 | else |
||
943 | append(dst, "back."); |
||
944 | } |
||
945 | |||
946 | static void |
||
947 | append_index(char *dst, GLint index) |
||
948 | { |
||
949 | char s[20]; |
||
950 | sprintf(s, "[%d]", index); |
||
951 | append(dst, s); |
||
952 | } |
||
953 | |||
954 | /** |
||
955 | * Make a string from the given state vector. |
||
956 | * For example, return "state.matrix.texture[2].inverse". |
||
957 | * Use free() to deallocate the string. |
||
958 | */ |
||
959 | char * |
||
960 | _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) |
||
961 | { |
||
962 | char str[1000] = ""; |
||
963 | char tmp[30]; |
||
964 | |||
965 | append(str, "state."); |
||
966 | append_token(str, state[0]); |
||
967 | |||
968 | switch (state[0]) { |
||
969 | case STATE_MATERIAL: |
||
970 | append_face(str, state[1]); |
||
971 | append_token(str, state[2]); |
||
972 | break; |
||
973 | case STATE_LIGHT: |
||
974 | append_index(str, state[1]); /* light number [i]. */ |
||
975 | append_token(str, state[2]); /* coefficients */ |
||
976 | break; |
||
977 | case STATE_LIGHTMODEL_AMBIENT: |
||
978 | append(str, "lightmodel.ambient"); |
||
979 | break; |
||
980 | case STATE_LIGHTMODEL_SCENECOLOR: |
||
981 | if (state[1] == 0) { |
||
982 | append(str, "lightmodel.front.scenecolor"); |
||
983 | } |
||
984 | else { |
||
985 | append(str, "lightmodel.back.scenecolor"); |
||
986 | } |
||
987 | break; |
||
988 | case STATE_LIGHTPROD: |
||
989 | append_index(str, state[1]); /* light number [i]. */ |
||
990 | append_face(str, state[2]); |
||
991 | append_token(str, state[3]); |
||
992 | break; |
||
993 | case STATE_TEXGEN: |
||
994 | append_index(str, state[1]); /* tex unit [i] */ |
||
995 | append_token(str, state[2]); /* plane coef */ |
||
996 | break; |
||
997 | case STATE_TEXENV_COLOR: |
||
998 | append_index(str, state[1]); /* tex unit [i] */ |
||
999 | append(str, "color"); |
||
1000 | break; |
||
1001 | case STATE_CLIPPLANE: |
||
1002 | append_index(str, state[1]); /* plane [i] */ |
||
1003 | append(str, ".plane"); |
||
1004 | break; |
||
1005 | case STATE_MODELVIEW_MATRIX: |
||
1006 | case STATE_PROJECTION_MATRIX: |
||
1007 | case STATE_MVP_MATRIX: |
||
1008 | case STATE_TEXTURE_MATRIX: |
||
1009 | case STATE_PROGRAM_MATRIX: |
||
1010 | { |
||
1011 | /* state[0] = modelview, projection, texture, etc. */ |
||
1012 | /* state[1] = which texture matrix or program matrix */ |
||
1013 | /* state[2] = first row to fetch */ |
||
1014 | /* state[3] = last row to fetch */ |
||
1015 | /* state[4] = transpose, inverse or invtrans */ |
||
1016 | const gl_state_index mat = state[0]; |
||
1017 | const GLuint index = (GLuint) state[1]; |
||
1018 | const GLuint firstRow = (GLuint) state[2]; |
||
1019 | const GLuint lastRow = (GLuint) state[3]; |
||
1020 | const gl_state_index modifier = state[4]; |
||
1021 | if (index || |
||
1022 | mat == STATE_TEXTURE_MATRIX || |
||
1023 | mat == STATE_PROGRAM_MATRIX) |
||
1024 | append_index(str, index); |
||
1025 | if (modifier) |
||
1026 | append_token(str, modifier); |
||
1027 | if (firstRow == lastRow) |
||
1028 | sprintf(tmp, ".row[%d]", firstRow); |
||
1029 | else |
||
1030 | sprintf(tmp, ".row[%d..%d]", firstRow, lastRow); |
||
1031 | append(str, tmp); |
||
1032 | } |
||
1033 | break; |
||
1034 | case STATE_POINT_SIZE: |
||
1035 | break; |
||
1036 | case STATE_POINT_ATTENUATION: |
||
1037 | break; |
||
1038 | case STATE_FOG_PARAMS: |
||
1039 | break; |
||
1040 | case STATE_FOG_COLOR: |
||
1041 | break; |
||
1042 | case STATE_DEPTH_RANGE: |
||
1043 | break; |
||
1044 | case STATE_FRAGMENT_PROGRAM: |
||
1045 | case STATE_VERTEX_PROGRAM: |
||
1046 | /* state[1] = {STATE_ENV, STATE_LOCAL} */ |
||
1047 | /* state[2] = parameter index */ |
||
1048 | append_token(str, state[1]); |
||
1049 | append_index(str, state[2]); |
||
1050 | break; |
||
1051 | case STATE_NORMAL_SCALE: |
||
1052 | break; |
||
1053 | case STATE_INTERNAL: |
||
1054 | append_token(str, state[1]); |
||
1055 | if (state[1] == STATE_CURRENT_ATTRIB) |
||
1056 | append_index(str, state[2]); |
||
1057 | break; |
||
1058 | default: |
||
1059 | _mesa_problem(NULL, "Invalid state in _mesa_program_state_string"); |
||
1060 | break; |
||
1061 | } |
||
1062 | |||
1063 | return _mesa_strdup(str); |
||
1064 | } |
||
1065 | |||
1066 | |||
1067 | /** |
||
1068 | * Loop over all the parameters in a parameter list. If the parameter |
||
1069 | * is a GL state reference, look up the current value of that state |
||
1070 | * variable and put it into the parameter's Value[4] array. |
||
1071 | * Other parameter types never change or are explicitly set by the user |
||
1072 | * with glUniform() or glProgramParameter(), etc. |
||
1073 | * This would be called at glBegin time. |
||
1074 | */ |
||
1075 | void |
||
1076 | _mesa_load_state_parameters(struct gl_context *ctx, |
||
1077 | struct gl_program_parameter_list *paramList) |
||
1078 | { |
||
1079 | GLuint i; |
||
1080 | |||
1081 | if (!paramList) |
||
1082 | return; |
||
1083 | |||
1084 | for (i = 0; i < paramList->NumParameters; i++) { |
||
1085 | if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { |
||
1086 | _mesa_fetch_state(ctx, |
||
1087 | paramList->Parameters[i].StateIndexes, |
||
1088 | paramList->ParameterValues[i]); |
||
1089 | } |
||
1090 | } |
||
1091 | } |
||
1092 | |||
1093 | |||
1094 | /** |
||
1095 | * Copy the 16 elements of a matrix into four consecutive program |
||
1096 | * registers starting at 'pos'. |
||
1097 | */ |
||
1098 | static void |
||
1099 | load_matrix(GLfloat registers[][4], GLuint pos, const GLfloat mat[16]) |
||
1100 | { |
||
1101 | GLuint i; |
||
1102 | for (i = 0; i < 4; i++) { |
||
1103 | registers[pos + i][0] = mat[0 + i]; |
||
1104 | registers[pos + i][1] = mat[4 + i]; |
||
1105 | registers[pos + i][2] = mat[8 + i]; |
||
1106 | registers[pos + i][3] = mat[12 + i]; |
||
1107 | } |
||
1108 | } |
||
1109 | |||
1110 | |||
1111 | /** |
||
1112 | * As above, but transpose the matrix. |
||
1113 | */ |
||
1114 | static void |
||
1115 | load_transpose_matrix(GLfloat registers[][4], GLuint pos, |
||
1116 | const GLfloat mat[16]) |
||
1117 | { |
||
1118 | memcpy(registers[pos], mat, 16 * sizeof(GLfloat)); |
||
1119 | } |
||
1120 | |||
1121 | |||
1122 | /** |
||
1123 | * Load current vertex program's parameter registers with tracked |
||
1124 | * matrices (if NV program). This only needs to be done per |
||
1125 | * glBegin/glEnd, not per-vertex. |
||
1126 | */ |
||
1127 | void |
||
1128 | _mesa_load_tracked_matrices(struct gl_context *ctx) |
||
1129 | { |
||
1130 | GLuint i; |
||
1131 | |||
1132 | for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) { |
||
1133 | /* point 'mat' at source matrix */ |
||
1134 | GLmatrix *mat; |
||
1135 | if (ctx->VertexProgram.TrackMatrix[i] == GL_MODELVIEW) { |
||
1136 | mat = ctx->ModelviewMatrixStack.Top; |
||
1137 | } |
||
1138 | else if (ctx->VertexProgram.TrackMatrix[i] == GL_PROJECTION) { |
||
1139 | mat = ctx->ProjectionMatrixStack.Top; |
||
1140 | } |
||
1141 | else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) { |
||
1142 | GLuint unit = MIN2(ctx->Texture.CurrentUnit, |
||
1143 | Elements(ctx->TextureMatrixStack) - 1); |
||
1144 | mat = ctx->TextureMatrixStack[unit].Top; |
||
1145 | } |
||
1146 | else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) { |
||
1147 | /* XXX verify the combined matrix is up to date */ |
||
1148 | mat = &ctx->_ModelProjectMatrix; |
||
1149 | } |
||
1150 | else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV && |
||
1151 | ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) { |
||
1152 | GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV; |
||
1153 | ASSERT(n < Elements(ctx->ProgramMatrixStack)); |
||
1154 | mat = ctx->ProgramMatrixStack[n].Top; |
||
1155 | } |
||
1156 | else { |
||
1157 | /* no matrix is tracked, but we leave the register values as-is */ |
||
1158 | assert(ctx->VertexProgram.TrackMatrix[i] == GL_NONE); |
||
1159 | continue; |
||
1160 | } |
||
1161 | |||
1162 | /* load the matrix values into sequential registers */ |
||
1163 | if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) { |
||
1164 | load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m); |
||
1165 | } |
||
1166 | else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_INVERSE_NV) { |
||
1167 | _math_matrix_analyse(mat); /* update the inverse */ |
||
1168 | ASSERT(!_math_matrix_is_dirty(mat)); |
||
1169 | load_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv); |
||
1170 | } |
||
1171 | else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_TRANSPOSE_NV) { |
||
1172 | load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->m); |
||
1173 | } |
||
1174 | else { |
||
1175 | assert(ctx->VertexProgram.TrackMatrixTransform[i] |
||
1176 | == GL_INVERSE_TRANSPOSE_NV); |
||
1177 | _math_matrix_analyse(mat); /* update the inverse */ |
||
1178 | ASSERT(!_math_matrix_is_dirty(mat)); |
||
1179 | load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv); |
||
1180 | } |
||
1181 | } |
||
1182 | }>=>>>>=>=>=>>>>>>>>>> |