2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-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 prog_statevars.c
27 * Program state variable management.
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 "main/fbobject.h"
38 #include "prog_statevars.h"
39 #include "prog_parameter.h"
43 * Use the list of tokens in the state[] array to find global GL state
44 * and return it in <value>. Usually, four values are returned in <value>
45 * but matrix queries may return as many as 16 values.
46 * This function is used for ARB vertex/fragment programs.
47 * The program parser will produce the state[] values.
50 _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
56 /* state[1] is either 0=front or 1=back side */
57 const GLuint face = (GLuint) state[1];
58 const struct gl_material *mat = &ctx->Light.Material;
59 ASSERT(face == 0 || face == 1);
60 /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */
61 ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT);
62 /* XXX we could get rid of this switch entirely with a little
63 * work in arbprogparse.c's parse_state_single_item().
65 /* state[2] is the material attribute */
68 COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]);
71 COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]);
74 COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]);
77 COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]);
80 value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0];
86 _mesa_problem(ctx, "Invalid material state in fetch_state");
92 /* state[1] is the light number */
93 const GLuint ln = (GLuint) state[1];
94 /* state[2] is the light attribute */
97 COPY_4V(value, ctx->Light.Light[ln].Ambient);
100 COPY_4V(value, ctx->Light.Light[ln].Diffuse);
103 COPY_4V(value, ctx->Light.Light[ln].Specular);
106 COPY_4V(value, ctx->Light.Light[ln].EyePosition);
108 case STATE_ATTENUATION:
109 value[0] = ctx->Light.Light[ln].ConstantAttenuation;
110 value[1] = ctx->Light.Light[ln].LinearAttenuation;
111 value[2] = ctx->Light.Light[ln].QuadraticAttenuation;
112 value[3] = ctx->Light.Light[ln].SpotExponent;
114 case STATE_SPOT_DIRECTION:
115 COPY_3V(value, ctx->Light.Light[ln].SpotDirection);
116 value[3] = ctx->Light.Light[ln]._CosCutoff;
118 case STATE_SPOT_CUTOFF:
119 value[0] = ctx->Light.Light[ln].SpotCutoff;
121 case STATE_HALF_VECTOR:
123 static const GLfloat eye_z[] = {0, 0, 1};
125 /* Compute infinite half angle vector:
126 * halfVector = normalize(normalize(lightPos) + (0, 0, 1))
127 * light.EyePosition.w should be 0 for infinite lights.
129 COPY_3V(p, ctx->Light.Light[ln].EyePosition);
131 ADD_3V(value, p, eye_z);
132 NORMALIZE_3FV(value);
137 _mesa_problem(ctx, "Invalid light state in fetch_state");
141 case STATE_LIGHTMODEL_AMBIENT:
142 COPY_4V(value, ctx->Light.Model.Ambient);
144 case STATE_LIGHTMODEL_SCENECOLOR:
148 for (i = 0; i < 3; i++) {
149 value[i] = ctx->Light.Model.Ambient[i]
150 * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i]
151 + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i];
153 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
158 for (i = 0; i < 3; i++) {
159 value[i] = ctx->Light.Model.Ambient[i]
160 * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i]
161 + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i];
163 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
166 case STATE_LIGHTPROD:
168 const GLuint ln = (GLuint) state[1];
169 const GLuint face = (GLuint) state[2];
171 ASSERT(face == 0 || face == 1);
174 for (i = 0; i < 3; i++) {
175 value[i] = ctx->Light.Light[ln].Ambient[i] *
176 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i];
178 /* [3] = material alpha */
179 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3];
182 for (i = 0; i < 3; i++) {
183 value[i] = ctx->Light.Light[ln].Diffuse[i] *
184 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i];
186 /* [3] = material alpha */
187 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
190 for (i = 0; i < 3; i++) {
191 value[i] = ctx->Light.Light[ln].Specular[i] *
192 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i];
194 /* [3] = material alpha */
195 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3];
198 _mesa_problem(ctx, "Invalid lightprod state in fetch_state");
204 /* state[1] is the texture unit */
205 const GLuint unit = (GLuint) state[1];
206 /* state[2] is the texgen attribute */
208 case STATE_TEXGEN_EYE_S:
209 COPY_4V(value, ctx->Texture.Unit[unit].GenS.EyePlane);
211 case STATE_TEXGEN_EYE_T:
212 COPY_4V(value, ctx->Texture.Unit[unit].GenT.EyePlane);
214 case STATE_TEXGEN_EYE_R:
215 COPY_4V(value, ctx->Texture.Unit[unit].GenR.EyePlane);
217 case STATE_TEXGEN_EYE_Q:
218 COPY_4V(value, ctx->Texture.Unit[unit].GenQ.EyePlane);
220 case STATE_TEXGEN_OBJECT_S:
221 COPY_4V(value, ctx->Texture.Unit[unit].GenS.ObjectPlane);
223 case STATE_TEXGEN_OBJECT_T:
224 COPY_4V(value, ctx->Texture.Unit[unit].GenT.ObjectPlane);
226 case STATE_TEXGEN_OBJECT_R:
227 COPY_4V(value, ctx->Texture.Unit[unit].GenR.ObjectPlane);
229 case STATE_TEXGEN_OBJECT_Q:
230 COPY_4V(value, ctx->Texture.Unit[unit].GenQ.ObjectPlane);
233 _mesa_problem(ctx, "Invalid texgen state in fetch_state");
237 case STATE_TEXENV_COLOR:
239 /* state[1] is the texture unit */
240 const GLuint unit = (GLuint) state[1];
241 if(ctx->Color._ClampFragmentColor)
242 COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
244 COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped);
247 case STATE_FOG_COLOR:
248 if(ctx->Color._ClampFragmentColor)
249 COPY_4V(value, ctx->Fog.Color);
251 COPY_4V(value, ctx->Fog.ColorUnclamped);
253 case STATE_FOG_PARAMS:
254 value[0] = ctx->Fog.Density;
255 value[1] = ctx->Fog.Start;
256 value[2] = ctx->Fog.End;
257 value[3] = (ctx->Fog.End == ctx->Fog.Start)
258 ? 1.0f : (GLfloat)(1.0 / (ctx->Fog.End - ctx->Fog.Start));
260 case STATE_CLIPPLANE:
262 const GLuint plane = (GLuint) state[1];
263 COPY_4V(value, ctx->Transform.EyeUserPlane[plane]);
266 case STATE_POINT_SIZE:
267 value[0] = ctx->Point.Size;
268 value[1] = ctx->Point.MinSize;
269 value[2] = ctx->Point.MaxSize;
270 value[3] = ctx->Point.Threshold;
272 case STATE_POINT_ATTENUATION:
273 value[0] = ctx->Point.Params[0];
274 value[1] = ctx->Point.Params[1];
275 value[2] = ctx->Point.Params[2];
278 case STATE_MODELVIEW_MATRIX:
279 case STATE_PROJECTION_MATRIX:
280 case STATE_MVP_MATRIX:
281 case STATE_TEXTURE_MATRIX:
282 case STATE_PROGRAM_MATRIX:
284 /* state[0] = modelview, projection, texture, etc. */
285 /* state[1] = which texture matrix or program matrix */
286 /* state[2] = first row to fetch */
287 /* state[3] = last row to fetch */
288 /* state[4] = transpose, inverse or invtrans */
289 const GLmatrix *matrix;
290 const gl_state_index mat = state[0];
291 const GLuint index = (GLuint) state[1];
292 const GLuint firstRow = (GLuint) state[2];
293 const GLuint lastRow = (GLuint) state[3];
294 const gl_state_index modifier = state[4];
297 ASSERT(firstRow >= 0);
298 ASSERT(firstRow < 4);
299 ASSERT(lastRow >= 0);
301 if (mat == STATE_MODELVIEW_MATRIX) {
302 matrix = ctx->ModelviewMatrixStack.Top;
304 else if (mat == STATE_PROJECTION_MATRIX) {
305 matrix = ctx->ProjectionMatrixStack.Top;
307 else if (mat == STATE_MVP_MATRIX) {
308 matrix = &ctx->_ModelProjectMatrix;
310 else if (mat == STATE_TEXTURE_MATRIX) {
311 ASSERT(index < Elements(ctx->TextureMatrixStack));
312 matrix = ctx->TextureMatrixStack[index].Top;
314 else if (mat == STATE_PROGRAM_MATRIX) {
315 ASSERT(index < Elements(ctx->ProgramMatrixStack));
316 matrix = ctx->ProgramMatrixStack[index].Top;
319 _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()");
322 if (modifier == STATE_MATRIX_INVERSE ||
323 modifier == STATE_MATRIX_INVTRANS) {
324 /* Be sure inverse is up to date:
326 _math_matrix_analyse( (GLmatrix*) matrix );
332 if (modifier == STATE_MATRIX_TRANSPOSE ||
333 modifier == STATE_MATRIX_INVTRANS) {
334 for (i = 0, row = firstRow; row <= lastRow; row++) {
335 value[i++] = m[row * 4 + 0];
336 value[i++] = m[row * 4 + 1];
337 value[i++] = m[row * 4 + 2];
338 value[i++] = m[row * 4 + 3];
342 for (i = 0, row = firstRow; row <= lastRow; row++) {
343 value[i++] = m[row + 0];
344 value[i++] = m[row + 4];
345 value[i++] = m[row + 8];
346 value[i++] = m[row + 12];
351 case STATE_DEPTH_RANGE:
352 value[0] = ctx->Viewport.Near; /* near */
353 value[1] = ctx->Viewport.Far; /* far */
354 value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */
357 case STATE_FRAGMENT_PROGRAM:
359 /* state[1] = {STATE_ENV, STATE_LOCAL} */
360 /* state[2] = parameter index */
361 const int idx = (int) state[2];
364 COPY_4V(value, ctx->FragmentProgram.Parameters[idx]);
367 COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]);
370 _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
376 case STATE_VERTEX_PROGRAM:
378 /* state[1] = {STATE_ENV, STATE_LOCAL} */
379 /* state[2] = parameter index */
380 const int idx = (int) state[2];
383 COPY_4V(value, ctx->VertexProgram.Parameters[idx]);
386 COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]);
389 _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
395 case STATE_NORMAL_SCALE:
396 ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1);
401 case STATE_CURRENT_ATTRIB:
403 const GLuint idx = (GLuint) state[2];
404 COPY_4V(value, ctx->Current.Attrib[idx]);
408 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
410 const GLuint idx = (GLuint) state[2];
411 if(ctx->Light._ClampVertexColor &&
412 (idx == VERT_ATTRIB_COLOR0 ||
413 idx == VERT_ATTRIB_COLOR1)) {
414 value[0] = CLAMP(ctx->Current.Attrib[idx][0], 0.0f, 1.0f);
415 value[1] = CLAMP(ctx->Current.Attrib[idx][1], 0.0f, 1.0f);
416 value[2] = CLAMP(ctx->Current.Attrib[idx][2], 0.0f, 1.0f);
417 value[3] = CLAMP(ctx->Current.Attrib[idx][3], 0.0f, 1.0f);
420 COPY_4V(value, ctx->Current.Attrib[idx]);
424 case STATE_NORMAL_SCALE:
426 ctx->_ModelViewInvScale,
427 ctx->_ModelViewInvScale,
428 ctx->_ModelViewInvScale,
432 case STATE_TEXRECT_SCALE:
433 /* Value = { 1/texWidth, 1/texHeight, 0, 1 }.
434 * Used to convert unnormalized texcoords to normalized texcoords.
437 const int unit = (int) state[2];
438 const struct gl_texture_object *texObj
439 = ctx->Texture.Unit[unit]._Current;
441 struct gl_texture_image *texImage = texObj->Image[0][0];
443 (GLfloat) (1.0 / texImage->Width),
444 (GLfloat) (1.0 / texImage->Height),
450 case STATE_FOG_PARAMS_OPTIMIZED:
451 /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog)
452 * might be more expensive than EX2 on some hw, plus it needs
453 * another constant (e) anyway. Linear fog can now be done with a
455 * linear: fogcoord * -1/(end-start) + end/(end-start)
456 * exp: 2^-(density/ln(2) * fogcoord)
457 * exp2: 2^-((density/(ln(2)^2) * fogcoord)^2)
459 value[0] = (ctx->Fog.End == ctx->Fog.Start)
460 ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start));
461 value[1] = ctx->Fog.End * -value[0];
462 value[2] = (GLfloat)(ctx->Fog.Density * M_LOG2E); /* M_LOG2E == 1/ln(2) */
463 value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2);
466 case STATE_POINT_SIZE_CLAMPED:
468 /* this includes implementation dependent limits, to avoid
469 * another potentially necessary clamp.
470 * Note: for sprites, point smooth (point AA) is ignored
471 * and we'll clamp to MinPointSizeAA and MaxPointSize, because we
472 * expect drivers will want to say their minimum for AA size is 0.0
473 * but for non-AA it's 1.0 (because normal points with size below 1.0
474 * need to get rounded up to 1.0, hence never disappear). GL does
475 * not specify max clamp size for sprites, other than it needs to be
476 * at least as large as max AA size, hence use non-AA size there.
480 if (ctx->Point.PointSprite) {
481 minImplSize = ctx->Const.MinPointSizeAA;
482 maxImplSize = ctx->Const.MaxPointSize;
484 else if (ctx->Point.SmoothFlag || ctx->Multisample._Enabled) {
485 minImplSize = ctx->Const.MinPointSizeAA;
486 maxImplSize = ctx->Const.MaxPointSizeAA;
489 minImplSize = ctx->Const.MinPointSize;
490 maxImplSize = ctx->Const.MaxPointSize;
492 value[0] = ctx->Point.Size;
493 value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize;
494 value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize;
495 value[3] = ctx->Point.Threshold;
498 case STATE_LIGHT_SPOT_DIR_NORMALIZED:
500 /* here, state[2] is the light number */
501 /* pre-normalize spot dir */
502 const GLuint ln = (GLuint) state[2];
503 COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection);
504 value[3] = ctx->Light.Light[ln]._CosCutoff;
508 case STATE_LIGHT_POSITION:
510 const GLuint ln = (GLuint) state[2];
511 COPY_4V(value, ctx->Light.Light[ln]._Position);
515 case STATE_LIGHT_POSITION_NORMALIZED:
517 const GLuint ln = (GLuint) state[2];
518 COPY_4V(value, ctx->Light.Light[ln]._Position);
519 NORMALIZE_3FV( value );
523 case STATE_LIGHT_HALF_VECTOR:
525 const GLuint ln = (GLuint) state[2];
527 /* Compute infinite half angle vector:
528 * halfVector = normalize(normalize(lightPos) + (0, 0, 1))
529 * light.EyePosition.w should be 0 for infinite lights.
531 COPY_3V(p, ctx->Light.Light[ln]._Position);
533 ADD_3V(value, p, ctx->_EyeZDir);
534 NORMALIZE_3FV(value);
540 value[0] = ctx->Pixel.RedScale;
541 value[1] = ctx->Pixel.GreenScale;
542 value[2] = ctx->Pixel.BlueScale;
543 value[3] = ctx->Pixel.AlphaScale;
547 value[0] = ctx->Pixel.RedBias;
548 value[1] = ctx->Pixel.GreenBias;
549 value[2] = ctx->Pixel.BlueBias;
550 value[3] = ctx->Pixel.AlphaBias;
553 case STATE_SHADOW_AMBIENT:
555 const int unit = (int) state[2];
556 const struct gl_texture_object *texObj
557 = ctx->Texture.Unit[unit]._Current;
562 value[3] = texObj->Sampler.CompareFailValue;
568 value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1);
569 value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1);
574 case STATE_FB_WPOS_Y_TRANSFORM:
575 /* A driver may negate this conditional by using ZW swizzle
576 * instead of XY (based on e.g. some other state). */
577 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
578 /* Identity (XY) followed by flipping Y upside down (ZW). */
582 value[3] = (GLfloat) ctx->DrawBuffer->Height;
584 /* Flipping Y upside down (XY) followed by identity (ZW). */
586 value[1] = (GLfloat) ctx->DrawBuffer->Height;
592 case STATE_ROT_MATRIX_0:
594 const int unit = (int) state[2];
595 GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
596 value[0] = rotMat22[0];
597 value[1] = rotMat22[2];
603 case STATE_ROT_MATRIX_1:
605 const int unit = (int) state[2];
606 GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
607 value[0] = rotMat22[1];
608 value[1] = rotMat22[3];
614 /* XXX: make sure new tokens added here are also handled in the
615 * _mesa_program_state_flags() switch, below.
618 /* Unknown state indexes are silently ignored here.
619 * Drivers may do something special.
626 _mesa_problem(ctx, "Invalid state in _mesa_fetch_state");
633 * Return a bitmask of the Mesa state flags (_NEW_* values) which would
634 * indicate that the given context state may have changed.
635 * The bitmask is used during validation to determine if we need to update
636 * vertex/fragment program parameters (like "state.material.color") when
637 * some GL state has changed.
640 _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
644 case STATE_LIGHTPROD:
645 case STATE_LIGHTMODEL_SCENECOLOR:
646 /* these can be effected by glColor when colormaterial mode is used */
647 return _NEW_LIGHT | _NEW_CURRENT_ATTRIB;
650 case STATE_LIGHTMODEL_AMBIENT:
655 case STATE_TEXENV_COLOR:
656 return _NEW_TEXTURE | _NEW_BUFFERS | _NEW_FRAG_CLAMP;
658 case STATE_FOG_COLOR:
659 return _NEW_FOG | _NEW_BUFFERS | _NEW_FRAG_CLAMP;
660 case STATE_FOG_PARAMS:
663 case STATE_CLIPPLANE:
664 return _NEW_TRANSFORM;
666 case STATE_POINT_SIZE:
667 case STATE_POINT_ATTENUATION:
670 case STATE_MODELVIEW_MATRIX:
671 return _NEW_MODELVIEW;
672 case STATE_PROJECTION_MATRIX:
673 return _NEW_PROJECTION;
674 case STATE_MVP_MATRIX:
675 return _NEW_MODELVIEW | _NEW_PROJECTION;
676 case STATE_TEXTURE_MATRIX:
677 return _NEW_TEXTURE_MATRIX;
678 case STATE_PROGRAM_MATRIX:
679 return _NEW_TRACK_MATRIX;
681 case STATE_DEPTH_RANGE:
682 return _NEW_VIEWPORT;
684 case STATE_FRAGMENT_PROGRAM:
685 case STATE_VERTEX_PROGRAM:
688 case STATE_NORMAL_SCALE:
689 return _NEW_MODELVIEW;
693 case STATE_CURRENT_ATTRIB:
694 return _NEW_CURRENT_ATTRIB;
695 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
696 return _NEW_CURRENT_ATTRIB | _NEW_LIGHT | _NEW_BUFFERS;
698 case STATE_NORMAL_SCALE:
699 return _NEW_MODELVIEW;
701 case STATE_TEXRECT_SCALE:
702 case STATE_SHADOW_AMBIENT:
703 case STATE_ROT_MATRIX_0:
704 case STATE_ROT_MATRIX_1:
706 case STATE_FOG_PARAMS_OPTIMIZED:
708 case STATE_POINT_SIZE_CLAMPED:
709 return _NEW_POINT | _NEW_MULTISAMPLE;
710 case STATE_LIGHT_SPOT_DIR_NORMALIZED:
711 case STATE_LIGHT_POSITION:
712 case STATE_LIGHT_POSITION_NORMALIZED:
713 case STATE_LIGHT_HALF_VECTOR:
721 case STATE_FB_WPOS_Y_TRANSFORM:
725 /* unknown state indexes are silently ignored and
726 * no flag set, since it is handled by the driver.
732 _mesa_problem(NULL, "unexpected state[0] in make_state_flags()");
739 append(char *dst, const char *src)
750 * Convert token 'k' to a string, append it onto 'dst' string.
753 append_token(char *dst, gl_state_index k)
757 append(dst, "material");
760 append(dst, "light");
762 case STATE_LIGHTMODEL_AMBIENT:
763 append(dst, "lightmodel.ambient");
765 case STATE_LIGHTMODEL_SCENECOLOR:
767 case STATE_LIGHTPROD:
768 append(dst, "lightprod");
771 append(dst, "texgen");
773 case STATE_FOG_COLOR:
774 append(dst, "fog.color");
776 case STATE_FOG_PARAMS:
777 append(dst, "fog.params");
779 case STATE_CLIPPLANE:
782 case STATE_POINT_SIZE:
783 append(dst, "point.size");
785 case STATE_POINT_ATTENUATION:
786 append(dst, "point.attenuation");
788 case STATE_MODELVIEW_MATRIX:
789 append(dst, "matrix.modelview");
791 case STATE_PROJECTION_MATRIX:
792 append(dst, "matrix.projection");
794 case STATE_MVP_MATRIX:
795 append(dst, "matrix.mvp");
797 case STATE_TEXTURE_MATRIX:
798 append(dst, "matrix.texture");
800 case STATE_PROGRAM_MATRIX:
801 append(dst, "matrix.program");
803 case STATE_MATRIX_INVERSE:
804 append(dst, ".inverse");
806 case STATE_MATRIX_TRANSPOSE:
807 append(dst, ".transpose");
809 case STATE_MATRIX_INVTRANS:
810 append(dst, ".invtrans");
813 append(dst, ".ambient");
816 append(dst, ".diffuse");
819 append(dst, ".specular");
822 append(dst, ".emission");
824 case STATE_SHININESS:
825 append(dst, "lshininess");
827 case STATE_HALF_VECTOR:
828 append(dst, ".half");
831 append(dst, ".position");
833 case STATE_ATTENUATION:
834 append(dst, ".attenuation");
836 case STATE_SPOT_DIRECTION:
837 append(dst, ".spot.direction");
839 case STATE_SPOT_CUTOFF:
840 append(dst, ".spot.cutoff");
842 case STATE_TEXGEN_EYE_S:
843 append(dst, ".eye.s");
845 case STATE_TEXGEN_EYE_T:
846 append(dst, ".eye.t");
848 case STATE_TEXGEN_EYE_R:
849 append(dst, ".eye.r");
851 case STATE_TEXGEN_EYE_Q:
852 append(dst, ".eye.q");
854 case STATE_TEXGEN_OBJECT_S:
855 append(dst, ".object.s");
857 case STATE_TEXGEN_OBJECT_T:
858 append(dst, ".object.t");
860 case STATE_TEXGEN_OBJECT_R:
861 append(dst, ".object.r");
863 case STATE_TEXGEN_OBJECT_Q:
864 append(dst, ".object.q");
866 case STATE_TEXENV_COLOR:
867 append(dst, "texenv");
869 case STATE_DEPTH_RANGE:
870 append(dst, "depth.range");
872 case STATE_VERTEX_PROGRAM:
873 case STATE_FRAGMENT_PROGRAM:
879 append(dst, "local");
881 /* BEGIN internal state vars */
883 append(dst, ".internal.");
885 case STATE_CURRENT_ATTRIB:
886 append(dst, "current");
888 case STATE_NORMAL_SCALE:
889 append(dst, "normalScale");
891 case STATE_TEXRECT_SCALE:
892 append(dst, "texrectScale");
894 case STATE_FOG_PARAMS_OPTIMIZED:
895 append(dst, "fogParamsOptimized");
897 case STATE_POINT_SIZE_CLAMPED:
898 append(dst, "pointSizeClamped");
900 case STATE_LIGHT_SPOT_DIR_NORMALIZED:
901 append(dst, "lightSpotDirNormalized");
903 case STATE_LIGHT_POSITION:
904 append(dst, "lightPosition");
906 case STATE_LIGHT_POSITION_NORMALIZED:
907 append(dst, "light.position.normalized");
909 case STATE_LIGHT_HALF_VECTOR:
910 append(dst, "lightHalfVector");
913 append(dst, "PTscale");
916 append(dst, "PTbias");
918 case STATE_SHADOW_AMBIENT:
919 append(dst, "CompareFailValue");
922 append(dst, "FbSize");
924 case STATE_FB_WPOS_Y_TRANSFORM:
925 append(dst, "FbWposYTransform");
927 case STATE_ROT_MATRIX_0:
928 append(dst, "rotMatrixRow0");
930 case STATE_ROT_MATRIX_1:
931 append(dst, "rotMatrixRow1");
934 /* probably STATE_INTERNAL_DRIVER+i (driver private state) */
935 append(dst, "driverState");
940 append_face(char *dst, GLint face)
943 append(dst, "front.");
945 append(dst, "back.");
949 append_index(char *dst, GLint index)
952 sprintf(s, "[%d]", index);
957 * Make a string from the given state vector.
958 * For example, return "state.matrix.texture[2].inverse".
959 * Use free() to deallocate the string.
962 _mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
967 append(str, "state.");
968 append_token(str, state[0]);
972 append_face(str, state[1]);
973 append_token(str, state[2]);
976 append_index(str, state[1]); /* light number [i]. */
977 append_token(str, state[2]); /* coefficients */
979 case STATE_LIGHTMODEL_AMBIENT:
980 append(str, "lightmodel.ambient");
982 case STATE_LIGHTMODEL_SCENECOLOR:
984 append(str, "lightmodel.front.scenecolor");
987 append(str, "lightmodel.back.scenecolor");
990 case STATE_LIGHTPROD:
991 append_index(str, state[1]); /* light number [i]. */
992 append_face(str, state[2]);
993 append_token(str, state[3]);
996 append_index(str, state[1]); /* tex unit [i] */
997 append_token(str, state[2]); /* plane coef */
999 case STATE_TEXENV_COLOR:
1000 append_index(str, state[1]); /* tex unit [i] */
1001 append(str, "color");
1003 case STATE_CLIPPLANE:
1004 append_index(str, state[1]); /* plane [i] */
1005 append(str, ".plane");
1007 case STATE_MODELVIEW_MATRIX:
1008 case STATE_PROJECTION_MATRIX:
1009 case STATE_MVP_MATRIX:
1010 case STATE_TEXTURE_MATRIX:
1011 case STATE_PROGRAM_MATRIX:
1013 /* state[0] = modelview, projection, texture, etc. */
1014 /* state[1] = which texture matrix or program matrix */
1015 /* state[2] = first row to fetch */
1016 /* state[3] = last row to fetch */
1017 /* state[4] = transpose, inverse or invtrans */
1018 const gl_state_index mat = state[0];
1019 const GLuint index = (GLuint) state[1];
1020 const GLuint firstRow = (GLuint) state[2];
1021 const GLuint lastRow = (GLuint) state[3];
1022 const gl_state_index modifier = state[4];
1024 mat == STATE_TEXTURE_MATRIX ||
1025 mat == STATE_PROGRAM_MATRIX)
1026 append_index(str, index);
1028 append_token(str, modifier);
1029 if (firstRow == lastRow)
1030 sprintf(tmp, ".row[%d]", firstRow);
1032 sprintf(tmp, ".row[%d..%d]", firstRow, lastRow);
1036 case STATE_POINT_SIZE:
1038 case STATE_POINT_ATTENUATION:
1040 case STATE_FOG_PARAMS:
1042 case STATE_FOG_COLOR:
1044 case STATE_DEPTH_RANGE:
1046 case STATE_FRAGMENT_PROGRAM:
1047 case STATE_VERTEX_PROGRAM:
1048 /* state[1] = {STATE_ENV, STATE_LOCAL} */
1049 /* state[2] = parameter index */
1050 append_token(str, state[1]);
1051 append_index(str, state[2]);
1053 case STATE_NORMAL_SCALE:
1055 case STATE_INTERNAL:
1056 append_token(str, state[1]);
1057 if (state[1] == STATE_CURRENT_ATTRIB)
1058 append_index(str, state[2]);
1061 _mesa_problem(NULL, "Invalid state in _mesa_program_state_string");
1065 return _mesa_strdup(str);
1070 * Loop over all the parameters in a parameter list. If the parameter
1071 * is a GL state reference, look up the current value of that state
1072 * variable and put it into the parameter's Value[4] array.
1073 * Other parameter types never change or are explicitly set by the user
1074 * with glUniform() or glProgramParameter(), etc.
1075 * This would be called at glBegin time.
1078 _mesa_load_state_parameters(struct gl_context *ctx,
1079 struct gl_program_parameter_list *paramList)
1086 for (i = 0; i < paramList->NumParameters; i++) {
1087 if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
1088 _mesa_fetch_state(ctx,
1089 paramList->Parameters[i].StateIndexes,
1090 ¶mList->ParameterValues[i][0].f);
1097 * Copy the 16 elements of a matrix into four consecutive program
1098 * registers starting at 'pos'.
1101 load_matrix(GLfloat registers[][4], GLuint pos, const GLfloat mat[16])
1104 for (i = 0; i < 4; i++) {
1105 registers[pos + i][0] = mat[0 + i];
1106 registers[pos + i][1] = mat[4 + i];
1107 registers[pos + i][2] = mat[8 + i];
1108 registers[pos + i][3] = mat[12 + i];
1114 * As above, but transpose the matrix.
1117 load_transpose_matrix(GLfloat registers[][4], GLuint pos,
1118 const GLfloat mat[16])
1120 memcpy(registers[pos], mat, 16 * sizeof(GLfloat));
1125 * Load current vertex program's parameter registers with tracked
1126 * matrices (if NV program). This only needs to be done per
1127 * glBegin/glEnd, not per-vertex.
1130 _mesa_load_tracked_matrices(struct gl_context *ctx)
1134 for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
1135 /* point 'mat' at source matrix */
1137 if (ctx->VertexProgram.TrackMatrix[i] == GL_MODELVIEW) {
1138 mat = ctx->ModelviewMatrixStack.Top;
1140 else if (ctx->VertexProgram.TrackMatrix[i] == GL_PROJECTION) {
1141 mat = ctx->ProjectionMatrixStack.Top;
1143 else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) {
1144 GLuint unit = MIN2(ctx->Texture.CurrentUnit,
1145 Elements(ctx->TextureMatrixStack) - 1);
1146 mat = ctx->TextureMatrixStack[unit].Top;
1148 else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) {
1149 /* XXX verify the combined matrix is up to date */
1150 mat = &ctx->_ModelProjectMatrix;
1152 else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV &&
1153 ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) {
1154 GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV;
1155 ASSERT(n < Elements(ctx->ProgramMatrixStack));
1156 mat = ctx->ProgramMatrixStack[n].Top;
1159 /* no matrix is tracked, but we leave the register values as-is */
1160 assert(ctx->VertexProgram.TrackMatrix[i] == GL_NONE);
1164 /* load the matrix values into sequential registers */
1165 if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) {
1166 load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
1168 else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_INVERSE_NV) {
1169 _math_matrix_analyse(mat); /* update the inverse */
1170 ASSERT(!_math_matrix_is_dirty(mat));
1171 load_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
1173 else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_TRANSPOSE_NV) {
1174 load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
1177 assert(ctx->VertexProgram.TrackMatrixTransform[i]
1178 == GL_INVERSE_TRANSPOSE_NV);
1179 _math_matrix_analyse(mat); /* update the inverse */
1180 ASSERT(!_math_matrix_is_dirty(mat));
1181 load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);