/*
* Mesa 3-D graphics library
- * Version: 6.5.3
+ * Version: 7.1
*
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
*/
-#include "glheader.h"
-#include "context.h"
-#include "hash.h"
-#include "imports.h"
-#include "macros.h"
-#include "mtypes.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/hash.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
#include "prog_statevars.h"
#include "prog_parameter.h"
-#include "nvvertparse.h"
/**
COPY_3V(value, ctx->Light.Light[ln].EyeDirection);
value[3] = ctx->Light.Light[ln]._CosCutoff;
return;
- case STATE_HALF:
+ case STATE_SPOT_CUTOFF:
+ value[0] = ctx->Light.Light[ln].SpotCutoff;
+ return;
+ case STATE_HALF_VECTOR:
{
- GLfloat eye_z[] = {0, 0, 1};
-
+ static const GLfloat eye_z[] = {0, 0, 1};
+ GLfloat p[3];
/* Compute infinite half angle vector:
- * half-vector = light_position + (0, 0, 1)
- * and then normalize. w = 0
- *
+ * halfVector = normalize(normalize(lightPos) + (0, 0, 1))
* light.EyePosition.w should be 0 for infinite lights.
*/
- ADD_3V(value, eye_z, ctx->Light.Light[ln].EyePosition);
+ COPY_3V(p, ctx->Light.Light[ln].EyePosition);
+ NORMALIZE_3FV(p);
+ ADD_3V(value, p, eye_z);
NORMALIZE_3FV(value);
- value[3] = 0;
- }
- return;
- case STATE_POSITION_NORMALIZED:
- COPY_4V(value, ctx->Light.Light[ln].EyePosition);
- NORMALIZE_3FV( value );
+ value[3] = 1.0;
+ }
return;
default:
_mesa_problem(ctx, "Invalid light state in fetch_state");
ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i];
}
/* [3] = material alpha */
- value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
+ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3];
return;
case STATE_DIFFUSE:
for (i = 0; i < 3; i++) {
ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i];
}
/* [3] = material alpha */
- value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
+ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3];
return;
default:
_mesa_problem(ctx, "Invalid lightprod state in fetch_state");
}
}
case STATE_TEXENV_COLOR:
- {
+ {
/* state[1] is the texture unit */
const GLuint unit = (GLuint) state[1];
COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
- }
+ }
return;
case STATE_FOG_COLOR:
COPY_4V(value, ctx->Fog.Color);
value[0] = ctx->Fog.Density;
value[1] = ctx->Fog.Start;
value[2] = ctx->Fog.End;
- value[3] = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+ value[3] = (ctx->Fog.End == ctx->Fog.Start)
+ ? 1.0f : (GLfloat)(1.0 / (ctx->Fog.End - ctx->Fog.Start));
return;
case STATE_CLIPPLANE:
{
value[2] = ctx->Point.Params[2];
value[3] = 1.0F;
return;
- case STATE_MATRIX:
+ case STATE_MODELVIEW_MATRIX:
+ case STATE_PROJECTION_MATRIX:
+ case STATE_MVP_MATRIX:
+ case STATE_TEXTURE_MATRIX:
+ case STATE_PROGRAM_MATRIX:
+ case STATE_COLOR_MATRIX:
{
- /* state[1] = modelview, projection, texture, etc. */
- /* state[2] = which texture matrix or program matrix */
- /* state[3] = first row to fetch */
- /* state[4] = last row to fetch */
- /* state[5] = transpose, inverse or invtrans */
-
+ /* state[0] = modelview, projection, texture, etc. */
+ /* state[1] = which texture matrix or program matrix */
+ /* state[2] = first row to fetch */
+ /* state[3] = last row to fetch */
+ /* state[4] = transpose, inverse or invtrans */
const GLmatrix *matrix;
- const gl_state_index mat = state[1];
- const GLuint index = (GLuint) state[2];
- const GLuint firstRow = (GLuint) state[3];
- const GLuint lastRow = (GLuint) state[4];
- const gl_state_index modifier = state[5];
+ const gl_state_index mat = state[0];
+ const GLuint index = (GLuint) state[1];
+ const GLuint firstRow = (GLuint) state[2];
+ const GLuint lastRow = (GLuint) state[3];
+ const gl_state_index modifier = state[4];
const GLfloat *m;
GLuint row, i;
- if (mat == STATE_MODELVIEW) {
+ ASSERT(firstRow >= 0);
+ ASSERT(firstRow < 4);
+ ASSERT(lastRow >= 0);
+ ASSERT(lastRow < 4);
+ if (mat == STATE_MODELVIEW_MATRIX) {
matrix = ctx->ModelviewMatrixStack.Top;
}
- else if (mat == STATE_PROJECTION) {
+ else if (mat == STATE_PROJECTION_MATRIX) {
matrix = ctx->ProjectionMatrixStack.Top;
}
- else if (mat == STATE_MVP) {
+ else if (mat == STATE_MVP_MATRIX) {
matrix = &ctx->_ModelProjectMatrix;
}
- else if (mat == STATE_TEXTURE) {
+ else if (mat == STATE_TEXTURE_MATRIX) {
matrix = ctx->TextureMatrixStack[index].Top;
}
- else if (mat == STATE_PROGRAM) {
+ else if (mat == STATE_PROGRAM_MATRIX) {
matrix = ctx->ProgramMatrixStack[index].Top;
}
+ else if (mat == STATE_COLOR_MATRIX) {
+ matrix = ctx->ColorMatrixStack.Top;
+ }
else {
_mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()");
return;
value[0] = ctx->Viewport.Near; /* near */
value[1] = ctx->Viewport.Far; /* far */
value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */
- value[3] = 0;
+ value[3] = 1.0;
return;
case STATE_FRAGMENT_PROGRAM:
{
}
}
return;
-
+
case STATE_VERTEX_PROGRAM:
{
/* state[1] = {STATE_ENV, STATE_LOCAL} */
}
return;
+ case STATE_NORMAL_SCALE:
+ ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1);
+ return;
+
case STATE_INTERNAL:
- {
- switch (state[1]) {
- case STATE_NORMAL_SCALE:
- ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1);
- break;
- case STATE_TEXRECT_SCALE: {
- const int unit = (int) state[2];
- const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
- if (texObj) {
- struct gl_texture_image *texImage = texObj->Image[0][0];
- ASSIGN_4V(value, 1.0 / texImage->Width, 1.0 / texImage->Height, 0, 1);
- }
- break;
- }
- default:
- /* unknown state indexes are silently ignored
- * should be handled by the driver.
- */
- return;
+ switch (state[1]) {
+ case STATE_NORMAL_SCALE:
+ ASSIGN_4V(value,
+ ctx->_ModelViewInvScale,
+ ctx->_ModelViewInvScale,
+ ctx->_ModelViewInvScale,
+ 1);
+ return;
+ case STATE_TEXRECT_SCALE:
+ {
+ const int unit = (int) state[2];
+ const struct gl_texture_object *texObj
+ = ctx->Texture.Unit[unit]._Current;
+ if (texObj) {
+ struct gl_texture_image *texImage = texObj->Image[0][0];
+ ASSIGN_4V(value, (GLfloat) (1.0 / texImage->Width),
+ (GLfloat)(1.0 / texImage->Height),
+ 0.0f, 1.0f);
+ }
+ }
+ return;
+ case STATE_FOG_PARAMS_OPTIMIZED:
+ /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog)
+ * might be more expensive than EX2 on some hw, plus it needs
+ * another constant (e) anyway. Linear fog can now be done with a
+ * single MAD.
+ * linear: fogcoord * -1/(end-start) + end/(end-start)
+ * exp: 2^-(density/ln(2) * fogcoord)
+ * exp2: 2^-((density/(ln(2)^2) * fogcoord)^2)
+ */
+ value[0] = (ctx->Fog.End == ctx->Fog.Start)
+ ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start));
+ value[1] = ctx->Fog.End * -value[0];
+ value[2] = (GLfloat)(ctx->Fog.Density * ONE_DIV_LN2);
+ value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2);
+ return;
+
+ case STATE_LIGHT_SPOT_DIR_NORMALIZED: {
+ /* here, state[2] is the light number */
+ /* pre-normalize spot dir */
+ const GLuint ln = (GLuint) state[2];
+ COPY_3V(value, ctx->Light.Light[ln]._NormDirection);
+ value[3] = ctx->Light.Light[ln]._CosCutoff;
+ return;
+ }
+
+ case STATE_LIGHT_POSITION: {
+ const GLuint ln = (GLuint) state[2];
+ COPY_4V(value, ctx->Light.Light[ln]._Position);
+ return;
+ }
+
+ case STATE_LIGHT_POSITION_NORMALIZED: {
+ const GLuint ln = (GLuint) state[2];
+ COPY_4V(value, ctx->Light.Light[ln]._Position);
+ NORMALIZE_3FV( value );
+ return;
+ }
+
+ case STATE_LIGHT_HALF_VECTOR: {
+ const GLuint ln = (GLuint) state[2];
+ GLfloat p[3];
+ /* Compute infinite half angle vector:
+ * halfVector = normalize(normalize(lightPos) + (0, 0, 1))
+ * light.EyePosition.w should be 0 for infinite lights.
+ */
+ COPY_3V(p, ctx->Light.Light[ln]._Position);
+ NORMALIZE_3FV(p);
+ ADD_3V(value, p, ctx->_EyeZDir);
+ NORMALIZE_3FV(value);
+ value[3] = 1.0;
+ return;
+ }
+
+
+ case STATE_PT_SCALE:
+ value[0] = ctx->Pixel.RedScale;
+ value[1] = ctx->Pixel.GreenScale;
+ value[2] = ctx->Pixel.BlueScale;
+ value[3] = ctx->Pixel.AlphaScale;
+ break;
+ case STATE_PT_BIAS:
+ value[0] = ctx->Pixel.RedBias;
+ value[1] = ctx->Pixel.GreenBias;
+ value[2] = ctx->Pixel.BlueBias;
+ value[3] = ctx->Pixel.AlphaBias;
+ break;
+ case STATE_PCM_SCALE:
+ COPY_4V(value, ctx->Pixel.PostColorMatrixScale);
+ break;
+ case STATE_PCM_BIAS:
+ COPY_4V(value, ctx->Pixel.PostColorMatrixBias);
+ break;
+ case STATE_SHADOW_AMBIENT:
+ {
+ const int unit = (int) state[2];
+ const struct gl_texture_object *texObj
+ = ctx->Texture.Unit[unit]._Current;
+ if (texObj) {
+ value[0] = texObj->ShadowAmbient;
+ value[1] = texObj->ShadowAmbient;
+ value[2] = texObj->ShadowAmbient;
+ value[3] = texObj->ShadowAmbient;
+ }
}
+ return;
+
+ default:
+ /* unknown state indexes are silently ignored
+ * should be handled by the driver.
+ */
+ return;
}
return;
* some GL state has changed.
*/
GLbitfield
-_mesa_program_state_flags(const GLint state[])
+_mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
{
switch (state[0]) {
case STATE_MATERIAL:
case STATE_POINT_ATTENUATION:
return _NEW_POINT;
- case STATE_MATRIX:
- switch (state[1]) {
- case STATE_MODELVIEW:
- return _NEW_MODELVIEW;
- case STATE_PROJECTION:
- return _NEW_PROJECTION;
- case STATE_MVP:
- return _NEW_MODELVIEW | _NEW_PROJECTION;
- case STATE_TEXTURE:
- return _NEW_TEXTURE_MATRIX;
- case STATE_PROGRAM:
- return _NEW_TRACK_MATRIX;
- default:
- _mesa_problem(NULL,
- "unexpected matrix in _mesa_program_state_flags()");
- return 0;
- }
+ case STATE_MODELVIEW_MATRIX:
+ return _NEW_MODELVIEW;
+ case STATE_PROJECTION_MATRIX:
+ return _NEW_PROJECTION;
+ case STATE_MVP_MATRIX:
+ return _NEW_MODELVIEW | _NEW_PROJECTION;
+ case STATE_TEXTURE_MATRIX:
+ return _NEW_TEXTURE_MATRIX;
+ case STATE_PROGRAM_MATRIX:
+ return _NEW_TRACK_MATRIX;
+ case STATE_COLOR_MATRIX:
+ return _NEW_COLOR_MATRIX;
case STATE_DEPTH_RANGE:
return _NEW_VIEWPORT;
case STATE_VERTEX_PROGRAM:
return _NEW_PROGRAM;
+ case STATE_NORMAL_SCALE:
+ return _NEW_MODELVIEW;
+
case STATE_INTERNAL:
switch (state[1]) {
- case STATE_NORMAL_SCALE:
- return _NEW_MODELVIEW;
case STATE_TEXRECT_SCALE:
+ case STATE_SHADOW_AMBIENT:
return _NEW_TEXTURE;
+ case STATE_FOG_PARAMS_OPTIMIZED:
+ return _NEW_FOG;
default:
/* unknown state indexes are silently ignored and
* no flag set, since it is handled by the driver.
{
switch (k) {
case STATE_MATERIAL:
- append(dst, "material.");
+ append(dst, "material");
break;
case STATE_LIGHT:
append(dst, "light");
case STATE_POINT_ATTENUATION:
append(dst, "point.attenuation");
break;
- case STATE_MATRIX:
- append(dst, "matrix.");
+ case STATE_MODELVIEW_MATRIX:
+ append(dst, "matrix.modelview");
break;
- case STATE_MODELVIEW:
- append(dst, "modelview");
+ case STATE_PROJECTION_MATRIX:
+ append(dst, "matrix.projection");
break;
- case STATE_PROJECTION:
- append(dst, "projection");
+ case STATE_MVP_MATRIX:
+ append(dst, "matrix.mvp");
break;
- case STATE_MVP:
- append(dst, "mvp");
+ case STATE_TEXTURE_MATRIX:
+ append(dst, "matrix.texture");
break;
- case STATE_TEXTURE:
- append(dst, "texture");
+ case STATE_PROGRAM_MATRIX:
+ append(dst, "matrix.program");
break;
- case STATE_PROGRAM:
- append(dst, "program");
+ case STATE_COLOR_MATRIX:
+ append(dst, "matrix.color");
break;
case STATE_MATRIX_INVERSE:
append(dst, ".inverse");
append(dst, ".invtrans");
break;
case STATE_AMBIENT:
- append(dst, "ambient");
+ append(dst, ".ambient");
break;
case STATE_DIFFUSE:
- append(dst, "diffuse");
+ append(dst, ".diffuse");
break;
case STATE_SPECULAR:
- append(dst, "specular");
+ append(dst, ".specular");
break;
case STATE_EMISSION:
- append(dst, "emission");
+ append(dst, ".emission");
break;
case STATE_SHININESS:
- append(dst, "shininess");
+ append(dst, "lshininess");
break;
- case STATE_HALF:
- append(dst, "half");
+ case STATE_HALF_VECTOR:
+ append(dst, ".half");
break;
case STATE_POSITION:
append(dst, ".position");
case STATE_SPOT_DIRECTION:
append(dst, ".spot.direction");
break;
+ case STATE_SPOT_CUTOFF:
+ append(dst, ".spot.cutoff");
+ break;
case STATE_TEXGEN_EYE_S:
append(dst, "eye.s");
break;
case STATE_LOCAL:
append(dst, "local");
break;
- case STATE_INTERNAL:
case STATE_NORMAL_SCALE:
- case STATE_POSITION_NORMALIZED:
+ append(dst, "normalScale");
+ break;
+ case STATE_INTERNAL:
append(dst, "(internal)");
break;
+ case STATE_PT_SCALE:
+ append(dst, "PTscale");
+ break;
+ case STATE_PT_BIAS:
+ append(dst, "PTbias");
+ break;
+ case STATE_PCM_SCALE:
+ append(dst, "PCMscale");
+ break;
+ case STATE_PCM_BIAS:
+ append(dst, "PCMbias");
+ break;
+ case STATE_SHADOW_AMBIENT:
+ append(dst, "ShadowAmbient");
+ break;
default:
;
}
append_index(char *dst, GLint index)
{
char s[20];
- _mesa_sprintf(s, "[%d].", index);
+ _mesa_sprintf(s, "[%d]", index);
append(dst, s);
}
* Use _mesa_free() to deallocate the string.
*/
const char *
-_mesa_program_state_string(const GLint state[6])
+_mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
{
char str[1000] = "";
char tmp[30];
append_token(str, (gl_state_index) state[2]);
break;
case STATE_LIGHT:
- append(str, "light");
append_index(str, state[1]); /* light number [i]. */
append_token(str, (gl_state_index) state[2]); /* coefficients */
break;
append_index(str, state[1]); /* tex unit [i] */
append(str, "color");
break;
- case STATE_FOG_COLOR:
- case STATE_FOG_PARAMS:
- break;
case STATE_CLIPPLANE:
append_index(str, state[1]); /* plane [i] */
- append(str, "plane");
- break;
- case STATE_POINT_SIZE:
- case STATE_POINT_ATTENUATION:
- break;
- case STATE_MATRIX:
+ append(str, ".plane");
+ break;
+ case STATE_MODELVIEW_MATRIX:
+ case STATE_PROJECTION_MATRIX:
+ case STATE_MVP_MATRIX:
+ case STATE_TEXTURE_MATRIX:
+ case STATE_PROGRAM_MATRIX:
+ case STATE_COLOR_MATRIX:
{
- /* state[1] = modelview, projection, texture, etc. */
- /* state[2] = which texture matrix or program matrix */
- /* state[3] = first row to fetch */
- /* state[4] = last row to fetch */
- /* state[5] = transpose, inverse or invtrans */
- const gl_state_index mat = (gl_state_index) state[1];
- const GLuint index = (GLuint) state[2];
- const GLuint firstRow = (GLuint) state[3];
- const GLuint lastRow = (GLuint) state[4];
- const gl_state_index modifier = (gl_state_index) state[5];
- append_token(str, mat);
- if (index)
+ /* state[0] = modelview, projection, texture, etc. */
+ /* state[1] = which texture matrix or program matrix */
+ /* state[2] = first row to fetch */
+ /* state[3] = last row to fetch */
+ /* state[4] = transpose, inverse or invtrans */
+ const gl_state_index mat = (gl_state_index) state[0];
+ const GLuint index = (GLuint) state[1];
+ const GLuint firstRow = (GLuint) state[2];
+ const GLuint lastRow = (GLuint) state[3];
+ const gl_state_index modifier = (gl_state_index) state[4];
+ if (index ||
+ mat == STATE_TEXTURE_MATRIX ||
+ mat == STATE_PROGRAM_MATRIX)
append_index(str, index);
if (modifier)
append_token(str, modifier);
append(str, tmp);
}
break;
+ case STATE_POINT_SIZE:
+ break;
+ case STATE_POINT_ATTENUATION:
+ break;
+ case STATE_FOG_PARAMS:
+ break;
+ case STATE_FOG_COLOR:
+ break;
case STATE_DEPTH_RANGE:
break;
case STATE_FRAGMENT_PROGRAM:
if (!paramList)
return;
+ /*assert(ctx->Driver.NeedFlush == 0);*/
+
for (i = 0; i < paramList->NumParameters; i++) {
if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
- _mesa_fetch_state(ctx,
- paramList->Parameters[i].StateIndexes,
+ _mesa_fetch_state(ctx,
+ (gl_state_index *) paramList->Parameters[i].StateIndexes,
paramList->ParameterValues[i]);
}
}
}
+
+/**
+ * Copy the 16 elements of a matrix into four consecutive program
+ * registers starting at 'pos'.
+ */
+static void
+load_matrix(GLfloat registers[][4], GLuint pos, const GLfloat mat[16])
+{
+ GLuint i;
+ for (i = 0; i < 4; i++) {
+ registers[pos + i][0] = mat[0 + i];
+ registers[pos + i][1] = mat[4 + i];
+ registers[pos + i][2] = mat[8 + i];
+ registers[pos + i][3] = mat[12 + i];
+ }
+}
+
+
+/**
+ * As above, but transpose the matrix.
+ */
+static void
+load_transpose_matrix(GLfloat registers[][4], GLuint pos,
+ const GLfloat mat[16])
+{
+ MEMCPY(registers[pos], mat, 16 * sizeof(GLfloat));
+}
+
+
+/**
+ * Load current vertex program's parameter registers with tracked
+ * matrices (if NV program). This only needs to be done per
+ * glBegin/glEnd, not per-vertex.
+ */
+void
+_mesa_load_tracked_matrices(GLcontext *ctx)
+{
+ GLuint i;
+
+ for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
+ /* point 'mat' at source matrix */
+ GLmatrix *mat;
+ if (ctx->VertexProgram.TrackMatrix[i] == GL_MODELVIEW) {
+ mat = ctx->ModelviewMatrixStack.Top;
+ }
+ else if (ctx->VertexProgram.TrackMatrix[i] == GL_PROJECTION) {
+ mat = ctx->ProjectionMatrixStack.Top;
+ }
+ else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) {
+ mat = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top;
+ }
+ else if (ctx->VertexProgram.TrackMatrix[i] == GL_COLOR) {
+ mat = ctx->ColorMatrixStack.Top;
+ }
+ else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) {
+ /* XXX verify the combined matrix is up to date */
+ mat = &ctx->_ModelProjectMatrix;
+ }
+ else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV &&
+ ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) {
+ GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV;
+ ASSERT(n < MAX_PROGRAM_MATRICES);
+ mat = ctx->ProgramMatrixStack[n].Top;
+ }
+ else {
+ /* no matrix is tracked, but we leave the register values as-is */
+ assert(ctx->VertexProgram.TrackMatrix[i] == GL_NONE);
+ continue;
+ }
+
+ /* load the matrix values into sequential registers */
+ if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) {
+ load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
+ }
+ else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_INVERSE_NV) {
+ _math_matrix_analyse(mat); /* update the inverse */
+ ASSERT(!_math_matrix_is_dirty(mat));
+ load_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
+ }
+ else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_TRANSPOSE_NV) {
+ load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
+ }
+ else {
+ assert(ctx->VertexProgram.TrackMatrixTransform[i]
+ == GL_INVERSE_TRANSPOSE_NV);
+ _math_matrix_analyse(mat); /* update the inverse */
+ ASSERT(!_math_matrix_is_dirty(mat));
+ load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
+ }
+ }
+}